รับรายการการเคลื่อนย้าย Tetris ส่งคืนจำนวนบรรทัดที่เสร็จสมบูรณ์


37

ลักษณะ

เราพิจารณาเวอร์ชั่นที่เรียบง่ายของ Tetris ที่การเคลื่อนไหวแต่ละครั้งประกอบด้วย:

  • หมุนชิ้นส่วนตามเข็มนาฬิกา 0 ถึง 3 ครั้ง
  • วางตำแหน่งชิ้นส่วนที่คอลัมน์ที่กำหนด
  • ลดลงอย่างรวดเร็ว

เป้าหมายคือการกำหนดจำนวนของสายที่เสร็จสมบูรณ์รับรายการของการเคลื่อนไหว Tetris ดังกล่าว

แถวที่เสร็จสมบูรณ์จะถูกลบออกเมื่อชิ้นส่วนถูกดร็อปตามกฎ Tetris มาตรฐาน

สนามแข่งขัน

สนามเด็กเล่นกว้าง 10 คอลัมน์ ไม่มีเกมโอเวอร์และสันนิษฐานว่ามีพื้นที่และเวลาเพียงพอในการดำเนินการข้างต้นเสมอไม่ว่าจะมีการกำหนดค่าของสนามเด็กเล่น ความสูงของสนามเด็กเล่นไม่สำคัญที่นี่ แต่คุณสามารถใช้มาตรฐาน 22 แถวเป็นขีด จำกัด บน

รูปร่างของ Tetrominoes

รูปร่าง

อินพุต / เอาต์พุต

อินพุต

รายการที่คั่นด้วยเครื่องหมายจุลภาคของการย้าย Tetris เข้ารหัสด้วย 3 ตัวอักษร อักขระสองตัวแรกอธิบายถึงรูปร่างของ Tetromino ที่จะใช้และตัวสุดท้ายจะอธิบายตำแหน่งที่มันหล่น

  1. tetromino: I, O, T, L, J, ZหรือSในลำดับเดียวกับที่ดังกล่าวข้างต้น
  2. จำนวนการหมุนตามเข็มนาฬิกา: 0ถึง3
  3. คอลัมน์: ที่จะ0 9นี่คือคอลัมน์ที่มุมบนซ้ายของชิ้น (ทำเครื่องหมายด้วยxภาพด้านบน) ตั้งอยู่หลังการหมุน1

มันจะสันนิษฐานว่าการเคลื่อนไหวทั้งหมดในรายการที่ให้นั้นถูกต้อง ไม่จำเป็นต้องตรวจสอบรายการที่ไม่ถูกต้องเช่นI07( Iรูปทรงแนวนอนวางอยู่ทางด้านขวาเกินไป)

1 คุณมีอิสระที่จะใช้อัลกอริทึมการหมุนจริงหรือฮาร์ดโค้ดรูปร่างที่แตกต่างกันทั้งหมดตราบใดที่xอยู่ในคอลัมน์ที่กำหนดโดยอักขระที่สามของการย้าย

เอาท์พุต

จำนวนบรรทัดที่เสร็จสมบูรณ์

ตัวอย่าง

ตัวอย่าง

O00,T24จะสร้างตำแหน่งแรกและO00,T24,S02,T01,L00,Z03,O07,L06,I05จะสร้างตำแหน่งที่สอง

ดังนั้นลำดับต่อไปนี้จะสร้าง Tetris และควรกลับมา4:

O00,T24,S02,T01,L00,Z03,O07,L06,I05,I19

กรณีทดสอบ

1) "O00,T24,S02,T01,L00,Z03,O07,L06,I05,I19" -> 4
2) "S00,J03,L27,Z16,Z18,I10,T22,I01,I05,O01,L27,O05,S13" -> 5
3) "I01,T30,J18,L15,J37,I01,S15,L07,O03,O03,L00,Z00,T38,T01,S06,L18,L14" -> 4
4) "S14,T00,I13,I06,I05,I19,L20,J26,O07,Z14,Z10,Z12,O01,L27,L04,I03,S07,I01,T25,J23,J27,O01,
    I10,I10" -> 8
