Chapter 15: Software development:
Answers to coursebook questions
and tasks
Task 15.01
© Cambridge University Press 2019
Task 15.02
© Cambridge University Press 2019
Task 15.03
© Cambridge University Press 2019
Task 15.04
1
FUNCTION CalculateAverage(N1, N2 : INTEGER) : REAL
DECLARE Average : REAL
Average (N1 + N2) / 2
RETURN Average
ENDFUNCTION
PROCEDURE InputNumbers(BYREF N1, N2 : INTEGER)
OUTPUT "Number1: "
INPUT N1
OUTPUT "Number2: "
INPUT N2
ENDPROCEDURE
PROCEDURE OutputMessage(a : REAL)
OUTPUT "The average is ", a
ENDPROCEDURE
PROCEDURE Averages;
DECLARE Average : REAL
DECLARE Number1, Number2 : INTEGER
CALL InputNumbers(Number1, Number2)
Average CalculateAverage(Number1, Number2)
CALL OutputMessage(Average)
ENDPROCEDURE
© Cambridge University Press 2019
2
FUNCTION GenerateSecretNumber RETURNS INTEGER
RETURN RANDOM(1000)
ENDFUNCTION
FUNCTION InputGuess RETURNS INTEGER
DECLARE Guess : INTEGER
OUTPUT "What is your guess? "
INPUT Guess
RETURN Guess
ENDFUNCTION
PROCEDURE OutputMessage(x, y : INTEGER)
IF x = y
THEN
OUTPUT "Congratulations, you have guessed correctly"
ELSE
OUTPUT "Sorry, the secret number is ", y
ENDPROCEDURE
PROCEDURE NumberGuessingGame
DECLARE SecretNumber, Guess : INTEGER
SecretNumber GenerateSecretNumber
Guess InputGuess
CALL OutputMessage(Guess, SecretNumber)
ENDPROCEDURE
© Cambridge University Press 2019
3 CONSTANT BLANK = ' '
PROCEDURE InitialiseBoard(BYREF Board : ARRAY OF CHAR)
DECLARE Row, Column : INTEGER
FOR Row 1 TO 6
FOR Column 1 TO 7
Board[Row, Column] BLANK
NEXT Column
NEXT Row
ENDPROCEDURE
PROCEDURE SetUpGame(BYREF ThisPlayer : CHAR, GameFinished : BOOLEAN)
ThisPlayer 'O' // Player O always starts
GameFinished FALSE
ENDPROCEDURE
PROCEDURE OutputBoard(Board : ARRAY OF CHAR)
DECLARE Row, Column : INTEGER
FOR Row 1 TO 6
FOR Column 1 TO 7
OUTPUT Board[Row, Column] // no new line
NEXT Column
OUTPUT Newline // move to next line
NEXT Row
ENDPROCEDURE
PROCEDURE PlayerMakesMove(ThisPlayer : CHAR, BYREF Board : ARRAY OF CHAR)
DECLARE ValidRow, ValidColumn : INTEGER
OUTPUT "Player " ThisPlayer " 's turn."
ValidColumn PlayerChoosesColumn(Board)
ValidRow FindFreeRow(Board, ValidColumn)
Board[ValidRow, ValidColumn] ThisPlayer
ENDPROCEDURE
FUNCTION PlayerChoosesColumn(Board : ARRAY OF CHAR) RETURNS INTEGER
REPEAT
OUTPUT "Enter a valid column number:"
INPUT ColumnNumber
UNTIL ColumnNumberValid(ColumnNumber, Board) = TRUE
RETURN ColumnNumber
ENDFUNCTION
FUNCTION ColumnNumberValid(ColumnNumber : INTEGER, Board : ARRAY OF CHAR)
RETURNS BOOLEAN
DECLARE Valid : BOOLEAN
Valid FALSE
© Cambridge University Press 2019
IF ColumnNumber >= 1 AND ColumnNumber <= 7
THEN
IF Board[6, ColumnNumber] = BLANK
THEN
Valid TRUE
ENDIF
ENDIF
RETURN Valid
ENDFUNCTION
FUNCTION FindFreeRow(Board : ARRAY OF CHAR, ValidColumn : INTEGER) RETURNS
INTEGER
DECLARE ThisRow : INTEGER
ThisRow 1
WHILE Board[ThisRow, ValidColumn] <> BLANK
ThisRow ThisRow + 1
ENDWHILE
RETURN ThisRow
ENDFUNCTION
PROCEDURE CheckGameFinished(Board, ThisPlayer, ValidRow, ValidColumn,
BYREF GameFinished)
DECLARE WinnerFound : BOOLEAN
CALL CheckIfPlayerHasWon(Board, ThisPlayer, ValidRow, ValidColumn,
WinnerFound)
IF WinnerFound = TRUE
THEN
GameFinished TRUE
OUTPUT ThisPlayer, " is the winner"
ELSE
CALL CheckForFullBoard(Board, GameFinished)
ENDIF
ENDPROCEDURE
PROCEDURE CheckIfPlayerHasWon(Board, ThisPlayer, ValidRow, ValidColumn
BYREF WinnerFound)
WinnerFound FALSE
CALL CheckHorizontalLine(Board, ValidRow, ThisPlayer, WinnerFound)
IF WinnerFound = FALSE
THEN
CALL CheckVerticalLine(Board, ValidRow, ValidColumn, WinnerFound)
ENDIF
ENDPROCEDURE
PROCEDURE CheckHorizontalLine(Board, ValidRow, ThisPlayer, BYREF
WinnerFound)
DECLARE i : INTEGER
© Cambridge University Press 2019
FOR i 1 TO 4
IF Board[ValidRow, i] = ThisPlayer AND
Board[ValidRow, i + 1] = ThisPlayer AND
Board[ValidRow, i + 2] = ThisPlayer AND
Board[ValidRow, i + 3] = ThisPlayer
THEN
WinnerFound TRUE
ENDIF
NEXT i
ENDPROCEDURE
PROCEDURE CheckVerticalLine(Board, ValidRow, ValidColumn, ThisPlayer,
BYREF WinnerFound)
IF ValidRow = 4 OR ValidRow = 5 OR ValidRow = 6
THEN
IF Board[ValidRow, ValidColumn] = ThisPlayer AND
Board[ValidRow - 1, ValidColumn] = ThisPlayer AND
Board[ValidRow - 2, ValidColumn] = ThisPlayer AND
Board[ValidRow - 3, ValidColumn] = ThisPlayer
THEN
WinnerFound TRUE
ENDIF
ENDIF
ENDPROCEDURE
PROCEDURE CheckForFullBoard(Board : ARRAY OF CHAR, BYREF GameFinished :
BOOLEAN)
DECLARE BlankFound : BOOLEAN
DECLARE ThisRow, ThisColumn : INTEGER
BlankFound FALSE
ThisRow 0
REPEAT
ThisColumn 0
ThisRow ThisRow + 1
REPEAT
ThisColumn ThisColumn + 1
IF Board[ThisRow, ThisColumn] = BLANK
THEN
BlankFound TRUE
ENDIF
UNTIL ThisColumn = 7 OR BlankFound = TRUE
UNTIL ThisRow = 6 OR BlankFound = TRUE
IF BlankFound = FALSE
THEN
OUTPUT "It is a draw"
GameFinished TRUE
© Cambridge University Press 2019
ENDIF
ENDPROCEDURE
PROCEDURE SwapThisPlayer(BYREF ThisPlayer : CHAR)
IF ThisPlayer = 'O'
THEN
ThisPlayer 'X'
ELSE
ThisPlayer 'O'
ENDIF
ENDPROCEDURE
PROGRAM Connect4
DECLARE Board : ARRAY[0..6, 0..7] OF CHAR
DECLARE ThisPlayer : CHAR
DECLARE GameFinished, WinnerFound : BOOLEAN
CALL InitialiseBoard(Board)
CALL SetUpGame(ThisPlayer, GameFinshed)
CALL OutputBoard(Board)
WHILE GameFinished = FALSE DO
CALL PlayerMakesMove(ThisPlayer, Board)
CALL OutputBoard(Board)
CALL CheckGameFinished(Board, GameFinished)
IF GameFinished = FALSE
THEN
CALL SwapThisPlayer(ThisPlayer)
ENDIF
ENDWHILE
ENDPROGRAM
© Cambridge University Press 2019
Task 15.05
CONSTANT Inactive = "System inactive"
CONSTANT Active = "System active"
CONSTANT Alert = "alert mode"
CONSTANT Alarm = "Alarm bell ringing"
PROCEDURE PressStart(BYREF State : STRING)
IF State = Inactive
THEN
State Active
ENDIF
OUTPUT State
ENDPROCEDURE
PROCEDURE EnterPin(BYREF State : STRING, Timer : INTEGER)
IF State = Active
THEN
State Inactive
ELSE
IF state = Alert
THEN
State Inactive
Timer 0
ELSE
IF State = Alarm
THEN
State Inactive
ENDIF
ENDIF
© Cambridge University Press 2019
ENDIF
OUTPUT State
ENDPROCEDURE
PROCEDURE ActivateSensor(BYREF State : STRING)
IF state = Active
THEN
state Alert
ENDIF
OUTPUT State
ENDPROCEDURE
PROCEDURE IncTimer(State : STRING, BYREF Timer : INTEGER)
IF State = Alert
THEN
Timer Timer + 1
ENDIF
ENDPROCEDURE
PROCEDURE StartBell(BYREF State : STRING, Timer : INTEGER)
IF (State = Alert) AND (Timer = 2)
THEN
State Alarm
ENDIF
OUTPUT State
ENDPROCEDURE
PROCEDURE ListEvents
OUTPUT "1 : Start button"
OUTPUT "2: Enter PIN"
OUTPUT "3: Activate Sensor"
ENDPROCEDURE
PROCEDURE Wait
DECLARE i : INTEGER
FOR i := 1 TO 2000 DO
// do nothing
OUTPUT ''
NEXT i
ENDPROCEDURE
DECLARE State : STRING
DECLARE Timer : INTEGER
DECLARE Event : CHAR
State Inactive
Timer 0
OUTPUT State
WHILE TRUE DO
CALL ListEvents
OUTPUT "Enter Event: "
INPUT Event
CASE OF Event
'1' : CALL PressStart(State)
'2' : CALL EnterPin(State, Timer)
© Cambridge University Press 2019
'3' : CALL ActivateSensor(State)
ENDCASE
CALL Wait;
CALL IncTimer(State, Timer)
CALL StartBell(State, Timer)
ENDWHILE
Question 15.01
1101 (in order of output) but this represents the number 1011
Extension Question 15.01
Yes
Task 15.06
FUNCTION ConvertFromHex(HexString : STRING) RETURNS INTEGER
DECLARE ValueSoFar, HexValue, HexLength, i : INTEGER
DECLARE HexDigit : CHAR
ValueSoFar 0
HexLength Length(HexString)
FOR i 1 TO HexLength
HexDigit HexString[i]
CASE OF HexDigit
'A': HexValue 10
'B': HexValue 11
'C': HexValue 12
'D': HexValue 13
'E': HexValue 14
'F': HexValue 15
OTHERWISE HexValue StringToInt(HexDigit)
ENDCASE
ValueSoFar ValueSoFar * 16 + HexValue
NEXT i
RETURN ValueSoFar
ENDFUNCTION
© Cambridge University Press 2019
HexString HexLength i HexDigit HexValue ValueSoFar
'A5' 2 0
1 'A' 10 10
2 '5' 5 165
Task 15.07
Test data for the number guessing game
1 Type of test data Example test data Expected output
valid same as secret congratulation
number
valid any integer consolation message
invalid any non-number program crashes
2 Test data for the Connect4 game
The only input is column number
Type of test data Example test data Expected output
Normal a number between 1 and 7 token should appear in the correct
column
test for a winning line:
four same colour in a column should get the winner message
four same colour in a row
Boundary a column where there are it should fill the top row of that column
already five tokens
a valid column in a grid the board should now be full, and it
where there is only one free should give a message to that effect
space
Invalid 0 or 8 invalid column number error message
a number between 1 and 7, can’t add a token to a full column, so
but the column is already full should get an error message
Task 15.08
INPUT BinaryString
StringLength Length(BinaryString)
FOR i 1 TO StringLength
Bit BinaryString[i]
BitValue IntegerValue(Bit) // convert string to integer
DenaryValue DenaryValue + 2 + BitValue
NEXT i
© Cambridge University Press 2019
1, 2 BinaryString StringLength i Bit BitValue DenaryValue
'101' 3 1 '1' 1 3
2 '0' 0 5
3 '1' 1 8
3 Errors:
DenaryValue should be initialised to 0 before the loop
The + highlighted in the code above should be a *.
Task 15.09
01 CALL InitialiseBoard
02 CALL SetUpGame
03 CALL OutputBoard
04 WHILE GameFinished = FALSE
05 CALL ThisPlayerMakesMove
06 CALL OutputBoard
07 CALL CheckIfThisPlayerHasWon
08 IF GameFinished = FALSE
09 THEN
10 CALL SwapThisPlayer
11 ENDIF
12 ENDWHILE
The procedure ThisPlayerMakesMove needs to be changed to:
PROCEDURE ThisPlayerMakesMove
IF ThisPlayer = 'X'
THEN
ValidColumn ComputerChoosesColumn
ELSE
ValidColumn ThisPlayerChoosesColumn
ENDIF
ValidRow FindNextFreePositionInColumn
Board[ValidRow, ValidColumn] ThisPlayer
ENDPROCEDURE
FUNCTION ComputerChoosesColumn // returns a valid column number
REPEAT
// a random number between 1 and 7
ColumnNumber Random(1,7)
// check whether the column number is valid
UNTIL ColumnNumberValid = TRUE
RETURN ColumnNumber
ENDFUNCTION
© Cambridge University Press 2019
Task 15.10
The validation should be put into the function. This reduces repetitive code. It is also more logical that a function
with identifier GetPositiveNumber should return a positive number.
FUNCTION GetPositiveNumber
DECLARE n : INTEGER
REPEAT
OUTPUT "Enter a positive number: "
INPUT n
IF n <= 0
THEN
OUTPUT "Not a positive number: "
ENDIF
UNTIL n > 0
RETURN n
ENDFUNCTION
// main program
Number1 GetPositiveNumber
Number2 GetPositiveNumber
Exam-style Questions
1 FUNCTION Binary(Number : INTEGER) : STRING
DECLARE BinaryString : STRING
DECLARE PlaceValue : INTEGER
BinaryString '' // empty string
PlaceValue 8
REPEAT
IF Number >= PlaceValue
THEN
BinaryString BinaryString & '1'
Number Number - PlaceValue
ELSE
BinaryString BinaryString & '0'
ENDIF
PlaceValue PlaceValue DIV 2
UNTIL Number = 0
RETURN BinaryString
ENDFUNCTION
a Dry-run the function call Binary(11) by completing the given trace table.
Number BinaryString PlaceValue Number>=PlaceValue
'' 8
11 '1' 4 TRUE
3 '10' 2 FALSE
1 '101' 1 TRUE
0 '1011' 0 TRUE
© Cambridge University Press 2019
The return value is 1011.
Marking guidance:
1 mark for each correctly completed column
1 mark for correct final return value
b i Dry-run the function call Binary(10) by completing the given trace table.
Number BinaryString PlaceValue Number>=PlaceValue
'' 8
10 '1' 4 TRUE
2 '10' 2 FALSE
0 '101' 1 TRUE
The return value is 101.
Marking guidance:
1 mark for correct Number column
1 mark for other 3 columns correct
1 mark for correct final return value
ii Marking guidance:
1 mark for each of the following:
The loop stops early if it is an even number
But need the final 0 for units
Boolean expression in UNTIL statement should read: UNTIL PlaceValue = 0
2 Test data for the parameter NumberToDraw:
Type of Example Expected output Justification
test data test data
Normal 1 / Check correct number of
4 //// bars output and fifth bar
5 ////\ sloping the other way
6 ////\/
Boundary 0 0 is smallest possible value
and no bars should be
output
Extreme e.g. 45 ////\////\////\////\////\////\////\ How is the procedure going
////\////\ to deal with a large number,
more than number of bars
that fit on a line
Marking guidance:
For each type of test data row award:
1 mark for suitable example of test data of the correct type
1 mark for correct expected output
1 mark for suitable justification
© Cambridge University Press 2019
3 a A: Initialise Tally
B: Generate random number
C: RandomNumber
D: Tally
E: Tally
Marking guidance:
1 mark for each correct label
b Pseudocode for random number tally
DECLARE Tally : ARRAY[1..20] OF INTEGER
DECLARE NumberOfTests, RandomNumber : INTEGER
DECLARE ExpectedFrequency : INTEGER
NumberOfTests 1000
CALL InitialiseTally(Tally)
FOR Count 1 TO NumberOfTests
RandomNumber GenerateRandomNumber(20)
CALL UpdateTally(RandomNumber, Tally)
NEXT Count
ExpectedFrequency NumberOfTests DIV 20
CALL OutputTally(Tally)
Marking guidance:
1 mark for each correct line of pseudocode
4
Marking guidance:
1 mark for each correct label
© Cambridge University Press 2019