15,569,696 members
See more:
Hi. I'm making a tic tac toe game and I've been looking online for tutorial on how I can make a save game function for loading the game later. Up until now I've had no luck with this. See the code for the game below. I'd like some help and insight on how I can achieve this. Cheers.

The code is running fine for me, it's just that I'm very confused as to how I would achieve making the save and load game function. Any help or advice would be very much appreciated.

The problem now is I'm getting two errors saying the load and save identifier cant be found would anyone have a solution to this I will paste the code I have done down below

What I have tried:

```#include <stdio.h>
char box[10] = { 'o','1','2','3','4','5','6','7','8','9' };// This is to Initialise the board
int checkWin();// This will be used to check for the win
void board();

int main() {

int player = 1, i, choice;
char xOrO; // X,O

if (!save(box, player))
{
fprintf(stderr, "Save function failed!\n");
//TODO: handle failure
}

{
//TODO: handle failure
}

do {
board();
player = (player % 2) ? 1 : 2;
printf("Player %d, enter the choice : ", player);
scanf("%d", &choice);
xOrO = (player == 1) ? 'X' : 'O';
if (choice == 1 && box[1] == '1')
box[1] = xOrO;
else if (choice == 2 && box[2] == '2')
box[2] = xOrO;
else if (choice == 3 && box[3] == '3')
box[3] = xOrO;
else if (choice == 4 && box[4] == '4')
box[4] = xOrO;
else if (choice == 5 && box[5] == '5')
box[5] = xOrO;
else if (choice == 6 && box[6] == '6')
box[6] = xOrO;
else if (choice == 7 && box[7] == '7')
box[7] = xOrO;
else if (choice == 8 && box[8] == '8')
box[8] = xOrO;
else if (choice == 9 && box[9] == '9')
box[9] = xOrO;

else {
printf("Invalid option !");
player--;
getchar();
}
i = checkWin();
player++;

} while (i == -1);

board();
if (i == 1) {
printf("==>Player %d won", --player);
}
else {
printf("==>Game draw");
}
getchar();
return 0;

}
int checkWin() {
if (box[1] == box[2] && box[2] == box[3])/**/
return 1;
else if (box[4] == box[5] && box[5] == box[6])
return 1;
else if (box[7] == box[8] && box[8] == box[9])
return 1;
else if (box[1] == box[4] && box[4] == box[7])
return 1;
else if (box[2] == box[5] && box[5] == box[8])
return 1;
else if (box[3] == box[6] && box[6] == box[9])
return 1;
else if (box[1] == box[5] && box[5] == box[9])
return 1;
else if (box[3] == box[5] && box[5] == box[7])
return 1;
else if (box[1] != '1' && box[2] != '2' && box[3] != '3' && box[4] != '4' && box[5] != '5' && box[6] != '6' && box[7] != '7' && box[8] != '8' && box[9] != '9')
return 0;
else
return -1;
}

void board() {
printf("\n\n\t Tic Tac Toe \n\n");
printf("Player1 (X) - Player2 (O) \n\n\n");
printf("     |     |     \n");
printf("  %c  |  %c  |  %c  \n", box[1], box[2], box[3]);
printf("_____|_____|_____\n");
printf("     |     |     \n");
printf("  %c  |  %c  |  %c  \n", box[4], box[5], box[6]);
printf("_____|_____|_____\n");
printf("     |     |     \n");
printf("  %c  |  %c  |  %c  \n", box[7], box[8], box[9]);
printf("     |     |     \n");
}

//this function returns whether the save operation was successful
bool save(char board_array[10], int player)
{
FILE* fp;

//open file
fp = fopen("savefile.txt", "wt");
if (fp == NULL)
{
fprintf(stderr, "Error opening file\n");
return false;
}

//save player's turn to file
if (fputc(player == 1 ? '1' : '2', fp) == EOF)
{
fprintf(stderr, "Error writing to file\n");
fclose(fp);
return false;
}

//save board to file
if (fwrite(board_array, 10, 1, fp) != 1)
{
fprintf(stderr, "Error writing to file\n");
fclose(fp);
return false;
}

//cleanup
fclose(fp);

return true;
}

//this function returns whether the load operation was successful
{
FILE* fp;

//open file
fp = fopen("savefile.txt", "rt");
if (fp == NULL)
{
fprintf(stderr, "Error opening file\n");
return false;
}

switch (fgetc(fp))
{
case EOF:
fclose(fp);
return false;
break;
case '1':
*player = 1;
break;
case '2':
*player = 2;
break;
default:
fprintf(stderr, "Unexpected character found in file!\n");
fclose(fp);
return false;
}

if (fread(board_array, 10, 1, fp) != 1)
{
fclose(fp);
return false;
}

//cleanup
fclose(fp);

return true;
}```
Posted
Updated 22-Aug-21 7:59am
v2
And what is the problem with this?
akeem jokosenumi 22-Aug-21 9:05am
The probelem is I keep getting the message load and save identifier cannot be found which makes it unable to open the file

