patternjavaModerate
Tic Tac Toe computer AI
Viewed 0 times
tacticcomputertoe
Problem
I am creating a TicTacToe game for my college project, and when I finished the code for computer AI, I ended up with a big chunk of code.
It allows the computer to make the winning move, stopping the player from winning and making a random move if the computer can't make any winning move or stop the player from winning. The code I have contains a series of
I was wondering if it would be possible to reduce this amount of code in any way. I have tried putting one of the
```
public void AI(){
count++;
if(buttons[1].getText().equals("O") && buttons[2].getText().equals("O") && buttons[3].getText().equals("")){
buttons[3].setText("O");
buttons[3].setEnabled(false);
} else if(buttons[4].getText().equals("O") && buttons[5].getText().equals("O") && buttons[6].getText().equals("")){
buttons[6].setText("O");
buttons[6].setEnabled(false);
} else if(buttons[7].getText().equals("O") && buttons[8].getText().equals("O") && buttons[9].getText().equals("")){
buttons[9].setText("O");
buttons[9].setEnabled(false);
}
else if(buttons[2].getText().equals("O") && buttons[3].getText().equals("O") && buttons[1].getText().equals("")){
buttons[1].setText("O");
buttons[1].setEnabled(false);
} else if(buttons[5].getText().equals("O") && buttons[6].getText().equals("O") && buttons[4].getText().equals("")){
buttons[4].setText("O");
buttons[4].setEnabled(false);
} else if(buttons[8].getText().equals("O") && buttons[9].getText().equals("O") && buttons[7].getText().equals("")){
buttons[7].setText("O");
buttons[7].setEnabled(false);
}
else if(butt
It allows the computer to make the winning move, stopping the player from winning and making a random move if the computer can't make any winning move or stop the player from winning. The code I have contains a series of
if and else if statements.I was wondering if it would be possible to reduce this amount of code in any way. I have tried putting one of the
if statements in a method and then calling the method several times, but this does not work because the else statement does not run.```
public void AI(){
count++;
if(buttons[1].getText().equals("O") && buttons[2].getText().equals("O") && buttons[3].getText().equals("")){
buttons[3].setText("O");
buttons[3].setEnabled(false);
} else if(buttons[4].getText().equals("O") && buttons[5].getText().equals("O") && buttons[6].getText().equals("")){
buttons[6].setText("O");
buttons[6].setEnabled(false);
} else if(buttons[7].getText().equals("O") && buttons[8].getText().equals("O") && buttons[9].getText().equals("")){
buttons[9].setText("O");
buttons[9].setEnabled(false);
}
else if(buttons[2].getText().equals("O") && buttons[3].getText().equals("O") && buttons[1].getText().equals("")){
buttons[1].setText("O");
buttons[1].setEnabled(false);
} else if(buttons[5].getText().equals("O") && buttons[6].getText().equals("O") && buttons[4].getText().equals("")){
buttons[4].setText("O");
buttons[4].setEnabled(false);
} else if(buttons[8].getText().equals("O") && buttons[9].getText().equals("O") && buttons[7].getText().equals("")){
buttons[7].setText("O");
buttons[7].setEnabled(false);
}
else if(butt
Solution
Yes, you really need to use loops and generalize this!
In order for you to learn the most, I won't give any exact code but I will tell you a bit about what you need to do
-
Your array seems to be index 1-9 based, I would recommend using index 0 to 8 instead. Array index always start at zero, it just seem like you're just not using it. Instead, use it.
-
Use for-loops to iterate through rows, columns and the diagonals of your game board. 3 rows, 3 columns, and 2 diagonals.
Once you have cleaned this up a bit, I recommend you post a follow-up question, as there is likely more things that can be cleaned up then.
In order for you to learn the most, I won't give any exact code but I will tell you a bit about what you need to do
-
Your array seems to be index 1-9 based, I would recommend using index 0 to 8 instead. Array index always start at zero, it just seem like you're just not using it. Instead, use it.
-
Use for-loops to iterate through rows, columns and the diagonals of your game board. 3 rows, 3 columns, and 2 diagonals.
for (int x = 0; x
-
Hint: The row and column of a button can be calculated by using either index / 3 or index % 3 (% is the 'modulo'-operator). This is a reason for why you should use zero-index based arrays. It makes it so much easier to do this calculation.
-
You might want to use an enum for UNPLAYED, X and O. Using an appropriate enum can really help clean up your code massively.
public enum PlayedBy {
UNPLAYED, X, O;
}
-
Decoupling. This is a bit more advanced and nothing you should be focusing on primarily. But in the future, it will help you greatly. Right now your AI knows everything about your view (view = the objects that the user sees). What if you wanted to make two AIs play against each other and only output to the console? What if you wanted to make an Android app of this? What if you wanted to make a Web application with GWT? (In the future you might want this!) You should look into the MVC pattern and/or use interfaces! to decouple your code.
You repeat this part very often
buttons[x].setText("O");
buttons[x].setEnabled(false);
That is something that should be put into a method:
void setButtonPlayer(JButton position, String player) {
position.setText(player);
position.setEnabled(false);
}
Now you only have to use setButtonPlayer(buttons[4], "O"); to make a move on button 4. If you use an enum, you could use setButtonPlayer(JButton button, PlayedBy player)`.Once you have cleaned this up a bit, I recommend you post a follow-up question, as there is likely more things that can be cleaned up then.
Code Snippets
buttons[x].setText("O");
buttons[x].setEnabled(false);void setButtonPlayer(JButton position, String player) {
position.setText(player);
position.setEnabled(false);
}Context
StackExchange Code Review Q#44608, answer score: 15
Revisions (0)
No revisions yet.