5) "O00,T24,L32,T16,L04,Z11,O06,L03,I18,J30,L23,Z07,I19,T05,T18,L30,I01,I01,I05,T02" -> 8

หน้าทดสอบ

คุณสามารถใช้JSFiddle นี้เพื่อทดสอบรายการย้าย


1
ชิ้นส่วนใดที่หมุนรอบแกน

1
@Arnauld ฉันขอแนะนำให้คุณดูที่ระบบการหมุนรอบสูงและแก้ไขภาพนิดหน่อย tetris.wikia.com/wiki/SRS

1
ดังนั้นเราสามารถรักษาสิ่งเหล่านี้เป็น 25 (15 ถ้าคุณไม่นับซ้ำ) รูปร่างที่แตกต่างกันแล้ว?

1
โซลูชันสามารถรับอินพุตเป็นอาร์เรย์แทนที่จะเป็นสตริงที่คั่นด้วยเครื่องหมายจุลภาคหรือไม่
จอร์แดน

1
นี่เป็นคำถาม PCG ที่ดีที่สุดที่ฉันเคยเห็นมานาน ช่างเป็นความคิดที่ยอดเยี่ยม! ที่ดีที่สุดในความรู้สึกส่วนตัวของที่น่าสนใจและการปฏิบัติและไม่ใหญ่เกินไป แต่ไม่เล็กเกินไป
GreenAsJade

คำตอบ:


5

PHP, 405 399 378 372 368 360 354 347 331 330 328 319 309 300 ไบต์

(ด้วยการแมปบล็อกของ Dave )

<?$f=[~0];L:for($y=0;$f[++$d+$y]|$s;$s>>=4)$y-=1022<$f[$d+$y]=$f[$d]|$s%16<<$x;$c-=$y;if(list($p,$r,$x)=$argv[++$z])for($s=I==$p?$r&1?4369:15:hexdec(decoct(O==$p?27:ord(base64_decode('M1ozWjqaF1kemR6ZPJMPyTnSJ0s')[ord($p)/4%5*4+$r])));;$d--)for($y=4;$y--;)if ($f[$d+$y]>>$x&$s>>$y*4&15)goto L;echo$c;

โปรแกรมใช้เวลาเคลื่อนย้ายเป็นอาร์กิวเมนต์แยกพิมพ์ผลลัพธ์

ฟังก์ชั่นการสลาย:

ใช้เวลาเคลื่อนย้ายเป็นอาร์เรย์ส่งคืนผลลัพธ์

function t($a)
{
    $f=[~$z=0];             // init field $f (no need to init $z in golfed version)
    L:                      // jump label
                            // A: paint previous piece at line $d+1:
#   if($s)paint($f,$s,$d+1,$x);
    for($y=0;               // $y = working line offset and temporary score
        $f[++$d-$y]|$s;$s>>=4)// next field line; while field or piece have pixels ...
        $s>>=4)                 // next piece line
        $y+=1022<               // 3: decrease temp counter if updated line is full
            $f[$d-$y]=$f[$d]    // 2: use $y to copy over dropped lines
                |$s%16<<$x;     // 1: set pixels in working line
    $c+=$y;                         // add temp score to global score
#   paint($f);var_dump($c);
    if(list($p,$r,$x)=$a[$z++])// B: next piece: $p=name; $r=rotation, $x=column
#   {echo"<b>$z:$p$r-$x</b><br>";
        for(                // C: create base 16 value:
            $s=I==$p
                ? $r&1?4369:15  // I shape (rotated:0x1111, not rotated:0xf)
                : hexdec(decoct(    // 5: convert from base 8 to base 16
                    O==$p ? 27  // O shape (rotation irrelevant: 033)
                    : ord(          // 4: cast char to byte
                                    // 0: 4 bytes for each remaining tetromino
                        base64_decode('M1ozWjqaF1kemR6ZPJMPyTnSJ0s')[
                            ord($p)/4%5 // 1: map STZJL to 01234
                            *4      // 2: tetromino offset
                            +$r]    // 3: rotation offset
            )));;$d--
        )
            for($y=4;$y--;) // D: loop $y through piece lines
                if ($f[$d+$y]>>$x & $s>>$y*4 & 15) // if collision ...
                    goto L;         // goto Label: paint piece, tetris, next piece
