Ihre Aufgabe ist es, eine Tetris-Strategie zu implementieren, die in Bezug auf Punktzahl und Codegröße ausgewogen ist.
In dieser Version des Spiels werden Tetrominos gedreht und von oben in ein Raster von 20 Zeilen und 10 Spalten abgelegt. Während des Fallens können sie nicht gedreht oder horizontal bewegt werden. Wie üblich stoppt ein fallengelassenes Teil, wenn es den unteren Rand des Gitters erreicht oder wenn eine weitere Abwärtsbewegung eine Kollision mit einem bereits belegten Feld verursachen würde.
Wenn n
horizontale Linien vollständig ausgefüllt sind, werden sie gleichzeitig ausgeblendet, das Raster wird oben mit n
leeren Linien aufgefüllt und die Punktzahl wird um 2 n -1 Punkte erhöht . Für n
= 1,2,3,4 sind das 1,3,7,15 Punkte. Nachdem die Linien verschwunden sind, können einige Blöcke in der Luft schweben (es gibt keine " Schwerkraftkettenreaktion ").
Wenn für das aktuelle Teil kein Platz mehr vorhanden ist, wird das Raster gelöscht, das aktuelle Teil ignoriert und das Spiel mit dem nächsten Teil als aktuell fortgesetzt. Dafür gibt es keine Strafe.
Sie sollten eine Reihe von Objekttypen lesen und entscheiden, wie sie gedreht und wo sie abgelegt werden sollen. Vorausschau für das nächste Stück (nur eines) ist zulässig: Sie können das Stück anschauen, i+1
bevor Sie darauf antworten i
, aber Sie müssen das Schicksal entschieden haben, i
bevor Sie es anschauen i+2
. Über den letzten Teil der Eingabe hinaus ist keine Vorausschau verfügbar.
Tetrominotypen und ihre Umdrehungen werden gemäß der folgenden Tabelle codiert:
type 0 1 2 3 4 5 6
O I Z J L S T
┌────┬────┬────┬────┬────┬────┬────┐
rotation 0 │## │# │## │ # │# │ ## │### │
│## │# │ ## │ # │# │## │ # │
│ │# │ │## │## │ │ │
│ │# │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
1 │## │####│ # │### │ # │# │# │
│## │ │## │ # │### │## │## │
│ │ │# │ │ │ # │# │
│ │ │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
2 │## │# │## │## │## │ ## │ # │
│## │# │ ## │# │ # │## │### │
│ │# │ │# │ # │ │ │
│ │# │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
3 │## │####│ # │# │### │# │ # │
│## │ │## │### │# │## │## │
│ │ │# │ │ │ # │ # │
│ │ │ │ │ │ │ │
└────┴────┴────┴────┴────┴────┴────┘
Die Eingabe ist binär - eine Folge von Bytes, deren durch 7 geteilte Reste als die interpretiert werden sollten OIZJLST
Tetromino . Sie werden mit ungefähr der gleichen Wahrscheinlichkeit auftreten (außer dass die ersten paar Typen etwas häufiger auftreten, weil 256 kein Vielfaches von 7 ist, aber das sollte vernachlässigbar sein). Die Eingabe kann von stdin oder aus einer Datei mit dem Namen "i" erfolgen oder als Argument übergeben werden. Sie können alle Eingaben auf einmal lesen, sofern Sie die Vorausschau-Einschränkung einhalten.
Die Ausgabe ist ebenfalls binär - eine Folge von Bytes mit der gleichen Länge wie die Eingabe. Dies kann stdout oder eine Datei mit dem Namen "o" oder das Ergebnis einer Funktion sein. Jedes Byte codiert r*16 + x
, wobei r
die gewünschte Drehung und x
der auf 0 basierende Index der Spalte ist, in die das am weitesten links stehende Quadrat des gedrehten Tetrominos gehen soll. Diese r
und x
müssen gültig sein, dh 0 ≤ r ≤ 3
und 0 ≤ x ≤ 10-w
, wo w
ist die Breite des entsprechenden Stückes.
Ihr Programm muss deterministisch sein - bei gleicher Eingabe muss es genau die gleiche Ausgabe liefern. Die Verwendung eines PRNG ist in Ordnung, solange es konstituiert ist.
Die Gesamtpunktzahl ist die Punktzahl aus dem Spiel abzüglich der Größe Ihres Codes in Bytes. Verwenden Sie als Eingabe die folgende Datei (64 KB Pseudozufallsrauschen): https://gist.github.com/ngn/857bf2c99bfafc649b8eaa1e489e75e4/raw/880f29bd790638aa17f51229c105e726bce60235/i
Das folgende python2 / python3-Skript liest die Dateien "i" und "o" aus dem aktuellen Verzeichnis, wiederholt das Spiel und druckt die Partitur aus (bitte denken Sie daran, Ihre Codegröße von der Partitur zu subtrahieren):
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)
Das gleiche gilt für das folgende, viel schnellere C-Programm, das jedoch garantiert nur unter Linux funktioniert:
#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;}
Die höchste Gesamtpunktzahl gewinnt. Standardlücken sind verboten.