Search code examples
javajavafx-8tic-tac-toe

My tic-tac-toe program that uses javafx isnt working. It has no compile error or runtime error. But it still doesn't work


Here is my code. I created a 3 by 3 set of buttons. Each button once clicked changes to an X or an O. When I run my program I get a visual display of a 3 by 3 set of buttons. But once I click one of those buttons nothing happens.

public class tic_tac_toe extends Application {
        String token = "X";
        public void start(Stage stage) {
            Text t = new Text("Hello world");
            GridPane p = new GridPane();
            p.setAlignment(Pos.TOP_LEFT);
            p.setHgap(10);
            p.setVgap(10);
            Button l0 = new Button("");
            Button l01 = new Button("");
            Button l02 = new Button("");
            Button l1 = new Button("");
            Button l11 = new Button("");
            Button l12 = new Button("");
            Button l2 = new Button("");
            Button l21 = new Button("");
            Button l22 = new Button("");
            l0.setOnAction(e ->  {
               if(l0.equals("X") | l0.equals("O")) {System.exit(0);}

                else if(l0.equals("") && token == "X") {
                l0.setText("O");
                token = "X";
               }
                else if(l0.equals("") && token == "O") {
                l0.setText("X");
                token = "X";
               }

           });
           l01.setOnAction(e -> {
            if(l01.equals("X") | l01.equals("O")) {System.exit(0);}
            else if(l01.equals("") && token == "X") {
                l01.setText("O");
                token = "X";
            }
            else if(l01.equals("") && token == "O") {
                l01.setText("X");
                token = "X";
            }
           });
           l02.setOnAction( e -> {
            if(l02.equals("X") | l02.equals("O")) {System.exit(0);}
            else if(l02.equals("") && token == "X") {
                l02.setText("O");
                token = "X";
            }
            else if(l02.equals("") && token == "O") {
                l02.setText("X");
                token = "X";
            }                                                                           
          });

          l1.setOnAction(e -> {
            if(l1.equals("X") | l1.equals("O")) {System.exit(0);}
            else if(l1.equals("") && token == "X") {
                l1.setText("O");
                token = "X";
            }
            else if(l1.equals("") && token == "O") {
                l1.setText("X");
                token = "X";
            }
          });
          l11.setOnAction(e -> {
            if(l11.equals("X") | l11.equals("O")) {System.exit(0);}
            else if(l11.equals("") && token == "X") {
                l11.setText("O");
                token = "X";
            }
            else if(l11.equals("") && token == "O") {
                l11.setText("X");
                token = "X";
            }
          });
          l12.setOnAction( e -> {
            if(l12.equals("X") | l12.equals("O")) {System.exit(0);}
            else if(l12.equals("") && token == "X") {
                l12.setText("O");
                token = "X";
            }
            else if(l12.equals("") && token == "O") {
                l12.setText("X");
                token = "X";
            }
          });

          l2.setOnAction(e -> {
            if(l2.equals("X") | l2.equals("O")) {System.exit(0);}
            else if(l2.equals("") && token == "X") {
                l2.setText("O");
                token = "X";
            }
            else if(l2.equals("") && token == "O") {
                l2.setText("X");
                token = "X";
            }
          });
          l21.setOnAction(e -> {
            if(l21.equals("X") | l21.equals("O")) {System.exit(0);}
            else if(l21.equals("") && token == "X") {
                l21.setText("O");
                token = "X";
            }
            else if(l21.equals("") && token == "O") {
                l21.setText("X");
                token = "X";
            }
          });
          l22.setOnAction( e -> {
            if(l22.equals("X") | l22.equals("O")) {System.exit(0);}
            else if(l22.equals("") && token == "X") {
                l22.setText("O");
                token = "X";
            }
            else if(l22.equals("") && token == "O") {
                l22.setText("X");
                token = "X";
            }
         });
         p.add(l0, 0, 0);
         p.add(l01, 1, 0);
         p.add(l02, 2, 0);

         p.add(l1, 0, 1);
         p.add(l11, 1, 1);
         p.add(l12, 2, 1);

         p.add(l2, 0, 2);
         p.add(l21, 1, 2);
         p.add(l22, 2, 2);
         Scene s = new Scene(p, 500, 500);
         stage.setScene(s);
         stage.show();
    }

}

Solution

  • There are a few concepts that you should learn to simplify your code. First of all you should learn about arrays and cycles (aka loops).

    Another thing that Dici is correct about is that typcial line such as

    if(l0.equals("") && token == "X")
    

    contains two significant logical mistakes in a single line:

    1. l0 has type Button and thus is never equals to an empty String ("")

    2. to compare Strings you should use equals instead of just ==

    Also I don't see any sense in System.exit(0); if user makes wrong click.

    I fixed those mistakes and simplified code with arrays and loops but significant piece of logic is still missing: when and how the game ends? This is up to you to implement. Note that this might require some changes in the existing code, more than just putting logic into checkForEnd.

    Please also make sure you understand how new createFieldButton works, this is really imporant.

    public class tic_tac_toe extends Application
    {
        private static final String X = "X";  // named constants are better than copy-paste
        private static final String O = "O";
    
        String token = X;
    
        private void checkForEnd()
        {
        }
    
        private Button createFieldButton()
        {
            Button b = new Button();
            b.setOnAction(e -> {
                if ("".equals(b.getText()))
                {
                    b.setText(token);
                    if (X.equals(token))
                        token = O;
                    else
                        token = X;
                    checkForEnd();
                }
            });
            return b;
        }
    
        public void start(Stage stage)
        {
            GridPane p = new GridPane();
            p.setAlignment(Pos.TOP_LEFT);
            p.setHgap(10);
            p.setVgap(10);
            Button[][] fieldButtons = new Button[3][];
            for (int y = 0; y < 3; y++)
            {
                fieldButtons[y] = new Button[3];
                for (int x = 0; x < 3; x++)
                {
                    fieldButtons[y][x] = createFieldButton();
                    p.add(fieldButtons[y][x], x, y);
                }
            }
    
            Scene s = new Scene(p, 500, 500);
            stage.setScene(s);
            stage.show();
        }   
    }