I realize I haven’t written anything about programming yet, so I thought I’d break it in with a simple post about saving a game state and loading it with C/C++. I’ll cover the basic functions needed, and you can build on that.
It doesn’t matter if you are using C or C++, they’ll both work just the same. For this example, I’ll write in C++ style. So you should have a basic understanding of game programming methodology and C++.
Here’s an example game class I’ll be using:
class Game{
public:
enum{ // save/load function return values
SUCCESS = 0,
OPEN_FAILED,
INVALID_MAGIC
};
Game();
~Game();
int load(const char* file);
int save(const char* file);
protected:
int m_lives;
int m_importantThings[10][10];
int m_level;
int m_strength;
};
Then you’ll want to set up your file save structure:
#define MAGIC_SIZE 12
#define MAGIC_STR "(=_MAGIC_=)"
typedef struct{
char magic[MAGIC_SIZE]; // magic header
int lives; // game data
int importantThings[10][10];
int level;
int strength;
} GAMESAVE, *PGAMESAVE;
This structure is the binary data you’ll be writing to and loading from the game file. The “magic” string represents the file header, and provides a method to check if the game file is valid, by comparing the strings when loading the file, which I’ll cover shortly.
Now you’ll want to create a function to save the game to a file (you might need to add the proper headers, look up the function names on Google to find the include file):
int Game::save(const char* file)
{
FILE* fp = 0;
GAMESAVE save;
memset(&save, 0, sizeof(save)); // fill struct with zeroes
strcpy(save.magic, MAGIC_STR); // set the magic string for later
memcpy(save.importantThings, m_importantThings, sizeof(m_importantThings)); // copy the important things
save.lives = m_lives; // copy the rest of the data
save.level = m_level;
save.strength = m_strength;
if((fp = fopen(file, "wb")) != NULL){ // open save file in write-binary mode
fwrite(&save, sizeof(save), 1, fp); // write the game save data
fclose(fp);
return SUCCESS;
}
return OPEN_FAILED;
}
And now for the slightly more complex loading function:
int Game::load(const char* file)
{
FILE* fp = 0;
GAMESAVE save;
memset(&save, 0, sizeof(save));
if((fp = fopen(file, "rb")) == NULL){ // open file in read-binary mode
return OPEN_FAILED;
}
fread(&save, sizeof(save), 1, fp); // load the game save data
fclose(fp);
/* now test if the file's header is correct */
if(strncmp(save.magic, MAGIC_STR, MAGIC_SIZE) != 0){
return INVALID_MAGIC;
}
/* we're good, load the game data */
memcpy(m_importantThings, save.importantThings, sizeof(save.importantThings));
m_lives = save.lives;
m_level = save.level;
m_strength = save.strength;
return SUCCESS;
}
And here’s an example of using these new functions (game is assumed to be global):
int someFunction(void){
char file[256] = {0};
int x = -1;
/* save the file first */
// get file save location from user...
// etc...
if(game.save(file) == Game::SUCCESS){
printf("File saved!\n");
}
else{
printf("File not saved :(\n");
}
/* now load the file */
switch((x = game.load(file))){
case Game::SUCCESS:
printf("There was great success.\n");
break;
case Game::OPEN_FAILED:
printf("Failed to open the file :(\n");
break;
case Game::INVALID_MAGIC:
printf("Your magic is invalid.\n");
break;
default:
break;
}
return 0;
}
You’ll want to create a special extension for your file, so it won’t be confused with other file types. If you want to automate the save function, so that it writes to a new save file each time, simply search the directory for files that have your custom extension, find the highest number, and increment the number.
If done correctly, when you try to view the saved file in notepad, it should look something like this:

I’ll write a tutorial later on directory searching in Windows for those that want to learn.