Multiple High Scores

How can we modify the high score example to store multiple high scores (e.g., the top 10) instead of just one?

To store multiple high scores, you could use an array or a std::vector within your data file. For example, let's store the top 5 scores.

You'll need to decide how you want to handle the situation when the file doesn't exist or has fewer than 5 scores. One approach is to initialize the file with 5 default scores (e.g., 0) if it is newly created.

Updating the File Structure

First, let's update the code to handle an array of 5 integers instead of a single integer:

#include <SDL.h>
#include <algorithm>
#include <iostream>

void UpdateHighScore(
  const char* Path, int32_t NewScore
) {
  // Open the file in "w+b" mode to create
  // or update
  SDL_RWops* File{SDL_RWFromFile(Path, "w+b")};
  if (!File) {
    std::cerr << "Error opening file: "
      << SDL_GetError() << "\n";
    return;
  }

  const int NumScores{5};
  int32_t HighScores[NumScores];

  // Read the current high scores from the file
  size_t ScoresRead{SDL_RWread(
    File, HighScores, sizeof(int32_t), NumScores
  )};

  // Initialize with default scores if fewer
  // than NumScores were read
  if (ScoresRead < NumScores) {
    std::cout << "Initializing new high scores\n";
    for (size_t i{ScoresRead}; i<NumScores; ++i) {
      HighScores[i] = 0;
    }
  }

  // Check if the new score is a high score
  bool IsHighScore{false};
  for (int i{0}; i < NumScores; ++i) {
    if (NewScore > HighScores[i]) {
      IsHighScore = true;
      break;
    }
  }

  if (IsHighScore) {
    std::cout << NewScore << " is a new high "
      "score! Updating file\n";

    // Add the new score and sort
    HighScores[NumScores - 1] = NewScore;
    std::sort(
      HighScores,
      HighScores + NumScores,
      std::greater<int32_t>()
    );

    // Rewind to the beginning of the file and
    // write the updated scores
    SDL_RWseek(File, 0, RW_SEEK_SET);
    SDL_RWwrite(
      File,
      HighScores,
      sizeof(int32_t),
      NumScores
    );
  } else {
    std::cout << "Not a high score - file "
      "not updated\n";
  }

  SDL_RWclose(File);
}

int main() {
  UpdateHighScore("highscores.dat", 5000);
  UpdateHighScore("highscores.dat", 3000);
  UpdateHighScore("highscores.dat", 6000);
  UpdateHighScore("highscores.dat", 4000);
  UpdateHighScore("highscores.dat", 2000);
  UpdateHighScore("highscores.dat", 5500);
  return 0;
}
Initializing new high scores
5000 is a new high score! Updating file
3000 is a new high score! Updating file
6000 is a new high score! Updating file
4000 is a new high score! Updating file
2000 is a new high score! Updating file
5500 is a new high score! Updating file

Explanation

  1. We declare an array HighScores to hold the top 5 scores.
  2. We attempt to read 5 scores from the file. If fewer are read (e.g., the file is new or incomplete), we initialize the remaining elements of HighScores to 0.
  3. We check if the NewScore is greater than any of the current high scores.
  4. If it is a high score, we add it to the array, sort the array in descending order using std::sort() and std::greater<>(), rewind to the beginning of the file, and write the updated scores. Note we have added an #include <algorithm> to support this change.
  5. We print a message to inform the user if the score was not added to the top 5

Remember that this example assumes you always want to maintain a fixed number of high scores (5 in this case).

You could make the system more flexible by storing the number of scores at the beginning of the file, but that would add complexity.

Read/Write Offsets and Seeking

Learn how to manipulate the read/write offset of an SDL_RWops object to control stream interactions.

Questions & Answers

Answers are generated by AI models and may not have been reviewed. Be mindful when running any code on your device.

Seeking Past EOF
If we seek past the end of a file using SDL_RWseek(), what happens when we try to read or write data? Will it extend the file, or will it result in an error? How can we use this behaviour to append to a file?
Closing SDL_RWops
Why is it important to close the SDL_RWops using SDL_RWclose() after we're finished with it? What are the potential consequences of not closing it?
Binary vs. Text Mode
What is the difference between binary mode ("wb" or "rb") and text mode ("w" or "r") when opening a file with SDL_RWFromFile()? Why is it important to use binary mode?
Storing Player Name
How could we modify the high score example to also store the player's name along with the score?
Searching Large Files
If we have a very large file, how can we efficiently search for a specific piece of data without reading the entire file into memory?
Or Ask your Own Question
Get an immediate answer to your specific question using our AI assistant