Question

In: Computer Science

Complete the project functions for this week. These functions are winner(), save_game() and load_game(). To complete...

Complete the project functions for this week. These functions are winner(), save_game() and load_game(). To complete these functions, first remove the library function call from the function in the template (save_game_lib, etc), then replace that with your own code to complete the function. You can test your functions separately from the project by creating a small main() function that calls them (with appropriate inputs), or you can compile the entire project and see if it works.

winner(): The winner function is rather long, as it needs to check in 4 different directions to 1305ENG (Programming Laboratory 8) Page 5 of 5 see if the game has been won: horizontally, vertically, and diagonally in two directions. Each of these requires loops to pick the starting position, then a statement to compare the 4 squares in the chosen direction to see if they are equal (and not equal to 0). Once you’ve found a single winning combination there’s no need to look any further, just return that result. If you search all four directions without finding a winner, return 0. HINTS: consider where the first square of a winning run of 4 tokens could possibly start. For example, horizontally these 4 tokens could start on the far left of the board, but only up to the 4th last on the right (COLS3). Any further right would not allow for 4 tokens to be in a row. Diagonally the possible starting positions are even fewer – the diagonal downward combinations can only start in the top 3 (ROWS-3) rows, and the leftmost 4 (COLS-3) columns, and similarly for the diagonally upwards direction except the bottom 3 rows. Once you know which possible starting points to loop through, you can then check the 4 tokens in the row starting from the spot.

save_game(): This function saves the specified game to the specified file. Note that a "Game" variable is a struct that has 5 fields: player1 and player2 are integers specifying whether the player is a human (1) or computer (0). The board field contains a COLSxROWS array of integers. The turn field defines whose turn it is in the game (1 or 2), and finally winner is an integer which stores the winner of the game (1 or 2) or 0 if nobody has won yet. All of these fields should be written to the file in the format:

player1 player2 turn winner

[board]

Where board is the entire board, one row at time. This should be printed out in a very similar way to the way the board is displayed, except use the numbers 0 (empty), 1 (player1) and 2 (player2) to represent each square, and there are no other characters such as | or – to format it. See the game.txt file on the website to get an example of what the file should look like. If the file is written successfully, 0 should be returned by the function. If there is any error, -1 should be returned.

load_game(): This function takes a pointer to a Game structure and a filename, and reads the game data from the specified file and puts it into the supplied struct. The format is identical to the save_game function. If the file is read successfully, 0 should be returned. If there is any error, -1 should be returned. More information on this week's functions can be found in the project instructions, and hints on the algorithms can be found in the template file

TEMPLATE FILE:

#include 
#include 
#include 
#include 
#include 
#include "connect4.h"

int main ( void ){

    int option ;
        Game g ;

        // intitialise random seed
        srand(time(NULL));

    while (( option = main_menu()) != -1 ){
        if ( option == 1 ){
            // setup a new game
            setup_game ( &g ) ;
            // now play this game
            play_game ( &g ) ;
        } else if ( option == 2 ){
            // attempt to load the game from the save file
            if ( load_game ( &g, "game.txt" ) == 0 ){
                // if the load went well, resume this game
                play_game ( &g ) ;
            } else {
                printf ( "Loading game failed.\n") ;
            }
        } else if ( option == -1 ){
            printf ( "Exiting game, goodbye!\n") ;
        }
    }
}

// WEEK 1 TASKS
// main_menu()
// column_full()
// get_move()

// displays the welcome screen and main menu of the game, and prompts the user to enter an option until
// a valid option is entered.
// Returns 1 for new game, 2 for load game, -1 for quit
int main_menu ( void ){

    // Dipslay Welcome message

    // Continue asking for an option until a valid option (n/l/q) is entered
    // if 'n', return 1
    // if 'l', return 2
    // if 'q', return -1
    // if anything else, give error message and ask again..

    return main_menu_lib () ;
}


// Returns TRUE if the specified column in the board is completely full
// FALSE otherwise
// col should be between 1 and COLS
int column_full ( int board[COLS][ROWS], int col ){

    // check the TOP spot in the specified column (remember column is between 1 and COLS, NOT 0 and COLS-1 so you'll need to modify slightly
    // if top spot isn't empty (0 is empty) then the column is full, return 1
    // otherwise, return 0
    return column_full_lib ( board, col ) ;
}


// prompts the user to enter a move, and checks that it is valid
// for the supplied board and board size
// Returns the column that the user has entered, once it is valid (1-COLS)
// note that this value is betweeen 1 and COLS (7), NOT between 0 and 6!!
// If the user enters 'S' or 's' the value -1 should be returned, indicating that the game should be saved
// If the user enters 'Q' or 'q' the value -2 should be returned, indicating that the game should be abandoned
int get_move ( int board[COLS][ROWS] ){

    // repeat until valid input is detected:

    // read a line of text from the user
    // check if the user has entered either 's' (return -1) or 'q' (return -2)
    // if not, read a single number from the inputted line of text using sscanf
    // if the column is valid and not full, return that column number
    // otherwise, give appropriate error message and loop again

    return get_move_lib ( board ) ;
}


// END OF WEEK 1 TASKS

// WEEK 2 TASKS
// board_full()
// display_board()
// add_move()


// adds a token of the given value (1 or 2) to the board at the
// given column (col between 1 and COLS inclusive)
// Returns 0 if successful, -1 otherwise
int add_move ( int board[COLS][ROWS], int col, int colour ){

    // check that the column isn't full - if it is, return -1 and abort

    // start at the bottom of the board, and move upwards in the specified column until an empty spot is found
    // put a token of the specified colour at that location
    return add_move_lib ( board, col, colour ) ;
}



// determines if the board is completely full or not.
// Return TRUE if full, false otherwise
int board_full ( int board[COLS][ROWS] ){

    // loop through each column
        // if a column ISN'T full, return 0 (board can't be full if a single column isnt

    // if all columns are checked and full, return 1

    return board_full_lib ( board ) ;
}


// displays the board to the screen
int display_board ( int board[COLS][ROWS] ){

    // loop through each row and column of the board and display in appropriate format
    // use | and - characters to draw boundaries of the board, and put numbers at the bottom to indicate the column numbers

    return display_board_lib ( board ) ;
}


// END OF WEEK 2 TASKS

// WEEK 3 TASKS
// winner()
// save_game()
// load_game()


// determines who (if anybody) has won.  Returns the player id of the
// winner (1 or 2), otherwise 0 if nobody has won yet
int winner ( int board[COLS][ROWS] ){

    // using loops, check all possible HORIZONTAL winning locations
        // check every row, for each row:
            // for starting vlaues of 1 to 4 (COLS-4+1), check if 4 squares are all the same player's colour
                // if so, return that colour as the result

    // do a similar process for VERTICAL winning combinations

    // do a similar process for DIAGONAL UPWARDS combinations

    // do a simlar process for DIAGONAL DOWNWARDS combinations

    // if no winner found, return 0
    return winner_lib ( board ) ;
}



// saves the game to the specified file. The file is text, with the following format
// player1 player2 turn winner
// board matrix, each row on a separate line
// Example:
//
//1 0 1 0        player 1 human, player 2 computer, player 1's turn, nobody has won
//0 0 0 0 0 0 0  board state - 1 for player 1's moves, 2 for player 2's moves, 0 for empty squares
//0 0 0 0 0 0 0
//0 0 0 2 0 0 0
//0 0 0 2 0 0 0
//0 2 1 1 1 0 0
//0 2 2 1 1 2 1
int save_game ( Game g, char filename[] ){
    return save_game_lib ( g, filename ) ;
}

// loads a saved game into the supplied Game structure. Returns 0 if successfully loaded, -1 otherwise.
// Format is identical to the save format described above, obviously.
int load_game ( Game *g, char filename[] ){
    return load_game_lib ( g, filename ) ;
}


// END OF WEEK 3 TASKS

// WEEK 4-5 TASKS
// setup_game()
// play_game()
// computer_move()


// calcualtes a column for the computer to move to, using artificial "intelligence"
// The 'level' argument describes how good the computer is, with higher numbers indicating better play
// 0 indicates very stupid (random) play, 1 is a bit smarter, 2 smarter still, etc..
int computer_move ( int board[COLS][ROWS], int colour, int level ){

    // If level 0, this is a 'dumb' opponent, pick a random column that isn't full and return that

    // If level 1, this is slightly smarter - if the computer's move can win the game, choose that column, otherwise random

    // If level 2, slightly smarter again. If computer can win it will do that, otherwise it will block an opponent's winning move, otherwise random

    // Higher levels are up to you!

    // Hint - you can copy the board into a 'temporary' board and trial putting a token in a column, then simply call the winner function to see
    // if that move has won the game. Doing this for the current player will check if that player can win, doing it for the opponent will see if the opponent can win next turn

    // You can use "lookahead" logic to search for the 'best' move many moves ahead

    return computer_move_lib ( board, colour, level ) ;
}


