This program is a four-operation arithmetic drill for up to 25 problems, covering addition, subtraction, multiplication, and division. The user selects an operation (1–4), and the program jumps directly to the corresponding routine using the expression `GO TO B*100`, a common Sinclair BASIC computed-jump idiom. Division problems are constructed by generating the divisor first and multiplying by a random integer to guarantee a whole-number answer. A custom UDG character (\a) is defined at startup via a DATA/POKE loop and used to render a division symbol (÷) in both the title screen and problem display. Scores are reported as a rounded percentage using `INT((C/A*100)+.5)`.
Program Analysis
Program Structure
The program is organized into clearly separated sections:
- Initialization (lines 15–85): Randomizes, calls the title-screen subroutine, collects the number of problems (
A) and the desired operation (B), then dispatches via computed jump. - Operation routines (lines 100–440): Each routine starts at a multiple of 100 (100 = addition, 200 = subtraction, 300 = multiplication, 400 = division) and shares the random-number subroutine at line 800 and the correct/incorrect feedback branches at lines 160 and 145.
- Scoring display (lines 505–550): Prints a decorative border, the percentage score, and a play-again prompt.
- Subroutines (lines 800–960): Line 800 generates two random integers 1–10; lines 850–960 define the UDG and display the title screen.
Computed GOTO Dispatch
Line 85 uses GO TO B*100 to jump directly to the routine for the chosen operation. Because B is constrained to 1–4 by line 80, this cleanly targets lines 100, 200, 300, or 400 without a chain of IF tests. This is a well-known Sinclair BASIC efficiency technique.
UDG Definition and Use
The subroutine starting at line 850 defines UDG \a (character 144) as a division symbol (÷) using eight bytes stored in a DATA statement and poked via POKE USR "\a"+a, b inside a FOR loop (lines 860–870). The data bytes 0,24,0,127,0,24,0,0 produce a dot-line-dot pattern. The UDG is then used on the title screen (lines 905–940) to spell out the division column header and in the division problem prompt at line 420.
Division Problem Generation
Lines 411–412 construct division problems that always yield a whole-number answer: the divisor F is picked first (1–10), then E is set to F times another random integer (1–10), ensuring E/F is an integer. This avoids the awkwardness of asking a student for a decimal answer.
Shared Feedback Branches
All four operation loops share the same correct/incorrect feedback code. A correct answer jumps to line 160 (plays a rising three-note beep, increments correct counter C), and an incorrect answer falls through or jumps to line 145 (plays a descending two-note beep, increments incorrect counter I). Both branches then continue to line 170 (NEXT J) or its equivalent in each loop.
Score Calculation
Line 520 computes the percentage as INT((C/A*100)+.5), which rounds to the nearest whole percent rather than truncating — a small but deliberate detail.
Bugs and Anomalies
- Subtraction answer check (line 240): The condition
IF G=E-F OR G=F-E THEN GO TO 160accepts either sign of the difference as correct. This is partially intentional (the display at line 220–225 always shows the larger number first), but because the display swap only occurs whenF>E, the problem shown and the accepted answer are not always in sync. WhenE>F, the problem is shown asE - F, yetF-E(a negative number) would also be accepted as correct. - Subtraction fallthrough (line 245): Line 245 uses
ORrather thanAND:IF G<>E-F OR G<>F-E THEN GO TO 145. Because at least one of the two conditions is always true for any value ofG, this line unconditionally branches to 145 and is logically redundant given the preceding check at line 240. TheANDoperator was almost certainly intended. - Incorrect counter
Iunused:Iis incremented at line 150 but never displayed in the score section — onlyC(correct answers) is used for the percentage. - Missing
NEXT Jfor division loop: The division loop (lines 400–440) has no explicitNEXT Jstatement before falling through to line 505. Execution will naturally reach line 505 after the last iteration, but the loop variableJis never formally closed. On Sinclair BASIC this works in practice because reaching the end of the program body simply exits the loop implicitly via the jump to 505.
Variable Summary
| Variable | Purpose |
|---|---|
A | Number of problems (1–25) |
B | Operation choice (1–4) |
C | Correct answer count |
I | Incorrect answer count (unused in output) |
J | Problem loop counter |
E, F | Random operands for each problem |
G | Student’s input answer |
H | Loop variable for correct-answer beep |
a, b | UDG definition loop variables |
Content
Image Gallery
Source Code
5 REM math VERSION 2.1
10 REM John Colonna SINCUS
15 RANDOMIZE : GO SUB 850
20 CLS : BORDER 6
25 PRINT
30 PRINT "HOW MANY PROBLEMS ARE YOU GOING TO DO (1 TO 25)?";
35 INPUT A
40 IF A>25 OR A<1 THEN GO TO 35
45 PRINT " "; INVERSE 1;A
50 LET C=0: LET I=0
55 PRINT
60 PRINT " "; PAPER 6;"ENTER 1 FOR ADDITION"
65 PRINT " "; PAPER 6;"ENTER 2 FOR SUBTRACTION"
70 PRINT " "; PAPER 6;"ENTER 3 FOR MULTIPLICATION"
72 PRINT " "; PAPER 6;"ENTER 4 FOR DIVISION"
75 INPUT B
80 IF B<1 OR B>4 THEN GO TO 75
85 GO TO B*100
100 FOR J=1 TO A
105 PRINT
110 PRINT " NUMBER "; INVERSE 1;J
115 GO SUB 800
120 PRINT " ";E;" + ";F;" = ";
125 INPUT G
130 PRINT G;
135 IF G=E+F THEN GO TO 160
140 IF G<>E+F THEN GO TO 145
145 PRINT ," INCORRECT": BEEP .5,0: BEEP .5,-5
150 LET I=I+1
155 GO TO 170
160 PRINT ," CORRECT": FOR H=15 TO 17: BEEP .2,H: NEXT H
165 LET C=C+1
170 NEXT J
175 GO TO 505
200 FOR J=1 TO A
205 PRINT
210 PRINT " NUMBER "; INVERSE 1;J
215 GO SUB 800
220 IF F>E THEN PRINT " ";F;" - ";E;" = ";: GO TO 230
225 PRINT " ";E;" - ";F;" = ";
230 INPUT G
235 PRINT G;
240 IF G=E-F OR G=F-E THEN GO TO 160
245 IF G<>E-F OR G<>F-E THEN GO TO 145
300 FOR J=1 TO A
305 PRINT
310 PRINT " NUMBER "; INVERSE 1;J
315 GO SUB 800
320 PRINT " ";E;" X ";F;" = ";
325 INPUT G
330 PRINT G;
335 IF G=E*F THEN GO TO 160
340 IF G<>E*F THEN GO TO 145
400 FOR J=1 TO A
405 PRINT
410 PRINT " NUMBER "; INVERSE 1;J
411 LET F=INT (RND*10)+1
412 LET E=F*(INT (RND*10)+1)
420 PRINT " ";E;" \a ";F;" = ";
425 INPUT G
430 PRINT G;
435 IF G=E/F THEN GO TO 160
440 IF G<>E/F THEN GO TO 145
505 PRINT : PRINT "\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''": PRINT
510 PRINT " YOUR SCORE IS"
515 PRINT : PRINT
520 PRINT " ";INT ((C/A*100)+.5);" PER CENT"
525 PRINT
530 PRINT "\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''"
535 PRINT "DO YOU WANT TO PLAY AGAIN? (y/n)"
540 PRINT
545 IF INKEY$="y" OR INKEY$="Y" THEN GO TO 20
550 GO TO 545
800 LET E=INT (RND*10)+1
805 LET F=INT (RND*10)+1
810 RETURN
850 REM udg
860 DATA 0,24,0,127,0,24,0,0
870 FOR a=0 TO 7: READ b: POKE USR "\a"+a,b: NEXT a
900 CLS
905 PRINT AT 6,3;"+ + - xxxxx \a \a "
910 PRINT TAB 3;"++ ++ - - x \a \a"
920 PRINT TAB 3;"+ + + ----- x \a\a\a\a\a"
930 PRINT TAB 3;"+ + - - x \a \a"
940 PRINT TAB 3;"+ + - - x \a \a"
950 PRINT : PRINT : PRINT : PRINT : PRINT TAB 3; FLASH 1;"Press any key to continue."
955 PAUSE 0
960 RETURN
9998 STOP
9999 SAVE "Math" LINE 1: BEEP 1,32
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.