#   }
    return$c;               // return score
}

สำหรับการอ้างอิง: การทำแผนที่เก่า

            hexdec(decoct(          // 3. map from base 8 to base 16
                                    // 0. dword values - from high to low: rotation 3,2,1,0
                [0x991e991e,0xc90f933c,0x4b27d239,0x1b1b1b1b,0,0x5a335a33,0x59179a3a]
                [ord($m[0])/2%9]    // 1. map ZJLO.ST to 0123.56 -> fetch wanted tetromino
                >>8*$m[1]&255       // 2. the $m[1]th byte -> rotated piece
            ))

การทดสอบ

ดูคำตอบ PHP อื่นของฉัน

ต้องการที่จะดู?

ลบออก#จากแหล่งฟังก์ชันและเพิ่มสิ่งนี้:

function paint($f,$s=0,$d=0,$x=0){echo'<pre>';for($y=count($f)+5;$y--;$g=0)if(($t=(($z=$y-$d)==$z&3)*($s>>4*$z&15)<<$x)|$r=$f[$y]|0){$z=$t?" $r|$t=<b".(1022<($z=$t|$r)?' style=color:green':'').">$z":" <b>$r";for($b=1;$b<513;$b*=2)$z=($t&$b?'<b>'.($r&$b?2:1).'</b>':($r&$b?1:'.')).$z;printf("%02d $z</b>\n",$y);}echo'</pre>';}

บางขั้นตอนการเล่นกอล์ฟ

รายได้ 5: การก้าวกระโดดครั้งใหญ่ (399- 21 = 378) เข้ามาโดยเพียงแค่การย้ายกะคอลัมน์
จากวงแยกต่างหากกับสองวงที่มีอยู่

Rev. 8: การสลับจากอาเรย์เป็นเบส 16 สำหรับชิ้นส่วน ($ s) ไม่ได้ให้อะไรมาก
แต่ทำเพื่อการตีกอล์ฟเพิ่มขึ้น

Rev. 17: crunched ค่าด้วยbase64_encode(pack('V*',<values>))
และใช้การทำดัชนีไบต์แทนunpackการบันทึก16ไบต์

รายได้ 25 ถึง 29: แรงบันดาลใจจากรหัสของ Dave: hashing ใหม่ (-2), การออกแบบลูปใหม่ (-9), goto (-10)
ไม่มีการเปลี่ยนล่วงหน้า ที่จะมีราคา 17 ไบต์

มีศักยภาพมากขึ้น

ด้วย/2%9ผมจะสามารถประหยัด 15 ไบต์ (เพียง 14 ไบต์ด้วย/4%5)
โดยการใส่ข้อมูลไบนารีลงในไฟล์แล้วการจัดทำดัชนีb ฉันต้องการสิ่งนั้นหรือไม่file(b)[0]

อักขระ UTF-8 จะมีราคาสูงมากสำหรับการเปลี่ยนแปลง

บน hashing

ผมใช้ZJLO.ST /2%9 -> 0123.56; แต่T.ZJLOS /3%7 -> 0.23456ก็ดีเหมือนกัน
หนึ่งไบต์ยาว: O.STJLZ %13/2 -> 0.23456
และอีกสาม:OSTZJ.L %17%12%9 -> 01234.6

ฉันไม่พบแฮชแบบสั้น (สูงสุด 5 ไบต์) ที่ไม่มีช่องว่าง
แต่เดฟพบว่าSTZJL /4%5 -> 01234ปล่อย O จากรายการ WTG!

BTW: TIJSL.ZO (%12%8) -> 01234.67ห้องใบสำหรับIรูปร่าง
(และสวมA, MหรือYรูปร่าง) %28%8และ%84%8ทำเช่นเดียวกัน (แต่Eแทนที่ด้วยA)