// sets up the game to a new state
// prompts the user if each player should be a human or computer, and initialises the relevant fields
// of the game structure accordingly
int setup_game ( Game *g ){

    // prompt the user to enter whether each player is a human or computer (h or c)
    // set the player1 and player2 fields of the struct accordingly (1 for human, 0 for computer)
    // initialise the board to all zeros
    // set winner to 0 ( no winner yet!)
    // set turn to either 1 or 2 (randomly)
    return setup_game_lib ( g ) ;
}


// Starts or resumes playing the Game g. Continues until the game is over or the user quits.
int play_game ( Game *g ){

    return play_game_lib ( g ) ;
}

Solutions

Expert Solution

int load_game_lib ( Game *g, char filename[] ) {
        
        FILE *fp; 
        fp = fopen(filename, "r"); // read mode
        
        if (fp == NULL)
        {
                return 0;
        }
        
        fscanf(fp, "%d %d %d %d", &g->player1, &g->player2, &g->turn, &g->winner);
        
        
        for(int i=0; i<COLS; i++) {
                for(int j=0; j<ROWS; j++) {
                        fscanf(fp, "%d", &g->board[i][j]);
                }
        }

        return 1;
}



int save_game_lib ( Game g, char filename[] ) {
        
        FILE *fp; 
        fp = fopen(filename, "w"); // read mode
        
        if (fp == NULL)
        {
                return 0;
        }
        
        fprintf(fp, "%d %d %d %d\n", g.player1, g.player2, g.turn, g.winner);
        
        
        for(int i=0; i<COLS; i++) {
                for(int j=0; j<ROWS; j++) {
                        fprintf(fp, "%d ", g.board[i][j]);
                }
                fprintf(fp, "\n");
        }

        return 1;
}

// loop through each row and column of the board and display in appropriate format
// use | and - characters to draw boundaries of the board, and put numbers at the bottom to indicate the column numbers
// return display_board_lib ( board ) ;
int winner (int data[COLS][ROWS] ) {


        // Check to see if four consecutive cells in a row match.
        // check rows
        for (int r = 0; r < COLS; r++) {
        for (int c = 0; c < ROWS - 3; c++) {
            if (    data[r][c] == data[r][c + 1] && 
                data[r][c] == data[r][c + 2] && 
                data[r][c] == data[r][c + 3] && data[r][c] != 0){
                return data[r][c];
            }
        }
        }

        // Check to see if four columns in the same row match
        // check columns
        for (int r = 0; r < COLS - 3; r++) {
        for (int c = 0; c < ROWS; c++) {
            if (    data[r][c] == data[r + 1][c] &&
                data[r][c] == data[r + 2][c] && 
                data[r][c] == data[r + 3][c] && data[r][c] != 0) {
                return data[r][c];
            }
        }
        }

        // Check to see if four diagonals match (top left to bottom right)
        // check major diagonal
        for (int r = 0; r < COLS - 3; r++) {
        for (int c = 0; c < ROWS - 3; c++) {
            if (    data[r][c] == data[r + 1][c + 1] && 
                data[r][c] == data[r + 2][c + 2] && 
                data[r][c] == data[r + 3][c + 3] && data[r][c] != 0) {
                return data[r][c];
            }
        }
        }

        // Check to see if four diagonals in the other direction match (top right to
        // bottom left)
        // check minor diagonal
        for (int r = 0; r < COLS - 3; r++) {
        for (int c = 3; c < ROWS; c++) {
            if (    data[r][c] == data[r + 1][c - 1] && 
                data[r][c] == data[r + 2][c - 2] && 
                data[r][c] == data[r + 3][c - 3] && data[r][c] != 0) {
                return data[r][c];
            }
        }
        }

        return 0;
}
**************************************************

Answering the functions related to save and load, Since seems you are asking for them.. Your other functions are not completed, so i can not test the functionality. Let me know if i can be of any further help.


Related Solutions

