Click here to Skip to main content
15,446,510 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I've pretty much finished off my code what I am trying to achieve now is when I save the games I should be able to reload an old game from a list of multiple saved games also I'd like to know how would I be able to achieve to show the program should display the board’s configuration and the current status of the game


What I have tried:

#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);
bool load(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);

        //read input from user
        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:
            //load game
            if (load(board, &first_player))
            {
                printf("Load successful.\n");
            }
            else
            {
                printf("Load failed!\n");
                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
bool load(char board[3][3], bool* first_player)
{
    FILE* fp;

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

    //read player's turn from file
    switch (fgetc(fp))
    {
    case EOF:
        fprintf(stderr, "Error reading from file\n");
        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;
    }
    //read board from file
    if (fread(board, 9, 1, fp) != 1)
    {
        fprintf(stderr, "Error reading from file\n");
        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");

            //discard remainder of line
            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");

            //discard remainder of line
            do
            {
                c = getchar();

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

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

            continue;
        }

        return toupper((unsigned char)buffer[0]) == 'Y';
    }
}
Posted
Updated 22-Aug-21 9:09am

1 solution

See here:
Help Online - Origin C - FindFirstFile[^]
Help Online - Origin C - FindNextFile[^]
Help Online - Origin C - FindClose[^]
That covers the load files list.

The other ... you'll have to think about exactly what you want to do before that can be even approached: and by the time you've worked that out fully, you'll already know what to do!
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900