นีซ; ฉันชอบการตรวจจับจิตรกรรม + เส้นรวมกันและเครื่องbreak 2นี้ดีกว่าที่ฉันต้องทำใน C มาก! คุณอาจบันทึกจำนวนไบต์ได้โดยใช้array_diff(ตั้งค่าบรรทัดที่เสร็จสมบูรณ์เป็นค่าคงที่แทนที่จะใช้unsetแทนที่array_valuesด้วยarray_diff) แต่ฉันไม่สามารถบอกได้จากเอกสารหากจะทำให้ค่าซ้ำซ้ำ (เช่น array_diff ([1,2, 2,3], [1]) -> [2,2,3] หรือเพียงแค่ [2,3])
เดฟ

@Dave: array_diffไม่ลบค่าซ้ำซ้อน และฉันมีค่าคงที่ (1,023); แต่มันก็ไม่ได้ดัชนีอาร์เรย์ ความคิดที่ดี แต่มันจะมีค่าเป็นไบต์
ติตัส

ว้าวนั่นเป็นเสียงหวือเมื่อคุณบินผ่านฉัน! ดูเหมือนว่าฉันจะต้องทำอะไรบ้าง!
เดฟ

ยินดีด้วยที่มีจำนวนถึง 300! ฉันจะใช้การเปลี่ยนแปลงที่แนะนำล่าสุดของคุณ (ไม่ได้คิดว่าจะทำให้การตรวจสอบการหมุนง่ายขึ้นในตอนนี้ซึ่งฉันไม่ต้องการใช้/10ทุกที่) แต่อย่างอื่นฉันคิดว่าฉันทำเสร็จแล้ว ฉันประหลาดใจที่การแข่งขันของ PHP และ C เป็นไปอย่างตรงไปตรงมา สนุกมาก - หวังว่า OP จะยอมรับคำตอบของคุณ!
เดฟ

@Dave & Titus - ฉันหวังว่าฉันจะยอมรับทั้งสองคำตอบ พวกคุณทำได้ดีมาก ขอแสดงความยินดีต่อไปเพื่อติตัสสำหรับการเข้าถึง 300 และผมคิดว่าเป็นจริง 299 ifตั้งแต่คุณมีพื้นที่ไร้ประโยชน์หลังจาก
Arnauld

16

C, 401 392 383 378 374 351 335 324 320 318 316 305 ไบต์

d[99]={'3Z3Z',983177049,513351321,1016270793,970073931,~0},*L=d+5,V,s;char c;main(x){B:for(c=0;c[++L]|V;V>>=4)c-=(L[c]=*L|(V&15)<<x)>1022;s-=c;if(scanf("%c%1d%d,",&c,&V,&x)>2)for(V=c^79?d[c/4%5]>>24-V*8:27,V=c^73?V/64%4<<8|V/8%8<<4|V%8:V&32?15:4369;;--L)for(c=4;c--;)if(L[c]>>x&V>>c*4&15)goto B;return s;}

รับอินพุตที่คั่นด้วยเครื่องหมายคอมม่าบน stdin ส่งคืนคะแนนในสถานะออก

ต้องcharมีการลงนาม (ซึ่งเป็นค่าเริ่มต้นสำหรับ GCC) และจำเป็นต้อง'3Z3Z'ตีความเป็น 861549402 (ซึ่งเป็นกรณีของ GCC บนเครื่องปลายทางเล็ก ๆ น้อย ๆ อย่างน้อย)


ตัวอย่างการใช้งาน:

echo "O00,T24,S02,T01,L00,Z03,O07,L06,I05,I19" | ./tetris; echo "$?";

คำอธิบายระดับสูง:

รูปร่างทั้งหมดยกเว้นเส้นสามารถใส่ในตาราง 3x3 โดยไม่มีมุมหนึ่งมุม:

6 7 -
3 4 5
0 1 2

ซึ่งหมายความว่าง่ายต่อการเก็บไว้ในไบต์ละ ตัวอย่างเช่น:

- - -         0 0 -
- # -   -->   0 1 0   -->   0b00010111
# # #         1 1 1

