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
- We declare an array
HighScores
to hold the top 5 scores. - 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
to0
. - We check if the
NewScore
is greater than any of the current high scores. - If it is a high score, we add it to the array, sort the array in descending order using
std::sort()
andstd::greater<>()
, rewind to the beginning of the file, and write the updated scores. Note we have added an#include <algorithm>
to support this change. - 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.