All about flooble | fun stuff | Get a free chatterbox | Free JavaScript | Avatars    
perplexus dot info

Home > Shapes
One Piece Tetris (Posted on 2007-12-19) Difficulty: 4 of 5
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.

See The Solution Submitted by Brian Smith    
Rating: 4.0000 (3 votes)

Comments: ( Back to comment list | You must be logged in to post comments.)
Hints/Tips a way to play around with this | Comment 1 of 5

Back in 1992, I had written a version of Tetris for QuickBasic. It certainly runs faster now on the processors currently available. It won't run under Vista, as that does not allow DOS full-screen graphics, but it works under XP Home and XP Professional.  But it was a quick modification to limit it to a given number of columns, and to override the random choice of piece with a constant piece.

As mentioned before, if you want to run this, the QuickBasic 4.5 IDE is available at http://www.winsite.com/bin/Info?14000000036569, http://www.qbcafe.net/qbc/english/download/compiler/qbasic_compiler.shtml and other sites. Also see the Wikipedia article http://en.wikipedia.org/wiki/QuickBASIC

The QuickBasic environment is entered from a Command Prompt in the directory in which the above software was loaded.  In the case of this program, which needs large arrays, the /AH switch is needed on QB's invocation:

QB  /AH

You can slow down the speed with - or speed it up with +. It's intended for use with NumLock on so it uses 4 to go left, 6 to go right, 2 to drop the piece into place and 5 to rotate CCW.

This version is only for tetrominoes, not pentominos.

It's set for piece 3 (the L) with 3 columns, as in part 1 of the puzzle, but perpetPiece and gWidth are set early in the program and can be changed:

DEFINT A-Z
RANDOMIZE TIMER
SCREEN 12
' $DYNAMIC
perpetPiece = 3
gWidth = 3
DIM sh&(850, 1 TO 7, 1 TO 4), area&(10000)
DIM grid(20, gWidth)
DATA 6,14
DATA -2,0, -1,0, 0,0, 1,0,   0,-2, 0,-1, 0,0, 0,1 : '****
DATA -2,0, -1,0, 0,0, 1,0,   0,-2, 0,-1, 0,0, 0,1
DATA 4,13
DATA -1,0, 0,0, 1,0, 0,1,    0,-1, 0,0, 0,1, 1,0  :  '***
DATA -1,0, 0,0, 1,0, 0,-1,   0,-1, 0,0, 0,1, -1,0 :  ' *
DATA 2,14
DATA -1,0, 0,0, 1,0, -1,1,   0,-1, 0,0, 0,1, 1,1  :  '***
DATA -1,0, 0,0, 1,0, 1,-1,   0,-1, 0,0, 0,1, -1,-1:  '*
DATA 4,14
DATA -1,0, 0,0, 1,0, 1,1,    0,-1, 0,0, 0,1, 1,-1  :  '***
DATA -1,0, 0,0, 1,0, -1,-1,  0,-1, 0,0, 0,1, -1,1  :  '  *
DATA 15,7
DATA -1,1, 0,1, -1,0, 0,0,  -1,1, 0,1, -1,0, 0,0  : ' **
DATA -1,1, 0,1, -1,0, 0,0,  -1,1, 0,1, -1,0, 0,0  : ' **
DATA 4,12
DATA -1,0, 0,0, 0,1, 1,1,  1,-1, 1,0, 0,0, 0,1  : ' **
DATA -1,0, 0,0, 0,1, 1,1,  1,-1, 1,0, 0,0, 0,1  : '  **
DATA 1,9
DATA 1,0, 0,0, 0,1, -1,1,  1,1, 1,0, 0,0, 0,-1  : '  **
DATA 1,0, 0,0, 0,1, -1,1,  1,1, 1,0, 0,0, 0,-1  : ' **

CLS
FOR piece = 1 TO 7
  READ color1(piece), color2(piece)
  FOR rot = 1 TO 4
    FOR square = 1 TO 4
      READ x(piece, rot, square), y(piece, rot, square)
    NEXT
    x1 = piece * 80: y1 = rot * 100 - 30
    FOR square = 1 TO 4
      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 4
      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 4
      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 4
    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 4
          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 4
          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 4
          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:23:17
Please log in:
Login:
Password:
Remember me:
Sign up! | Forgot password


Search:
Search body:
Forums (0)
Newest Problems
Random Problem
FAQ | About This Site
Site Statistics
New Comments (7)
Unsolved Problems
Top Rated Problems
This month's top
Most Commented On

Chatterbox:
Copyright © 2002 - 2024 by Animus Pactum Consulting. All rights reserved. Privacy Information