Created
November 17, 2015 00:38
-
-
Save andradei/410e476ed6b57ed4af7e to your computer and use it in GitHub Desktop.
Tic-Tac-Toe in C++
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
// | |
// main.cpp | |
// Tic-Tac-Toe | |
// | |
// Created by Isaac Andrade on 9/2/13. | |
// Copyright (c) 2013 Isaac Andrade. All rights reserved. | |
// | |
#include <iostream> | |
#include <string> | |
#include <array> | |
using namespace std; | |
// Global variables - available in nay scope of this program | |
const int ROWS = 3; | |
const int COLUMNS = 3; | |
const char BS = ' '; | |
// Declare functions: function prototypes | |
int gameStatus (int, char[ROWS][COLUMNS]); | |
void drawBoard(char[ROWS][COLUMNS]); | |
/************************************************************ | |
Function to translate user input into actual array positions | |
a1 = 0,0 a2 = 0,1 a3 = 0,2 | |
b1 = 1,0 b2 = 1,1 b3 = 1,2 | |
c1 = 2,0 c2 = 2,1 c3 = 2,2 | |
*************************************************************/ | |
void translateInput(string *p_position, int *p_x, int *p_y) { | |
string x = *p_position; | |
char row = x[0]; | |
char column = x[1]; | |
if (x.length() != 2) *p_position = "Invalid position, please try again."; | |
if (row == 'a') { | |
switch (column) { | |
case '1': | |
*p_x = 0; | |
*p_y = 0; | |
break; | |
case '2': | |
*p_x = 0; | |
*p_y = 1; | |
break; | |
case '3': | |
*p_x = 0; | |
*p_y = 2; | |
break; | |
default: | |
*p_position = "Invalid position, please try again."; | |
break; | |
} | |
} | |
else if (row == 'b') { | |
switch (column) { | |
case '1': | |
*p_x = 1; | |
*p_y = 0; | |
break; | |
case '2': | |
*p_x = 1; | |
*p_y = 1; | |
break; | |
case '3': | |
*p_x = 1; | |
*p_y = 2; | |
break; | |
default: | |
*p_position = "Invalid position, please try again."; | |
break; | |
} | |
} | |
else if (row == 'c') { | |
switch (column) { | |
case '1': | |
*p_x = 2; | |
*p_y = 0;; | |
break; | |
case '2': | |
*p_x = 2; | |
*p_y = 1;; | |
break; | |
case '3': | |
*p_x = 2; | |
*p_y = 2; | |
break; | |
default: | |
*p_position = "Invalid position, please try again."; | |
break; | |
} | |
} | |
else *p_position = "Invalid position, please try again."; | |
} | |
/*************************** | |
MAIN | |
****************************/ | |
int main() | |
{ | |
// Variables | |
char marks[] = {'O', 'X'}; // O = 0, X = 1 | |
int players[] = {2, 1}; // logic starts getting index 1, then it alternates until the end of program. See line 148 | |
int round = 1; | |
int status = 0; | |
char playerGame[ROWS][COLUMNS] = {{BS,BS,BS},{BS,BS,BS},{BS,BS,BS}}; | |
int x_cord, y_cord; // these receive values passed by reference through the translateInput() function | |
string position = ""; | |
//Start the game loop | |
while (status == 0) { | |
// Draw the board with the current game | |
drawBoard(playerGame); | |
// Get user input and assess it | |
do { | |
cout << "Round " << round << endl; | |
cout << "Player " << players[round%2]<< ", enter a position:"; | |
cin >> position; | |
translateInput(&position, &x_cord, &y_cord); | |
cout << position << endl; | |
} while (position.length() != 2); | |
// If input was valid, add it to the board | |
if (position.length() == 2) playerGame[x_cord][y_cord] = marks[round%2]; | |
// Get ready for next round | |
round++; | |
// store game status | |
status = gameStatus(round, playerGame); | |
} | |
// Exit game properly - diplaying message to user | |
drawBoard(playerGame); | |
if (status == 1) | |
cout << "Player 1 won!" << endl; | |
else if (status == 2) | |
cout << "Player 2 won!" << endl; | |
else if (status == 3) | |
cout << "We have a draw!" << endl; | |
else | |
cout << "Match ended with invalid status." << endl; | |
// The End | |
return 0; | |
} | |
// Define functions declared up top | |
/*********************************** | |
Function to check if the game ended | |
0 - Game is ongoing | |
1 - Player 1 won | |
2 - Player 2 won | |
3 - Draw | |
************************************/ | |
int gameStatus (int round, char playerGame[ROWS][COLUMNS]) { | |
// true = someone won | |
bool status = ((playerGame[0][0] == playerGame[0][1]) && (playerGame[0][0] == playerGame[0][2]) && (playerGame[0][0] != BS)) || // 1st row | |
((playerGame[1][0] == playerGame[1][1]) && (playerGame[1][0] == playerGame[1][2]) && (playerGame[1][0] != BS)) || // 2nd row | |
((playerGame[2][0] == playerGame[2][1]) && (playerGame[2][0] == playerGame[2][2]) && (playerGame[2][0] != BS)) || // 3rd row | |
((playerGame[0][0] == playerGame[1][0]) && (playerGame[0][0] == playerGame[2][0]) && (playerGame[0][0] != BS)) || // 1st column | |
((playerGame[0][1] == playerGame[1][1]) && (playerGame[0][1] == playerGame[2][1]) && (playerGame[0][1] != BS)) || // 2nd column | |
((playerGame[0][2] == playerGame[1][2]) && (playerGame[0][2] == playerGame[2][2]) && (playerGame[0][2] != BS)) || // 3rd column | |
((playerGame[0][0] == playerGame[1][1]) && (playerGame[0][0] == playerGame[2][2]) && (playerGame[0][0] != BS)) || // diagonal '\' | |
((playerGame[0][2] == playerGame[1][1]) && (playerGame[0][2] == playerGame[2][0]) && (playerGame[0][2] != BS)); // diagonal '/' | |
if (round >= 5 && round < 9 && status) { // Someone won! | |
if (round % 2 != 0) return 2; | |
else return 1; | |
} | |
else if(!status && round == 9) return 3; // It is a draw! | |
else return 0; // Game is ongoing | |
} | |
/********************************* | |
Function that will draw the board | |
1 2 3 -> c | |
01234 -> j | |
a 0 | | \n | |
1 -----\n | |
b 2 | | \n | |
3 -----\n | |
c 4 | | \n | |
| | | |
| |-> i | |
|-> r | |
**********************************/ | |
void drawBoard(char pG[ROWS][COLUMNS]) { | |
for (int i=0, r=0; i < ROWS+2; i++) { | |
if (i%2 != 0) { | |
cout << "-----\n"; | |
} else { | |
for (int j=0, c=0; j < COLUMNS+2; j++) { | |
if (j%2 != 0) { | |
cout << "|"; | |
} else { | |
cout << pG[r][c]; | |
++c; // keep scanning the columns | |
if (j == 4) cout << endl; // carriage return in the end of every row | |
} | |
} | |
++r; // keep scanning the rows | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment