
A Warehouse level is a grid of squares - up to sixteen across and ten down, a hundred and sixty of them. Nobody wants a hundred and sixty variables. An array is one variable that holds many values of the same type, each picked out by a number, and a grid is an array of arrays.
var
A: array[1..4] of Integer;
A holds four integers, A[1] to A[4]. Each is used exactly like an ordinary variable - A[2] := 7, Writeln(A[3]) - and the number in the square brackets, the index, can be any expression: A[I], A[I + 1]. That is the whole point. A loop can visit every element:
for I := 1 to 4 do
A[I] := I * I;
The index does not have to start at 1, and it does not have to be a number. With S17's tiles, an array can be indexed by the tile itself:
var
Count: array[Tile] of Integer;
...
Count[Crate] := 5;
One array can be copied into another of the same type in a single assignment, B := A, and then they are separate: changing B does not change A.
A grid needs two indexes, a row and a column:
var
Board: array[1..16, 1..20] of Tile;
Board[3, 5] is the square in row 3, column 5. You can also write it Board[3][5], which is the same square - the board is an array of rows, and each row is an array of squares.
To visit every square, put one loop inside another (S13):
for R := 1 to 16 do
for C := 1 to 20 do
Board[R, C] := Floor;
A typed constant is a variable whose starting value is written in the program:
const
Look: array[Tile] of Char =
('#', ' ', '.', '$');
Look[Crate] is then '$' - a one-line way to turn a tile into the character that draws it. An array of strings makes a perfectly good level:
const
Level: array[1..5] of Str20 = (
'#######',
'# #',
'# $ . #',
'# @ #',
'#######');
The values go in brackets, separated by commas, and they may run over as many lines as you like. Level[3] is the third row, a string, and Level[3][3] is its third character, $.
A typed constant is a variable, not a constant, so it cannot be used to size an array (Error 41); use a plain const for that.
What is A[5] of a four-element array? It does not exist - but unless you ask for checking, Turbo will not stop you using it, and the result is worse than an error. Declare X, then a three-element array A, then Y; set X to 1 and Y to 2; then put 100 in A[0] and 400 in A[4]. Print X and Y, and you get 400 and 100: the writes have landed on the variables next door.
This is the most dangerous mistake in the course, because the damage shows up somewhere else entirely. With {$R+} at the top of the program, every index is checked, and the first one out of range stops the program:
Run-time error 90, PC=00A3
Program aborted
with ESC pointing at the statement. Use {$R+} for any program with arrays while you are writing it.
Arrays also cost memory, and the Einstein has only so much: an array of twenty thousand integers is Error 98: Memory overflow before the program even runs. A Warehouse board is no trouble: even a 16 by 20 array of tiles, bigger than the game needs, reported Data: 327 bytes - about one byte a square - with over 26,000 bytes still free.
program Board;
type
Str20 = string[20];
const
Level: array[1..5] of Str20 = (
'#######',
'# #',
'# $ . #',
'# @ #',
'#######');
var
R, C, Crates: Integer;
begin
for R := 1 to 5 do
Writeln(Level[R]);
Crates := 0;
for R := 1 to 5 do
for C := 1 to Length(Level[R]) do
if Level[R][C] = '$' then
Crates := Crates + 1;
Writeln('Crates: ', Crates);
Writeln('At row 4, column 4: ',
Level[4][4]);
end.
Your first warehouse: walls, one crate, one goal, and the worker, @.
Starting from
Turbo freshly started, Y, a new work file called BOARD.
What you should see
#######
# #
# $ . #
# @ #
#######
Crates: 1
At row 4, column 4: @
$ in the second row. What does the count say?{$R+} as the first line and change the first loop to run 1 to 6. What happens after the fifth row?Level[4][4] to Level[4][5]. What is printed at the end of the last line, and why does it look like nothing?19.1 Five marks are 7, 8, 10, 6 and 9. Put them in a typed constant array and print their average to one decimal place.
19.2 Ask for five numbers, one at a time, into an array, and print them in reverse order.
19.3 Using Pos on each row of this section's level, print the row and column where the worker, @, is standing.
Worked solutions are in Appendix II.
| Symptom | Cause |
|---|---|
| Variables change that the program never set | An array index out of range, writing over its neighbours. Put {$R+} at the top and run again. |
Run-time error 90 | An index out of range, with {$R+} on. ESC shows where. |
Error 98: Memory overflow | An array too big for the machine's memory. |
Error 41 at an array's size | The size uses a typed constant. Use a plain const. |
[ and ] look like arrows | That is how the Einstein draws them (S3). |
array[1..n] of T holds n values of type T, picked out with A[I]; the index can be a number range or an enumerated type. array[1..R, 1..C] is a grid, B[R, C] a square. Typed constants fill arrays in the program. An index out of range is not caught unless {$R+} is on - and without it, it damages other variables.
S20, Records - several values of different types held together: a level with its name, its size and its best score.