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

Code Discussion
When you first run your code you will probably find that everything appears to work. Don't be deceived, try and load the top scores. It probably won't work; we need to get the top scores file in the correct location, so that when we select the load the option from the menu it actually loads the file:

Correct Load Location
Inside the  sub routine you'll find the line that is giving you trouble All this line is doing is trying to find the HiScores.txt file inside the folder where your code is running. On Windows machines this will be: ConsoleApplication1\bin\Debug You can fix this by copying the HiScores.txt file into here. Or alternatively you can copy the file into the root of your project, in this case being the poorly named project: ConsoleApplication1 We then need to make the line we looked at above point to this file: The ../../ means to take the Debug folder where the code is running, and to look two folders up to find the HiScores.txt file:
 * If the code is running in ConsoleApplication1\bin\Debug
 * "../../HiScores.txt" will find the file in ConsoleApplication1\

Potential Questions
This list is by no means a list of the questions you will be asked in the exam, but by solving these problems you should get to understand the code a little better.

Validating the LoadTopScores(TopScores)
You might be worried about people accidentally overwriting the top scores from the main menu. Imagine that you have just played the game for an hour and you accidentally click on option 3 on the main menu, you'd overwrite all your scores! How could we validate the entry of the load game to make sure that this didn't happen:

The option menu
Add a new option to the menu to:

Reset the top scores
An option that appears to be missing, is the ability for the user to reset the top scores that are currently stored in the TopScores array. We need to add an option (option 5) to the menu so that users can manually reset the top scores. Make sure that you get all the menu option checks to allow for the new menu option number.

Making sure each player has a different name
When you start the game the following scenario could occur: What is player one's name? Aubrey What is player two's name? Aubrey This means that you wouldn't know who was who, which Aubrey is which? It would be far better if we forced the users to have different names. To do this you are going to need a loop to check that the second name is different from the first name:

Save current top scores to the CSV file
A glaring omission from the code is the ability to save the current top scores back to the CSV file. You might well be asked to implement this. Let's first take a look at the code that reads the data from the file: There are three important things that you need to gain from this.

1. this line opens the file in read only mode and allocates it to file variable 1, we need another mode that writes to the file

2. This code reads a line from the file and saves it into the LineFromFile string. Notice the 1 is referring to the file variable. This line is inside a loop that loops from on the variable Count, why is this?

3. Finally we have some house keeping, where we need to close the file to make sure we free up resources

Using these ideas we need to create a sub routine to save the files. Let's get some pseudo code together:

sub savefiles(TopScores) end sub
 * 1) open the text file for writing
 * 2) loop through 1 to 4 with count
 * 3) write TopScores(count) to the text file in a CSV format
 * 4) close the file

But what real code can we use to do the above?

1. open file for writing, use Output instead of Input 2. Print a line to a file instead of reading from it. Remember you will need a loop to write all 4 lines When you are writing to the file, remember that each line you are writing must have this format: Try the code out yourself and see if you can get it to work:

CSV file

 * add more fields to the CSV file when saving
 * number of balls survived
 * average score per ball

Displaying scores
You might be asked to display results in different ways, there are several potential questions, be ready for them all.

Find the highest score
To do this we need to add a new sub routine, let's call it DisplayHighestScore, and we'll need to pass it the TopScore data structure:

sub displaytopscore(TopScores) end sub
 * 1) create a pointer to the topscore: hiscore
 * 2) set hiscore = 1 so that it points to the first element in TopScores
 * 3) go through each of the TopScores
 * 4) if topscores value is bigger than value being pointed to by hiscores
 * 5) then set hiscores to point to new top score
 * 6) print out the TopScores(hiscore)

Try to code this solution yourself:

Find the lowest score
To do this we need to add a new sub routine, let's call it DisplayLowestScore, and we'll need to pass it the TopScore data structure:

sub displaylowestscore(TopScores) end sub
 * 1) create a pointer to the topscore: hiscore
 * 2) set hiscore = 1 so that it points to the first element in TopScores
 * 3) go through each of the TopScores
 * 4) if topscores value is smaller than value being pointed to by hiscores
 * 5) then set hiscores to point to new lowest score
 * 6) print out the TopScores(hiscore)

Try to code this solution yourself:

Printing out all the scores in order
You might be asked to print out all the high scores in order. That means we need to order the items. We can do this in two ways:

Bubble Sort
They could well ask you to perform a full sort on the high score table. A bubble sort is a potential solution to doing this. Take a look at the following pseudo code to perform a bubble sort. You need to make your own version of this to sort all the data:

Create a sub routine called bubbleSort. It should have the following features:
 * reorder the TopScores array
 * look at the pseudo code above
 * remember you are dealing with an array of records
 * prints out the sorted array using: Console.Writeline(Count & ": " & TopScores(Count).Name & " " & TopScores(Count).Name)
 * called from menu item 5.