## Solution 1

You need to place your Main() function at the bottom in C so everything else is declared first.

Another option would be to use Function Prototypes[^]

v2

## Solution 2

C is an old language: it does not "look ahead" to see what sunctionsmight be declared later.

So since your `save` and `load` functions are only declared at the bottom of the file, when you try to call them from `main` it doesn't understand what you mean as it hasn't encountered the names before.

The solution is to use forward references: put these two lines above your `main` function:
```bool save(char board_array[10], int player);

I'd also reverse the parameters when you save the data - change:
```if (fwrite(board_array, 10, 1, fp) != 1)
```
To
```if (fwrite(board_array, 1, 10, fp) != 1)
```

as the array "element" is one byte wide (a char) and you have ten of them.

v2
Rick York 22-Aug-21 12:32pm
If you tell fwrite to write ten items it will return 10 if is successful.
akeem jokosenumi 22-Aug-21 12:59pm
Hi I changed this now its working my question now is how would this load at the start of the because I'm now getting error writing to the file would anyone have clue as to why this is as I'm so close to finishing off this project

## Solution 3

```#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <stdarg.h>
#include <stdbool.h>

void reset_game(char board[3][3], bool* player);
bool save(char board[3][3], bool player);
int  check_win(char board[3][3]);
void print_board(char board[3][3]);
int  get_int_from_user(const char* prompt, ...);
bool get_YN_from_user(const char* prompt, ...);

int main()
{
//array which holds the board contents
char board[3][3];

//this variable specifies whether it is the first player's turn
bool first_player;

//this variable will store the user's input
int choice;

//initialize the game state
reset_game(board, &first_player);

for (;;) //infinite loop, equivalent to while(true)
{
print_board(board);

choice = get_int_from_user(
"Enter a number 1 to 9 to select a field, or\n"
"the number 10 to save the game, or\n"
"the number 11 to load the game, or\n"
"the number 12 to quit the game.\n"
"Player %d, enter your choice :\n",
first_player ? 1 : 2
);

//handle user input
switch (choice)
{
case 10:
//save game
if (save(board, first_player))
{
printf("Save successful.\n");
}
else
{
printf("Save failed!\n");
}
break;
case 11:
{
}
else
{
printf("Resetting game, as the game may now be in a corrupt state.\n");
reset_game(board, &first_player);
}
break;
case 12:
//quit game
printf("Bye!\n");
exit(EXIT_SUCCESS);
default:
if (1 <= choice && choice <= 9)
{
//user selected a field

int i;

//calculate corresponing row and column
i = choice - 1;
int row = i / 3;
int column = i % 3;

//make sure field is not already occupied
if (board[row][column] != 'E')
{
printf("Invalid choice! The specified field is not empty!\n");
break;
}

//make the move
board[row][column] = first_player ? 'X' : 'O';

i = check_win(board);

if (i != -1)
{
print_board(board);
if (i == 1)
printf("==>Player %d won\n", first_player ? 1 : 2);
else
printf("==>Game draw\n");
if (get_YN_from_user("Do you want to play again? (y/n)\n"))
{
reset_game(board, &first_player);
continue;
}
else
exit(EXIT_SUCCESS);
}

//change the player's turn
first_player = !first_player;
}
else
{
printf("Invalid choice! Choice must be a number between 1 and 12.\n");
}
}
}
}

void reset_game(char board[3][3], bool* first_player)
{
//set all fields of the board to contain 'E', which stands for "empty"
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
board[i][j] = 'E';

//make it the first player's turn
*first_player = true;
}

int check_win(char board[3][3])
{
//check for horizontal win
for (int i = 0; i < 3; i++)
{
char c = board[i][0];

if (c != 'E' && board[i][1] == c && board[i][2] == c)
return 1;
}

//check for vertical win
for (int i = 0; i < 3; i++)
{
char c = board[0][i];

if (c != 'E' && board[1][i] == c && board[2][i] == c)
return 1;
}

//check for diagonal win
for (int i = 0; i < 3; i++)
{
char c;

//check for top-left to bottom-right win
c = board[0][0];
if (c != 'E' && board[1][1] == c && board[2][2] == c)
return 1;

//check for bottom-left to top-right win
c = board[2][0];
if (c != 'E' && board[1][1] == c && board[0][2] == c)
return 1;
}

//check for draw
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (board[i][j] == 'E')
return -1;

return 0;
}

