Problem
Anyone have any tips on how to divide my code up into classes? This seems to work from me but would prefer to have it divided up into one or two separate classes if possible.
static Scanner sc = new Scanner(System.in);
public static void main(String[] args)
{
System.out.println();
System.out.println();
String prompt = "Welcome to our X and O's game . Please take your first go: ";
String playerMove = "";
String cpuMove = "";
boolean gameIsDecided = false;
for (int i = 1; i <=9; i++)
{
playerMove = getMove(prompt);
updateBoard(playerMove, 1);
displayBoard();
if (isGameDecided())
{
System.out.println("Congratulations , you have beaten me!!");
gameIsDecided = true;
break;
}
// Gives the human player its identity(2) and sets out what happens if computer wins
if (i < 9)
{
cpuMove = getCpuMove();
System.out.println(cpuMove);
updateBoard(cpuMove, 2);
displayBoard();
if (isGameDecided())
{
System.out.println("Unlucky , I win. Better luck next time :");
gameIsDecided = true;
break;
}
prompt = "Take your next go: ";
i++;
}
}
if (!gameIsDecided)
System.out.println("So nothing can separate us , the game is a draw !!");
}
// This section tests to see if the input from the user is valid. If not alerts user of invalid play
public static String getMove(String prompt)
{
String turn;
System.out.print(prompt);
do
{
turn = sc.nextLine();
if (!isAcceptablePlay(turn))
{
System.out.println("Unfortunately this move isn't valid , please try again !!");
}
} while (!isAcceptablePlay(turn));
return turn;
}
I managed to get this code working but ideally would like to break it up into classes to make it a lot tidier
public static boolean isAcceptablePlay(String turn)
{
if (turn.equalsIgnoreCase("A1") & A1 == 0)
return true;
if (turn.equalsIgnoreCase("A2") & A2 == 0)
return true;
if (turn.equalsIgnoreCase("A3") & A3 == 0)
return true;
if (turn.equalsIgnoreCase("B1") & B1 == 0)
return true;
if (turn.equalsIgnoreCase("B2") & B2 == 0)
return true;
if (turn.equalsIgnoreCase("B3") & B3 == 0)
return true;
if (turn.equalsIgnoreCase("C1") & C1 == 0)
return true;
if (turn.equalsIgnoreCase("C2") & C2 == 0)
return true;
if (turn.equalsIgnoreCase("C3") & C3 == 0)
return true;
return false;
}
//This section updates the board in relation to what the user selects
public static void updateBoard(String turn, int player)
{
if (turn.equalsIgnoreCase("A1"))
A1 = player;
if (turn.equalsIgnoreCase("A2"))
A2 = player;
if (turn.equalsIgnoreCase("A3"))
A3 = player;
if (turn.equalsIgnoreCase("B1"))
B1 = player;
if (turn.equalsIgnoreCase("B2"))
B2 = player;
if (turn.equalsIgnoreCase("B3"))
B3 = player;
if (turn.equalsIgnoreCase("C1"))
C1 = player;
if (turn.equalsIgnoreCase("C2"))
C2 = player;
if (turn.equalsIgnoreCase("C3"))
C3 = player;
}
//This is responsible for displaying the board on the command line after every go.
//Each row is declared and using the getSymbol method , the square is filled each turn
public static void displayBoard()
{
String row = "";
System.out.println();
row = " " + getSymbol(A1) + " | " + getSymbol(A2) + " | " + getSymbol(A3);
System.out.println(row);
System.out.println("-----------");
row = " " + getSymbol(B1) + " | " + getSymbol(B2) + " | " + getSymbol(B3);
System.out.println(row);
System.out.println("-----------");
row = " " + getSymbol(C1) + " | " + getSymbol(C2) + " | " + getSymbol(C3);
System.out.println(row);
System.out.println();
}
//Each section is declared as a square and this fills the square with X or O
//Depending on which person chooses to fill that square.
public static String getSymbol(int square)
{
if (square == 1)
return "X";
if (square == 2)
return "O";
return " ";
}
//This controls the Computer move . By mixing them up we make the computer more competitive
public static String getCpuMove()
{
if (B2 == 0)
return "B2";
if (A3 == 0)
return "A3";
if (C2 == 0)
return "C2";
if (B1 == 0)
return "B1";
if (B3 == 0)
return "B3";
if (C1 == 0)
return "C1";
if (A1 == 0)
return "A1";
if (C3 == 0)
return "C3";
if (A2 == 0)
return "A2";
return "";
}
//This contains all the possible winning combinations .
public static boolean isGameDecided()
{
if (is3inARow(A1, A2, A3))
return true;
if (is3inARow(B1, B2, B3))
return true;
if (is3inARow(C1, C2, C3))
return true;
if (is3inARow(A1, B1, C1))
return true;
if (is3inARow(A2, B2, C2))
return true;
if (is3inARow(A3, B3, C3))
return true;
if (is3inARow(A1, B2, C3))
return true;
if (is3inARow(A3, B2, C1))
return true;
return false;
}
public static boolean is3inARow(int a, int b, int c)
{
return ((a == b) & (a == c) & (a != 0));
}
}
Solution
I don’t want to tell you how you should specifically format your code, but this is how I would approach it. In general, you want each class to do one task, and do that task well. So, in your case of making Tic-Tac-Toe, write out what the program does:
In this game, the player places game pieces (X’s or O’s) on a board. If the player places 3 consecutive X’s or O’s in a row, they win. From this we look at the nouns:
- Game
- Player
- Board
- Game Pieces
- Win
Player in this case is an actor and an object. Most of the time you would remove the actors, but since you need to keep score, leave it. Now we can see that we will need a class to contain the instance of the game, players, board, pieces and win scenarios. The structure could be something like this:
- Game contains a board and two players
- Board knows the position of the game pieces
- Board implements ‘Win Checker’
- Player knows which piece is theirs (X or O) and if you want you could add a score
This website has a lot of basic object oriented design patterns that could come in handy too. If you are new to programming, I would suggest going to a used book store and looking for a design patterns book too.