List the number of balls survived
To do this we are going to need to implement a counting variable to keep track of the number of balls survived by each person and print this out when they are out: You are out. Your final score was: 176 You survived 34 balls As this variable is a whole number we are going to use an integer to store it:

Keeping track of sixes and fours
You might be asked to put some code in place to keep track of how many sixes and fours were scored by each side. Once each person has finished batting the score of that person should be displayed alongside the numbers of 4s and 6s: You are out. Your final score was: 176 You got: 2 sixes and 9 fours. You can solve this in several ways so don't be worried if you have a different solution to the one below:

Changing the number of scores in stored in TopScores
We'll need to adjust some things here

Adding a new way to be out
Add a new way to be out: "Run out".

Drawn games

 * put a routine in to handle what happens when a game is drawn

This isn't too hard...

If PlayerOneScore = PlayerTwoScore Then Console.WriteLine("You have drawn!") End If

Handling how drawn scores update the high score list if there is only one current high score is less than the two drawn scores is much trickier!

Monty,1 is the current lowest score.. so if both players score 2 runs and draw the game what scores should be recorded.

The program currently will record the high score for player one.... then when the routine checks it returns that player two doesn't have a high score (i.e. a score that is higher than any of the scores held in the topscores array). This is because the playerOne score has already been recorded. There are only four possible solutions:
 * 1) Neither score is recorded
 * 2) Both scores are recorded, adding an extra record (element) to the array
 * 3) Concatenate both player names and assign the playerName field of the Topscores array of records
 * 4) Have only one score recorded BUT... select which of the players Names is added
 * Randomly
 * Using a prompt to allow the user to decide

Playing the game

 * Randomise who goes first

Manual dice validation
If you play the game with real dice and you type in a string of letters instead of a number the program will crash. We need to catch this error and fix it. By now you should be familiar with the Try Catch code What line in the  function is the problem occurring at? There are two other areas that need fixing, where are they? They might ask you to keep looping until with an error message until the user inputs a correct answer, to do this you'll need a loop:

Only one entry per person
If the player's name is already in the TopScores array then update the value rather than adding someone more than once.

The useless: DisplayCurrentPlayerNewScore
This subroutine isn't used (isn't called anywhere). They might ask you to call this function from the PlayDiceGame sub, or elsewhere in the code.

This code has one parameter: CurrentPlayerScore As Integer

Where might we use it? Where is there similar functionality already? Take a look at the PlayDiceGame code:

So we could easily replace this line with the a call to the code above:

They might also ask you to do add a little to the complexity of the DisplayCurrentPlayerNewScore sub routine. For example, make it so that each score displayed looks like: Try and implement this
 * 1) Current Score#
 * 2)    45       #
 * 1)    45       #
 * 1)    45       #

Set limit on the number of balls
In the current skeleton program, the players are permitted to carry on playing the game as long as the appeal dice is not greater than or equal to 2. Therefore, we may be asked to set a constraint on the maximum number of balls available for each player. In the following program code, I will demonstrate how the aforementioned problem can be tackled. The limit is typed in each time the game is played, making it possible for the players to set the limit in the way they want. I create a function call BallLimit The limit is represented by the variable NumberOfBalls Firstly, the player is asked whether he wants to set a limit or not. If the answer is "Y", he will have to enter the limit, which must be greater than 0 (it is not realistic to have no balls). Otherwise, the limit is set to 0 The value of the variable is copied to the integer BallLimit, which is then returned to the subroutine PlayDiceGame as you will see

The following code is written in the PlayDiceGame subroutine 2 new variables are declared. The variable NumberOfBalls will take the value returned by the function BallLimit as stated above Each time a new player starts the game, the value of x is set to 0 Each time the Do loop is executed the value of x is incremented by 1. We must also change the condition of the Do loop as follow: So how does this actually work?

If the player set a limit on the number of balls, say 10, the number is passed to the variable NumberOfBalls in the PlayDiceGame subroutine. Each time the player rolls the bowl dice, one ball is deemed to be lost. That's why the x is incremented by 1 each time. It is used to keep track of the number of balls that have been used so far. Therefore, when the value of x reaches 10, the loop will stop because the player runs out of balls. The player may be out before the limit is reached. In this case, the condition PlayerOut is executed.

If the player did not set a limit, the number 0 is passed to the variable NumberOfBalls in the PlayDiceGame subroutine. The value of x when it enters the first Do loop is x = 0 + 1 = 1. It will keep increasing thereafter and so x is always greater than 1. In other words, the condition x = NumberOfBalls will NEVER be satisfied in this case. PlayerOut is the only condition that may work. Therefore, there is no limit on the number of balls

Linear Search
You need to implement a linear search: Please insert the name you are looking for: Kenny to tell you either: Kenny scored 5. or: We couldn't find a user named Kenny. Try again.