├── 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 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
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 | //}
--------------------------------------------------------------------------------