0
\$\begingroup\$

After seeing Snake coded in 10 minutes, I decided to try a similar challenge, albeit easier. The following is Tic Tac Toe that I coded in 10 minutes. Given the short time frame, I'm sure there are style and convention errors abound, and would appreciate any suggestions :)

I will also specifically ask about one thing - checking if there is a winner(done in the only ActionPerformed method). It feels long and convoluted, but it was the best I could think of at the time. Looking back, I still can't really think of any ways to write it better, actually...

import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
public class TicTacToe {
  private JFrame main;
  private TicButton[][] buttons;
  private JPanel[] rows;
  private boolean p1turn = true;
  private final Color bg1 = new Color(255,0,0);
  private final Color bg2 = new Color(0,255,0);
  public static void main(String[] args) {
    new TicTacToe().go();
  }
  public void go() {
    main = new JFrame("Tic Tac Toe!");
    buttons = new TicButton[3][3];
    rows = new JPanel[3];
    int r = 0;
    main.getContentPane().setLayout(new BoxLayout(main.getContentPane(),BoxLayout.Y_AXIS));
    for (int i = 0; i < 3; i++) {
      rows[r] = new JPanel();
      for (int j = 0; j < 3; j++) {
        buttons[i][j] = new TicButton();
        rows[r].add(buttons[i][j]);
      }
      main.getContentPane().add(rows[r]);
      r++;
    }
    main.pack();
    main.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    main.setVisible(true);
  }
  private class TicButton extends JButton{
    int value;
    private boolean clicked;
    public TicButton() {
      super("-");
      this.value = -1;
      clicked = false;
      setFocusable(false);
      this.addActionListener(new ActionListener(){  
        public void actionPerformed(ActionEvent e){  
            if (!clicked) {
              clicked = true;
              setText(p1turn ? "X" : "O");
              value = p1turn ? 1 : 2;
              setBackground(p1turn ? bg1 : bg2);
              p1turn = !p1turn;
              setEnabled(false);
            }

          boolean winner = false;
          String win = "";
          for (TicButton[] tt : buttons) {
            if (tt[0].value == tt[1].value && tt[0].value == tt[2].value && tt[0].value != -1) {
              winner = true;
              win = tt[0].value == 1 ? "X" : "O";
              break;
            }
          }
          for (int j = 0; j < 3; j++) {
            if (buttons[0][j].value == buttons[1][j].value && 
                buttons[0][j].value == buttons[2][j].value &&
                buttons[0][j].value != -1) {
              winner = true;
              win = buttons[0][j].value == 1 ? "X" : "O";
              break;
            }
          }
          if (buttons[0][0].value == buttons[1][1].value && buttons[0][0].value == buttons[2][2].value &&
              buttons[0][0].value != -1) {
            winner = true;
            win = buttons[0][0].value == 1 ? "X" : "O";
          }
          if (buttons[0][2].value == buttons[1][1].value && buttons[0][2].value == buttons[2][0].value &&
              buttons[0][2].value != -1) {
            winner = true;
            win = buttons[0][2].value == 1 ? "X" : "O";
          }
          if (winner) {
            JOptionPane.showMessageDialog(main, win + " wins!");
            main.setVisible(false);
            System.exit(0);
          }
        }  
      }); 
    }
  }

}
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

When it is X’s turn, and they make a move, only player X can win. Similarly, only Y can win on Y’s turn. So why all these tests?

win = tt[0].value == 1 ? "X" : "O";

If there is a winner, just test p1turn in the if (winner) { code!

String win = p1turn ? "X" : "O";

Okay, you may want to move p1turn = !p1turn; to the end of the function, first, to avoid X/O confusion.


This code is checking if the row has all the same symbols, and the symbol is not blank:

if (tt[0].value == tt[1].value && tt[0].value == tt[2].value && tt[0].value != -1) {

When the player moves, this.value is set to their code. And only they can win on this move. So we could instead write:

if (tt[0].value == value && tt[1].value == value && tt[2].value == value) {

Slightly shorter. But we can do better.

Change X’s & O’s values to +1 and -1. Use 0 for blank. Then, if a row sums to +3 or -3, you have a winner!

if (tt[0].value + tt[1].value + tt[2].value == 3*value) {

Similarly for other winning directions.

\$\endgroup\$
1
  • \$\begingroup\$ Wow, that last trick is really neat, thanks :) \$\endgroup\$
    – Quintec
    Sep 27, 2018 at 12:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.