cs106a – Assignment #5 – Extra Task #1

The complete specification of assignment #5 can be found as part of the stream at iTunes.

Add a high score feature

Save the top ten highest scores and names to a file and make it persistent between runs of the program. Read the file when you start and print out the hall of fame. If a player gets a score that preempts one of the early high scores, congratulate them and update the file before you quit so it is recorded for next time.

Add a new method to display the high scores:

	public void run() {
		showHighScores();
		setupPlayers();
		initDisplay();
		playGame();
	}

Load the high scores form previous games and display them when available in a dialog message:

        private void showHighScores() {		
		String text = "Highscores:\n";
		loadHighScores();

		if (highScoreNames.size() == 0) {
			text += "none available yet";
		} else {
			for (int i = 0; i < highScoreNames.size(); i++) {
				int value = highScoreValues.get(i);
				if (value / 100 == 0) text += "  ";
				if (value / 10 == 0) text += "  ";
				text += value + " " + highScoreNames.get(i) + "\n";
			}
		}

		IODialog dialog = getDialog();
		dialog.println(text);		
	}

Prepare two instance variables as array lists to hold the high score values and the name of the successful players. To load the old high scores use a scanner as to first scan for all lines in the file and process them:

	private ArrayList<String> highScoreNames;
	private ArrayList<Integer> highScoreValues;

	private void loadHighScores() {
		highScoreNames = new ArrayList<String>();
		highScoreValues = new ArrayList<Integer>();
		File file = new File(HIGHSCORE_FILE);
		try {
			Scanner scanner = new Scanner(new FileReader(file));
			while (scanner.hasNextLine()) {
				processHighScoresLine(scanner.nextLine());
			}
			scanner.close();
		} catch (IOException ex) {
			// don't care do nothing
		}
	}

Every line of the high score file holds a value of the high score and the name of the successful player separated by an equal sign. To separate them use another scanner and use the result to fill the array lists:

	protected void processHighScoresLine(String line){
		Scanner scanner = new Scanner(line);
		scanner.useDelimiter("=");
		if (scanner.hasNext()) {
			highScoreValues.add(new Integer(scanner.next()));
			highScoreNames.add(scanner.next());
		}
	}

At the end of the program when the results are checked for the winner, test again if the scores of the players are new high scores, and let them know if they set a new high score:

	private void findWinner() {
                ...
		if (newHighScore()) {
			display.printMessage("Congratulations, " + winner + ", you won with a new high score of " + winningScore + "!");
		} else {
			display.printMessage("Congratulations, " + winner + ", you won with a total score of " + winningScore + "!");
		}			
	}

To test for a new high score loop for each player over the old ones, starting with the smallest value which is the last one in the array list. Continue as long as the current old high score is small then the new score, till the correct position is found and add the new high score. If any new high score has been found, save the new file, and notify the calling method:

	private boolean newHighScore() {
		boolean fileNeedsUpdate = false;
		for (int player = 0; player < nPlayers; player++) {
			boolean newHighScore = false;
			for (int i = highScoreNames.size() - 1; i >= 0; i--) {				
				if (highScoreValues.get(i).intValue() <= totalScore[player]) {
					newHighScore = true;
					fileNeedsUpdate = true;
					if (i == 0) {
						addHighScore(i, player);
					}
				} else {
					if (newHighScore) {
						addHighScore(i + 1, player);						
					}
					break;
				}
			
			}
		}
		if (fileNeedsUpdate) saveHighScores();
		
		return fileNeedsUpdate;
	}

When a new high score is added and the number of high scores is higher than the maximum allowed number, remove the last (smalles) high score:

	private void addHighScore(int i, int player) {
		highScoreNames.add(i, playerNames[player]);
		highScoreValues.add(i, new Integer(totalScore[player]));
		if (highScoreNames.size() > N_HIGHSCORES) {
			highScoreNames.remove(N_HIGHSCORES);
			highScoreValues.remove(N_HIGHSCORES);
		}
	}

To save the high score files, print all currently stored high scores formatted to the file:

	private void saveHighScores() {
		try {
			PrintWriter printWriter = new PrintWriter(new FileWriter(HIGHSCORE_FILE));
			for (int i = 0; i < highScoreNames.size(); i++) {
				printWriter.println(highScoreValues.get(i) + "=" + highScoreNames.get(i));
			}
			printWriter.close();
		} catch (IOException ex) {
			throw new ErrorException(ex);
		}
	}

Like always, use constants instead of actual values inside the code:

	private static final String HIGHSCORE_FILE = "HighScores.txt";
	private static final int N_HIGHSCORES = 10;

The code for this assignment is available on github.

FacebooktwitterredditpinterestlinkedintumblrmailFacebooktwitterredditpinterestlinkedintumblrmail

Leave a Reply

Your email address will not be published.