├── README.md ├── Screenshots ├── GameBoard.JPG ├── ResultPage.JPG └── WelcomePage.JPG ├── module-info.java └── src ├── TicTacToeJavaFX ├── GameBoard.fxml ├── GameBoardController.java ├── GameResult.fxml ├── GameResultController.java ├── Main.java ├── Utils.java ├── WelcomeScreen.fxml └── WelcomeScreenController.java └── module-info.java /README.md: -------------------------------------------------------------------------------- 1 | # javaFX_tic_tac_toe 2 | This is a basic mini project on TicTacToe Game designed using JavaFX. 3 | 4 | This is a easy project to start with javaFX GUI programming. 5 | 6 | In this game, currently only Player vs Player mode is available. 7 | However anyone interested person can implement Player vs Computer mode also. 8 | 9 | IDE used : IntelliJ IDEA Community Edition 10 | 11 | Thanks for reading this and Enjoy Coding ♥!!!!! 12 | -------------------------------------------------------------------------------- /Screenshots/GameBoard.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akgarg0472/JavaFX_TicTacToe/ad5c1947aa68eaeb2f2114822f495164d6522490/Screenshots/GameBoard.JPG -------------------------------------------------------------------------------- /Screenshots/ResultPage.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akgarg0472/JavaFX_TicTacToe/ad5c1947aa68eaeb2f2114822f495164d6522490/Screenshots/ResultPage.JPG -------------------------------------------------------------------------------- /Screenshots/WelcomePage.JPG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/akgarg0472/JavaFX_TicTacToe/ad5c1947aa68eaeb2f2114822f495164d6522490/Screenshots/WelcomePage.JPG -------------------------------------------------------------------------------- /module-info.java: -------------------------------------------------------------------------------- 1 | module RuralBankingManagement { 2 | 3 | requires javafx.fxml; 4 | requires javafx.controls; 5 | 6 | opens com.akgarg.bankingsystem; 7 | } -------------------------------------------------------------------------------- /src/TicTacToeJavaFX/GameBoard.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 |
6 | 7 | 8 |
26 | 27 | 28 | 30 | 31 |
-------------------------------------------------------------------------------- /src/TicTacToeJavaFX/GameBoardController.java: -------------------------------------------------------------------------------- 1 | package TicTacToeJavaFX; 2 | 3 | import javafx.fxml.FXML; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Scene; 6 | import javafx.scene.control.Button; 7 | import javafx.scene.paint.Paint; 8 | import javafx.scene.text.Font; 9 | import javafx.stage.Stage; 10 | 11 | import java.io.IOException; 12 | import java.util.Objects; 13 | 14 | @SuppressWarnings({"UnusedDeclaration", "SameParameterValue"}) 15 | public class GameBoardController { 16 | 17 | private String playerOneName, playerTwoName; 18 | private String playerOneSymbol; 19 | private String playerTwoSymbol; 20 | private String playerOneColor, playerTwoColor; 21 | private int turnsCount = 0; 22 | 23 | @FXML 24 | private Button btn1; 25 | @FXML 26 | private Button btn2; 27 | @FXML 28 | private Button btn3; 29 | @FXML 30 | private Button btn4; 31 | @FXML 32 | private Button btn5; 33 | @FXML 34 | private Button btn6; 35 | @FXML 36 | private Button btn7; 37 | @FXML 38 | private Button btn8; 39 | @FXML 40 | private Button btn9; 41 | 42 | public void initialize() { 43 | this.setButtonDimensions(); 44 | this.setButtonsFont(Main.BUTTON_DEFAULT_FONT_SIZE); 45 | 46 | this.playerOneName = WelcomeScreenController.getPlayerOneName(); 47 | this.playerTwoName = WelcomeScreenController.getPlayerTwoName(); 48 | 49 | this.playerOneSymbol = WelcomeScreenController.getPlayerOneSymbol(); 50 | this.playerTwoSymbol = WelcomeScreenController.getPlayerTwoSymbol(); 51 | 52 | this.playerOneColor = WelcomeScreenController.getPlayerOneColor(); 53 | this.playerTwoColor = WelcomeScreenController.getPlayerTwoColor(); 54 | 55 | this.buttonClickHandler(btn1, btn2, btn3, btn4); 56 | this.buttonClickHandler(btn5, btn6, btn7, btn8); 57 | this.buttonClickHandlerTwo(btn9); 58 | } 59 | 60 | private void buttonClickHandler( 61 | final Button btn1, 62 | final Button btn2, 63 | final Button btn3, 64 | final Button btn4 65 | ) { 66 | this.clickHandler(btn1, btn2); 67 | this.clickHandler(btn3, btn4); 68 | } 69 | 70 | private void clickHandler( 71 | final Button btn1, 72 | final Button btn2 73 | ) { 74 | this.buttonClickHandlerTwo(btn1); 75 | this.buttonClickHandlerTwo(btn2); 76 | } 77 | 78 | private void buttonClickHandlerTwo(final Button button) { 79 | button.setOnMouseClicked(event -> { 80 | if (turnsCount % 2 == 0 && button.getText().equals("")) { 81 | turnsCount++; 82 | button.setText(playerOneSymbol); 83 | button.setTextFill(Paint.valueOf(playerOneColor)); 84 | } else if (turnsCount % 2 != 0 && button.getText().equals("")) { 85 | turnsCount++; 86 | button.setText(playerTwoSymbol); 87 | button.setTextFill(Paint.valueOf(playerTwoColor)); 88 | } 89 | resultTest(Main.getPrimaryStage(), button.getText()); 90 | }); 91 | } 92 | 93 | // this method set the font size of the text which will be visible on the button (either 'O' or 'X') 94 | private void setButtonsFont(final double font) { 95 | Font font1 = new Font(font); 96 | btn1.setFont(font1); 97 | btn2.setFont(font1); 98 | btn3.setFont(font1); 99 | btn4.setFont(font1); 100 | btn5.setFont(font1); 101 | btn6.setFont(font1); 102 | btn7.setFont(font1); 103 | btn8.setFont(font1); 104 | btn9.setFont(font1); 105 | } 106 | 107 | // this method set the width and height of the buttons which are going to be visible on the game board 108 | private void setButtonDimensions() { 109 | final double buttonWidth = Main.STAGE_DEFAULT_WIDTH / 3; 110 | final double buttonHeight = Main.STAGE_DEFAULT_HEIGHT / 3; 111 | 112 | btn1.setPrefSize(buttonWidth, buttonHeight); 113 | btn2.setPrefSize(buttonWidth, buttonHeight); 114 | btn3.setPrefSize(buttonWidth, buttonHeight); 115 | btn4.setPrefSize(buttonWidth, buttonHeight); 116 | btn5.setPrefSize(buttonWidth, buttonHeight); 117 | btn6.setPrefSize(buttonWidth, buttonHeight); 118 | btn7.setPrefSize(buttonWidth, buttonHeight); 119 | btn8.setPrefSize(buttonWidth, buttonHeight); 120 | btn9.setPrefSize(buttonWidth, buttonHeight); 121 | } 122 | 123 | // this method check the all possible conditions of winning of a player and 124 | // also check for draw case when all blocks are filled with the data provided by the players playing game 125 | private void resultTest(final Stage primaryStage, final String buttonText) { 126 | final String buttonOneText = btn1.getText(); 127 | final String buttonTwoText = btn2.getText(); 128 | final String buttonThreeText = btn3.getText(); 129 | 130 | if (buttonOneText.equals(buttonTwoText) && buttonTwoText.equals(buttonThreeText) && !buttonOneText.equals("")) { 131 | gameOverDialog(primaryStage, buttonText); 132 | } else { 133 | final String buttonSevenText = btn7.getText(); 134 | final String buttonFourText = btn4.getText(); 135 | 136 | if (buttonOneText.equals(buttonFourText) && buttonFourText.equals(buttonSevenText) && !buttonOneText.equals("")) { 137 | gameOverDialog(primaryStage, buttonText); 138 | } else { 139 | final String buttonSixText = btn6.getText(); 140 | final String buttonNineText = btn9.getText(); 141 | 142 | if (buttonThreeText.equals(buttonSixText) && buttonSixText.equals(buttonNineText) && !buttonThreeText.equals("")) { 143 | gameOverDialog(primaryStage, buttonText); 144 | } else { 145 | final String buttonEightText = btn8.getText(); 146 | 147 | if (buttonSevenText.equals(buttonEightText) && buttonEightText.equals(buttonNineText) && !buttonSevenText.equals("")) { 148 | gameOverDialog(primaryStage, buttonText); 149 | } else { 150 | final String buttonFiveText = btn5.getText(); 151 | 152 | if (buttonThreeText.equals(buttonFiveText) && buttonFiveText.equals(buttonSevenText) && !buttonThreeText.equals("")) { 153 | gameOverDialog(primaryStage, buttonText); 154 | } else if (buttonOneText.equals(buttonFiveText) && buttonFiveText.equals(buttonNineText) && !buttonOneText.equals("")) { 155 | gameOverDialog(primaryStage, buttonText); 156 | } else if (buttonTwoText.equals(buttonFiveText) && buttonFiveText.equals(buttonEightText) && !buttonTwoText.equals("")) { 157 | gameOverDialog(primaryStage, buttonText); 158 | } else if (buttonFourText.equals(buttonFiveText) && buttonFiveText.equals(buttonSixText) && !buttonFourText.equals("")) { 159 | gameOverDialog(primaryStage, buttonText); 160 | } else { 161 | if (!buttonOneText.equals("") && !buttonTwoText.equals("") && !buttonThreeText.equals("") && !buttonFourText.equals("") && !buttonFiveText.equals("") && !buttonSixText.equals("") && !buttonSevenText.equals("") && !buttonEightText.equals("") && !buttonNineText.equals("")) { 162 | gameOverDialog(primaryStage, "Draw"); 163 | } 164 | } 165 | } 166 | } 167 | } 168 | } 169 | } 170 | 171 | // this method is used to display the final result of the game 172 | // this method will be called only when either any of player wins the game 173 | // or game get draw. In other cases, this method will not be called by resultTest method 174 | private void gameOverDialog(final Stage primaryStage, final String buttonText) { 175 | final FXMLLoader fxmlLoader = new FXMLLoader(); 176 | fxmlLoader.setLocation(getClass().getResource("GameResult.fxml")); 177 | GameResultController gameResultController; 178 | 179 | try { 180 | primaryStage.setScene(new Scene(fxmlLoader.load(), Main.STAGE_DEFAULT_WIDTH, Main.STAGE_DEFAULT_HEIGHT)); 181 | gameResultController = fxmlLoader.getController(); 182 | Objects.requireNonNull(gameResultController); 183 | 184 | if (buttonText.equals("Draw")) { 185 | gameResultController.setGameResultText("Draw", ""); 186 | } else { 187 | if (playerOneSymbol.equals(buttonText)) { 188 | gameResultController.setGameResultText("win", playerOneName); 189 | } else { 190 | gameResultController.setGameResultText("win", playerTwoName); 191 | } 192 | } 193 | } catch (IOException e) { 194 | e.printStackTrace(); 195 | } 196 | } 197 | 198 | } -------------------------------------------------------------------------------- /src/TicTacToeJavaFX/GameResult.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | 42 |
43 | -------------------------------------------------------------------------------- /src/TicTacToeJavaFX/GameResultController.java: -------------------------------------------------------------------------------- 1 | package TicTacToeJavaFX; 2 | 3 | import javafx.event.EventHandler; 4 | import javafx.fxml.FXML; 5 | import javafx.fxml.FXMLLoader; 6 | import javafx.scene.Scene; 7 | import javafx.scene.control.Button; 8 | import javafx.scene.control.Label; 9 | import javafx.scene.input.MouseEvent; 10 | import javafx.scene.text.Font; 11 | import javafx.scene.text.FontWeight; 12 | 13 | import java.io.IOException; 14 | import java.net.URL; 15 | import java.util.Objects; 16 | 17 | @SuppressWarnings("UnusedDeclaration") 18 | public class GameResultController { 19 | 20 | @FXML 21 | private Label congratsLabel; 22 | @FXML 23 | private Label winnerName; 24 | @FXML 25 | private Label gameOverLabel; 26 | @FXML 27 | private Label complementLabel; 28 | @FXML 29 | private Button playAgainButton; 30 | @FXML 31 | private Button exitGameButton; 32 | 33 | public void initialize() { 34 | this.playAgainButton.setOnMouseClicked(new EventHandler() { 35 | @Override 36 | public void handle(MouseEvent event) { 37 | try { 38 | final URL welcomeScreenResource = getClass().getResource("WelcomeScreen.fxml"); 39 | Objects.requireNonNull(welcomeScreenResource, "Error loading game welcome screen"); 40 | 41 | Main.getPrimaryStage().setScene(new Scene( 42 | FXMLLoader.load(welcomeScreenResource), 43 | Main.STAGE_DEFAULT_WIDTH, 44 | Main.STAGE_DEFAULT_HEIGHT 45 | )); 46 | } catch (IOException e) { 47 | e.printStackTrace(); 48 | } 49 | } 50 | }); 51 | 52 | exitGameButton.setOnMouseClicked(event -> Main.getPrimaryStage().close()); 53 | } 54 | 55 | // this method dynamically update the content of the final result scene of the game according to the game result 56 | void setGameResultText(final String gameResultText1, final String winner) { 57 | if (gameResultText1.equals("Draw")) { 58 | gameOverLabel.setFont(Font.font("Algerian", FontWeight.BOLD, 45)); 59 | congratsLabel.setFont(new Font(35)); 60 | winnerName.setFont(new Font(30)); 61 | congratsLabel.setVisible(false); 62 | complementLabel.setVisible(false); 63 | winnerName.setText("Game Draw"); 64 | } else { 65 | gameOverLabel.setFont(Font.font("Algerian", FontWeight.BOLD, 45)); 66 | congratsLabel.setFont(new Font(35)); 67 | winnerName.setFont(new Font(25)); 68 | congratsLabel.setVisible(true); 69 | complementLabel.setVisible(true); 70 | 71 | if (winner.length() > 30) { 72 | winnerName.setText(winner.substring(0, 30)); 73 | } else { 74 | winnerName.setText(winner); 75 | } 76 | 77 | winnerName.setWrapText(true); 78 | } 79 | } 80 | 81 | } -------------------------------------------------------------------------------- /src/TicTacToeJavaFX/Main.java: -------------------------------------------------------------------------------- 1 | package TicTacToeJavaFX; 2 | 3 | import javafx.application.Application; 4 | import javafx.fxml.FXMLLoader; 5 | import javafx.scene.Parent; 6 | import javafx.scene.Scene; 7 | import javafx.stage.Stage; 8 | 9 | import java.net.URL; 10 | import java.util.Objects; 11 | 12 | public class Main extends Application { 13 | 14 | static final double STAGE_DEFAULT_WIDTH = 350; 15 | static final double STAGE_DEFAULT_HEIGHT = 350; 16 | static final int BUTTON_DEFAULT_FONT_SIZE = 40; 17 | 18 | private static Stage stage; 19 | 20 | // method used to retrieve the primaryStage 21 | static Stage getPrimaryStage() { 22 | return stage; 23 | } 24 | 25 | public static void main(String[] args) { 26 | launch(args); 27 | } 28 | 29 | @Override 30 | public void start(Stage primaryStage) throws Exception { 31 | stage = primaryStage; 32 | final URL mainResource = getClass().getResource("WelcomeScreen.fxml"); 33 | Objects.requireNonNull(mainResource, "Error in initializing game board. System error occurred."); 34 | final Parent screen = FXMLLoader.load(mainResource); 35 | primaryStage.setTitle("Tic Tac Toe"); 36 | final Scene scene = new Scene(screen, STAGE_DEFAULT_WIDTH, STAGE_DEFAULT_HEIGHT); 37 | primaryStage.setScene(scene); 38 | primaryStage.setResizable(false); 39 | primaryStage.show(); 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/TicTacToeJavaFX/Utils.java: -------------------------------------------------------------------------------- 1 | package TicTacToeJavaFX; 2 | 3 | /** 4 | * @author Akhilesh Garg 5 | * @since 08-03-2023 6 | */ 7 | final class Utils { 8 | 9 | private Utils() { 10 | throw new UnsupportedOperationException(); 11 | } 12 | 13 | static boolean isStringValid(final String str) { 14 | return str != null && !str.trim().isEmpty(); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/TicTacToeJavaFX/WelcomeScreen.fxml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 9 | 10 | 11 | 12 | 14 | 15 | 17 | 18 | 19 | 20 | 22 | 23 | 25 | 26 | 27 | 28 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /src/TicTacToeJavaFX/WelcomeScreenController.java: -------------------------------------------------------------------------------- 1 | package TicTacToeJavaFX; 2 | 3 | import javafx.event.ActionEvent; 4 | import javafx.event.EventHandler; 5 | import javafx.fxml.FXML; 6 | import javafx.fxml.FXMLLoader; 7 | import javafx.scene.Parent; 8 | import javafx.scene.Scene; 9 | import javafx.scene.control.*; 10 | import javafx.scene.paint.Color; 11 | import javafx.scene.text.Font; 12 | 13 | import java.io.IOException; 14 | import java.net.URL; 15 | import java.util.Objects; 16 | 17 | @SuppressWarnings("UnusedDeclaration") 18 | public class WelcomeScreenController { 19 | 20 | private static final String PLAYER_ONE_DEFAULT_NAME = "Player 1"; 21 | private static final String PLAYER_TWO_DEFAULT_NAME = "Player 2"; 22 | private static final Font font = new Font(14); 23 | 24 | private static String playerOneName; 25 | private static String playerTwoName; 26 | private static String playerOneSymbol; 27 | private static String playerTwoSymbol; 28 | private static String playerOneColor; 29 | private static String playerTwoColor; 30 | 31 | @FXML 32 | private Label playerOneNameLabel; 33 | @FXML 34 | private TextField playerOneNameField; 35 | @FXML 36 | private Label playerTwoNameLabel; 37 | @FXML 38 | private TextField playerTwoNameField; 39 | @FXML 40 | private Label playerOneSymbolLabel; 41 | @FXML 42 | private RadioButton crossSymbol; 43 | @FXML 44 | private RadioButton zeroSymbol; 45 | @FXML 46 | private Label playerOneColorLabel; 47 | @FXML 48 | private ColorPicker playerOneColorPicker; 49 | @FXML 50 | private Label playerTwoColorLabel; 51 | @FXML 52 | private ColorPicker playerTwoColorPicker; 53 | @FXML 54 | private Button startGameButton; 55 | 56 | static String getPlayerOneName() { 57 | return playerOneName; 58 | } 59 | 60 | static String getPlayerTwoName() { 61 | return playerTwoName; 62 | } 63 | 64 | static String getPlayerOneSymbol() { 65 | return playerOneSymbol; 66 | } 67 | 68 | static String getPlayerTwoSymbol() { 69 | return playerTwoSymbol; 70 | } 71 | 72 | static String getPlayerOneColor() { 73 | return playerOneColor; 74 | } 75 | 76 | static String getPlayerTwoColor() { 77 | return playerTwoColor; 78 | } 79 | 80 | public void initialize() { 81 | final ToggleGroup toggleGroup = new ToggleGroup(); 82 | crossSymbol.setToggleGroup(toggleGroup); 83 | zeroSymbol.setToggleGroup(toggleGroup); 84 | 85 | playerOneName = PLAYER_ONE_DEFAULT_NAME; 86 | playerTwoName = PLAYER_TWO_DEFAULT_NAME; 87 | 88 | playerOneNameLabel.setFont(font); 89 | playerTwoNameLabel.setFont(font); 90 | playerOneSymbolLabel.setFont(font); 91 | playerOneColorLabel.setFont(font); 92 | playerTwoColorLabel.setFont(font); 93 | 94 | playerOneColorPicker.setValue(Color.BLACK); 95 | playerTwoColorPicker.setValue(Color.BLACK); 96 | 97 | this.startGameButton.setOnAction(new EventHandler() { 98 | @Override 99 | public void handle(ActionEvent actionEvent) { 100 | final String _playerOneName = playerOneNameField.getText(); 101 | if (Utils.isStringValid(_playerOneName)) { 102 | playerOneName = _playerOneName; 103 | } 104 | 105 | final String _playerTwoName = playerTwoNameField.getText(); 106 | if (Utils.isStringValid(_playerTwoName)) { 107 | playerTwoName = _playerTwoName; 108 | } 109 | 110 | if (crossSymbol.isSelected()) { 111 | playerOneSymbol = "X"; 112 | playerTwoSymbol = "O"; 113 | } else { 114 | playerOneSymbol = "O"; 115 | playerTwoSymbol = "X"; 116 | } 117 | 118 | playerOneColor = playerOneColorPicker.getValue().toString(); 119 | playerTwoColor = playerTwoColorPicker.getValue().toString(); 120 | 121 | try { 122 | final URL gameBoardResource = getClass().getResource("GameBoard.fxml"); 123 | Objects.requireNonNull(gameBoardResource, "Error loading game board screen"); 124 | final Parent root = FXMLLoader.load(gameBoardResource); 125 | final Scene scene = new Scene(root, Main.STAGE_DEFAULT_WIDTH, Main.STAGE_DEFAULT_HEIGHT); 126 | Main.getPrimaryStage().setScene(scene); 127 | } catch (IOException e) { 128 | e.printStackTrace(); 129 | } 130 | } 131 | }); 132 | } 133 | 134 | } -------------------------------------------------------------------------------- /src/module-info.java: -------------------------------------------------------------------------------- 1 | //module SampleJavaFX { 2 | // requires jfxrt; 3 | // requires rt; 4 | // 5 | // opens TicTacToeJavaFX; 6 | //} --------------------------------------------------------------------------------