In: Computer Science
Tic-Tac-Toe, also called X's and O's, Noughts and Crosses, and X and 0 is a simple game played on a 3x3 grid, referred to as the board. Lines may be horizontal, vertical, or diagonal.
You will implement a Board class to represent the 3x3 grid. This class will have functions to determine which symbol, if any, is in a cell, to place a symbol in a cell, to determine the winner, if any so far, and to print the board to standard output. The board should appear as below:
Implement a Board class with the following functionality:
Default constructor, copy constructor, destructor, assignment operator.
Determine the symbol at the specified grid position.
Change the symbol at the specified grid position.
Determine the winner of the game, if any. You must distinguish between the case where there is no winner because the game is not over yet, and the case where there is no winner because the game ended in a tie.
Create four constants for the four game states and return one of them.
Find a way to pass the position in the grid as a single value. This can be done by creating a record (struct) to store the row and column, or by representing both values using a single integer.
Print the board to standard output.
TicTacToe.java
import javax.swing.JOptionPane;
public class TicTacToe {
public static void main(String[] args)
{
try
{
int choice =
JOptionPane.showOptionDialog(null, "Would you like to play
Tic-Tac-Toe?", "Tic-Tac-Toe",
JOptionPane.YES_NO_OPTION,
JOptionPane.QUESTION_MESSAGE, null, null, null);
if (choice ==
0)
{
TTTGame game = new TTTGame();
game.play();
}
}
catch (NullPointerException
exception)
{
}
}
}
TTTGame.java
import java.util.Scanner;
import javax.swing.JOptionPane;
public class TTTGame
{
//constants
private static final String PLAYER_1 = "X";
private static final String PLAYER_2 = "0";
//instance variables
private String lastPiece;
private String currentPiece;
private String nextPiece;
private boolean keepPlaying;
private TTTBoard board;
//constructor
public TTTGame()
{
lastPiece = PLAYER_2;
currentPiece = PLAYER_1;
nextPiece = PLAYER_2;
board = new TTTBoard();
keepPlaying = true;
}
// takes a piece type (char) and gets a tic-tac-toe
board location from the player
// returns the chosen location as an array of ints of
length 2
public int[] chooseSquare(String piece)
{
int[] location = new int[2];
boolean validInput = false;
while (!validInput)
{
String input =
JOptionPane.showInputDialog(null, board.toString() + "\nThe current
player is " + piece + ". "
+ "\nInput the location of
your next move in the form row,column.");
Scanner
inputScanner = new Scanner(input);
inputScanner.useDelimiter(",");
if(inputScanner.hasNextInt())
{
if (inputScanner.hasNextInt())
{
for (int i = 0; i <
location.length; i++)
{
location[i] = inputScanner.nextInt();
}
validInput = true;
}
}
else
{
JOptionPane.showMessageDialog(null, "Invalid
input. Please enter two numbers separated by a comma.");
}
inputScanner.close();
}
return location;
}
// allows two players to play the game
public void play()
{
while (keepPlaying)
{
int[] location =
chooseSquare(currentPiece);
if
(board.move(currentPiece, location[0], location[1]))
{
if (board.winner())
{
JOptionPane.showMessageDialog(null, board.toString() + "\nThe
winner is " + currentPiece + ". \nCongratulations!");
keepPlaying = false;
}
else if (board.isBoardFull() &&
!board.winner())
{
JOptionPane.showMessageDialog(null, board.toString() + "\nGame
over! \nThe board is full with no winner.");
keepPlaying = false;
}
lastPiece = currentPiece;
currentPiece = nextPiece;
nextPiece = lastPiece;
}
else
{
JOptionPane.showMessageDialog(null, "Invalid
move! The square is full!");
}
}
}
}
TTTBoard.java
public class TTTBoard
{
//instance variables
private final int ROWS = 3;
private final int COLUMNS = 3;
private String[][] board = new
String[ROWS][COLUMNS];
//constructor which creates a blank tic-tac-toe game
board
//2d array of pieces (char) and board layout
public TTTBoard()
{
for (int i = 0; i < ROWS;
i++)
{
for (int j = 0;
j < COLUMNS; j++)
{
board[i][j] = "";
}
}
}
// takes a board location (row and column numbers) and
determines if that location is currently occupied
public boolean isSquareFull(int xpos, int ypos)
{
if (board[xpos][ypos] == "")
{
return
false;
}
else
return
true;
}
// takes a piece type (char) and a board location and
places the piece in that location, updating the board
// returns true if this was successful
// does nothing if there is already a piece there or
if that player made the last move
public boolean move(String piece, int xpos, int
ypos)
{
int tempX = xpos - 1;
int tempY = ypos - 1;
// check if that player made the
last move too
if (!isSquareFull(tempX,
tempY))
{
board[tempX][tempY] = piece;
return
true;
}
else
{
return
false;
}
}
// determines if the board is full
public boolean isBoardFull()
{
for (int i = 0; i < ROWS;
i++)
{
for (int j = 0;
j < COLUMNS; j++)
{
if (!isSquareFull(i, j))
{
return false;
}
}
}
return true;
}
// determines if a player has won
// a player wins if they have a straight line
vertically, horizontally, or diagonally
public boolean winner()
{
// vertical winner
for (int i = 0; i < ROWS;
i++)
{
int j = 0;
if
((board[i][j].equals(board[i][j+1])) &&
(board[i][j].equals(board[i][j+2])) &&
(!board[i][j].equals("")))
return true;
}
// horizontal winner
for (int j = 0; j < COLUMNS;
j++)
{
int i = 0;
if
((board[i][j].equals(board[i+1][j])) &&
(board[i][j].equals(board[i+2][j])) &&
(!board[i][j].equals("")))
return true;
}
// diagonal winner
if (board[0][0].equals(board[1][1])
&& board[0][0].equals(board[2][2]) &&
(!board[0][0].equals("")))
return
true;
else if
(board[2][0].equals(board[1][1]) &&
board[2][0].equals(board[0][2]) &&
(!board[2][0].equals("")))
return
true;
else
return
false;
}
// returns the board as a string
public String toString()
{
String boardString = new
String("
1
2 3 ");
for (int i = 0; i <
this.board.length; i++)
{
boardString +=
"\n" + (i+1) + " ";
for (int j = 0;
j < this.board[0].length; j++)
{
if (this.board[i][j] != "")
{
boardString += "[_" +
board[i][j] + "_]";
}
else
{
boardString += "[___]";
}
}
}
return boardString;
}
// main method for testing data type
public static void main(String[] args)
{
TTTBoard currentBoard = new
TTTBoard();
System.out.println(currentBoard.toString() + "\n");
String playerChar = "X";
String computerChar = "O";
currentBoard.move(playerChar, 1,
1);
System.out.println(currentBoard.toString());
System.out.println(currentBoard.winner());
currentBoard.move(computerChar, 3,
3);
System.out.println(currentBoard.toString());
System.out.println(currentBoard.winner());
currentBoard.move(playerChar, 1,
2);
System.out.println(currentBoard.toString());
System.out.println(currentBoard.winner());
currentBoard.move(computerChar, 2,
3);
System.out.println(currentBoard.toString());
System.out.println(currentBoard.winner());
currentBoard.move(playerChar, 1,
3);
System.out.println(currentBoard.toString());
System.out.println(currentBoard.winner());
currentBoard.move(computerChar, 2,
2);
System.out.println(currentBoard.toString());
System.out.println(currentBoard.winner());
}
}