Keyboard Memory is a matching card game that uses the 18 keys of the QWERTY home and upper rows as the “cards” on screen. The program arranges those 18 keys in a 3×6 grid and pairs each key with a two-digit numeric code stored in the string `b$`; a random rotation offset (1–9) shuffles which code is hidden behind which key at the start of each game. The player presses two keys per turn to reveal their hidden values, and if the values match, both keys are removed from the board; the game ends when all 9 pairs are found. A best-score tracker (`tb`) persists across replays within the same session, recording the minimum number of turns needed to clear the board.
Program Structure
The program divides into five logical phases:
- Initialization (lines 5–35): Dimensions arrays, seeds a random rotation offset
r, resets per-game counterstu(turns used) andte(total matched pairs), and preserves the session best scoretb. - Board setup (lines 40–130): Builds the key layout string
a$and the hidden-value stringb$, then populates display arrayt$and value arrayw$using a circular offset so the pairing is randomized each game. - Board rendering (lines 140–180): Prints the 18 keys in a 3×6 grid using
PRINT AT 4*k, 4*j. - Gameplay loop (lines 190–370): Handles two keystrokes per turn, reveals hidden values, checks for a pair match, and loops until all 9 pairs are cleared.
- End screen (lines 380–500): Reports turn count and session best score, then offers replay or quit.
Key Data Structures
| Variable | Purpose |
|---|---|
a$ | 18-character string of QWERTY keys used as card labels |
b$ | 18-character string of digit pairs; values hidden behind each key |
t$(1,n) | Current visible label for position n; set to space when a pair is matched |
w$(1,n) | Hidden value assigned to position n after rotation |
q$(1,k) | Stores the two keys pressed in the current turn (k=1 or 2) |
n(k) | Grid position index of the key pressed for each half of a turn |
tu / te | Turns used / pairs matched this game |
tb | Session best score (minimum turns); initialized to 1000 |
Pairing via Circular Rotation
The pairing mechanism is elegant: b$ encodes 9 two-character values repeated in positions 1–18 (e.g., "175662951734409032" — each adjacent pair of digits appears exactly twice). A random offset r (1–9) is added to each position index n to compute dis (line 89), with wraparound handled at line 110 (dis = dis - 18). This rotates which slot in b$ maps to which key, producing a different pairing arrangement every game without any explicit shuffle algorithm.
Gameplay Loop Mechanics
The inner FOR k=1 TO 2 loop (lines 190–320) collects two keypresses per turn. For each keypress, a linear scan of all 18 positions (lines 250–310) finds the matching key label in t$ and reveals its hidden value on screen. Line 315 detects if both presses selected the same key (n(1)=n(2)) and rejects it with a beep, looping back for a second valid choice. After both picks are made, line 330 checks whether their hidden values match; a mismatch jumps to line 135 (a non-existent line, which falls through to line 140) to redraw the board for the next turn. A match increments te and blanks both positions in t$.
Notable Techniques and Idioms
- 1D string array as board state: Both
t$andw$are dimensioned(1,18)— a single-row 2D string array used as a 1D array, which is idiomatic for this dialect of BASIC where true 1D string arrays are not directly supported. - GO TO non-existent line 135: Line 330’s mismatch branch targets line 135, which does not exist; execution advances to line 140, the board-rendering loop. This is a deliberate technique to re-render the board after a failed match without a separate GOSUB.
- INKEY$ polling loop: Lines 200–210 and 410–415 use the standard
INKEY$busy-wait idiom for responsive keypress detection. - Session best score persistence:
tbis initialized at line 6 outside the game-restart path (line 10), so it survives replays and correctly tracks the minimum turn count across multiple games. - Variable
stdeclared but unused: Line 230 setsLET st=0butstis never subsequently read. This appears to be a leftover from an earlier version of the program.
Bugs and Anomalies
- Unused variable
st: As noted,stis assigned at line 230 but never used, consuming memory unnecessarily. - No input validation for non-board keys: If the player presses a key not present in
a$, the scan at lines 250–310 will find no match,n(k)retains its previous value (or 0 on first use), and the turn counter still increments at line 240. This can cause incorrect behavior or a false match on the second press. - Board flicker on mismatch: Jumping to line 135 (→140) redraws all 18 key labels unconditionally, including already-matched (blank) positions. Matched positions stored as
" "int$print a space, so previously cleared slots are effectively re-blanked — functionally correct but slightly wasteful.
Content
Source Code
5 REM Keyboard Memory
6 LET tb=1000
10 DIM t$(1,18):DIM w$(1,18):DIM q$(1,2):DIM n(2)
20 LET r= INT (RND*9+1)
30 CLS :RANDOMIZE
35 LET tu=0:LET te=0
40 LET a$="qwertyasdfghzxcvbn"
60 LET B$="175662951734409032"
70 FOR n=1 TO 18
80 LET t$(1,n)=a$(n)
90 LET dis=n+r
100 IF dis<19 THEN GO TO 120
110 LET dis=dis-18
120 LET w$(1,n)=b$(dis)
130 NEXT n
140 FOR k=1 TO 3
150 FOR j=1 TO 6
160 PRINT AT 4*k,4*j;t$(1,(k-1)*6+j)
170 NEXT j
180 NEXT k
190 FOR k=1 TO 2
200 LET k$= INKEY$
210 IF k$="" THEN GO TO 200
220 LET q$(1,k)=k$
230 LET st=0
240 LET tu=tu+1
250 FOR n=1 TO 18
260 LET kk= INT ((n-0.5)/6+1)
270 LET j=n-(kk-1)*6
280 IF t$(1,n) <>q$(1,k) THEN GO TO 310
290 PRINT AT 4*kk,4*j;w$(1,n)
300 LET n(k)=n
310 NEXT n
315 IF n(1)=n(2) THEN BEEP .5,12:GO TO 200
320 NEXT k
330 IF w$(1,n(1)) <>w$(1,n(2)) THEN GO TO 135
340 LET te=te+1
350 LET t$(1,n(1))=" "
360 LET t$(1,n(2))=" "
370 IF te<9 THEN GO TO 135
375 IF tu<tb THEN LET tb=tu
380 CLS
390 PRINT AT 10,5;"NUMBER OF TURNS = ";tu
395 PRINT AT 15,5;"BEST SCORE = ";tb
400 PRINT AT 18,5;"ANOTHER GAME? (Y or N)"
410 LET z$= INKEY$
411 IF z$="y" OR z$="Y" THEN CLS :GO TO 10
415 IF z$="" THEN GO TO 400
430 IF z$="n" OR z$="N" THEN CLS :PRINT AT 15,5;"TRY AGAIN SOMETIME":GO TO 500
440 CLS :PRINT AT 15,5;"IS THIS A DIFFICULT TASK?":GO TO 400
490 SAVE "MATCH" LINE 0
500 STOP
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