(เราจัดแต่ละชิ้นให้ตรงกับด้านล่างซ้ายของกล่องเพื่อให้วางได้ง่ายขึ้น)

เนื่องจากเราได้อย่างน้อย 4 ไบต์ถึง int นี่หมายความว่าเราสามารถเก็บการหมุน 4 อันของแต่ละชิ้นในจำนวนเต็มหนึ่งเดียวโดยมีตัวพิมพ์พิเศษสำหรับบรรทัด นอกจากนี้เรายังสามารถใส่แต่ละแถวของตารางเกมลงใน int (ต้องการเพียง 10 บิต) และชิ้นส่วนที่ตกลงมาเป็นยาว (4 บรรทัด = 40 บิต)


ชำรุด:

d[99]={             // General memory
  '3Z3Z',           //  Shape of "S" piece (multi-char literal, value = 861549402)
  983177049,        //  Shape of "T" piece
  513351321,        //  Shape of "Z" piece
  1016270793,       //  Shape of "J" piece
  970073931,        //  Shape of "L" piece
  ~0                //  Bottom of game grid (solid row)
},                  //  Rest of array stores lines in the game
*L=d+5,             // Working line pointer (start >= base of grid)
V,                  // Current piece after expansion (also stores rotation)
s;                  // Current score (global to initialise as 0)
char c;             // Input shape identifier (also counts deleted lines)
main(x){            // "x" used to store x location
  B:                                // Loop label; jumps here when piece hits floor
  for(c=0;c[++L]|V;V>>=4)           // Paint latest piece & delete completed lines
    c-=(L[c]=*L|(V&15)<<x)>1022;
  s-=c;                             // Increment score
  if(scanf("%c%1d%d,",&c,&V,&x)>2)  // Load next command
    for(V=c^79?                     // Identify piece & rotation
          d[c/4%5]>>24-V*8          //  Not "O": load from data
        :27,                        //  Else "O": always 27
        V=c^73?                     // If not "I" (line):
          V/64%4<<8|V/8%8<<4|V%8    //  expand shape to 16-bits
        :                           // Else we are a line:
          V&32?                     //  "I" coincides with "J"; use this to check
               15:4369;             //  horizontal/vertical
        ;--L)                       // Loop from top-to-bottom of grid
      for(c=4;c--;)                 //  Loop through rows of piece
        if(L[c]>>x&V>>c*4&15)       //   If collides with existing piece:
          goto B;                   //    Exit loops
  return s;                         // Return score in exit status
}

-4, -1 ต้องขอบคุณ @Titus และ -23, -11 ด้วยแรงบันดาลใจจากคำตอบของพวกเขา


ทำได้ดีนี่! คุณอาจจะทำs+=(d[A-x]=d[A])โดยไม่ต้องใช้x?
Arnauld

น่าเสียดายที่xจำเป็นต้องติดตามจำนวนแถวที่จะยุบในขั้นตอนปัจจุบัน (แต่ละแถวAถูกกำหนดเป็นค่าของแถวA-xเมื่อวนรอบดำเนินไป)
เดฟ

D'โอ้! ความผิดฉันเอง. ขออภัยสำหรับคำแนะนำที่งี่เง่า :)
Arnauld

1
@Titus เป็นการละเมิดการจัดทำดัชนีอาร์เรย์ของ C ใส่เพียง1[a]และa[1]ทำสิ่งเดียวกัน (หรือแม่นยำมากขึ้นa[b]แปลเป็น*(a+b)) มันถูกทารุณเช่นนี้เพื่อหลีกเลี่ยงการวงเล็บ ในกรณีนี้1[*v]== (*v)[1]คือตัวอักษรตัวที่สองของคำสั่งคือการหมุน
เดฟ

1
คุณสามารถกำจัดIตัวยึดตำแหน่งได้หรือไม่? ถ้าเป็นเช่นนั้นลองเป็นกัญชาแทน/2%9 ถ้าไม่. %12%12%8
ติตัส

2

Ruby, 474 443 428 379 + 48 = 427 ไบต์

-1 ต้องขอบคุณ @Titus

