테트리스 전략


18

당신의 임무는 점수 대 코드 크기의 관점에서 균형 잡힌 테트리스 전략을 구현하는 것입니다.

이 버전의 게임에서 테트라 미노는 회전하여 20 행 10 열의 그리드로 드롭됩니다. 넘어지는 동안에는 수평으로 회전하거나 이동할 수 없습니다. 평소와 같이 떨어진 조각은 그리드의 바닥에 도달하거나 아래쪽으로 더 아래로 이동하면 이미 점유 된 사각형과 충돌 할 때 중지됩니다.

n수평선이 완전히 채워 지면 수평선이 동시에 축소되고 그리드 n에 맨 위에 빈 줄 이 채워 지고 점수가 2 n -1 포인트 씩 증가합니다 . 들어 n= 각각 1,3,7,15 점이다 1,2,3,4. 라인이 사라진 후에 일부 블록은 공중에 떠있는 상태로 남아있을 수 있습니다 ( " 중력 연쇄 반응 "이 없음).

현재 피스를 원하는 곳에 표시 할 공간이 없으면 그리드가 지워지고 현재 피스가 무시되고 게임은 다음 피스를 현재로 계속 진행합니다. 그것에 대한 형벌은 없습니다.

조각 유형의 스트림을 읽고 회전 방법과 놓을 위치를 결정해야합니다. 당신이 조각을 볼 수 있습니다 : 다음 조각 (한)을 찾아 미리은 허용 i+1에 응답하기 전에 i,하지만 당신의 운명을 결정해야합니다 i보기 전에 i+2. 마지막 입력을 넘어선 미리보기가 없습니다.

Tetromino 유형 및 회전은 다음 표에 따라 인코딩됩니다.

        type 0    1    2    3    4    5    6
             O    I    Z    J    L    S    T
            ┌────┬────┬────┬────┬────┬────┬────┐
 rotation 0 │##  │#   │##  │ #  │#   │ ## │### │
            │##  │#   │ ## │ #  │#   │##  │ #  │
            │    │#   │    │##  │##  │    │    │
            │    │#   │    │    │    │    │    │
            ├────┼────┼────┼────┼────┼────┼────┤
          1 │##  │####│ #  │### │  # │#   │#   │
            │##  │    │##  │  # │### │##  │##  │
            │    │    │#   │    │    │ #  │#   │
            │    │    │    │    │    │    │    │
            ├────┼────┼────┼────┼────┼────┼────┤
          2 │##  │#   │##  │##  │##  │ ## │ #  │
            │##  │#   │ ## │#   │ #  │##  │### │
            │    │#   │    │#   │ #  │    │    │
            │    │#   │    │    │    │    │    │
            ├────┼────┼────┼────┼────┼────┼────┤
          3 │##  │####│ #  │#   │### │#   │ #  │
            │##  │    │##  │### │#   │##  │##  │
            │    │    │#   │    │    │ #  │ #  │
            │    │    │    │    │    │    │    │
            └────┴────┴────┴────┴────┴────┴────┘

입력은 이진-나머지 7을 나눈 값을 OIZJLST테트로 미노 로 해석하는 바이트 시퀀스입니다 . 그것들은 대략 같은 확률로 발생할 것입니다 (처음 몇 가지 유형은 256이 7의 배수가 아니기 때문에 약간 더 자주 나타날 수는 있지만 무시할 만합니다). stdin 또는 "i"라는 파일에서 입력하거나 인수로 전달할 수 있습니다. 미리보기 제한을 준수하면 모든 입력을 한 번에 읽을 수 있습니다.

출력도 이진입니다. 입력과 길이가 같은 바이트 시퀀스입니다. stdout 또는 "o"라는 파일 또는 함수의 결과 일 수 있습니다. 각 바이트는 원하는 회전 r*16 + x위치를 인코딩 하며 회전 된 테트로 미노의 가장 왼쪽에있는 사각형의 0 기반 인덱스입니다. 그 와 유효해야합니다, 즉 및 곳, 해당 부분의 폭이다.rxrx0 ≤ r ≤ 30 ≤ x ≤ 10-ww

프로그램은 결정 론적이어야합니다. 동일한 입력이 주어지면 정확히 동일한 출력을 생성해야합니다. PRNG를 사용해도 괜찮습니다.

총 점수는 게임의 점수에서 코드 크기를 뺀 바이트입니다. 다음 파일 (의사 랜덤 노이즈의 64kiB)을 입력으로 사용하십시오. https://gist.github.com/ngn/857bf2c99bfafc649b8eaa1e489e75e4/raw/880f29bd790638aa17f51229c105e726bce60235/i

다음 python2 / python3 스크립트는 현재 디렉토리에서 "i"및 "o"파일을 읽고 게임을 재생하고 점수를 인쇄합니다 (점수에서 코드 크기를 빼는 것을 잊지 마십시오) :

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)

다음과 같이 훨씬 빠른 C 프로그램도 작동하지만 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;}

총 점수가 가장 높습니다. 표준 허점은 금지되어 있습니다.


현재 작품이 원하는 곳에 표시 될 공간이 없을 때 내가 올바르게 이해하는지 봅시다. 예를 들어, 가장 왼쪽 열이 완전히 채워지고 프로그램이 다음 조각을 여기에 배치하려는 경우 다른 공간이 충분하더라도 그리드가 지워집니다. 그 맞습니까?
Arnauld

@Arnauld 네, 맞습니다
ngn

i 파일 을 최적화해도 괜찮 습니까? 좋은 도전, BTW!
Arnauld

예, 내 / dev / urandom에서 가져 왔으므로 악용 가능한 패턴이있을 것으로 기대하지 않습니다. 감사합니다 :)
ngn

1
더 정확하게는 : "테트리스를 기다리는 대신 이동 # 147에서 분명한 2 줄, 그렇지 않으면 스택이 너무 높아질 것"과 같이 i에 특정한 도우미 데이터를 코드에 저장하는 것이 합법적 입니까? (이것은 '입력 파일에서 조각 i + 2를 보지 마십시오'와 충돌하지 않는 것 같습니다.)
Arnauld

답변:


7

C, 점수 : 4136 (4290-154 바이트)

#include <stdio.h>
main(){int c,p=0,t[]={7,9,21,0,0,51,1,32,16,48,0,33,0,32,16,49};for(;(c=getchar())>=0;putchar(c)){c%=7;c=t[!c||!(10%c)?c:2*c+p++%4];}}

아이디어는 블록 S, Z, O, 고정 위치 및 회전을 사용한다는 것입니다.

                  |
      s     z     |
      s s z z # # |
        s z   # # |
0 1 2 3 4 5 6 7 8 9

나머지 J, L, T는 주기적 회전으로 처음 세 열로 압축됩니다.

언 골프 버전 :

#include <stdio.h>
int main() {
    int c,p=0,t[] = {7,9,21,51, 1,32,16,48, 16,48,0,33, 0,32,16,49 };
    while ((c=getchar())!=EOF) {
            switch(c%7) {
            case 0: c = t[0]; break;
            case 1: c = t[1]; break;
            case 2: c = t[2]; break;
            case 3: c = t[4+p++%4]; break;
            case 4: c = t[8+p++%4]; break;
            case 5: c = t[3]; break;
            case 6: c = t[12+p++%4]; break;
            }
            putchar(c);
    }
    return 0;
}

간단하고 효율적-잘했습니다!
ngn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.