Skip to content
Game 8 Unit 9 of 16 1 hr learning time

Cursor Movement

Navigate the grid with INKEY$ and highlight the current cell.

56% of Minefield

The grid is drawn. Now the player needs to navigate it. A cursor shows which cell is selected — bright green brackets around the current position.

The Program

10 CLS
20 DIM m(8, 8)
30 DIM s(8, 8)
40 LET r = 1: LET c = 1
50 REM place 10 mines
60 FOR i = 1 TO 10
70 LET y = INT (RND * 8) + 1
80 LET x = INT (RND * 8) + 1
90 IF m(y, x) = 9 THEN GO TO 70
100 IF y = 1 AND x = 1 THEN GO TO 70
110 LET m(y, x) = 9
120 NEXT i
130 GO SUB 500
135 LET r = 1: LET c = 1
140 GO SUB 600
150 REM game loop
160 REM highlight cursor
170 PRINT AT r + 2, c * 2; INK 4; BRIGHT 1; "[": PRINT AT r + 2, c * 2 + 2; "]"
180 LET k$ = INKEY$
190 IF k$ = "" THEN GO TO 180
200 REM clear cursor
210 GO SUB 600
220 IF k$ = "q" AND r > 1 THEN LET r = r - 1
230 IF k$ = "a" AND r < 8 THEN LET r = r + 1
240 IF k$ = "o" AND c > 1 THEN LET c = c - 1
250 IF k$ = "p" AND c < 8 THEN LET c = c + 1
260 GO TO 160
270 STOP
500 REM === calculate counts ===
510 FOR r = 1 TO 8
520 FOR c = 1 TO 8
530 IF m(r, c) = 9 THEN GO TO 590
540 LET n = 0
550 FOR i = r - 1 TO r + 1
560 FOR j = c - 1 TO c + 1
570 IF i < 1 OR i > 8 OR j < 1 OR j > 8 THEN GO TO 582
580 IF m(i, j) = 9 THEN LET n = n + 1
582 NEXT j
584 NEXT i
586 LET m(r, c) = n
590 NEXT c
595 NEXT r
598 RETURN
600 REM === draw grid ===
610 FOR r = 1 TO 8
620 FOR c = 1 TO 8
630 IF s(r, c) = 0 THEN PRINT AT r + 2, c * 2 + 1; INK 5; "."
640 IF s(r, c) = 1 AND m(r, c) = 0 THEN PRINT AT r + 2, c * 2 + 1; " "
650 IF s(r, c) = 1 AND m(r, c) > 0 AND m(r, c) < 9 THEN PRINT AT r + 2, c * 2 + 1; INK 6; m(r, c)
660 IF s(r, c) = 1 AND m(r, c) = 9 THEN PRINT AT r + 2, c * 2 + 1; INK 2; "*"
670 NEXT c
680 NEXT r
690 RETURN

How It Works

Line 40 sets the starting position: row 1, column 1 (top-left corner).

Line 100 protects the start cell from mines. Without this, the player could start on a mine with no chance of survival.

Line 135 resets r and c after the calculate subroutine runs. The subroutine uses FOR r = 1 TO 8 and FOR c = 1 TO 8 — after completion, both variables are set to 9. Without this reset, the cursor would start at an invalid position.

Line 170 draws the cursor:

170 PRINT AT r + 2, c * 2; INK 4; BRIGHT 1; "[": PRINT AT r + 2, c * 2 + 2; "]"

Green (INK 4) bright brackets frame the current cell. The left bracket goes at c * 2 and the right at c * 2 + 2, with the cell content at c * 2 + 1 between them.

Lines 220-250 handle movement with INKEY$ and boundary checks:

220 IF k$ = "q" AND r > 1 THEN LET r = r - 1
230 IF k$ = "a" AND r < 8 THEN LET r = r + 1

The AND condition prevents moving off the grid. Press Q at row 1 — nothing happens.

Line 210 redraws the grid before moving, which erases the old cursor position.

Variable Clobbering

The calculate subroutine at line 500 uses FOR r and FOR c — the same variables as the cursor position. After GO SUB 500, r and c are both 9 (the loop variable ends at limit + 1 after a FOR loop completes). Line 135 fixes this by resetting both to 1.

This is a common gotcha in Spectrum BASIC. Variables are global — subroutines share them with the main program. Always check what your subroutines do to shared variables.

Try This

Cell info. After drawing the cursor, print the current cell’s mine data: PRINT AT 0, 0; "Cell: "; m(r,c). This shows the hidden value — useful for debugging.

Wrap around. Remove the boundary checks. When r goes below 1 or above 8, PRINT AT will crash with “Integer out of range”. Boundary checks aren’t optional.

What You’ve Learnt

  • Cursor display — brackets around the selected cell
  • INKEY$ movement — Q/A/O/P with boundary checks
  • Variable clobbering — FOR loop variables persist after the loop ends
  • Safe start — preventing mines at the player’s starting position