title: Updating UI of TicTacToe in javafx
body: <p>Here, I have a code below which I collected from the Internet for understanding TicTacToe game's code in java. I understand how the code is written along with its logics. It is played in a single window where two users are differentiated based on the button of the mouse clicked. Now I want to make a similar game which could be played over a network built with a server and a client.</p>
  <p><strong>TicTacToe.java</strong></p>
  <pre><code>package sample;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import javafx.animation.KeyFrame;
  import javafx.animation.KeyValue;
  import javafx.animation.Timeline;
  import javafx.application.Application;
  import javafx.geometry.Pos;
  import javafx.scene.Parent;
  import javafx.scene.Scene;
  import javafx.scene.input.MouseButton;
  import javafx.scene.layout.Pane;
  import javafx.scene.layout.StackPane;
  import javafx.scene.paint.Color;
  import javafx.scene.shape.Line;
  import javafx.scene.shape.Rectangle;
  import javafx.scene.text.Font;
  import javafx.scene.text.Text;
  import javafx.stage.Stage;
  import javafx.util.Duration;
  
  public class Main extends Application {
  
      private boolean playable = true;
      private boolean turnX = true;
      private Tile[][] board = new Tile[3][3];
      private List&lt;Combo&gt; combos = new ArrayList&lt;&gt;();
  
      private Pane root = new Pane();
  
      private Parent createContent() {
          root.setPrefSize(600, 600);
  
          for (int i = 0; i &lt; 3; i++) {
              for (int j = 0; j &lt; 3; j++) {
                  Tile tile = new Tile(); //each tile is a rectangular block
                  tile.setTranslateX(j * 200);
                  tile.setTranslateY(i * 200);
  
                  root.getChildren().add(tile);
  
                  board[j][i] = tile;
              }
          }
  
          // horizontal
          for (int y = 0; y &lt; 3; y++) {
              combos.add(new Combo(board[0][y], board[1][y], board[2][y]));
          }
  
          // vertical
          for (int x = 0; x &lt; 3; x++) {
              combos.add(new Combo(board[x][0], board[x][1], board[x][2]));
          }
  
          // diagonals
          combos.add(new Combo(board[0][0], board[1][1], board[2][2]));
          combos.add(new Combo(board[2][0], board[1][1], board[0][2]));
  
          return root;
      }
  
      @Override
      public void start(Stage primaryStage) throws Exception {
          primaryStage.setScene(new Scene(createContent()));
          primaryStage.show();
      }
  
      private void checkState() {
          for (Combo combo : combos) {
              if (combo.isComplete()) {
                  playable = false;
                  playWinAnimation(combo);
                  break;
              }
          }
      }
  
      private void playWinAnimation(Combo combo) {
          Line line = new Line();
          line.setStartX(combo.tiles[0].getCenterX());
          line.setStartY(combo.tiles[0].getCenterY());
          line.setEndX(combo.tiles[0].getCenterX());
          line.setEndY(combo.tiles[0].getCenterY());
  
          root.getChildren().add(line);
  
          Timeline timeline = new Timeline();
          timeline.getKeyFrames().add(new KeyFrame(Duration.seconds(1),
                  new KeyValue(line.endXProperty(), combo.tiles[2].getCenterX()),
                  new KeyValue(line.endYProperty(), combo.tiles[2].getCenterY())));
          timeline.play();
      }
  
      private class Combo {
          private Tile[] tiles;
          public Combo(Tile... tiles) {
              this.tiles = tiles;
          }
  
          public boolean isComplete() {
              if (tiles[0].getValue().isEmpty())
                  return false;
  
              return tiles[0].getValue().equals(tiles[1].getValue())
                      &amp;&amp; tiles[0].getValue().equals(tiles[2].getValue());
          }
      }
  
      private class Tile extends StackPane {
          private Text text = new Text();
          private boolean clicked = false;;
  
          public Tile() {
              Rectangle border = new Rectangle(200, 200);
              border.setFill(null);
              border.setStroke(Color.BLACK);
  
              text.setFont(Font.font(72));
  
              setAlignment(Pos.CENTER);
              getChildren().addAll(border, text);
  
              setOnMouseClicked(event -&gt; {
                  if (!playable || clicked)
                      return;
  
                  if (event.getButton() == MouseButton.PRIMARY) {
                      if (!turnX)
                          return;
  
                      if(!clicked){
                          drawX();
                          turnX = false;
                          clicked = true;
                          checkState();
                      }
                  }
                  else if (event.getButton() == MouseButton.SECONDARY) {
                      if (turnX)
                          return;
  
                      if(!clicked){
                          drawO();
                          turnX = true;
                          clicked = true;
                          checkState();
                      }
                  }
              });
          }
  
          public double getCenterX() {
              return getTranslateX() + 100;
          }
  
          public double getCenterY() {
              return getTranslateY() + 100;
          }
  
          public String getValue() {
              return text.getText();
          }
  
          private void drawX() {
              text.setText(&quot;X&quot;);
          }
  
          private void drawO() {
              text.setText(&quot;O&quot;);
          }
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  </code></pre>
  <p>I want to build the server and client in different files. The <em>server.java</em> will contain server sockets, input-output streams, and accept connections from a socket. I have no problem with that. Similarly, the <em>client.java</em> will also have sockets and necessary streams. Both the server file and the client file will also have the <em>TicTacToe.java</em>. I can set up the code up to this point.</p>
  <p><strong>My problem:</strong></p>
  <p>I cannot update the UI over the socket network. How can I do it? I've watched few codes on Platform.runLater() but do not understand them well. I wanted insight.</p>
  <p>It would be very helpful for me if someone could give me a direction on how to write a code for this and implementing what I want so that I can solve my problem.</p>
  <p>Thanks ...</p>