Darksaber2213

ConnectFour.java

Oct 7th, 2021
442
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 8.59 KB | None | 0 0
  1. package connectfour;
  2.  
  3. import javafx.application.Application;
  4. import javafx.scene.Scene;
  5. import javafx.scene.control.Label;
  6. import javafx.scene.layout.BorderPane;
  7. import javafx.scene.layout.GridPane;
  8. import javafx.scene.layout.Pane;
  9. import javafx.scene.paint.Color;
  10. import javafx.scene.shape.Ellipse;
  11. import javafx.stage.Stage;
  12.  
  13. /**
  14.  * A version of Connect Four for JavaFX.
  15.  *
  16.  * @since 2021-10-06
  17.  * @author Cameron Bennett | CIS 161 177
  18.  */
  19. public class ConnectFour extends Application {
  20.     // Initialize a 4-by-4 array of Cells.
  21.     private Cell[][] cells = new Cell[4][4];
  22.  
  23.     // Initialize a label for the game status.
  24.     private Label status = new Label();
  25.  
  26.     // Initialize a boolean value for holding whose turn it is.
  27.     private boolean turn;
  28.     // Initialize a boolean value for the game state.
  29.     private boolean gameOver = false;
  30.  
  31.     /**
  32.      * Gets the {@code Cell} at a specified {@code (x,y)} coordinate.
  33.      * @param x the x-coordinate.
  34.      * @param y the y-coordinate.
  35.      * @return the {@code Cell} at {@code (x,y)}.
  36.      */
  37.     public Cell getCellAt(int x, int y) { return this.cells[x][y]; }
  38.  
  39.     /**
  40.      * Sets the {@code Cell} at a specified {@code (x,y)} coordinate.
  41.      * @param cell the cell to set at {@code (x,y)}.
  42.      * @param x the x-coordinate.
  43.      * @param y the y-coordinate.
  44.      * @return the {@code Cell} that was set.
  45.      */
  46.     public Cell setCellAt(Cell cell, int x, int y) { return this.cells[x][y] = cell; }
  47.  
  48.     public Label getStatusMessage() { return this.status; }
  49.     public void setStatusMessage(String status) { this.getStatusMessage().setText(status); }
  50.  
  51.     /**
  52.      * Gets the name of the specified player.
  53.      * @return a {@code String} representing the name of the current player.
  54.      */
  55.     public String getPlayerName(boolean turn) { return turn ? "YELLOW" : "RED"; }
  56.  
  57.     /**
  58.      * Gets the color of the specified player.
  59.      * @return the {@code Color} of the specified player.
  60.      */
  61.     public Color getPlayerColor(boolean turn) { return turn ? Color.YELLOW : Color.RED; }
  62.  
  63.     /**
  64.      * Gets whose turn it currently is.
  65.      * @return the {@code boolean} value of whose turn it is.
  66.      */
  67.     public boolean getTurn() { return this.turn; }
  68.  
  69.     /**
  70.      * Sets whose turn it currently is and updates the status message.
  71.      */
  72.     public void setTurn(boolean turn) {
  73.         this.turn = turn;
  74.  
  75.         // Update the status message.
  76.         this.setStatusMessage(String.format("%s's turn.", getPlayerName(turn)));
  77.     }
  78.  
  79.     public boolean isGameOver() { return gameOver; }
  80.     public void setGameOver(boolean gameOver) { this.gameOver = gameOver; }
  81.  
  82.     public boolean checkWin(Color check) {
  83.         // Quick and dirty method.
  84.  
  85.         // Check columns.
  86.         for(int x = 0; x < 4; x++) {
  87.             if(
  88.                     this.getCellAt(x, 0).getColor() == check &&
  89.                     this.getCellAt(x, 1).getColor() == check &&
  90.                     this.getCellAt(x, 2).getColor() == check &&
  91.                     this.getCellAt(x, 3).getColor() == check
  92.             ) {
  93.                 return true;
  94.             }
  95.         }
  96.  
  97.         // Check rows.
  98.         for(int y = 0; y < 4; y++) {
  99.             if(
  100.                     this.getCellAt(0, y).getColor() == check &&
  101.                     this.getCellAt(1, y).getColor() == check &&
  102.                     this.getCellAt(2, y).getColor() == check &&
  103.                     this.getCellAt(3, y).getColor() == check
  104.             ) {
  105.                 return true;
  106.             }
  107.         }
  108.  
  109.         // Check major diagonal.
  110.         if(
  111.                 this.getCellAt(0, 0).getColor() == check &&
  112.                 this.getCellAt(1, 1).getColor() == check &&
  113.                 this.getCellAt(2, 2).getColor() == check &&
  114.                 this.getCellAt(3, 3).getColor() == check
  115.         ) {
  116.             return true;
  117.         }
  118.  
  119.         // Check minor diagonal.
  120.         return  this.getCellAt(0, 3).getColor() == check &&
  121.                 this.getCellAt(1, 2).getColor() == check &&
  122.                 this.getCellAt(2, 1).getColor() == check &&
  123.                 this.getCellAt(3, 0).getColor() == check;
  124.     }
  125.  
  126.     public boolean checkFull() {
  127.         // Another quick and dirty method.
  128.  
  129.         // Loop through all the Cells and check for an empty one.
  130.         for(int x = 0; x < 4; x++) {
  131.             for(int y = 0; y < 4; y++) {
  132.                 // Check if the Cell at the (x,y) coordinate is empty.
  133.                 if(!this.getCellAt(x, y).isFilled()) {
  134.                     return false;
  135.                 }
  136.             }
  137.         }
  138.  
  139.         // If the method reached this point, there are no empty Cells in the grid.
  140.         return true;
  141.     }
  142.  
  143.     @Override
  144.     public void start(Stage stage) {
  145.         // Set the starting player's turn.
  146.         this.setTurn(false);
  147.  
  148.         // Create a grid to hold the cells.
  149.         GridPane cellGrid = new GridPane();
  150.  
  151.         // Fill the grid with cells.
  152.         for(int x = 0; x < 4; x++) {
  153.             for(int y = 0; y < 4; y++) {
  154.                 cellGrid.add(this.setCellAt(new Cell(x, y), x, y), x, y);
  155.             }
  156.         }
  157.  
  158.         // Create a BorderPane to hold the grid.
  159.         BorderPane container = new BorderPane(cellGrid);
  160.         container.setBottom(this.getStatusMessage());
  161.  
  162.         // Create and show the main scene.
  163.         Scene main = new Scene(container);
  164.         stage.setTitle("Connect Four");
  165.         stage.setScene(main);
  166.         stage.show();
  167.     }
  168.  
  169.     public static void main(String[] args) { launch(); }
  170.  
  171.     /**
  172.      * A Cell class for Connect Four.
  173.      */
  174.     class Cell extends Pane {
  175.         // Initialize a Color for holding the fill color of the Cell.
  176.         private Color color;
  177.  
  178.         // Initialize two ints for holding the (x,y) coordinates of the Cell.
  179.         private final int x;
  180.         private final int y;
  181.  
  182.         /**
  183.          * Default Cell constructor.
  184.          */
  185.         public Cell(int x, int y) {
  186.             this.x = x;
  187.             this.y = y;
  188.  
  189.             // Set the border color & size of the Cell.
  190.             this.setStyle("-fx-border-color: black;");
  191.             this.setPrefSize(100, 100);
  192.  
  193.             // Attach a mouse click handler to the Cell to detect when a player clicks on a Cell.
  194.             this.setOnMouseClicked(e -> handleMouseClick());
  195.         }
  196.  
  197.         public Color getColor() { return color; }
  198.         public void setColor(Color color) { this.color = color; }
  199.  
  200.         public boolean isFilled() { return this.color != null; }
  201.         public void setFilled(Color fill) {
  202.             this.setColor(fill);
  203.  
  204.             // Create new ellipse.
  205.             Ellipse ellipse = new Ellipse(
  206.                     this.getWidth() / 2,
  207.                     this.getHeight() / 2,
  208.                     this.getWidth() / 2 - 10,
  209.                     this.getHeight() / 2 - 10
  210.             );
  211.  
  212.             // Bind center X and center Y properties.
  213.             ellipse.centerXProperty().bind(
  214.                     this.widthProperty().divide(2)
  215.             );
  216.  
  217.             ellipse.centerYProperty().bind(
  218.                     heightProperty().divide(2)
  219.             );
  220.  
  221.             // Bind height and width properties.
  222.             ellipse.radiusXProperty().bind(
  223.                     widthProperty().divide(2).subtract(10)
  224.             );
  225.  
  226.             ellipse.radiusYProperty().bind(
  227.                     heightProperty().divide(2).subtract(10)
  228.             );
  229.  
  230.             // Set color.
  231.             ellipse.setStroke(Color.BLACK);
  232.             ellipse.setFill(fill);
  233.  
  234.             // Attach ellipse to the cell.
  235.             this.getChildren().add(ellipse);
  236.         }
  237.  
  238.         /**
  239.          * Gets this Cell's x-coordinate.
  240.          * @return this Cell's x-coordinate.
  241.          */
  242.         public int getX() { return this.x; }
  243.  
  244.         /**
  245.          * Gets this Cell's y-coordinate.
  246.          * @return this Cell's y-coordinate.
  247.          */
  248.         public int getY() { return this.y; }
  249.  
  250.         /**
  251.          * Fills a cell with the current turn color and checks for a win condition.
  252.          */
  253.         public void activate() {
  254.             // Fill the Cell with the color of the current player.
  255.             boolean currentTurn = ConnectFour.this.getTurn();
  256.             Color currentColor = ConnectFour.this.getPlayerColor(currentTurn);
  257.             this.setFilled(currentColor);
  258.  
  259.             if(ConnectFour.this.checkWin(currentColor)) {
  260.                 // Update the game state.
  261.                 ConnectFour.this.setGameOver(true);
  262.  
  263.                 // Update the status message.
  264.                 ConnectFour.this.setStatusMessage(String.format("%s wins!", ConnectFour.this.getPlayerName(currentTurn)));
  265.             } else if(ConnectFour.this.checkFull()) {
  266.                 // Update the game state.
  267.                 ConnectFour.this.setGameOver(true);
  268.  
  269.                 // Update the status message.
  270.                 ConnectFour.this.setStatusMessage("There are no more empty spaces! Game over.");
  271.             } else {
  272.                 // Update the turn order.
  273.                 ConnectFour.this.setTurn(!ConnectFour.this.getTurn());
  274.             }
  275.         }
  276.  
  277.         /**
  278.          * Searches upwards for an empty space to fill a Cell at.
  279.          * @param startingX the x-coordinate to start at.
  280.          */
  281.         public void placeAtColumn(int startingX) {
  282.             // Loop through the Cells from the bottom up, searching for an empty Cell.
  283.             for(int currentY = 3; currentY >= 0; currentY--) {
  284.                 // Get the Cell at the current y-value.
  285.                 Cell currentCell = ConnectFour.this.getCellAt(startingX, currentY);
  286.  
  287.                 // Check if the Cell is not filled.
  288.                 if(!currentCell.isFilled()) {
  289.                     // Fill the Cell.
  290.                     currentCell.activate();
  291.                     return;
  292.                 }
  293.             }
  294.  
  295.             // If the method reached this point, there are no empty Cells in the column.
  296.             ConnectFour.this.setStatusMessage("You can't do that.");
  297.         }
  298.  
  299.         /**
  300.          * Method for handling when a player clicks on a Cell.
  301.          */
  302.         private void handleMouseClick() {
  303.             // Check if the game is over before trying to fill a Cell.
  304.             if(!ConnectFour.this.isGameOver())
  305.                 placeAtColumn(this.getX());
  306.         }
  307.     }
  308. }
Add Comment
Please, Sign In to add comment