นี่สามารถเล่นกอล์ฟได้มากขึ้นอย่างแน่นอน

อ่านพจนานุกรมไบนารีของชิ้น (ดูด้านล่าง) จาก STDIN $ cat pieces | ruby script.rb O00,T24,S02,...หรือชื่อไฟล์และใช้เวลารายการย้ายเป็นอาร์กิวเมนต์เช่น

q=$*.pop
z=$<.read.unpack('S*')
b=c=g=i=0
x=10
u=1023
r=->n{n&2**x-1>0?n:r[n>>x]}
y=->n{n>0?[n&u]+y[n>>x]:[]}
l=->c,n{z.find{|m|m>>x==c<<2|n.to_i}||l[c,n-2]}
q.scan(/(\w)(\d)(\d)/){n=l["IOTLJSZ".index($1),$2.to_i]
v=(n&1|(n&6)<<9|(n&56)<<17|(n&960)<<24)<<$3.to_i
(y[b].size+1).times{t=b<<40
t&v>0&&break
g=t|v
v<<=x}
b=0
a=y[r[g]]
a.grep_v(u){|o|b|=o<<x*i
i+=1}
c+=a.count u}
p c

ข้อมูลชิ้นส่วนไบนารี (รูปแบบ xxd)

0000000: c003 4b04 d810 d814 b820 9c24 d029 5a2c  ..K...... .$.)Z,
0000010: 7830 9634 e039 ca3c 3841 d444 c849 4e4c  x0.4.9.<8A.D.INL
0000020: 9861 9869 5c64 5c6c f050 f058 9a54 9a5c  .a.i\d\l.P.X.T.\

ดูได้ที่ repl.it (พร้อมอาร์กิวเมนต์แบบตายตัวพจนานุกรม): https://repl.it/Cqft/2

Ungolfed & คำอธิบาย

# Move list from ARGV
q = $*.pop

# Read piece dictionary; pieces are 16-bit integers: 3 for letter,
# 2 for rotation, 10 for shape (and 1 wasted)
z = $<.read.unpack('S*')

# Empty board and various counters
b = c = g = i = 0
x = 10 # Magic numbers
u = 1023

# A function to remove empty lines
r = ->n{ n & 2**x - 1 > 0 ? n : r[n >> x] }

# A function to split the board into lines
y = ->n{ n > 0 ? [n & u] + y[n >> x] : [] }

# A function to lookup a piece by letter and rotation index
l = ->c,n{ z.find {|m| m >> x == c << 2 | n.to_i } || l[c, n-2] }

# Read the move list
q.scan(/(\w)(\d)(\d)/) {
  # Look up the piece
  n = l["IOTLJSZ".index($1), $2.to_i]

  # Convert the 10-bit piece to a 40-bit piece (4 rows of 10 columns)
  v = (n & 1 |
        (n & 6) << 9 |
        (n & 56) << 17 |
        (n & 960) << 24
      ) << $3.to_i # Shift by the appropriate number of columns

  # Drop the piece onto the board
  (y[b].size + 1).times {
    t = b << 40
    t & v > 0 && break
    g = t | v
    v <<= x
  }

  # Clear completed rows
  b = 0
  a = y[r[g]]
  a.grep_v(u) {|o|
    b |= o << x * i
    i += 1
  }

  c += a.count u # Count cleared rows
}
p c

1 ไบต์: m >> 10อาจเป็นได้m >> x
ติตัส

@Titus ตาดี ขอบคุณ!
จอร์แดน

ไม่จำเป็นต้องระบุอย่างชัดเจน\dในนิพจน์ทั่วไป: /(\w)(\d)(\d)//(\w)(.)(.)/
จัดการ

2

PHP, 454 435 427 420 414 ไบต์

เขตบิตสำหรับชิ้นส่วนและแผนที่ แต่ไม่มีกรณีพิเศษสำหรับIรูปร่างเหมือนการเล่นกอล์ฟของ Dave

