Using C++ language ONLY design a program that allows two players to play a game
ID: 3760651 • Letter: U
Question
Using C++ language ONLY design a program that allows two players to play a game of tic
tac toe. Use a two-dimenional String array with three rows and
three columns as the game board. Each element of the array should
be initialized with an asterisk (*). The program should run a loop
that does the following:
1. Displays the contents of the board array.
2. Allows player 1 to select a location on the board for an X.
The program should ask the user to enter the row and column
number.
3. Allows player 2 to select a location on the board for an O.
The program should ask the user to enter the row and column
number.
4. Determines whether a player has won or if a tie has occurred.
If a player has won, the program should declare that player the
winner and end. If a tie has occurred, the program should say so
and end.
5. Player 1 wins when there are three Xs in a row on the game
board. Player 2 wins when there are three Os in a row on the game
board. The winning Xs or Os can appear in a row, in a column, or
diagonally across the board. A tie occurs when all of the locations
on the board are full, but there is a winner.
6. Program must be modular and have input validation
Explanation / Answer
TTTConsoleNonOO2P.java
import java.util.Scanner;
/**
* Tic-Tac-Toe: Two-player console, non-graphics, non-OO version.
* All variables/methods are declared as static (belong to the class)
* in the non-OO version.
*/
public class TTTConsoleNonOO2P {
// Name-constants to represent the seeds and cell contents
public static final int EMPTY = 0;
public static final int CROSS = 1;
public static final int NOUGHT = 2;
// Name-constants to represent the various states of the game
public static final int PLAYING = 0;
public static final int DRAW = 1;
public static final int CROSS_WON = 2;
public static final int NOUGHT_WON = 3;
// The game board and the game status
public static final int ROWS = 3, COLS = 3; // number of rows and columns
public static int[][] board = new int[ROWS][COLS]; // game board in 2D array
// containing (EMPTY, CROSS, NOUGHT)
public static int currentState; // the current state of the game
// (PLAYING, DRAW, CROSS_WON, NOUGHT_WON)
public static int currentPlayer; // the current player (CROSS or NOUGHT)
public static int currntRow, currentCol; // current seed's row and column
public static Scanner in = new Scanner(System.in); // the input Scanner
/** The entry main method (the program starts here) */
public static void main(String[] args) {
// Initialize the game-board and current status
initGame();
// Play the game once
do {
playerMove(currentPlayer); // update currentRow and currentCol
updateGame(currentPlayer, currntRow, currentCol); // update currentState
printBoard();
// Print message if game-over
if (currentState == CROSS_WON) {
System.out.println("'X' won! Bye!");
} else if (currentState == NOUGHT_WON) {
System.out.println("'O' won! Bye!");
} else if (currentState == DRAW) {
System.out.println("It's a Draw! Bye!");
}
// Switch player
currentPlayer = (currentPlayer == CROSS) ? NOUGHT : CROSS;
} while (currentState == PLAYING); // repeat if not game-over
}
/** Initialize the game-board contents and the current states */
public static void initGame() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
board[row][col] = EMPTY; // all cells empty
}
}
currentState = PLAYING; // ready to play
currentPlayer = CROSS; // cross plays first
}
/** Player with the "theSeed" makes one move, with input validation.
Update global variables "currentRow" and "currentCol". */
public static void playerMove(int theSeed) {
boolean validInput = false; // for input validation
do {
if (theSeed == CROSS) {
System.out.print("Player 'X', enter your move (row[1-3] column[1-3]): ");
} else {
System.out.print("Player 'O', enter your move (row[1-3] column[1-3]): ");
}
int row = in.nextInt() - 1; // array index starts at 0 instead of 1
int col = in.nextInt() - 1;
if (row >= 0 && row < ROWS && col >= 0 && col < COLS && board[row][col] == EMPTY) {
currntRow = row;
currentCol = col;
board[currntRow][currentCol] = theSeed; // update game-board content
validInput = true; // input okay, exit loop
} else {
System.out.println("This move at (" + (row + 1) + "," + (col + 1)
+ ") is not valid. Try again...");
}
} while (!validInput); // repeat until input is valid
}
/** Update the "currentState" after the player with "theSeed" has placed on
(currentRow, currentCol). */
public static void updateGame(int theSeed, int currentRow, int currentCol) {
if (hasWon(theSeed, currentRow, currentCol)) { // check if winning move
currentState = (theSeed == CROSS) ? CROSS_WON : NOUGHT_WON;
} else if (isDraw()) { // check for draw
currentState = DRAW;
}
// Otherwise, no change to currentState (still PLAYING).
}
/** Return true if it is a draw (no more empty cell) */
// TODO: Shall declare draw if no player can "possibly" win
public static boolean isDraw() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
if (board[row][col] == EMPTY) {
return false; // an empty cell found, not draw, exit
}
}
}
return true; // no empty cell, it's a draw
}
/** Return true if the player with "theSeed" has won after placing at
(currentRow, currentCol) */
public static boolean hasWon(int theSeed, int currentRow, int currentCol) {
return (board[currentRow][0] == theSeed // 3-in-the-row
&& board[currentRow][1] == theSeed
&& board[currentRow][2] == theSeed
|| board[0][currentCol] == theSeed // 3-in-the-column
&& board[1][currentCol] == theSeed
&& board[2][currentCol] == theSeed
|| currentRow == currentCol // 3-in-the-diagonal
&& board[0][0] == theSeed
&& board[1][1] == theSeed
&& board[2][2] == theSeed
|| currentRow + currentCol == 2 // 3-in-the-opposite-diagonal
&& board[0][2] == theSeed
&& board[1][1] == theSeed
&& board[2][0] == theSeed);
}
/** Print the game board */
public static void printBoard() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
printCell(board[row][col]); // print each of the cells
if (col != COLS - 1) {
System.out.print("|"); // print vertical partition
}
}
System.out.println();
if (row != ROWS - 1) {
System.out.println("-----------"); // print horizontal partition
}
}
System.out.println();
}
/** Print a cell with the specified "content" */
public static void printCell(int content) {
switch (content) {
case EMPTY: System.out.print(" "); break;
case NOUGHT: System.out.print(" O "); break;
case CROSS: System.out.print(" X "); break;
}
}
}
*******************************************
Cell.java
/**
* The Cell class models each individual cell of the game board.
*/
public class Cell { // save as Cell.java
// package access
Seed content; // content of this cell of type Seed.
// take a value of Seed.EMPTY, Seed.CROSS, or Seed.NOUGHT
int row, col; // row and column of this cell, not used in this program
/** Constructor to initialize this cell */
public Cell(int row, int col) {
this.row = row;
this.col = col;
clear(); // clear content
}
/** Clear the cell content to EMPTY */
public void clear() {
content = Seed.EMPTY;
}
/** Paint itself */
public void paint() {
switch (content) {
case CROSS: System.out.print(" X "); break;
case NOUGHT: System.out.print(" O "); break;
case EMPTY: System.out.print(" "); break;
}
}
}
*********************************************************
Board.java
/**
* The Board class models the game-board.
*/
public class Board { // save as Board.java
// Named-constants for the dimensions
public static final int ROWS = 3;
public static final int COLS = 3;
// package access
Cell[][] cells; // a board composes of ROWS-by-COLS Cell instances
int currentRow, currentCol; // the current seed's row and column
/** Constructor to initialize the game board */
public Board() {
cells = new Cell[ROWS][COLS]; // allocate the array
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
cells[row][col] = new Cell(row, col); // allocate element of the array
}
}
}
/** Initialize (or re-initialize) the contents of the game board */
public void init() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
cells[row][col].clear(); // clear the cell content
}
}
}
/** Return true if it is a draw (i.e., no more EMPTY cell) */
public boolean isDraw() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
if (cells[row][col].content == Seed.EMPTY) {
return false; // an empty seed found, not a draw, exit
}
}
}
return true; // no empty cell, it's a draw
}
/** Return true if the player with "theSeed" has won after placing at
(currentRow, currentCol) */
public boolean hasWon(Seed theSeed) {
return (cells[currentRow][0].content == theSeed // 3-in-the-row
&& cells[currentRow][1].content == theSeed
&& cells[currentRow][2].content == theSeed
|| cells[0][currentCol].content == theSeed // 3-in-the-column
&& cells[1][currentCol].content == theSeed
&& cells[2][currentCol].content == theSeed
|| currentRow == currentCol // 3-in-the-diagonal
&& cells[0][0].content == theSeed
&& cells[1][1].content == theSeed
&& cells[2][2].content == theSeed
|| currentRow + currentCol == 2 // 3-in-the-opposite-diagonal
&& cells[0][2].content == theSeed
&& cells[1][1].content == theSeed
&& cells[2][0].content == theSeed);
}
/** Paint itself */
public void paint() {
for (int row = 0; row < ROWS; ++row) {
for (int col = 0; col < COLS; ++col) {
cells[row][col].paint(); // each cell paints itself
if (col < COLS - 1) System.out.print("|");
}
System.out.println();
if (row < ROWS - 1) {
System.out.println("-----------");
}
}
}
}
*****************************************************************
GameMain.java
import java.util.Scanner;
/**
* The main class for the Tic-Tac-Toe (Console-OO, non-graphics version)
* It acts as the overall controller of the game.
*/
public class GameMain {
private Board board; // the game board
private GameState currentState; // the current state of the game (of enum GameState)
private Seed currentPlayer; // the current player (of enum Seed)
private static Scanner in = new Scanner(System.in); // input Scanner
/** Constructor to setup the game */
public GameMain() {
board = new Board(); // allocate game-board
// Initialize the game-board and current status
initGame();
// Play the game once. Players CROSS and NOUGHT move alternately.
do {
playerMove(currentPlayer); // update the content, currentRow and currentCol
board.paint(); // ask the board to paint itself
updateGame(currentPlayer); // update currentState
// Print message if game-over
if (currentState == GameState.CROSS_WON) {
System.out.println("'X' won! Bye!");
} else if (currentState == GameState.NOUGHT_WON) {
System.out.println("'O' won! Bye!");
} else if (currentState == GameState.DRAW) {
System.out.println("It's Draw! Bye!");
}
// Switch player
currentPlayer = (currentPlayer == Seed.CROSS) ? Seed.NOUGHT : Seed.CROSS;
} while (currentState == GameState.PLAYING); // repeat until game-over
}
/** Initialize the game-board contents and the current states */
public void initGame() {
board.init(); // clear the board contents
currentPlayer = Seed.CROSS; // CROSS plays first
currentState = GameState.PLAYING; // ready to play
}
/** The player with "theSeed" makes one move, with input validation.
Update Cell's content, Board's currentRow and currentCol. */
public void playerMove(Seed theSeed) {
boolean validInput = false; // for validating input
do {
if (theSeed == Seed.CROSS) {
System.out.print("Player 'X', enter your move (row[1-3] column[1-3]): ");
} else {
System.out.print("Player 'O', enter your move (row[1-3] column[1-3]): ");
}
int row = in.nextInt() - 1;
int col = in.nextInt() - 1;
if (row >= 0 && row < Board.ROWS && col >= 0 && col < Board.COLS
&& board.cells[row][col].content == Seed.EMPTY) {
board.cells[row][col].content = theSeed;
board.currentRow = row;
board.currentCol = col;
validInput = true; // input okay, exit loop
} else {
System.out.println("This move at (" + (row + 1) + "," + (col + 1)
+ ") is not valid. Try again...");
}
} while (!validInput); // repeat until input is valid
}
/** Update the currentState after the player with "theSeed" has moved */
public void updateGame(Seed theSeed) {
if (board.hasWon(theSeed)) { // check for win
currentState = (theSeed == Seed.CROSS) ? GameState.CROSS_WON : GameState.NOUGHT_WON;
} else if (board.isDraw()) { // check for draw
currentState = GameState.DRAW;
}
// Otherwise, no change to current state (still GameState.PLAYING).
}
/** The entry main() method */
public static void main(String[] args) {
new GameMain(); // Let the constructor do the job
}
}
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.