'How to check if it's a tie in "Tic-Tac-Toe"?
I was following a tutorial and changed the winner check code and it works fine (it was all if statements in the tutorial) but couldn't figure out how to check if it's a tie. I tried a for loop which would increase a count variable according to how many places in the grid is filled but it didnt work well. Also in some games the person gets 2 rounds. e.g. X plays but it doesnt switch to O. Im new to java, we learned python last semester so im sorry if this is a dumb question. (https://codeshare.io/eV4Bwx this is the tutors code to check the winner)
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
public class TicTacToe implements ActionListener{
Random random = new Random();
JFrame frame = new JFrame();
JPanel title_panel = new JPanel();
JPanel button_panel = new JPanel();
JLabel textfield = new JLabel();
JButton[] buttons = new JButton[9];
boolean player1_turn;
TicTacToe(){
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(800,800);
frame.getContentPane().setBackground(new Color(50,50,50));
frame.setLayout(new BorderLayout());
frame.setVisible(true);
textfield.setBackground(new Color(25, 25, 25));
textfield.setForeground(new Color(40,23,50));
textfield.setFont(new Font("Ink Free", Font.BOLD,75));
textfield.setHorizontalAlignment(JLabel.CENTER);
textfield.setText("Tic-Tac-Toe");
textfield.setOpaque(true);
title_panel.setLayout(new BorderLayout());
title_panel.setBounds(0, 0, 800, 100);
button_panel.setLayout(new GridLayout(3,3));
textfield.setBackground(new Color(50, 100, 150));
for (int i = 0; i < 9; i++){
buttons[i] = new JButton();
button_panel.add(buttons[i]);
buttons[i].setFont(new Font("MV Boli", Font.BOLD,120));
buttons[i].setFocusable(false);
buttons[i].addActionListener(this);
}
title_panel.add(textfield);
frame.add(title_panel, BorderLayout.NORTH);
frame.add(button_panel);
firstTurn();
check_x();
}
@Override
public void actionPerformed(ActionEvent e){
for (int i = 0; i < 9; i++){
if (e.getSource() == buttons[i]){
if (player1_turn){
if (buttons[i].getText() == ""){
buttons[i].setForeground(new Color(25,50,55));
buttons[i].setText("X");
player1_turn = false;
textfield.setText("O turn");
}
}else {
if (buttons[i].getText() == ""){
buttons[i].setForeground(new Color(55,0,25));
buttons[i].setText("O");
player1_turn = true;
textfield.setText("X turn");
}
}
}
}
}
public void firstTurn(){
try{
Thread.sleep(2000);
} catch (InterruptedException e){
e.printStackTrace();
}
if (random.nextInt(2) == 0){
player1_turn = true;
textfield.setText("X turn");
}else{
player1_turn = false;
textfield.setText("O turn");
}
}
public void check_x(){
int[][] win = {{0,1,2}, {3,4,5}, {6,7,8}, {0,4,8}, {2,4,6}, {0,3,6}, {1,4,7}, {2,5,8}};
while (true) {
//Check Y
boolean t = false;
for (int i = 0; i < win.length; i++) {
int q = win[i][0];
int w = win[i][1];
int e = win[i][2];
if ((buttons[q].getText() == "O") && (buttons[w].getText() == "O") && (buttons[e].getText() == "O")) {
textfield.setText("O wins");
t = true;
buttons[q].setBackground(Color.GREEN);
buttons[w].setBackground(Color.GREEN);
buttons[e].setBackground(Color.GREEN);
for(int s=0;s<9;s++) {
buttons[s].setEnabled(false);
}
}
}if(t){break;}
//Check X
boolean n = false;
for (int i = 0; i < win.length; i++) {
int w = win[i][1];
int q = win[i][0];
int e = win[i][2];
if ((buttons[q].getText() == "X") && (buttons[w].getText() == "X") && (buttons[e].getText() == "X")) {
textfield.setText("X wins");
n = true;
buttons[q].setBackground(Color.GREEN);
buttons[w].setBackground(Color.GREEN);
buttons[e].setBackground(Color.GREEN);
for(int s=0;s<9;s++) {
buttons[s].setEnabled(false);
}
}
}if (n){break;}
}
}
}
Solution 1:[1]
For good practice, the only thing between your loops different is the X and the O. You could put it in a separate function and call it twice: didWin("X"); didWin("O");
I tried a for loop which would increase a count variable according to how many places in the grid is filled but it didnt work well.
That would exactly be what i do. What did not work?
private int[][] win = {{0,1,2}, {3,4,5}, {6,7,8}, {0,4,8}, {2,4,6}, {0,3,6}, {1,4,7}, {2,5,8}}; // either can be init like that or filled in constructor
public void check_x(){
while (true) {
if(didWin("X") || didWin("O") || isDraw()) break;
}
}
private boolean didWin(string playerToken){
for (int i = 0; i < win.length; i++) {
int q = win[i][0];
int w = win[i][1];
int e = win[i][2];
if ((buttons[q].getText().equals(playerToken)) && (buttons[w].getText().equals(playerToken)) && (buttons[e].getText().equals(playerToken))) {
endGame(playerToken+" wins"); // more useful to end the game with a separate function, so we can use it for the draw again.
return true;
}
}
return false;
}
private void endGame(string message){
textfield.setText(message);
buttons[q].setBackground(Color.GREEN);
buttons[w].setBackground(Color.GREEN);
buttons[e].setBackground(Color.GREEN);
for(int s=0;s<9;s++) {
buttons[s].setEnabled(false);
}
}
private boolean isDraw(){
int usedFields = 0;
for(int i=0;i<9;i++){
if(buttons[i].getText().equals("")) usedFields++;
}
if( usedFields==9){
endGame("its a draw");
return true;
}
return false;
}
If you want, put the whole while(true) away, rename it to checkGameEnd() and call it each time in actionPerformed.
Add another variable player1_symbol and you can change between X and O for player 1 and play more rounds.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | cookie |
