content: package com.almasb.minesweeper;
  
  import java.util.ArrayList;
  import java.util.List;
  
  import javafx.application.Application;
  import javafx.scene.Parent;
  import javafx.scene.Scene;
  import javafx.scene.layout.Pane;
  import javafx.scene.layout.StackPane;
  import javafx.scene.paint.Color;
  import javafx.scene.shape.Rectangle;
  import javafx.scene.text.Font;
  import javafx.scene.text.Text;
  import javafx.stage.Stage;
  
  public class MinesweeperApp extends Application {
  
      private static final int TILE_SIZE = 40;
      private static final int W = 800;
      private static final int H = 600;
  
      private static final int X_TILES = W / TILE_SIZE;
      private static final int Y_TILES = H / TILE_SIZE;
  
      private Tile[][] grid = new Tile[X_TILES][Y_TILES];
      private Scene scene;
  
      private Parent createContent() {
          Pane root = new Pane();
          root.setPrefSize(W, H);
  
          for (int y = 0; y < Y_TILES; y++) {
              for (int x = 0; x < X_TILES; x++) {
                  Tile tile = new Tile(x, y, Math.random() < 0.2);
  
                  grid[x][y] = tile;
                  root.getChildren().add(tile);
              }
          }
  
          for (int y = 0; y < Y_TILES; y++) {
              for (int x = 0; x < X_TILES; x++) {
                  Tile tile = grid[x][y];
  
                  if (tile.hasBomb)
                      continue;
  
                  long bombs = getNeighbors(tile).stream().filter(t -> t.hasBomb).count();
  
                  if (bombs > 0)
                      tile.text.setText(String.valueOf(bombs));
              }
          }
  
          return root;
      }
  
      private List<Tile> getNeighbors(Tile tile) {
          List<Tile> neighbors = new ArrayList<>();
  
          // ttt
          // tXt
          // ttt
  
          int[] points = new int[] {
                -1, -1,
                -1, 0,
                -1, 1,
                0, -1,
                0, 1,
                1, -1,
                1, 0,
                1, 1
          };
  
          for (int i = 0; i < points.length; i++) {
              int dx = points[i];
              int dy = points[++i];
  
              int newX = tile.x + dx;
              int newY = tile.y + dy;
  
              if (newX >= 0 && newX < X_TILES
                      && newY >= 0 && newY < Y_TILES) {
                  neighbors.add(grid[newX][newY]);
              }
          }
  
          return neighbors;
      }
  
      private class Tile extends StackPane {
          private int x, y;
          private boolean hasBomb;
          private boolean isOpen = false;
  
          private Rectangle border = new Rectangle(TILE_SIZE - 2, TILE_SIZE - 2);
          private Text text = new Text();
  
          public Tile(int x, int y, boolean hasBomb) {
              this.x = x;
              this.y = y;
              this.hasBomb = hasBomb;
  
              border.setStroke(Color.LIGHTGRAY);
  
              text.setFont(Font.font(18));
              text.setText(hasBomb ? "X" : "");
              text.setVisible(false);
  
              getChildren().addAll(border, text);
  
              setTranslateX(x * TILE_SIZE);
              setTranslateY(y * TILE_SIZE);
  
              setOnMouseClicked(e -> open());
          }
  
          public void open() {
              if (isOpen)
                  return;
  
              if (hasBomb) {
                 System.out.println("Game Over");
                 scene.setRoot(createContent());
                 return;
              }
  
              isOpen = true;
              text.setVisible(true);
              border.setFill(null);
  
              if (text.getText().isEmpty()) {
                  getNeighbors(this).forEach(Tile::open);
              }
          }
      }
  
      @Override
      public void start(Stage stage) throws Exception {
          scene = new Scene(createContent());
  
          stage.setScene(scene);
          stage.show();
      }
  
      public static void main(String[] args) {
          launch(args);
      }
  }
  