Tilez is a sliding tile puzzle implementing the classic 15-puzzle (a 4×4 grid with 15 lettered tiles and one blank space). The board state is stored as a 4×4 string array B$(4,4), and the goal arrangement spells out the alphabet from A through O with the blank in the bottom-right corner. The shuffle routine randomly distributes letters by drawing from a shrinking substring of the alphabet rather than performing swap operations. A notable feature is that the move logic handles multi-tile slides: pressing a letter in the same row or column as the blank space shifts all intervening tiles in one operation using string slicing. Move count is tracked and displayed, and the player is prompted to play again upon completing the puzzle.
Program Analysis
Program Structure
The program is organized into clearly labeled subroutines whose entry-point line numbers are stored as named variables at the top of the program, giving the code a readable, almost structured style:
| Variable | Value | Purpose |
|---|---|---|
SHUFFLE | 900 | Randomly fills the board |
BOARD | 100 | Draws the current board state |
CHECK | 200 | Tests for win condition |
FIND | 300 | Locates a tile by letter |
Execution begins at line 1000 via GOTO 1000 at line 99, skipping the subroutine blocks entirely. The main game loop runs from line 1020 to 1400, with branching to subroutines for all major operations.
Data Representation
The board is a 4×4 string array B$(4,4), where each element holds one character — a letter A–O or a space representing the blank. The blank’s current row and column are tracked explicitly in variables SA and SB, initialized to 4,4 and updated after every move.
Shuffle Routine (lines 900–990)
The shuffle works by building a string A$="ABCDEFGHIJKLMNO" and repeatedly picking a random character from it, placing it into B$(A,B), then removing that character from A$ using string slicing. This is a clean, non-repeating random draw. The routine exits early (via RETURN at line 970) when A$ becomes empty, which happens mid-grid because there are only 15 tiles for 16 cells — the blank is left wherever the traversal ran out, not necessarily at position (4,4). This means SA and SB are hardcoded to 4,4 at line 1016–1017 without being updated to reflect the actual blank position after shuffling — a potential bug that could cause incorrect move validation at the start of a game.
Move Logic (lines 1100–1265)
The move system supports sliding multiple tiles at once, which is a step beyond a basic 15-puzzle implementation. When the player presses a letter, GOSUB FIND locates it in the array. If it shares a row or column with the blank (SA, SB), the move is legal.
- Row move (lines 1120–1140): Handled entirely with string slicing on
B$(A), reassembling the row string so the blank shifts and all intervening tiles slide in one operation. - Column move (lines 1200–1265): Handled with a
FOR...NEXTloop stepping through individual array elements, copying each cell one position toward where the blank was.
After a move, SA and SB are updated to the tile’s old position (now the blank’s new position), and the move counter M is incremented.
Win Check (lines 200–260)
The CHECK subroutine compares each row of B$ against hardcoded target strings using four sequential IF ... THEN RETURN guards. If all four rows match, F is set to 1. The win display at line 260 re-draws the board with a celebratory layout — though it uses mismatched AT coordinates (row 7 uses column 1 instead of 14), which would misplace the second row of the winning display.
Key Input Handling
Lines 1030–1040 use a simple polling loop: INKEY$ is read repeatedly until a character in the range A–Z is detected. The pressed letter is echoed to position AT 0,31 before the move is processed. The FIND subroutine uses early RETURN from inside the loop body (line 330), leaving A and B set to the found coordinates — a classic idiom for returning multiple values without additional variables.
FAST/SLOW Usage
The program wraps the shuffle (GOSUB SHUFFLE) and the GOSUB FIND call in FAST/SLOW pairs (lines 1010–1012 and 1046–1055). This suppresses display during computation-heavy or search operations, reducing flicker and improving perceived responsiveness.
Notable Anomalies
- The shuffle can leave the blank at any position, but
SA=4,SB=4is always assumed — this means the first move of each game may behave incorrectly if the blank ended up elsewhere. - Line
260usesAT 7,1instead ofAT 7,14, misaligning the second row of the win display. - The instructions at line
1007contain “A A TIME” (duplicated “A”), a typo in the message string. - Lines
1500–1510(SAVEandRUN) are utility lines for tape storage and are not part of game execution.
Content
Image Gallery
Source Code
8 REM ** [T] [I] [L] [E] [Z] **
10 DIM B$(4,4)
11 LET SHUFFLE=900
12 LET BOARD=100
13 LET CHECK=200
14 LET FIND=300
99 GOTO 1000
100 REM █[B][O][A][R][D]█[D][R][A][W]█
110 FOR A=1 TO 4
120 PRINT AT 5+A,14;B$(A);
130 NEXT A
140 PRINT AT 0,0;"[M][O][V][E][S] ";M
150 RETURN
200 REM █[C][H][E][C][K]█[F][I][N][I][S][H]█
205 LET F=0
210 IF B$(1)<>"ABCD" THEN RETURN
220 IF B$(2)<>"EFGH" THEN RETURN
230 IF B$(3)<>"IJKL" THEN RETURN
240 IF B$(4)<>"MNO " THEN RETURN
250 LET F=1
260 PRINT AT 6,14;"[A][B][C][D]";AT 7,1;"[E][F][G][H]";AT 8,14;"[I][J][K][L]";AT 9,14;"[M][N][O]█"
270 RETURN
300 REM █[F][I][N][D]█
310 FOR A=1 TO 4
320 FOR B=1 TO 4
330 IF B$(A,B)=K$ THEN RETURN
340 NEXT B
350 NEXT A
900 REM █[S][H][U][F][F][L][E]█
910 LET A$="ABCDEFGHIJKLMNO"
920 FOR A=1 TO 4
930 FOR B=1 TO 4
940 LET C=INT (RND*LEN A$)+1
950 LET B$(A,B)=A$(C)
960 LET A$=A$( TO C-1)+A$(C+1 TO )
970 IF A$="" THEN RETURN
980 NEXT B
985 NEXT A
990 RETURN
1000 REM █[M][A][I][N]█[S][E][C][T][I][O][N]█
1001 PRINT AT 5,13;"▛▀▀▀▀▜";AT 10,13;"▙▄▄▄▄▟"
1002 PRINT AT 6,13;"▌ ▐";AT 7,13;"▌ ▐"
1003 PRINT AT 8,13;"▌ ▐";AT 9,13;"▌ ▐"
1005 PRINT AT 12,0;"[T] [I] [L] [E] [Z]"
1006 PRINT
1007 PRINT "PRESS LETTER OF TILE TO MOVE TO-WARD THE BLANK SPACE. YOU MAY MOVE MORE THAN ONE A A TIME."
1008 PRINT
1009 PRINT "OBJECT IS TO ORDER THE TILES ALPHABETICALLY ACROSS AND DOWN."
1010 FAST
1011 GOSUB SHUFFLE
1012 SLOW
1015 LET M=0
1016 LET SA=4
1017 LET SB=4
1020 GOSUB BOARD
1025 PRINT AT 0,31;" ";
1030 LET K$=INKEY$
1040 IF K$<"A" OR K$>"Z" THEN GOTO 1030
1045 PRINT AT 0,31;K$
1046 FAST
1050 GOSUB FIND
1055 SLOW
1060 IF A=SA OR B=SB THEN GOTO 1100
1090 GOTO 1025
1100 REM **MOVEABLE**
1110 IF B=SB THEN GOTO 1200
1120 REM **ROW MOVE
1130 IF SB<B THEN LET B$(A)=B$(A, TO SB-1)+B$(A,SB+1 TO B)+" "+B$(A,B+1 TO )
1140 IF SB>B THEN LET B$(A)=B$(A, TO B-1)+" "+B$(A,B TO SB-1)+B$(A,SB+1 TO )
1160 GOTO 1300
1200 REM **COLUMN MOVE
1205 IF SA<A THEN GOTO 1250
1210 FOR C=SA TO A+1 STEP -1
1215 LET B$(C,B)=B$(C-1,B)
1220 NEXT C
1225 LET B$(A,B)=" "
1230 GOTO 1300
1250 FOR C=SA TO A-1
1255 LET B$(C,B)=B$(C+1,B)
1260 NEXT C
1265 GOTO 1225
1299 REM **MOVED
1300 LET SA=A
1310 LET SB=B
1320 LET M=M+1
1330 GOSUB CHECK
1340 IF NOT F THEN GOTO 1020
1350 PRINT AT 0,6;M
1360 PRINT AT 21,0;"[N][O][T]█[B][A][D][.]█[A][N][O][T][H][E][R]█[G][O][?]"
1370 INPUT A$
1380 IF A$="N" THEN STOP
1390 CLS
1400 GOTO 1000
1500 SAVE "TILE[Z]"
1510 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.