void print_board(char board[3][3])
{
printf("\n\n      Tic Tac Toe \n\n");
printf("Player1 (X) - Player2 (O) \n\n\n");

for (int i = 0; i < 3; i++)
{
printf("        |     |     \n");

printf(
"     %c  |  %c  |  %c  \n",
board[i][0] == 'E' ? '1' + i * 3 : board[i][0],
board[i][1] == 'E' ? '2' + i * 3 : board[i][1],
board[i][2] == 'E' ? '3' + i * 3 : board[i][2]
);

if (i != 2)
printf("   _____|_____|_____\n");
else
printf("        |     |     \n");
}

printf("\n");
}

//this function returns whether the save operation was successful
bool save(char board[3][3], bool first_player)
{
FILE* fp;

fp = fopen("savefile.txt", "wt");
if (fp == NULL)
{
fprintf(stderr, "Error opening file\n");
return false;
}

if (fputc(first_player ? '1' : '2', fp) == EOF)
{
fprintf(stderr, "Error writing to file\n");
fclose(fp);
return false;
}

if (fwrite(board, 9, 1, fp) != 1)
{
fprintf(stderr, "Error writing to file\n");
fclose(fp);
return false;
}

fclose(fp);

return true;
}

///this function returns whether the load operation was successful
{
FILE* fp;

//open file
fp = fopen("savefile.txt", "rt");
if (fp == NULL)
{
fprintf(stderr, "Error opening file\n");
return false;
}

switch (fgetc(fp))
{
case EOF:
fclose(fp);
return false;
break;
case '1':
*first_player = true;
break;
case '2':
*first_player = false;
break;
default:
fprintf(stderr, "Unexpected character found in file!\n");
fclose(fp);
return false;
}
if (fread(board, 9, 1, fp) != 1)
{
fclose(fp);
return false;
}

//cleanup
fclose(fp);

return true;
}

int get_int_from_user(const char* prompt, ...)
{
for (;;) //loop forever until user enters a valid number
{
char buffer[1024], * p;
va_list vl;
long l;

va_start(vl, prompt);
vprintf(prompt, vl);
va_end(vl);

if (fgets(buffer, sizeof buffer, stdin) == NULL)
{
fprintf(stderr, "unrecoverable error reading from input\n");
exit(EXIT_FAILURE);
}

//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if (strchr(buffer, '\n') == NULL)
{
int c;

printf("line input was too long!\n");

do
{
c = getchar();

if (c == EOF)
{
fprintf(stderr, "unrecoverable error reading from input\n");
exit(EXIT_FAILURE);
}

} while (c != '\n');

continue;
}

errno = 0;
l = strtol(buffer, &p, 10);

if (p == buffer)
{
printf("error converting string to number\n");
continue;
}

if (errno == ERANGE || l < INT_MIN || l > INT_MAX)
{
printf("number out of range error\n");
continue;
}

//make sure remainder of line contains only whitespace,
//so that input such as "12dfghoh" gets rejected
for (; *p != '\0'; p++)
{
if (!isspace((unsigned char)*p))
{
printf("unexpected input encountered!\n");

//cannot use `continue` here, because that would go to
//the next iteration of the innermost loop, but we
//want to go to the next iteration of the outer loop
goto next_outer_loop_iteration;
}
}

return l;

next_outer_loop_iteration:
continue;
}
}

//this function will ask the user a yes/no question
bool get_YN_from_user(const char* prompt, ...)
{
for (;;) //loop forever until user enters a valid number
{
char buffer[1024];
va_list vl;

va_start(vl, prompt);
vprintf(prompt, vl);
va_end(vl);

if (fgets(buffer, sizeof buffer, stdin) == NULL)
{
fprintf(stderr, "unrecoverable error reading from input\n");
exit(EXIT_FAILURE);
}

//make sure that entire line was read in (i.e. that
//the buffer was not too small)
if (strchr(buffer, '\n') == NULL)
{
int c;

printf("line input was too long!\n");

do
{
c = getchar();

if (c == EOF)
{
fprintf(stderr, "unrecoverable error reading from input\n");
exit(EXIT_FAILURE);
}

} while (c != '\n');

continue;
}

}
}```

v2