Click here to Skip to main content
14,920,539 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
First of I'm a beginner in programming. I am using C.
And I started of this project to make a connect-4 game which can save the look of the board while playing and load it to continue where it was left of.
Basically I managed to get everything to work perfectly to work except to make a save and load function. I need this save function to be able to be accessed while the game is in progress then ask for a what file name the users wants to give it, then the file to be created with that name and contain the look of the board at the time it was saved.

I studied about creating files and writing reading them .. but i dont understand how is ti possible to do what i need(and even if its possible)

here is the code of the whole game: (even if you dont have the answer any tips for the code would be great)

C++
//libraries included
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//define included
#define BOARD_ROWS 6
#define BOARD_COLS 7
#define DIM 15

//all functions so i can access them when i need
void printBoard(char *board);
int takeTurn(char *board, int player, const char*);
int checkWin(char *board);
int checkFour(char *board, int, int, int, int);
int horizontalCheck(char *board);
int verticalCheck(char *board);
int diagonalCheck(char *board);
int newGame();
int mainMenu();
void nameInput();

//universal variables
char firstPlayer[DIM], secondPlayer[DIM];

// _____________________________________________ MAIN __________________________________________________
//main function
int main(){
    mainMenu();
}

// _____________________________________________ play new game option __________________________________________________
int newGame(){ //function needs integer value argc(argument count) and char value argv(argument value)

    const char *PIECES = "XO"; //these are the pieces the player use, player one = X player two = O
    char board[BOARD_ROWS * BOARD_COLS]; // the board = board-rows * board-cols which is 7*6=42
    memset(board, ' ', BOARD_ROWS * BOARD_COLS); // this function fills board with the value ' ' and that is to
                                                //be done (board-rows*board-cols) times which is 42 times

    int turn, done = 0;

    for(turn = 0; turn < BOARD_ROWS * BOARD_COLS && !done; turn++){ //looping until done is 0 (which it is by default) AND turn is 46
        printBoard(board);
        while(!takeTurn(board, turn % 2, PIECES)){ //the while will happen until takeTurn returns 0
            printBoard(board);
            puts("**Column full!**\n");//so basically when it returns 0 the column is full
      }//once it returns 1 we move own
        done = checkWin(board);//basically when ever the move goes through victory is checked
   }
        printBoard(board);

    if(turn == BOARD_ROWS * BOARD_COLS && !done){ //if turn is equal to 42 which is the last turn AND done is 0
        puts("It's a tie!");// then its a tie
    } else {//this is where the winner is calculated
        turn--;//41
        printf("Player %d (%c) wins!\n", turn % 2 + 1, PIECES[turn % 2]);//41%2+1=2 , 41%2=1 and PIECES[1] is O or X given a different example
   }
    return 0;//end of program
}

//name input function
void inputName(){
    printf("First player enter your name:\n");
    getchar();//to get the \n before scan takes it
    scanf("%c", firstPlayer);
    printf("Second player enter your name:\n");
    getchar();//to get the \n before scan takes it
    scanf("%c", secondPlayer);

    //maybe like this
    //FILE *firstPlayer;
    //firstPlayer = fopen ("*firstPlayer", "r");
}

void printBoard(char *board){
   int row, col; //counters for loops
   //int legitMove; //int to only allow 1-7 and 0 for save
    //do{
   //system("clear");
   puts("\n    ****Connect Four****\n"); //heading
   for(row = 0; row < BOARD_ROWS; row++){ //6 times
      for(col = 0; col < BOARD_COLS; col++){ //7 times
         printf("| %c ",  board[BOARD_COLS * row + col]); //this prints the character filling in row by row
      }
      puts("|");
      puts("-----------------------------"); // these are to style the look of the board and differentiate between

   }
   puts("  1   2   3   4   5   6   7\n"); //this is for the players to know which column is which and not have to count
}

int takeTurn(char *board, int player, const char *PIECES){ //takes (board, turn % 2, PIECES)
   int row, col = 0;
   printf("Player %c (%c):\nEnter number coordinate: ", player + 1, PIECES[player]); //player+1 is 0+1=1 and so PIECES[1] will be O
//                                                                                                       and so PIECES[0] will be X
while(1){
      if(1 != scanf("%d", &col) || col < 1 || col > 7 ){ //here is the input for the first move it is allowed only in 1-7 values
         while(getchar() != '\n'); //this loop discards unwanted characters and basically gives a clean line to print
         puts("Number out of bounds! Try again.");
      } else {
         break; //if the input is 1-7 then it breaks
      }
   }
   col--;//after that one spot is taken for the players move, that's why it decrements

   for(row = BOARD_ROWS - 1; row >= 0; row--){
      if(board[BOARD_COLS * row + col] == ' '){//if the space selected
         board[BOARD_COLS * row + col] = PIECES[player];//then the space is marked either X or O
         return 1;
      }
   }
   return 0;
}
int checkWin(char *board){
    return (horizontalCheck(board) || verticalCheck(board) || diagonalCheck(board));
}

int checkFour(char *board, int a, int b, int c, int d){
    return (board[a] == board[b] && board[b] == board[c] && board[c] == board[d] && board[a] != ' ');
}

