Created
November 16, 2015 06:10
-
-
Save andrewfhart/e79eb09682313c0cf94c to your computer and use it in GitHub Desktop.
Tic-tac-toe Tutorial (Step 5)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <iostream> | |
#include <cstdlib> | |
#include <ctime> | |
using namespace std; | |
/** | |
* Draw a 3x3 tic-tac-toe board with row and column labels | |
* The cell data in board will be interpreted as follows: | |
* 1 = owned by 'x' | |
* 2 = owned by 'o' | |
* all other values = empty | |
* | |
* @param int[3][3] board The current state of each board cell | |
* @return void | |
*/ | |
void drawBoard(int board[][3]) { | |
cout << " " << " A B C " << endl; | |
cout << " " << "+---+---+---+" << endl; | |
for (int row = 0; row < 3; row++) { | |
cout << row << " "; | |
for (int col = 0; col < 3; col++) { | |
switch (board[row][col]) { | |
case 1: cout << "| " << "x" << " "; break; | |
case 2: cout << "| " << "o" << " "; break; | |
default:cout << "| " << " " << " "; break; | |
} | |
} | |
cout << "|" << endl; | |
cout << " " << " " << "+---+---+---+" << endl; | |
} | |
} | |
/** | |
* Get the next move from the player, and make sure that the | |
* desired move is valid. Validity means: | |
* - column value is within bounds [A, B, C] | |
* - row value is within bounds [0, 1, 2] | |
* - the selected cell is empty board[row][col] == 0 | |
* Once input has been validated, update the board. | |
* | |
* @param int[3][3] board The current state of the board | |
* @return void | |
*/ | |
void nextPlayerMove(int board[][3]) { | |
bool col_valid = true; // assume correct input until proven wrong | |
bool row_valid = true; // ... | |
char col_c; // container for the character value of the column | |
int col; // container for the integer value of the column | |
int row; // container for the integer value of the row | |
cout << "Your turn. Where would you like to move next?" << endl; | |
cout << "Type your move as two characters separated by a space (ex: A 1)" << endl; | |
do { | |
// Obtain input from the user (one character for column, one int for row) | |
cin >> col_c >> row; | |
// Validate the provided column value | |
if (col_c == 'a' || col_c == 'A') { col = 0; } | |
else if (col_c == 'b' || col_c == 'B') { col = 1; } | |
else if (col_c == 'c' || col_c == 'C') { col = 2; } | |
else { | |
cout << "! Invalid column value entered. Your choices are: [A, B, C] " << endl; | |
col_valid = false; | |
} | |
// Validate the provided row value | |
if (row < 0 || row > 2) { | |
cout << "! Invalid row value entered. Your choices are: [0, 1, 2] " << endl; | |
row_valid = false; | |
} | |
// Ensure that the choice corresponds to an empty cell | |
if (row_valid && col_valid && board[row][col] != 0) { | |
cout << "! That cell is not empty. Please try a different cell " << endl; | |
col_valid = false; | |
row_valid = false; | |
} | |
} while (!col_valid || !row_valid); | |
// Update the board with the user's latest choice | |
board[row][col] = 1; // user is always 'x' | |
} | |
/** | |
* Determine the next move the computer should make. For now | |
* the strategy will be simple: randomly pick an available | |
* cell. | |
* Once a cell has been picked, update the board | |
* | |
* @param int[3][3] board The current state of the board | |
* @return void | |
*/ | |
void nextComputerMove(int board[][3]) { | |
int row, col; | |
do { | |
row = rand() % 3; // Choose a random row | |
col = rand() % 3; // Choose a random column | |
} while (board[row][col] != 0); // If taken, try again | |
// Update the board state | |
board[row][col] = 2; // computer is always 'o' | |
} | |
int main (int argc, char* argv[]) | |
{ | |
// State variables | |
// | |
// Board: | |
// 0 1 2 | |
// +---+---+---+ | |
// 0 | | | x | x = board[0][2] | |
// +---+---+---+ | |
// 1 | | | | | |
// +---+---+---+ | |
// 2 | | | | | |
// +---+---+---+ | |
// | |
// Each board square will be in one of three possible | |
// states: 0=empty, 1=owned by 'x', 2=owned by 'o'. | |
int board[3][3] = {}; | |
// Flag to determine whether or not the game is finished | |
// false: game should end: someone has won or there are no more valid moves | |
// true: game may continue | |
bool gameIsValid = true; | |
// Flag to determine whose turn it is | |
// false: it is the computer's turn to make a move | |
// true: it is the player's turn to make a move | |
bool playerTurn = true; | |
/* Game Flow */ | |
// 1. determine who goes first | |
playerTurn = rand() % 2; // coin flip | |
// 2. Enter the main game "loop" | |
while (gameIsValid) { | |
// a. draw the board | |
drawBoard(board); | |
// b. current player makes a move | |
// the logic here depends on whether or not the | |
// computer or the player is the current player | |
if (playerTurn) { | |
// Some function for asking the user what the | |
// next move should be... | |
nextPlayerMove(board); | |
} else { | |
// Some function for determining what the next | |
// move should be... | |
nextComputerMove(board); | |
} | |
// c. check if the current player has just won | |
// d. swap current player | |
playerTurn = (playerTurn) ? false : true; | |
} | |
// 3. print final game result message | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment