Il tuo compito è implementare una strategia Tetris bilanciata in termini di punteggio e dimensioni del codice.
In questa versione del gioco i tetromini vengono ruotati e rilasciati dall'alto in una griglia di 20 righe e 10 colonne. Durante la caduta, non possono essere ruotati o spostati in orizzontale. Come al solito, un pezzo lasciato cadere si ferma quando raggiunge il fondo della griglia o quando un ulteriore movimento verso il basso causerebbe la collisione con un quadrato già occupato.
Quando nle linee orizzontali vengono riempite completamente, collassano simultaneamente, la griglia viene riempita con nlinee vuote in alto e il punteggio viene incrementato di 2 n -1 punti. Per n= 1,2,3,4 corrispondono rispettivamente a 1,3,7,15 punti. Dopo che le linee scompaiono, alcuni blocchi potrebbero rimanere fluttuanti nell'aria (non c'è " reazione a catena di gravità ").
Quando non è disponibile spazio per far apparire il pezzo corrente dove desiderato, la griglia viene cancellata, il pezzo corrente viene ignorato e il gioco continua con il pezzo successivo come corrente. Non c'è penalità per quello.
Dovresti leggere un flusso di tipi di pezzi e decidere come ruotarli e dove lasciarli cadere. È consentito guardare avanti per il prossimo pezzo (solo uno): puoi guardare il pezzo i+1prima di rispondere i, ma devi aver deciso il destino di iprima di guardare i+2. Non è disponibile alcun aspetto oltre l'ultimo pezzo dell'input.
I tipi di tetromino e le loro rotazioni sono codificati secondo la seguente tabella:
type 0 1 2 3 4 5 6
O I Z J L S T
┌────┬────┬────┬────┬────┬────┬────┐
rotation 0 │## │# │## │ # │# │ ## │### │
│## │# │ ## │ # │# │## │ # │
│ │# │ │## │## │ │ │
│ │# │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
1 │## │####│ # │### │ # │# │# │
│## │ │## │ # │### │## │## │
│ │ │# │ │ │ # │# │
│ │ │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
2 │## │# │## │## │## │ ## │ # │
│## │# │ ## │# │ # │## │### │
│ │# │ │# │ # │ │ │
│ │# │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
3 │## │####│ # │# │### │# │ # │
│## │ │## │### │# │## │## │
│ │ │# │ │ │ # │ # │
│ │ │ │ │ │ │ │
└────┴────┴────┴────┴────┴────┴────┘
L'input è binario - una sequenza di byte i cui resti quando divisi per 7 devono essere interpretati come i OIZJLSTtetromini. Si verificheranno approssimativamente con la stessa probabilità (tranne per il fatto che i primi pochi tipi potrebbero apparire leggermente più spesso a causa del 256 che non è un multiplo di 7, ma che dovrebbe essere trascurabile). L'input può provenire da stdin o da un file chiamato "i" o passato come argomento. Puoi leggere tutti gli input in una sola volta, a condizione di assicurarti di rispettare la restrizione look-ahead.
Anche l'output è binario: una sequenza di byte della stessa lunghezza dell'input. Può essere stdout o un file chiamato "o" o il risultato di una funzione. Ogni byte codifica r*16 + x, dove si rtrova la rotazione desiderata ed xè l'indice in base 0 della colonna dove dovrebbe andare il quadrato più a sinistra del tetromino ruotato. Quelli re xdevono essere validi, cioè 0 ≤ r ≤ 3e 0 ≤ x ≤ 10-w, dov'è wla larghezza del pezzo corrispondente.
Il programma deve essere deterministico - dato lo stesso input, deve produrre esattamente lo stesso output. L'uso di un PRNG è ok purché sia seminato.
Il punteggio totale è il punteggio del gioco meno la dimensione del codice in byte. Utilizzare il seguente file (64 kB di rumore pseudo-casuale) come input: https://gist.github.com/ngn/857bf2c99bfafc649b8eaa1e489e75e4/raw/880f29bd790638aa17f51229c105e726bce60235/i
Il seguente script python2 / python3 legge i file "i" e "o" dalla directory corrente, riproduce il gioco e stampa il punteggio (ricordarsi di sottrarre la dimensione del codice dal punteggio):
a = [0] * 23 # grid (1square=1bit, 1row=1int, LSB is left, 3 empty rows on top)
# O I Z J L S T tetrominoes
t = [[[3,3],[1,1,1,1],[3,6], [2,2,3],[1,1,3],[6,3], [7,2] ],
[[3,3],[15], [2,3,1],[7,4], [4,7], [1,3,2],[1,3,1]],
[[3,3],[1,1,1,1],[3,6], [3,1,1],[3,2,2],[6,3], [2,7] ],
[[3,3],[15], [2,3,1],[1,7], [7,1], [1,3,2],[2,3,2]]]
tw = [[2,1,3,2,2,3,3],[2,4,2,3,3,2,2],[2,1,3,2,2,3,3],[2,4,2,3,3,2,2]] # widths
th = [[2,4,2,3,3,2,2],[2,1,3,2,2,3,3],[2,4,2,3,3,2,2],[2,1,3,2,2,3,3]] # heights
score = 0
for p, rx in zip(bytearray(open('i', 'rb').read()),
bytearray(open('o', 'rb').read())):
p %= 7; r = rx >> 4; x = rx & 15 # p:piece type, r:rotation, x:offset
b = [u << x for u in t[r][p]] # as a bit-matrix (list of ints)
bw = tw[r][p]; bh = th[r][p] # width and height
y = 0 # drop it
while y <= 23 - bh and all((a[y + i] & b[i]) == 0 for i in range(bh)):
y += 1
y -= 1
if y < 3: # no room?
a = [0] * len(a) # clear the grid and carry on
else:
for i in range(bh): # add the piece to the grid
a[y + i] |= b[i]
n = 0
for i in reversed(range(bh)): # collapse full lines
if a[y + i] == (1 << 10) - 1:
n += 1; del a[y + i]; a = [0] + a
score += (1 << n) - 1
print(score)
Così fa il seguente programma C molto più veloce ma è garantito che funzioni solo su Linux:
#include<stdio.h>
#include<fcntl.h>
#include<sys/mman.h>
#include<sys/stat.h>
#define F(i,n,b...)for(i=0;i<n;i++){b;}
typedef int I;typedef char C;
I a[23],t[]={
51,4369,99,802,785,54,39,51,15,306,71,116,561,305,
51,4369,99,275,547,54,114,51,15,306,113,23,561,562};
C*th="2423322213223324233222132233";
I main(){
struct stat h;stat("i",&h);I i,j,k,l=h.st_size,z=0;
C*mi=mmap(0,l,1,1,open("i",0,0),0),*mo=mmap(0,l,1,1,open("o",0,0),0);
F(k,l,
I p=(mi[k]&255)%7,r=3&mo[k]>>4,q=r*7+p,x=mo[k]&15,y=0,h=th[q]-'0',b[4];
F(i,h,b[i]=(t[q]>>(4*i)&15)<<x)
while(y<=23-h){I u=0;F(i,h,u|=a[y+i]&b[i])if(u)break;y++;}
if(--y<3){F(i,23,a[i]=0)continue;}
F(i,h,a[y+i]|=b[i])
I n=0;F(i,23,n+=a[i]==1023)
if(n){j=23;F(i,20,a[j]=a[22-i];j-=a[j]!=1023)F(i,j,a[i]=0);z+=(1<<n)-1;})
printf("%d\n",z);return 0;}
Il punteggio totale più alto vince. Sono vietate le scappatoie standard.