A-level Computing/AQA/Problem Solving, Programming, Data Representation and Practical Exercise/Skeleton code/2012 Exam/Section D

From Wikibooks, open books for an open world
Jump to navigation Jump to search

When you first run your code you will probably find that everything appears to work. Don't be deceived, try and put incorrect menu choices in, try and move your character outside the map. We have a lot to fix and any errors are very likely to come up as questions in the exam, where you have to fix them!

Adjustments to the code[edit | edit source]

Miscellaneous[edit | edit source]

How to resume in a game

Answer:

There are 3 steps of resuming in the game.

1. This is the code to be created:

   Function gameinprogress(ByVal MonsterPosition As CellReference) As Boolean
       ' using monsterposition as a test to see if game in progress
       If MonsterPosition.NoOfCellsEast <> 0 Then
           gameinprogress = True
       Else
           gameinprogress = False
       End If
   End Function

You need to create this code[ABOVE CODE AS SHOWN] under the code BELOW:

  Module Module1
   Const NoOfTraps = 2
   Const NSDistance = 5
   Const WEDistance = 7

2. Then change from this:

  Sub DisplayMenu()
       Console.WriteLine("MAIN MENU")
       Console.WriteLine()
       Console.WriteLine("1.  Start new game")
       Console.WriteLine("2.  Load game")
       Console.WriteLine("3.  Save game")
       Console.WriteLine("4.  Play training game")
       Console.WriteLine("9.  Quit")
       Console.WriteLine()
       Console.Write("Please enter your choice: ")
   End Sub

To this:

 Sub DisplayMenu(ByVal MonsterPosition as cellreference)
       Console.WriteLine("MAIN MENU")
       Console.WriteLine()
       Console.WriteLine("1.  Start new game")
       Console.WriteLine("2.  Load game")
       Console.WriteLine("3.  Save game")
       Console.WriteLine("4.  Play training game")

If gameinprogress(monsterposition) then console.writeline(“5. Resume game”)

       Console.WriteLine("9.  Quit")
       Console.WriteLine()
       Console.Write("Please enter your choice: ")
   End Sub

3. After, create a case 5:

