A typical game of
Tetris has 10 columns and 7 pieces. Consider a variation with fewer columns and only one piece, which repeats indefinitely.
For some pieces and column widths it is trivial to see that an infinite game is possible. For example the I tetromino with any column width or any other of the
tetrominoes with an even column width.
For other pieces, an infinite game is possible, but not trivially so. Consider the T tetromino in three columns, an infinite game is possible by following a pattern:
The first piece is horizontal with the stem of the T pointing down.
The second piece is vertical, with the stem of the T pointing to the right and the T is pushed to the left edge.
The third piece is vertical, with the stem of the T pointing to the left and the T is pushed to the right edge. |
|
For each piece and number of columns listed below, find a strategy for each which allows for an infinite game:
1. 2.
### in three columns ### in four columns
# #
#
3. 4.
### in four columns ##### in five columns
# #
#
-----------------------------------------------------
Notes:
1 - Using the reflection of an asymmetrical piece is not allowed.
2 - Use classic gravity: when a row is filled, it is removed and all rows above move down, but no fragments of one partially filled row fall into another partially filled row.
(In reply to
a way to play around with this by Charlie)
A versionfor pentominoes follows. I haven't made a version for hexominoes, but look at the data statements and the arrays for the pieces, to see how to modify.
DEFINT A-Z
RANDOMIZE TIMER
SCREEN 12
' $DYNAMIC
perpetPiece = 2
gWidth = 4
DIM sh&(850, 1 TO 2, 1 TO 5), area&(10000)
DIM grid(20, gWidth)
DATA 9,14
DATA 1,1, 0,1, -1,1, -1,0, -1,-1, 1,1, 0,1, -1,1, 1,0, 1,-1 : '***
DATA -1,-1, 0,-1, 1,-1, 1,0, 1,1, -1,-1, 0,-1, 1,-1, -1,0, -1,1: '*
'*
DATA 2,14
DATA 1,0, 0,0, -1,-1, -1,0, -1,1, 1,1, 0,1, -1,1, 0,0, 0,-1: '***
DATA -1,0, 0,0, 1,-1, 1,0, 1,1, -1,-1, 0,-1, 1,-1, 0,0, 0,1: ' *
' *
CLS
FOR piece = 1 TO 2
READ color1(piece), color2(piece)
FOR rot = 1 TO 4
FOR square = 1 TO 5
READ x(piece, rot, square), y(piece, rot, square)
NEXT
x1 = piece * 80: y1 = rot * 100 - 30
FOR square = 1 TO 5
x = x(piece, rot, square): y = y(piece, rot, square)
x = x * 20 + x1: y = y * 20 + y1
LINE (x, y)-(x + 19, y + 19), color2(piece), B
LINE (x + 1, y + 1)-(x + 18, y + 18), color2(piece), B
PAINT (x + 10, y + 10), color1(piece), color2(piece)
NEXT
GET (x1 - 40, y1 - 40)-(x1 + 39, y1 + 39), sh&(0, piece, rot)
NEXT
NEXT
t# = TIMER: DO: LOOP UNTIL TIMER >= t# + 2 OR TIMER < t#
' DO: a$ = INKEY$: LOOP UNTIL a$ > "": IF a$ = CHR$(27) THEN END
CLS
top = 40: left = 219
LINE (left, top)-(left + 20 * gWidth + 1, top + 401), 15, B
ERASE grid: REDIM grid(20, gWidth)
delay! = .5
piece = INT(RND(1) * 7 + 1): rot = 1
nxtPiece = piece
DO
piece = nxtPiece
nxtPiece = INT(RND(1) * 7 + 1): rot = 1
IF perpetPiece > 0 THEN nxtPiece = perpetPiece: piece = perpetPiece
PUT (5, 20), sh&(0, nxtPiece, 1), PSET
row = 1: col = 2
DO
flag = 0
FOR sq = 1 TO 5
IF y(piece, rot, sq) + row < 0 THEN
flag = 1
ELSEIF grid(y(piece, rot, sq) + row, x(piece, rot, sq) + col) > 0 THEN
EndIt = 1
END IF
NEXT
IF EndIt = 1 THEN GOTO GameOver
IF flag > 0 THEN row = row + 1
LOOP UNTIL flag = 0
initRow = row
old.x = 0: old.y = 0
DO
y = top + row * 20 - 59: x = left + col * 20 - 59
IF old.x > 0 THEN PUT (old.x, old.y), sh&(0, piece, old.rot), XOR
PUT (x, y), sh&(0, piece, rot), XOR
old.x = x: old.y = y: old.rot = rot
t# = TIMER
DO
a$ = INKEY$: IF a$ > "" THEN GOSUB Keyboard
LOOP UNTIL TIMER > t# + delay! OR accel = 1
hit = 0
FOR i = 1 TO 5
trow = y(piece, rot, i) + row + 1
IF trow > 20 THEN hit = 1: EXIT FOR
IF grid(trow, x(piece, rot, i) + col) > 0 THEN hit = 1
NEXT
IF hit = 1 THEN GOSUB HandleHit: EXIT DO: ELSE row = row + 1
LOOP
LOOP
END
GameOver:
LOCATE 30, 36: PRINT "Game Over.";
DO: a$ = INKEY$: LOOP UNTIL a$ > "": IF a$ = CHR$(27) THEN END
RUN
HandleHit:
rMax = 0
FOR i = 1 TO 5
r = row + y(piece, rot, i): c = col + x(piece, rot, i)
grid(r, c) = 1
IF r > rMax THEN rMax = r
NEXT
r = rMax
DO
all = 1
FOR i = 1 TO gWidth
IF grid(r, i) = 0 THEN all = 0: EXIT FOR
NEXT
IF all = 1 THEN GOSUB DelRow ELSE r = r - 1
IF r < 2 OR r < rMax - 4 THEN EXIT DO
LOOP
accel = 0
RETURN
DelRow:
FOR i = 1 TO gWidth
FOR row = r TO 2 STEP -1
grid(row, i) = grid(row - 1, i)
NEXT
grid(1, i) = 0
NEXT
GET (left + 1, top + 1)-(left + 20 * gWidth, top + (r - 1) * 20), area&
PUT (left + 1, top + 21), area&, PSET
LINE (left + 1, top + 1)-(left + 20 * gWidth, top + 20), 0, BF
RETURN
Keyboard:
DO
SELECT CASE a$
CASE CHR$(27)
END
CASE "5"
rot = rot + 1: IF rot > 4 THEN rot = 1
hit = 0
FOR i = 1 TO 5
trow = y(piece, rot, i) + row + 1
tcol = x(piece, rot, i) + col
IF trow > 20 THEN hit = 1: EXIT FOR
IF tcol > gWidth OR tcol < 1 THEN hit = 1: EXIT FOR
IF grid(trow, tcol) > 0 THEN hit = 1
NEXT
IF hit = 1 THEN rot = rot - 1: IF rot < 1 THEN rot = 4
CASE "6"
good = 1
FOR i = 1 TO 5
xp = x(piece, rot, i) + col: yp = y(piece, rot, i) + row
IF xp >= gWidth THEN good = 0: EXIT FOR
IF yp > 0 THEN IF grid(yp, xp + 1) > 0 THEN good = 0: EXIT FOR
NEXT
IF good = 1 THEN col = col + 1
CASE "4"
good = 1
FOR i = 1 TO 5
xp = x(piece, rot, i) + col: yp = y(piece, rot, i) + row
IF xp <= 1 THEN good = 0: EXIT FOR
IF yp > 0 THEN IF grid(yp, xp - 1) > 0 THEN good = 0: EXIT FOR
NEXT
IF good = 1 THEN col = col - 1
CASE "2"
accel = 1
CASE "+"
delay! = delay! / 2
CASE "-"
delay! = delay! * 2
END SELECT
y = top + row * 20 - 60: x = left + col * 20 - 59
IF old.x > 0 THEN PUT (old.x, old.y), sh&(0, piece, old.rot), XOR
PUT (x, y), sh&(0, piece, rot), XOR
old.x = x: old.y = y: old.rot = rot
a$ = INKEY$: IF a$ = CHR$(27) THEN END
LOOP WHILE a$ > ""
RETURN
|
Posted by Charlie
on 2007-12-19 14:38:59 |