Introduction
This Tic-Tac-Toe game is a classic game where players take turns putting X's and O's on the board until the result ends up
either with 3 X's or O's in a line or a tie. By default, the board size is a 3x3 grid, but you can change the size by running the
file from a command terminal. Next, set the directory to TicTacToe.jar and enter the command "java -jar TicTacToe.jar" where a
number can be added to the end of that statement for a bigger board. The program is divided up into five class: TicTacToe,
TicTacToeController, TicTacToeView, TicTacToeModel, TicTacToeMove. The TicTacToe class contains the main function.
Main and Controller
After retrieving the size of the board and initializing the model and view of the program, the controller calls the "start()" function. A loop starts to test whether the game is over and within that the view's "toString()" function displays the board. It also retrieves the player's next move through the "getNextMove()" function and takes the correct players turn into account switching a boolean from true to false, also meaning player one (x) and player two (o). If the move is invalid it displays an error message (talked upon later). After all that is completed it is looped until the "isGameOver()" boolean is switched to true. To switch the boolean, a winner or tie must be decided then the board shows the result of the game above it.
View and Move
Output and input are handled in the view (aside from the user input of board size which is taken care of in the command line. When the view is initialized in the main, a scanner is assigned to a variable for assisting with further input. An if statement then outputs whose move it is depending on which turn was last, unless it was the first turn where player one begins always. This instructions
("Enter the row and column numbers, separated by a space:") are printed to the screen and the next input is recorded. When inputting the string it checks for any errors and if it is not in the format (int int) then an error is recorded on screen. It splits the string of numbers up and each become numbers in an array to be used for putting either an X or O in the correct column and row. If all tests passed, then the array is parsed into coordinates of the players selection and are further stored in TicTacToeMove for use in the model class.
Model
This is where the brains of the program lie. Variables declared at the beginning of the model include board size, the boolean to determine what player is next, and the physical board which is a two-dimensional array of marks. The strings in the function are "X" "O" "-". Using the same method, the results after completion are stored as either "X" "O" "TIE" and "NONE". Next, the two dimensional array of marks is delcared using the size of the board to set the column and row length, and a loop populates all empty space with "-" marks.
The "makeMark()" function is used for making a mark on the board by accepting a row and column, and it also takes into account the player's turn. The main code of the function lies in its further error checking. Along with checking in the view, this checks the selection by using the "isValidSquare()" and "isSquareMarked()" functions. When checking if the move is valid it also checks to see if the selection is within the bounds of the board. If the mark is within bounds and is not in the same location as another mark, then the board marks "X" or "O" based on player turn. Additionally, the "getMark()" function returns the mark requested in the parameters, the "isXTurn()" function returns a boolean indicating if player one or two is playing and the "getWidth)" function returns the size of the board.
To determine a winner the "getResults()" function must be called by the "isGameOver()" function. In the "getResult()" function, the appropriate result are returned based on "isMarkWin()" or "isTie()." These functions contain the algorithms for setting win and tie conditions based on size of the board. Using nested if and loop statments each square is checked left to right and up to down and finally diagonally. For the "isTie()" function, the board is iterated through, and if there are no empty spaces, and there are no winners, a true boolean value is returned to indicate a tie.
The board construction takes place in the "toString()" method of the model. Stringbuilders are the primary component of constructionas the correct strings are appended in an efficient manner. First, the column headers are appended with the help of a for loop. Next,after adding a new line, a nested for loop iterates through the board and appends each row at a time from left to right by adding the row number, row marks, then a new line. Additionally, a new line is also added before the string is returned.
Example
Player 1 (X) move:
Enter the row and column numbers, separated by a space: 1 2
012
0 ---
1 --X
2 ---
Player 2 (O) move:
Enter the row and column numbers, separated by a space: 1 4
entered location is invalid, already marked, or out of bounds.
012
0 ---
1 --X
2 ---
Player 2 (O) move:
Enter the row and column numbers, separated by a space:
Graphical Possibilities
With only edits to the view and associated calls from the controller, this program may be made into a graphical program. By extending the view to a JFrame with the appropriate algorithms to convert the model to graphical objects, a window with any size board can be filled with buttons.
To start, a two-dimensional array of JButtons must be created for the board, and they are then populated with an imbedded for-loop that adds each JButton to a JPanel. To keep track of the coordinates, the button's names are set to include their coordinates. With the JPanel added to the JFrame, a label is also added to the frame to greet the players and announce a winner. Now that the board is created, there must be functions to change the board. The first is "setButton()" When a player clicks a button, it is sent to this function, disabling the button and setting the text to either "X" or "O" respectively. Similarly, when the game is marked as over, the "setWinner()" function sets the label as "X" "O" or "TIE" respectively.
Changes to the controller include an action performed function that collects information from a button when it is clicked. It first sets the button in the view, then sets a winner if one is found. The rest of the controller consists of the function that creates the JFrame from the view class.