DisplayMenu()

           Choice = GetMainMenuChoice()
           Select Case Choice
               Case 1
                   SetUpGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake, True)
                   PlayGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
               Case 2
                   LoadGame(TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
                   SetUpGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake, False)
                   PlayGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
               Case 3 : SaveGame(TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
               Case 4
                   SetUpTrainingGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
                   PlayGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
           End Select
       Loop Until Choice = 9
   End Sub

This is what you put in case 5:

Case 5

                   If gameinprogress(MonsterPosition) Then
                       PlayGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
                   Else
                       Console.WriteLine("no game currently in progress")
                   End If


In a test game display the position of monster, flask and traps from the start so user can see them when moving around the map

Answer:


Adding a cheat feature to see all cavern items

Answer:

First, you need to declare a boolean variable to the code to allow it to have an enable function.

Const NoOfTraps = 2
    Const NSDistance = 5
    Const WEDistance = 7
    Dim Cheating As Boolean = False 'Placed here for it to be global'

We then need to allow the an input to take place so we add it to sub makemove.

Case "E"
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
            Case "C"
                If Cheating = False Then
                    Cheating = True  'Allows cheat to have an on and off function'
                Else
                    Cheating = False
                End If
        End Select

We then need to allow the input to be valid.(Section is Sub CheckValidMove)

  If Not (Direction = "N" Or Direction = "S" Or Direction = "W" Or Direction = "E" Or Direction = "M" Or Direction = "C") Then
            ValidMove = False
        End If

Finally, we need to make it when cheat = true, then it will display all the cavern items. This is added to the sub DisplayCavern.

    Dim Count1 As Integer
        Dim Count2 As Integer
        For Count1 = 1 To NSDistance
            Console.WriteLine(" ------------- ")
            If Cheating = True Then
                For Count2 = 1 To WEDistance
                    Console.Write("|" & Cavern(Count1, Count2))
                Next
            Else
                For Count2 = 1 To WEDistance
                    If Cavern(Count1, Count2) = " " Or Cavern(Count1, Count2) = "*" Or (Cavern(Count1, Count2) = "M" And MonsterAwake) Then
                        Console.Write("|" & Cavern(Count1, Count2))
                    Else
                        Console.Write("| ")
                    End If
                Next
            End If
            Console.WriteLine("|")


Movement[edit | edit source]

Stop player moving off the edge of the map, catch the error

Answer:

There are limits to where the player can move, on the x axis, it is all spaces above and including 1, and all spaces below and including NoOfCellsEast:

1 =< x =< NoOfCellsEast

on the y axis, it is all spaces above and including 1, and all spaces below and including NoOfCellsSouth

1 =< y =< NoOfCellsSouth

Using this knowledge we need to stop the MakeMove subroutine allowing the user to move outside these bounds.

Think about why PlayerPosition has been passed to CheckValidMove sub, and that it isn't currently being used. Could the check be done there? At the moment to check that it is a valid move it uses:

 If Not (Direction = "N" Or Direction = "S" Or Direction = "W" Or Direction = "E" Or Direction = "M") Then
   ValidMove = False
 End If

But this doesn't take into account the times when an attempted move is not valid, for example when the player chooses N (UP) when they are in the first row (row 1):

Direction = "N" And PlayerPosition.NoOfCellsSouth = 1

We need to update the IF STATEMENT above that sets ValidMove = False, to:

If Direction = "N" And PlayerPosition.NoOfCellsSouth = 1 Then
  ValidMove = False
ElseIf Direction = "S" And PlayerPosition.NoOfCellsSouth = NSDistance Then
  ValidMove = False
ElseIf Direction = "E" And PlayerPosition.NoOfCellsEast = WEDistance Then
  ValidMove = False
ElseIf Direction = "W" And PlayerPosition.NoOfCellsEast = 1 Then
  ValidMove = False
End If

Also we might want to add a little feedback to PlayGame sub, highlighting when moves are not valid. We need to add the following code above the line that says: Loop Until ValidMove

  If Not ValidMove Then      
    Console.WriteLine("Invalid Move. Try again")
  End If
Loop Until ValidMove 'this line already exists!

For Pascal

Function CheckValidMove(PlayerPosition : TCellReference; Direction : Char) : Boolean;
  Var
    ValidMove : Boolean;
  Begin
    ValidMove := True;
    If Not (Direction In ['N','S','W','E','M'])
      Then ValidMove := False;
    If (Direction = 'N') And (PlayerPosition.NoOfCellsSouth = 1)
    Then ValidMove := False;
    If (Direction = 'W') And (PlayerPosition.NoOfCellsEast = 1)
    Then ValidMove := False;
    If (Direction = 'E') And (PlayerPosition.NoOfCellsEast = WEDistance)
    Then ValidMove := False;
    If (Direction = 'S') And (PlayerPosition.NoOfCellsSouth = NSDistance)
    Then ValidMove := False;

    If ValidMove = False
    Then
    Writeln('This move is invalid, please move in cavern');
    Repeat

    GetMove
     Until ValidMove = True;
    CheckValidMove := ValidMove;
  End;


Make it so the monster moves automatically instead of the user having to input two characters for the monster to complete its moves. Cagey play.

Answer:

Remove the 3 lines

  Console.WriteLine()
  Console.WriteLine("Press Enter key to continue")
  Console.ReadLine()

from:

  Do
    MakeMonsterMove(Cavern, MonsterPosition, FlaskPosition, PlayerPosition)
    Eaten = CheckIfSameCell(MonsterPosition, PlayerPosition)
    Console.WriteLine()
    Console.WriteLine("Press Enter key to continue")
    Console.ReadLine()
    DisplayCavern(Cavern, MonsterAwake)
    Count = Count + 1
  Loop Until Count = 2 Or Eaten

And replace them with:

Threading.Thread.Sleep(1000) 'wait for 1 second

If this question is going to be asked it is very unlikely that you'll be asked to remember the sleep command, and you'll probably be given it


Allow the player to move diagonally

Answer:

Sub MakeMove(ByRef Cavern(,) As Char, ByVal Direction As Char, ByRef PlayerPosition As CellReference)
        Cavern(PlayerPosition.NoOfCellsSouth, PlayerPosition.NoOfCellsEast) = " "
        Dim Counter As Integer = 0
        If CheckValidMove(Direction, PlayerPosition) = True Then
            Select Case Direction
                Case "N"
                    PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth - 1
                Case "S"
                    PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth + 1
                Case "W"
                    PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast - 1
                Case "E"
                    PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
                Case "9"
                    PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth - 1
                    PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
                Case "7"
                    PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth - 1
                    PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast - 1
                Case "3"
                    PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth + 1
                    PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
                Case "1"
                    PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth + 1
                    PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast - 1
                End Select
        End If
        Cavern(PlayerPosition.NoOfCellsSouth, PlayerPosition.NoOfCellsEast) = "*"
    End Sub


Allow the player to move diagonally using ["NE", "SE", "SW", "NW"]

Answer:

First you'll need to add the case for the new commands to be recognised in the MakeMove sub-routine:

   Sub MakeMove(ByRef Cavern(,) As Char, ByVal Direction As String, ByRef PlayerPosition As CellReference)
        Cavern(PlayerPosition.NoOfCellsSouth, PlayerPosition.NoOfCellsEast) = " "
        Select Case Direction
            Case "N"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth - 1
            Case "S"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth + 1
            Case "W"
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast - 1
            Case "E"
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
            Case "NE"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth - 1
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
            Case "SE"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth + 1
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
            Case "SW"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth + 1
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast - 1
            Case "NW"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth - 1
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast - 1
        End Select
        Cavern(PlayerPosition.NoOfCellsSouth, PlayerPosition.NoOfCellsEast) = "*"
    End Sub

But this doesn't work! Can you spot why?

It is because the variables MoveDirection, Move and the GetMove() Function have been declared as a Char (accepting only ONE character) and each time 'Direction' has been passed, it has passed as a Char also.

They all need to be changed (inefficiently in terms of memory) to the String data type to allow the user to type more than one character to move the position of the player (i.e. "NE", "SE", "SW", "NW").

Use 'Ctrl + F' (Find and Replace box should appear) to find and replace all of the Char datatypes to String for ONLY the following variables or Function:

  • Replace 'GetMove() As Char' to 'GetMove() As String'
  • Replace 'Dim Move As Char' to 'Dim Move As String'
  • Replace 'Dim MoveDirection As Char' to 'Dim MoveDirection As String' in the PlayGame sub-routine
  • Replace 'Direction As Char' to 'Direction As String' in the MakeMove procedure and the CheckValidMove function.

Of course you must also update the move options here:

    Sub DisplayMoveOptions()
        Console.WriteLine()
        Console.WriteLine("Enter N to move NORTH")
        Console.WriteLine("Enter E to move EAST")
        Console.WriteLine("Enter S to move SOUTH")
        Console.WriteLine("Enter W to move WEST")
        Console.WriteLine("Enter NE to move NORTH-EAST")
        Console.WriteLine("Enter SE to move SOUTH-EAST")
        Console.WriteLine("Enter SW to move SOUTH-WEST")
        Console.WriteLine("Enter NW to move NORTH-WEST")
        Console.WriteLine("Enter M to return to the Main Menu")
        Console.WriteLine()
    End Sub


Change the keys that move the player from ["N", "E", "S", "W"] to ["W", "D", "S", "A"] respectively.

Answer:


There are 3 sub-routines that need to be edited for this. First the sub-routine that writes out move options on the screen for the user:

    Sub DisplayMoveOptions()
        Console.WriteLine()
        Console.WriteLine("Enter W to move NORTH")
        Console.WriteLine("Enter D to move EAST")
        Console.WriteLine("Enter S to move SOUTH")
        Console.WriteLine("Enter A to move WEST")
        Console.WriteLine("Enter M to return to the Main Menu")
        Console.WriteLine()
    End Sub

Second, the MakeMove sub-routine which actually processes the movement of the player when a key is pressed:

    Sub MakeMove(ByRef Cavern(,) As Char, ByVal Direction As Char, ByRef PlayerPosition As CellReference)
        Cavern(PlayerPosition.NoOfCellsSouth, PlayerPosition.NoOfCellsEast) = " "
        Select Case Direction
            Case "W"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth - 1
            Case "S"
                PlayerPosition.NoOfCellsSouth = PlayerPosition.NoOfCellsSouth + 1
            Case "A"
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast - 1
            Case "D"
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
        End Select
        Cavern(PlayerPosition.NoOfCellsSouth, PlayerPosition.NoOfCellsEast) = "*"
    End Sub

Lastly, the CheckValidMove which simply checks if the key they have pressed is a valid choice:

    Function CheckValidMove(ByVal PlayerPosition As CellReference, ByVal Direction As Char) As Boolean
        Dim ValidMove As Boolean
        ValidMove = True
        If Not (Direction = "W" Or Direction = "S" Or Direction = "A" Or Direction = "D" Or Direction = "M") Then
            ValidMove = False
        End If
        CheckValidMove = ValidMove
    End Function


During a game press "T" to teleport, this can only be used once

Answer:

First we need to create a subroutine to teleport the user. This will need access to the playerPosition so we can update it, and the GetNewRandomPosition function so we can randomly assign a new position: But this won't let the player teleport to position[1,1]?!

Sub teleport(ByRef PlayerPosition As CellReference)
  PlayerPosition = GetNewRandomPosition()
End Sub

Now we have declared the sub routine we must create an option in the MakeMove subroutine to to handle pressing "T":

  Case "T"
    teleport(PlayerPosition)
End Select

We must add the "T" option to the DisplayMoveOptions sub routine:

Console.WriteLine("Enter W to move WEST")
Console.WriteLine("Enter T to move Teleport")
Console.WriteLine("Enter M to return to the Main Menu")

And finally we must allow the "T" option to be a CheckValidMove sub routine:

If Not (Direction = "N" Or Direction = "S" Or Direction = "W" Or Direction = "E" Or Direction = "M" Or Direction = "T") Then
  ValidMove = False
End If

With this code the player can teleport as many times as they like. An additional boolean variable is needed if the player is only going to be allowed to teleport once. The record structure will also need changing. Possibly too many changes for the exam?

Alternative way and to allow to ONLY teleport once:

We need to make a boolean variable to see if we used teleport or if we didnt, true or false:

Module Module1
    Const NoOfTraps = 2
    Const NSDistance = 5
    Const WEDistance = 7
    Dim Teleport As Boolean = True ''Create here as we will have to use it throughout the program code

Then we need to add a menu option here:

        Console.WriteLine("Enter W to move WEST")
        Console.WriteLine("Enter T to TELEPORT")  '<----- We need to add a Display option for the user to see
        Console.WriteLine("Enter M to return to the Main Menu")
        Console.WriteLine()

Then we Have to add a code to allow to teleport to a new random position

            Case "E"
                PlayerPosition.NoOfCellsEast = PlayerPosition.NoOfCellsEast + 1
            Case "T"
                PlayerPosition = GetNewRandomPosition()  ' Makes the current player position a new random position.
                Teleport = False     ' used to show that once we use teleport it becomes unuseable agian ... changes to false.

        End Select

Now we need to update the code that checks if its a valid move. IT has to be "T" and teleport has to be = "True"

Function CheckValidMove(ByVal PlayerPosition As CellReference, ByVal Direction As Char) As Boolean
        Dim ValidMove As Boolean
        ValidMove = True
        If Not (Direction = "N" Or Direction = "S" Or Direction = "W" Or Direction = "E" Or Direction = "M" Or Direction = "T" And Teleport = True) Then ' add a validation check
            ValidMove = False
        End If
        CheckValidMove = ValidMove
    End Function

Next we need to fix a small problem to allow user to go back to the main menu, start a new game and BE ABLE to teleport once again since its a new game.

Sub PlayGame(ByRef Cavern(,) As Char, ByVal TrapPositions() '..... ect
        Dim Count As Integer
        Dim Eaten As Boolean
        Dim FlaskFound As Boolean
        Dim MoveDirection As Char
        Dim ValidMove As Boolean
        Eaten = False
        FlaskFound = False
        DisplayCavern(Cavern, MonsterAwake)
        Do
            Do
                DisplayMoveOptions()
                MoveDirection = GetMove()
                ValidMove = CheckValidMove(PlayerPosition, MoveDirection)
            Loop Until ValidMove
            If MoveDirection <> "M" Then
                Teleport = True ''''' This resets the ability to Teleport if user goes to main menu and starts a new game it will let him.
                MakeMove(Cavern, MoveDirection, PlayerPosition)
                DisplayCavern(Cavern, MonsterAwake)
                FlaskFound = CheckIfSameCell(PlayerPosition, FlaskPosition)


      • OR*** (Visual Basic)
 Function CheckValidMove(ByVal PlayerPosition As CellReference, ByVal Direction As Char) As Boolean
   Dim ValidMove As Boolean
   ValidMove = True
   If Not (Direction = "N" Or Direction = "S" Or Direction = "W" Or Direction = "E" Or Direction = "M") Then
     ValidMove = False
       End If
       If Direction = "N" And PlayerPosition.NoOfCellsSouth = 1 Then
           ValidMove = False
       End If
   CheckValidMove = ValidMove
 End Function

Input Validation[edit | edit source]

Update the code to accept upper and lower case direction inputs

Answer:

In the GetMove function change the line:

Move = Console.ReadLine

to:

Move = UCase(Console.ReadLine)

'Or

Move = Console.ReadLine.ToUpper

'Or in python 3

Move = input().upper()

'Or in Java

move = Character.toUpperCase(move);

This converts whatever the input is into an Upper Case letter


Collect menu choices as char rather than integer so that they can be validated and letter entry doesn't crash the program

Answer:

To stop the menu breaking on you typing in "g" or "one" we have to change the code in several places:

We then need to catch any errors when the program converts the input into an Integer by adjusting the GetMainMenuChoice() function:

    Function GetMainMenuChoice() As Integer
        Dim Choice As String
        Try
            Choice = CInt(Console.ReadLine())
            Console.WriteLine()
            GetMainMenuChoice = Choice
        Catch ex As Exception
            GetMainMenuChoice = 0 'return an in valid number if not a number
        End Try
    End Function

This should work. But to make it even better we should probably give an error message to tell them when they have typed in an incorrect menu choice if the number is incorrect. Take a look at the Main() function again and at the case statement. We are going to add an else case that will handle any incorrect input:

 Case 4
  SetUpTrainingGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
  PlayGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
 Case Else
  Console.WriteLine("Please enter a valid numeric value")
End Select


Make it so an inappropriate menu entry brings up an error message

Answer:

Change the GetMainMenuChoice function to:

    Function GetMainMenuChoice() As Integer
        Dim Choice As Integer
        Do
            Choice = CInt(Console.ReadLine())
            Console.WriteLine()
            GetMainMenuChoice = Choice
            If Choice < 1 Or (Choice > 4 And Not Choice = 9) Then
                Console.WriteLine("You must choice a value between 1 & 4 or enter 9." & vbNewLine)
            End If
        Loop Until (Choice >= 1 And Choice <= 4) Or Choice = 9
    End Function

For Pascal

Function GetMainMenuChoice : Integer;
  Var
    Choice : Integer;
  Begin
    Readln(Choice);
    Writeln;
    GetMainMenuChoice := Choice;
    If (Choice < 1) Or (Choice > 4) And (Choice <> 9)
    Then
    Writeln('You must choose a value between 1 and 4 or enter 9');
  End;

Adding a TYPE Check validation (try/catch) to GetMenuChoice will stop runtime exceptions being thrown

Make it so an input that cannot be converted to integer doesn't crash the program

Answer:

Change the GetMainMenuChoice function to:

    Function GetMainMenuChoice() As Integer

        Dim Choice As Integer
        Dim ValidChoice As Boolean = False
   
        Do
            Try 'type check
                Choice = CInt(Console.ReadLine())
                Console.WriteLine()
                GetMainMenuChoice = Choice
                'range check
                If (Choice >= 1 And Choice <= 4) Or Choice = 9 Then
                    ValidChoice = True
                Else
                    ValidChoice = False
                End If
            Catch ex As Exception
                ValidChoice = False
            End Try

            If ValidChoice = False Then
                Console.WriteLine("You Must Choose A Value Between 1 & 4 Or 9")
                Console.WriteLine()
                Console.Write("Please enter your choice: ")
            End If

        Loop Until ValidChoice = True
    End Function


Make it so an invalid move command brings up an error message

Answer:

We might want to add a little feedback to PlayGame sub, highlighting when moves are not valid

  If Not ValidMove Then      
    Console.WriteLine("Invalid Move. Try again")
  End If
Loop Until ValidMove


Loading and Saving[edit | edit source]

When saving in the main menu give the option to resume the game

Answer:


Make it so selecting to load a non-existent file doesn't crash the program

Answer:

A simple solution:

                Case 2
                    Try
                        LoadGame(TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
                        SetUpGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake, False)
                        PlayGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
                    Catch ex As Exception
                        Console.WriteLine("wrong file name, try again"  & vbNewLine)
                    End Try
                Case 3 : SaveGame(TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)


Count the number of moves taken before the player is eaten or finds the lamp and display this

Answer:

In playGame method

//add to top { int moveCounter = 0; } add in if statement

if (moveDirection != 'M' && validMovement(moveDirection, playerPosition)==true) {

  moveCounter++;
  makeMove(cavern, moveDirection, playerPosition);
  displayCavern(cavern, monsterAwake);
  ...

}

add in the if Statement for flaskfound

if (flaskfound) {

    displayWonGameMessage();
    console.println("You completed the game in "+moveCounter+" moves);

}

How to do for VB.net

Sub PlayGame(ByRef Cavern(,) As Char, ByVal TrapPositions() As CellReference, ByRef MonsterPosition As CellReference, ByRef PlayerPosition As CellReference, ByRef FlaskPosition As CellReference, ByRef MonsterAwake As Boolean)
Dim Count As Integer
        Dim Eaten As Boolean
        Dim FlaskFound As Boolean
        Dim MoveDirection As Char
        Dim ValidMove As Boolean
        Dim moveCounter As Integer '<----DECLARE THE COUNTER 
        Eaten = False
        FlaskFound = False
        DisplayCavern(Cavern, MonsterAwake)
        Do
            Do
                DisplayMoveOptions()
                MoveDirection = GetMove()
                ValidMove = CheckValidMove(PlayerPosition, MoveDirection)
            Loop Until ValidMove
            If MoveDirection <> "M" Then
                MakeMove(Cavern, MoveDirection, PlayerPosition)
                DisplayCavern(Cavern, MonsterAwake)
                moveCounter = moveCounter + 1 '<---- MAKE THE COUNTER INCREASE BY 1 AFTER EACH MOVE
                FlaskFound = CheckIfSameCell(PlayerPosition, FlaskPosition)
                If FlaskFound Then
                    DisplayWonGameMessage(moveCounter) '<---- ADD THIS
                End If

Then we add the score to the win message

Sub DisplayWonGameMessage(ByVal moveCounter As Integer) '<--- ADD THIS
        Console.WriteLine("Well done!  You have found the flask containing the Styxian potion." & vbNewLine & 
"You have completed the game in " & moveCounter & " turns") <----ADD COUNTER TO THE WIN MESSAGE
        Console.WriteLine("You have won the game of MONSTER!")
        Console.WriteLine()
    End Sub

Another thought - what about if the game is saved. Wouldn't we also need to save the number of moves?? If so, this makes the problem considerably more difficult as it involves changing the record structure.


Make sure that a filename is entered when saving a game

Answer:

Sub SaveGame(ByVal TrapPositions() As CellReference, ByVal MonsterPosition As CellReference, ByVal PlayerPosition As CellReference, ByVal FlaskPosition As CellReference, ByVal MonsterAwake As Boolean)

       Dim Filename As String
       Dim FileCheck As Integer
       Dim CurrentGameData As GameData
       CurrentGameData.TrapPositions = TrapPositions
       CurrentGameData.MonsterPosition = MonsterPosition
       CurrentGameData.PlayerPosition = PlayerPosition
       CurrentGameData.FlaskPosition = FlaskPosition
       CurrentGameData.MonsterAwake = MonsterAwake
       Do While FileCheck < 4
           Console.Write("Enter new file name: ")
           Filename = Console.ReadLine
           FileCheck = Len(Filename)
           If FileCheck > 4 Then
               Console.WriteLine()
               FileOpen(1, Filename, OpenMode.Binary, OpenAccess.Write)
               FilePut(1, CurrentGameData)
               FileClose(1)
           Else
               Console.WriteLine()
               Console.WriteLine("You need a save name of at least four characters!")
               Console.WriteLine()
           End If
       Loop 
   End Sub

Adapt LoadGame so that it checks to ensure that the entered filename exists and that the file is a valid saved game.

Adapt SaveGame so that it checks to ensure that the current game has not already been completed.

Menu Additions[edit | edit source]

Add a menu choice 5 to "display story" or display instructions

Answer:

You must add the option to the main menu:

Sub DisplayMenu()
        Console.WriteLine("MAIN MENU")
        Console.WriteLine("1.  Start new game")
        Console.WriteLine("2.  Load game")
        Console.WriteLine("3.  Save game")
        Console.WriteLine("4.  Play training game")
        Console.WriteLine("5.  Display storyline")
        Console.WriteLine("9.  Quit")
        Console.WriteLine()
        Console.Write("Please enter your choice: ")
End Sub

We must create a sub routine to display the story:

Sub DisplayStory()
  Console.WriteLine("STORY STORY STORY STORY STORY")
End Sub

We must add the option to display the story to the main menu system in the main() subroutine:

    PlayGame(Cavern, TrapPositions, MonsterPosition, PlayerPosition, FlaskPosition, MonsterAwake)
  Case 5
    DisplayStory() ' subroutine call
End Select


Other[edit | edit source]

Change the size of the map

Answer:

Module Module1
    Const NoOfTraps = 2
    Const NSDistance = 10 'Change this
    Const WEDistance = 10 'Change this
'Also need to change the number of "----" to this
            For Count1 = 1 To NSDistance
            Console.WriteLine(" ------------------- ")
                For Count2 = 1 To WEDistance
                    If Cavern(Count1, Count2) = " " Or Cavern(Count1, Count2) = "*" Or (Cavern(Count1, Count2) = "M" And MonsterAwake) Then
                        Console.Write("|" & Cavern(Count1, Count2))
                    Else
                        Console.Write("| ")
                    End If
                Next
                Console.WriteLine("|")
            Next
            Console.WriteLine(" ------------------- ")
            Console.WriteLine()
        End If

'Second Option

    Sub DisplayCavern(ByVal Cavern(,) As Char, ByVal MonsterAwake As Boolean)
        Dim Count1 As Integer
        Dim Count2 As Integer
        For Count1 = 1 To NSDistance
            Console.Write(" ")
            For count = 1 To WEDistance
                If count < WEDistance Then
                    Console.Write("--")
                Else
                    Console.WriteLine("-")
                End If
            Next
            For Count2 = 1 To WEDistance
                If Cavern(Count1, Count2) = " " Or Cavern(Count1, Count2) = "*" Or (Cavern(Count1, Count2) = "M" And MonsterAwake) Then
                    Console.Write("|" & Cavern(Count1, Count2))
                Else
                    Console.Write("| ")
                End If

            Next
            Console.WriteLine("|")
        Next
        Console.Write(" ")
        For count = 1 To WEDistance
            If count < WEDistance Then
                Console.Write("--")
            Else
                Console.WriteLine("-")
            End If
        Next

Change the number of traps. What is the problem with the current code?

Answer:

the number of traps is hard coded in: Const NoOfTraps = 2 But later it is not used when cycling through the traps, this means that if you adjust the number of traps then the code will not include any more than two and break on any less than two. However the number of traps must remain a constant and not changed at runtime as it is used to create the TrapPositions array.

REMOVE:

MonsterAwake = CheckIfSameCell(PlayerPosition, TrapPositions(1))
    If Not MonsterAwake Then
       MonsterAwake = CheckIfSameCell(PlayerPosition, TrapPositions(2))
    End If

AND MAKE THE CHANGES IN HERE:

              Eaten = CheckIfSameCell(MonsterPosition, PlayerPosition)
                For Count = 1 To NoOfTraps '<-- Add this!
                    If Not MonsterAwake And Not FlaskFound And Not Eaten Then
                        MonsterAwake = CheckIfSameCell(PlayerPosition, TrapPositions(Count)) '<--Change TrapPosition to count!
                    End If
                Next
                If MonsterAwake Then
                    DisplayTrapMessage()
                    DisplayCavern(Cavern, MonsterAwake)
                End If


Final Question[edit | edit source]

The final question of the exam is usually an extend and stretch question. It won't require you to code anything, but to discuss how you would code the solution to the problem if you had the time:

In order to make the game more playable, it has been decided to make the cavern have different levels. This means that the player will be able to move up or down in some parts on the cavern. This means that the player will be offered the choices

Enter N to move NORTH
Enter E to move EAST
Enter S to move SOUTH
Enter W to move WEST
Enter U to move UP
Enter D to move DOWN
Enter M to return to the Main Menu

Describe the changes necessary to the following data structures in order to make this possible.

  • TCellReference
  • TCavern
  • TGameData