#include "game.h" #include #include // Checks whether or not the game is finished. // A game is considered finished when all lines have been drawn. bool game_is_finished(const Grid &grid) { for (unsigned int j = 0; j < grid.num_rows(); ++j) { for (unsigned int i = 0; i < grid.num_cols(); ++i) { if (grid.field(i, j) == ' ') return false; } } return true; } // Draw a line in the grid starting at point (row, col) going towards the given // direction void draw_line(Grid &grid, unsigned int row, unsigned int col, char direction) { switch (direction) { case 'r': grid.horizontal(row, col) = true; break; case 'l': grid.horizontal(row, col - 1) = true; break; case 'd': grid.vertical(row, col) = true; break; case 'u': grid.vertical(row - 1, col) = true; break; default: // We should never reach this point. std::cout << "Invalid line direction."; assert(false); } } // Checks whether or not a box (or field) is newly completed. // A box is newly completed if all four sides are drawn but the box is not // claimed yet. bool is_newly_completed_box(const Grid &grid, unsigned int row, unsigned int col) { bool state; if (grid.vertical(row, col) == true && grid.horizontal(row, col) == true && grid.vertical(row, col + 1) && grid.horizontal(row + 1, col) == true) state = true; else state = false; return state; } // Play the players move. // This function returns true if the player completed a box with their move. // Otherwise it returns false. bool play_move(Grid &grid, char player, unsigned int row, unsigned int col, char direction) { // Note: we assume the move is valid // draw the new line draw_line(grid, row, col, direction); // check if the current players move completed a new box bool completed_new_box = false; switch (direction) { case 'r': // we drew a horizontal line // check if box above the horizontal line is newly completed // Note: box above only exists if the line is not at the top edge of // the grid! if (row > 0 && is_newly_completed_box(grid, row - 1, col)) { completed_new_box = true; grid.field(row - 1, col) = player; } if (row >= 0 && row < grid.num_rows() && is_newly_completed_box(grid, row, col)) { completed_new_box = true; grid.field(row, col) = player; } break; case 'l': if (row > 0 && is_newly_completed_box(grid, row - 1, col - 1)) { completed_new_box = true; grid.field(row - 1, col - 1) = player; } if (row >= 0 && row < grid.num_rows() && is_newly_completed_box(grid, row, col - 1)) { completed_new_box = true; grid.field(row, col - 1) = player; } break; case 'u': if (col > 0 && is_newly_completed_box(grid, row - 1, col - 1)) { completed_new_box = true; grid.field(row - 1, col - 1) = player; } if (col >= 0 && col < grid.num_cols() && is_newly_completed_box(grid, row - 1, col)) { completed_new_box = true; grid.field(row - 1, col) = player; } break; case 'd': if (col > 0 && is_newly_completed_box(grid, row, col - 1)) { completed_new_box = true; grid.field(row, col - 1) = player; } if (col >= 0 && col < grid.num_cols() && is_newly_completed_box(grid, row, col)) { completed_new_box = true; grid.field(row, col) = player; } break; } return completed_new_box; } // Computes a players score. // A Players score is the number of fields claimed by the player. unsigned int compute_player_score(const Grid &grid, char player) { int score = 0; for (unsigned int j = 0; j < grid.num_rows(); j++) { for (unsigned int i = 0; i < grid.num_rows(); i++) { if (grid.field(i, j) == player) ++score; } } return score; } // Checks if the move is within the bounds of the grid, // and the line is not already drawn bool is_valid_move(const Grid &grid, unsigned int row, unsigned int col, char direction) { bool state = false; switch (direction) { case 'l': if (col > 0 && row <= grid.num_rows() && grid.horizontal(row, col - 1) == false) state = true; break; case 'r': if (col < grid.num_cols() && row <= grid.num_rows() && grid.horizontal(row, col) == false) state = true; break; case 'u': if (row > 0 && col <= grid.num_cols() && grid.vertical(row - 1, col) == false) state = true; break; case 'd': if (row < grid.num_rows() && col <= grid.num_cols() && grid.vertical(row, col) == false) state = true; break; default: state = false; break; } return state; } // Main game loop void play_game(Grid &grid) { // initialize player and step char current_player = 'A'; unsigned int current_move = 1; // print initial grid grid.print_grid(); // initialize user input unsigned int row, col; char direction; // loop while game is not finished while (!game_is_finished(grid)) { std::cout << "Move # " << current_move << std::endl; // get a valid move std::cout << "Player " << current_player << "'s move: " << std::endl; std::cin >> row >> col >> direction; while (!is_valid_move(grid, row, col, direction)) { std::cout << "Invalid move!" << std::endl; std::cin >> row >> col >> direction; } // play the move bool move_completed_box = play_move(grid, current_player, row, col, direction); current_move += 1; // print grid grid.print_grid(); // change current player switch (current_player) { case 'A': if (move_completed_box == true) current_player = 'A'; else current_player = 'B'; break; case 'B': if (move_completed_box == true) current_player = 'B'; else current_player = 'A'; break; default: // We should never reach this point. std::cout << "Unknown Player"; assert(false); } } // Game loop exited. The game must be finished std::cout << "Game finished" << std::endl; // Compute and display player scores unsigned int score_a = compute_player_score(grid, 'A'); unsigned int score_b = compute_player_score(grid, 'B'); std::cout << "Player A: " << score_a << std::endl; std::cout << "Player B: " << score_b << std::endl; if (score_a == score_b) { std::cout << "It's a draw!" << std::endl; } else { char winner; if (score_a > score_b) winner = 'A'; else winner = 'B'; std::cout << "Player " << winner << " wins!" << std::endl; } }