int horizontalCheck(char *board){
    int row, col, index;
    const int WIDTH = 1;

    for(row = 0; row < BOARD_ROWS; row++){
       for(col = 0; col < BOARD_COLS - 3; col++){
          index = BOARD_COLS * row + col;//index is 0 here since 7*0+0 is 0
          if(checkFour(board, index, index + WIDTH, index + WIDTH * 2, index + WIDTH * 3)){
             return 1;
          }
       }
    }
    return 0;
}

int verticalCheck(char *board){
    int row, col, index;
    const int HEIGHT = 7;

    for(row = 0; row < BOARD_ROWS - 3; row++){
       for(col = 0; col < BOARD_COLS; col++){
          index = BOARD_COLS * row + col;
          if(checkFour(board, index, index + HEIGHT, index + HEIGHT * 2, index + HEIGHT * 3)){
              return 1;
          }
       }
    }
    return 0;
}

int diagonalCheck(char *board){
   int row, col, index, count = 0;
   const int DIAG_RGT = 6, DIAG_LFT = 8;

   for(row = 0; row < BOARD_ROWS - 3; row++){
      for(col = 0; col < BOARD_COLS; col++){
         index = BOARD_COLS * row + col;
         if(((count <= 3) && (checkFour(board, index, index + DIAG_LFT, index + DIAG_LFT * 2, index + DIAG_LFT * 3))) ||
         ((count >= 3) && (checkFour(board, index, index + DIAG_RGT, index + DIAG_RGT * 2, index + DIAG_RGT * 3)))){
            return 1;
         }
         count++;
      }
      count = 0;
   }
   return 0;
}

//print main menu and guide through options
int mainMenu(){
    int choiceMainProblem = 0;// I introduce this variable to make the menu only take values 1 2 or 3 and not allow any other
    int choiceMain;
    do{
    printf("Connect-4 game\n");
    printf("1.Play new game\n");
    printf("2.Load already existing game\n");
    printf("3.Exit the game\n");
    printf("\n");
    printf("Choose an option(1-3):\n");//all of the above until here is printing the look of the main menu
    scanf("%d", &choiceMain);

    if((choiceMain > 3) || (choiceMain <1)){
        choiceMainProblem = 1;
        printf("Try again values supported are 1 2 3!\n");
    }
    }
    while(choiceMainProblem);

    switch(choiceMain){
        case 1: inputName(); break;
        //value 2:
        case 3: return 0;
    }
    return 0;
}


What I have tried:

I havent tried anything since i dont know how is it possible
Posted
Updated 1-Jan-21 10:38am
v2
Comments
raddevus 1-Jan-21 16:34pm
   
I tried your code. It failed upon attempting to enter the two player names. I wanted to see it run so I altered the case 1 statement to include newGame() and the game started without a player 2 name anyways.
I played an entire game and I'm impressed with this example program in C. It's quite nice and amazing that it actually determines a winner.
Also... to save your data you should just save each value the user enters into a CSV (comma separated values) file.
Jovan Miljkovic 2-Jan-21 5:33am
   
yes that is the way its supposed to run thank you for the answer i will try today!

I recommand that you use basic file I/O and write an read text data because it is easier to understand and debug.

One simple way is to create a complete string of the data and write it and read the data as string to use it again. Be sure to sync read and write function all time.

PS: best style is to write some test code to verify all code.
   
Comments
Jovan Miljkovic 2-Jan-21 5:40am
   
Thank you so much for the tips! Have a good year!
Add some code like the following so you can save the col value integer that the user types each time to select a column where the game piece is dropped.

C++
void saveCharToFile(int data){
    FILE *fp;
 
    fp = fopen("game.txt", "a");
 
    if(fp == NULL) {
        printf("file can't be opened\n");
        exit(1);
    } 
    fprintf(fp, "%d,", data);
    fclose(fp);
}


This will write to a file named game.txt in the directory where you run the game.
Each time the method is called with an integer value, it will be written to the file with a trailing comma (to create a CSV file).

Next, just add the one line of code (2nd line shown below) to your program to your takeTurn() function:

C++
col--;//after that one spot is taken for the players move, that's why it decrements
    saveCharToFile(col); // add this new line


Now, each time the user selects a valid value it will be added to your game.txt file.

There is much more work to do, such as reloading the value, but I'll let you work on that.
   
Comments
Jovan Miljkovic 2-Jan-21 5:39am
   
Thank you do much this helped a lot! I hope you have a good year!
It is just a question of writing the required data to a file. The actual data depends on the requirements of the program. You can write it out in binary as a complete dump of your data structure, or compose it into separate items which may be written in a specific order, or with key identifiers to allow you to recreate them when you read it back in. So the first thing you need to do is to create a structure that contains all the data that you need to save. You can then work from there to code your save and load functions.
   
Comments
Jovan Miljkovic 2-Jan-21 5:36am
   
thank you for the tip!
TIme to learn about serialization: Serialization - Wikipedia[^].
   
Comments
Jovan Miljkovic 2-Jan-21 5:36am
   
thank you i will check it out!
CPallini 2-Jan-21 6:42am
   
You are welcome.

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