Tugas Anda adalah mengimplementasikan strategi Tetris yang seimbang dalam hal skor vs ukuran kode.
Dalam versi ini, permainan tetromino diputar dan dijatuhkan dari atas ke dalam kisi 20 baris dan 10 kolom. Saat jatuh, mereka tidak dapat diputar atau dipindahkan secara horizontal. Seperti biasa, potongan yang jatuh berhenti ketika mencapai bagian bawah kisi atau ketika gerakan ke bawah lebih lanjut akan menyebabkan tabrakan dengan kotak yang sudah ditempati.
Ketika n
garis horizontal mendapatkan diisi sepenuhnya, mereka runtuh secara bersamaan, grid diisi kembali dengan n
baris kosong di bagian atas, dan skor bertambah dengan 2 n -1 poin. Untuk n
= 1,2,3,4, masing-masing 1,3,7,15 poin. Setelah garis hilang, beberapa blok mungkin tetap mengambang di udara (tidak ada " reaksi berantai gravitasi ").
Ketika tidak ada ruang yang tersedia untuk bagian saat ini untuk muncul di mana yang diinginkan, kotak dihapus, bagian saat ini diabaikan, dan permainan berlanjut dengan bagian berikutnya sebagai saat ini. Tidak ada penalti untuk itu.
Anda harus membaca aliran jenis potongan dan memutuskan cara memutarnya dan di mana menjatuhkannya. Lihatlah ke depan untuk potongan berikutnya (hanya satu) diperbolehkan: Anda dapat melihat potongan i+1
sebelum menanggapi i
, tetapi Anda harus memutuskan nasib i
sebelum melihat i+2
. Tidak ada pandangan di depan tersedia di luar bagian terakhir dari input.
Jenis tetromino dan rotasinya dikodekan per tabel berikut:
type 0 1 2 3 4 5 6
O I Z J L S T
┌────┬────┬────┬────┬────┬────┬────┐
rotation 0 │## │# │## │ # │# │ ## │### │
│## │# │ ## │ # │# │## │ # │
│ │# │ │## │## │ │ │
│ │# │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
1 │## │####│ # │### │ # │# │# │
│## │ │## │ # │### │## │## │
│ │ │# │ │ │ # │# │
│ │ │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
2 │## │# │## │## │## │ ## │ # │
│## │# │ ## │# │ # │## │### │
│ │# │ │# │ # │ │ │
│ │# │ │ │ │ │ │
├────┼────┼────┼────┼────┼────┼────┤
3 │## │####│ # │# │### │# │ # │
│## │ │## │### │# │## │## │
│ │ │# │ │ │ # │ # │
│ │ │ │ │ │ │ │
└────┴────┴────┴────┴────┴────┴────┘
Input adalah biner - urutan byte yang sisa ketika dibagi 7 harus ditafsirkan sebagai OIZJLST
tetromino. Mereka akan muncul dengan probabilitas yang kira-kira sama (kecuali bahwa beberapa tipe pertama mungkin muncul sedikit lebih sering karena 256 tidak kelipatan 7, tetapi itu harus diabaikan). Input dapat dari stdin atau dari file bernama "i" atau diteruskan sebagai argumen. Anda dapat membaca semua input sekaligus, asalkan Anda pastikan untuk mematuhi pembatasan lihat-depan.
Output juga biner - urutan byte dengan panjang yang sama dengan input. Itu bisa stdout atau file bernama "o" atau hasil dari suatu fungsi. Setiap byte mengkodekan r*16 + x
, di mana r
rotasi yang diinginkan dan x
merupakan indeks berbasis kolom 0 di mana kuadrat paling kiri dari tetromino diputar harus pergi. Itu r
dan x
harus valid, yaitu 0 ≤ r ≤ 3
dan 0 ≤ x ≤ 10-w
, di mana w
lebar potongan yang sesuai.
Program Anda harus deterministik - diberi input yang sama, harus menghasilkan output yang sama persis. Menggunakan PRNG tidak apa-apa asalkan itu adalah konst-seeded.
Skor total adalah skor dari gim dikurangi ukuran kode Anda dalam byte. Silakan gunakan file berikut (64kiB dari pseudo-random noise) sebagai masukan: https://gist.github.com/ngn/857bf2c99bfafc649b8eaa1e489e75e4/raw/880f29bd790638aa17f51229c105e726bce60235/i
Skrip python2 / python3 berikut membaca file "i" dan "o" dari direktori saat ini, mengulang permainan dan mencetak skor (harap ingat untuk mengurangi ukuran kode Anda dari skor):
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)
Begitu juga program C yang jauh lebih cepat tetapi dijamin hanya berfungsi di 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;}
Total skor tertinggi menang. Celah standar dilarang.
Jawaban:
C, skor: 4136 (4290 - 154 byte)
Idenya adalah bahwa blok S, Z, O, saya menggunakan lokasi dan rotasi tetap:
Sisanya - J, L, T - dikemas ke dalam tiga kolom pertama dengan beberapa putaran siklik.
Versi tidak disatukan:
sumber