I tried to recreate Connect Four, and I succeeded. But I wanted to give the player an indication of where the winning four discs were, by switching the color every so often. I am new to threads and the concept of time in programming.
I also succeeded in giving the user this indication, but after I close the application, the console still gives output, also when I use setOnCloseRequest.
A few other questions:
1: for colors I used html names, is it better to use a hex triplet or no preference.
2: To stop the grid and other elements from hugging the left side of the screen, I added a border with the same color as the background, is there a better way of doing this?
3: I did not create a method for translating the keycode to an integer but instead created in the init function. I did this because I don't know how to pass the keyevent. How to do this?
Here is the code:
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.layout.GridPane; import javafx.scene.layout.HBox; import javafx.scene.layout.VBox; import javafx.stage.Stage; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; public class FourInARow extends Application { GridPane boardGrid = new GridPane(); Label[][] labels = new Label[7][7]; Label statusLabel = new Label(); int[][] cell = new int[7][6]; int player = 0; int won = 0; String baseStyle = "-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: "; ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); public static void main(String[] args){launch(args);} private void init(Stage window){ createLabels(); startGame(); Label above = new Label("Try to connect four discs in a row!"); above.setStyle("-fx-font-size: 30; -fx-alignment: center; -fx-min-width: 600"); boardGrid.setStyle("-fx-background-color: silver;-fx-border-color: #F4F4F4;-fx-border-width: 0 20 0 20"); Button newGame = new Button("New Game"); newGame.setStyle("-fx-min-width: 100;-fx-font-size:20"); newGame.setOnAction(e -> startGame()); statusLabel.setStyle("-fx-font-size: 30;-fx-alignment: center; -fx-min-width: 300;"); HBox below = new HBox(); below.setStyle("-fx-border-width: 0 0 0 20;-fx-border-color: #F4F4F4"); below.getChildren().addAll(newGame, statusLabel); VBox layout = new VBox(); layout.getChildren().addAll(above, boardGrid, below); Scene scene = new Scene(layout, 600, 620); scene.setOnKeyPressed(e -> { if (won == 0) { try { String k = e.getCode().toString(); int l = k.length(); int col = Integer.parseInt(k.substring(l - 1, l)) - 1; placeDisc(col, player); switchPlayer(); updateScreen(); } catch (NumberFormatException | ArrayIndexOutOfBoundsException error) { System.out.println("error: " + error); } } }); window.setScene(scene); window.setTitle("Connect Four"); threadThing(); } private void threadThing() { service.scheduleAtFixedRate(() -> { try { wonStyle(); } catch (InterruptedException e) { e.printStackTrace(); } }, 0, 1, TimeUnit.SECONDS); } private void startGame() { cell = new int[7][6]; won = player = 0; statusLabel.setText(""); updateScreen(); } private void updateScreen() { for (int i = 0; i < 7; i++) { for (int j = 0; j < 6; j++) { labels[i][j].setStyle(baseStyle + addStyle(cell[i][j])); } labels[i][6].setText(Integer.toString(i+1)); labels[i][6].setStyle("-fx-alignment: center;-fx-min-width: 80;-fx-background-color: #F4F4F4;-fx-font-size: 30;"); } switch(won) { case 1: statusLabel.setText("Blue has won!");break; case 2: statusLabel.setText("Yellow has won!");break; } } private String addStyle(int cell) { String style = "silver"; switch(cell){ case 1: style = "blue"; break; case 2: style = "yellow"; break; case 3: style = "darkblue"; break; case 4: style = "gold;"; break; } return style; } private void placeDisc(int col, int player) { for (int i = 5; i >= 0 ; i--) { if(cell[col][i] == 0){ cell[col][i] = 1; if(player == 1) cell[col][i] = 2; break; }else{ if(i==0) switchPlayer(); } } checkWon(); } private void checkWon() { for (int i = 0; i < 7; i++) { for (int j = 0; j < 6; j++) { if (cell[i][j] != 0) { try { if (cell[i][j] == cell[i][j + 1] && cell[i][j] == cell[i][j + 2] && cell[i][j] == cell[i][j + 3]) { won = cell[i][j]; cell[i][j] = cell[i][j + 1] = cell[i][j + 2] = cell[i][j + 3] = cell[i][j] + 2; } }catch(ArrayIndexOutOfBoundsException error) {} try { if (cell[i][j] == cell[i + 1][j] && cell[i][j] == cell[i + 2][j] && cell[i][j] == cell[i + 3][j]) { System.out.println("Horizontal win"); won = cell[i][j]; cell[i][j] = cell[i + 1][j] = cell[i + 2][j] = cell[i + 3][j] = cell[i][j] + 2; } }catch(ArrayIndexOutOfBoundsException error) {} try { if (cell[i][j] == cell[i + 1][j + 1] && cell[i][j] == cell[i + 2][j + 2] && cell[i][j] == cell[i + 3][j + 3]) { won = cell[i][j]; cell[i][j] = cell[i + 1][j + 1] = cell[i + 2][j + 2] = cell[i + 3][j + 3] = cell[i][j] + 2; } }catch(ArrayIndexOutOfBoundsException error) {} try { if (cell[i][j] == cell [i + 1][j - 1] && cell[i][j] == cell[i + 2][j - 2] && cell[i][j] == cell[i + 3][j - 3]) { won = cell[i][j]; cell[i][j] = cell[i + 1][j - 1] = cell[i + 2][j - 2] = cell[i + 3][j - 3] = cell[i][j] + 2; } }catch(ArrayIndexOutOfBoundsException error) {} } } } } private void switchPlayer() { if(player == 0) player = 2; player--; } private void createLabels() { for (int i = 0; i < 7; i++) { for (int j = 0; j < 7; j++) { labels[i][j] = new Label(); boardGrid.add(labels[i][j], i, j); } } } private void wonStyle() throws InterruptedException { System.out.println("Test"); boolean run = false; for (int i = 0; i < 7; i++) { for (int j = 0; j < 6; j++) { if(cell[i][j] > 2 && !run){ Thread.sleep(500); addStyleFlicker(); run = true; } } } } private void addStyleFlicker() throws InterruptedException { String[] styleOne = {"-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: blue;", "-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: darkblue;"}; String[] styleTwo = {"-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: yellow;", "-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: gold;"}; for (int i = 0; i < 7; i++) { for (int j = 0; j < 6; j++) { if(cell[i][j] == 3){ labels[i][j].setStyle(styleOne[0]); }else if(cell[i][j] == 4){ labels[i][j].setStyle(styleTwo[0]); } } } Thread.sleep(500); for (int i = 0; i < 7; i++) { for (int j = 0; j < 6; j++) { if(cell[i][j] == 3){ labels[i][j].setStyle(styleOne[1]); }else if(cell[i][j] == 4) { labels[i][j].setStyle(styleTwo[1]); } } } } @Override public void start(Stage window) throws Exception { init(window); window.show(); } }