''' Problem 1: Formin' Functions Define and complete the functions described below. The functions are called...
''' Problem 1: Formin' Functions Define and complete the functions described below. The functions are called in the code at the very bottom. So you should be able simply to run the script to test that your functions work as expected. ''' ''' * function name: say_hi * parameters: none * returns: N/A * operation: Uhh, well, just say "hi" when called. And by "say" I mean "print". * expected output: >>> say_hi() hi ''' ''' * function name: personal_hi...
Kim and Kanye are playing a single game of Rock-Paper-Scissors. They have complete information. The winner...
Kim and Kanye are playing a single game of Rock-Paper-Scissors. They have complete information. The winner must pay the loser $1,000. If they make the same choice they each get nothing. What is the Nash equilibrium for the game?
Week 1 Assignment Complete this two page assignment by the end of week 1! Download and...
Week 1 Assignment Complete this two page assignment by the end of week 1! Download and open the Word document below....fill in the blank and highlight the answer to the questions or fill in the blank. Resubmit here when you're finished by adding your completed assignment as a file! BIO 212 Assignment 1.docx BIO 212 Assignment 1 Fill in the Blank: Use the table on pg. 848-853 in your textbook to help you fill in the blank. Drug Classification Action...
Complete the provided C++ program, by adding the following functions. Use prototypes and put your functions...
Complete the provided C++ program, by adding the following functions. Use prototypes and put your functions below main. 1. Write a function harmonicMeans that repeatedly asks the user for two int values until at least one of them is 0. For each pair, the function should calculate and display the harmonic mean of the numbers. The harmonic mean of the numbers is the inverse of the average of the inverses. The harmonic mean of x and y can be calculated...
Python 3 Forming Functions Define and complete the functions described below. * function name: say_hi *...
Python 3 Forming Functions Define and complete the functions described below. * function name: say_hi * parameters: none * returns: N/A * operation: just say "hi" when called. * expected output: >>> say_hi() hi * function name: personal_hi * parameters: name (string) * returns: N/A * operation: Similar to say_hi, but you should include the name argument in the greeting. * expected output: >>> personal_hi("Samantha") Hi, Samantha * function name: introduce * parameters: name1 (string) name2 (string) * returns: N/A...
Python 3 Functions that give answers Define and complete the functions described below. * function name:...
Python 3 Functions that give answers Define and complete the functions described below. * function name: get_name * parameters: none * returns: string * operation: Here, I just want you to return YOUR name. * expected output: JUST RETURNS THE NAME...TO VIEW IT YOU CAN PRINT IT AS BELOW >>> print(get_name()) John * function name: get_full_name * parameters: fname (string) lname (string) first_last (boolean) * returns: string * operation: Return (again, NOT print) the full name based on the first...
Week 4 Project - Submit Files Hide Submission Folder Information Submission Folder Week 4 Project Instructions...
Week 4 Project - Submit Files Hide Submission Folder Information Submission Folder Week 4 Project Instructions Changes in Monetary Policy Assume that the Bank of Ecoville has the following balance sheet and the Fed has a 10% reserve requirement in place: Balance Sheet for Ecoville International Bank ASSETS LIABILITIES Cash $33,000 Demand Deposits $99,000 Loans 66,000 Now assume that the Fed lowers the reserve requirement to 8%. What is the maximum amount of new loans that this bank can make?...
This week you will utilize various variable and functions to develop the first functionality for the...
This week you will utilize various variable and functions to develop the first functionality for the Employee Management System Project. For this assignment, write a Python script to allow users to enter the following string values: employeeName, employeeSSN*, employeePhone, employeeEmail, and employeeSalary. *(employeeSSN = Employee Social Security Number. For example, 123121234) Once you have entered your values, you should display it in the following format: ---------------------------- Mike Smith ----------------------------- SSN: 123123123 Phone: (111)222-3333 Email: mike@ g m a i l....
WEEK 1 HOMEWORK (based on your week 1 assignment) Please answer the following questions in complete...
WEEK 1 HOMEWORK (based on your week 1 assignment) Please answer the following questions in complete sentences. Identify and define at least 5 fallacies about racism. What areas of life does racism affect? Define the two types of racism (institutional and interpersonal). What is symbolic violence when it comes to race? At one time Jews dominated basketball; now it is a game almost exclusively for African Americans. The text authors identify at least two reasons why both of these groups...
This week we will look at the test for goodness of fit. In order to complete...
This week we will look at the test for goodness of fit. In order to complete this discussion board, you will need a small bag of plain m&m’s.   M&m’s have six colors, listed below. The Mars Candy Company has published the percentage of each color that we should see in any given bag of m&m’s. We are going to determine if our purchases m&m’s are significantly different from what we should expect. Our Null Hypothesis is that our percentages will...
ADVERTISEMENT
ADVERTISEMENT
ADVERTISEMENT