<?$t=[I=>[15,4369],O=>[51],T=>[114,562,39,305],L=>[113,802,71,275],J=>[116,547,23,785],Z=>[54,561],S=>[99,306]];foreach($argv as$z=>$m)if($z){$s=$t[$m[0]][$m[1]%count($t[$m[0]])];for($d=$i=0;$i<4;$i++)for($k=0;$k<4;$k++)if($s>>4*$k&1<<$i){for($y=0;$y++<count($f);)if($f[$y-1]&1<<$m[2]+$i)$d=max($d,$y-$k);$k=3;}for($k=$d;$s;$k++,$s>>=4)if(1022<$f[$k]|=$s%16<<$m[2]){$c++;unset($f[$k]);}$f=array_values($f);}echo$c;

รับอาร์กิวเมนต์จากบรรทัดคำสั่งพิมพ์ผลลัพธ์

ungolfed เป็นฟังก์ชัน

รับอาร์กิวเมนต์เป็นอาร์เรย์ส่งคืนผลลัพธ์

function t($a)
{
    // bitwise description of the stones and rotations
    $t=[I=>[15,4369],O=>[51],T=>[114,562,39,305],L=>[113,802,71,275],J=>[116,547,23,785],Z=>[54,561],S=>[99,306]];
    foreach($a as$m)
    {
        $s=$t[$m[0]][$m[1]%count($t[$m[0]])];   // $s=stone
        // find dropping space
        for($d=$i=0;$i<4;$i++)
            // a) lowest pixel of stone in column i
            for($k=0;$k<4;$k++)
                if($s>>4*$k&1<<$i)
                {
                    // b) top pixel of field in column x+i 
                    for($y=0;$y++<count($f);)
                        if($f[$y-1]&1<<$m[2]+$i)$d=max($d,$y-$k);
                    $k=3; // one byte shorter than `break;`
                }
        // do drop
        for($k=$d;$s;$k++,$s>>=4)
            if(1022<$f[$k]|=$s%16<<$m[2])   // add block pixels to line pixels ... if full,
            {$c++;unset($f[$k]);}           // tetris
        $f=array_values($f);
    }
    return$c;
}

การทดสอบ (ในฟังก์ชั่น)

$data=[
    "O00,T24,S02,T01,L00,Z03,O07,L06,I05,I19"=>4,
    "S00,J03,L27,Z16,Z18,I10,T22,I01,I05,O01,L27,O05,S13" => 5,
    "I01,T30,J18,L15,J37,I01,S15,L07,O03,O03,L00,Z00,T38,T01,S06,L18,L14" => 4,
    "S14,T00,I13,I06,I05,I19,L20,J26,O07,Z14,Z10,Z12,O01,L27,L04,I03,S07,I01,T25,J23,J27,O01,I10,I10" => 8,
    // additional example for the two last tetrominoes:
    'O00,T24,L32,T16,L04,Z11,O06,L03,I18,J30,L23,Z07,I19,T05,T18,L30,I01,I01,I05,T02' => 8,
];
function out($a){if(is_object($a)){foreach($a as$v)$r[]=$v;return'{'.implode(',',$r).'}';}if(!is_array($a))return$a;$r=[];foreach($a as$v)$r[]=out($v);return'['.join(',',$r).']';}
function cmp($a,$b){if(is_numeric($a)&&is_numeric($b))return 1e-2<abs($a-$b);if(is_array($a)&&is_array($b)&&count($a)==count($b)){foreach($a as $v){$w = array_shift($b);if(cmp($v,$w))return true;}return false;}return strcmp($a,$b);}
function test($x,$e,$y){static $h='<table border=1><tr><th>input</th><th>output</th><th>expected</th><th>ok?</th></tr>';echo"$h<tr><td>",out($x),'</td><td>',out($y),'</td><td>',out($e),'</td><td>',cmp($e,$y)?'N':'Y',"</td></tr>";$h='';}
foreach($data as $v=>$e)
{
    $x=explode(',',$v);
    test($x,$e,t($x));
}

427? คุณอยู่ใน!
จอร์แดน

@Jordan: และผู้ที่ 427 รวมถึง<?ค่าใช้จ่าย :)
ติตัส
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.