Instructions
Requirements and Specifications
Source Code
import java.util.Random;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.control.TextField;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.input.KeyCode;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.StackPane;
import javafx.scene.text.Font;
import javafx.scene.text.FontWeight;
import javafx.stage.Stage;
/**
* Jordle class.
*/
public class Jordle extends Application {
/**
* This variable stores all textfields of the grid.
*/
private TextField[][] fields;
/**
* Variable to hold the current row being used in grid.
*/
private int row;
/**
* Variable to hold the current column being used in grid.
*/
private int col;
/**
* Variable to hold the current word being guessed.
*/
private String word;
/**
* Variable to know if the game ended or not.
*/
private boolean gameEnded;
/**
* GridPane object that contains all TextFields.
*/
private GridPane gridPane;
/**
* Restart game button.
*/
private Button restartBtn;
/**
* Instructions button.
*/
private Button instructionsBtn;
/**
* Label to display info.
*/
private Label infoLabel;
/**
* Label to display title of game.
*/
private Label titleLabel;
/**
* StackPane that contains the rest of components.
*/
private StackPane mainPane;
/**
* Method to pick a random word from the list of words.
* @return
*/
public String choseWord() {
// Create Random object
Random rnd = new Random();
// Pick one random word
int index = rnd.nextInt(Words.list.size());
// Return
return Words.list.get(index);
}
/**
* Method to display info to user when s/he press enters without.
* filling the row
*/
public void displayMustFillRowAlert() {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Error");
alert.setHeaderText("Error");
alert.setContentText("Please enter a 5-letter word");
alert.showAndWait();
}
/**
* Given a row id, check if it is filled with a word.
* @param rowId Index of row
* @return boolean
*/
public boolean isRowFilled(int rowId) {
// If the current row is filled, check for correct, incorrect letters
boolean isFilled = true;
for (int coli = 0; coli < 5; coli++) {
if (fields[row][coli].getText().isEmpty()) {
isFilled = false;
break;
}
}
return isFilled;
}
/**
* Method to clear all words from grid.
*/
public void clearGrid() {
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 5; j++) {
// Clear background color
fields[i][j].setStyle("");
}
}
gridPane.requestFocus();
}
/**
* The following method creates a grid.
* This method will create a grid of 6x5 filled with TextField objects
* @return GridPane object
*/
public GridPane createGrid() {
fields = new TextField[6][5];
GridPane grid = new GridPane();
grid.setAlignment(Pos.CENTER);
// Add the 6x5 textfields
for (int i = 0; i < 6; i++) {
for (int j = 0; j < 5; j++) {
TextField field = new TextField() {
@Override
public void replaceText(int start, int end, String text) {
super.replaceText(start, end, text.toUpperCase());
}
};
field.setFont(Font.font("Verdana", FontWeight.BOLD, 25));
field.setPrefWidth(50);
field.setPrefHeight(50);
field.setEditable(false);
fields[i][j] = field;
grid.add(fields[i][j], j, i, 1, 1);
}
}
return grid;
}
/**
* JavaFX required method.
*/
@Override
public void start(Stage primaryStage) throws Exception {
// Create Grid
gridPane = createGrid();
// Create the info label, the restart and instructions button
titleLabel = new Label("Jordle");
infoLabel = new Label("Try guessing a word!");
restartBtn = new Button("Restart");
instructionsBtn = new Button("Instructions");
mainPane = new StackPane();
// Add events to buttons
instructionsBtn.setOnAction(new EventHandler() {
/**
* Event method for the instructions buttons.
* @param event Event object
*/
@Override
public void handle(ActionEvent event) {
Alert alert = new Alert(AlertType.INFORMATION);
alert.setTitle("Instructions");
alert.setHeaderText("Instructions");
alert.setContentText("Welcome to Jordle! Try guessing some words!\n"
+ "You have to guess a 5-letters word.\n\n"
+ "Enter the letters of the word and press enter.\n"
+ "All letters in the correct position will be coloured green\n"
+ "The letters present in the word but at incorrect position will be coloured yellow\n"
+ "All other letters (not in word) are coloured gray\n\n"
+ "You only have 6 attemps");
alert.showAndWait();
}
});
restartBtn.setOnAction(new EventHandler() {
/**
* Event handler for restart Button.
* @param event Event object
*/
@Override
public void handle(ActionEvent event) {
// Pick a new word
word = choseWord();
row = 0;
col = 0;
gameEnded = false;
infoLabel.setText("Try guessing a word!");
// Clear all text fields
clearGrid();
}
});
mainPane.getChildren().add(gridPane);
Scene scene = new Scene(mainPane, 500, 500);
// Handle the inputs here
// Start game
// Pick random word
gameEnded = false;
word = choseWord();
row = 0;
col = 0;
// This one uses a lambda function
scene.addEventFilter(KeyEvent.KEY_PRESSED, event -> {
if (gameEnded) {
return;
}
// Check that the key is in the alphabet
if (event.getCode().isLetterKey()) {
if (row < 6 && col < 5 && fields[row][col].getText().isEmpty()) {
fields[row][col].setText(event.getCode().toString());
col++;
}
} else if (event.getCode().equals(KeyCode.ENTER)) {
if (row > 5) {
return;
}
// If the current row is filled, check for correct, incorrect letters
if (isRowFilled(row)) {
// Get word from filled fields
String inputWord = "";
for (int coli = 0; coli < 5; coli++) {
inputWord += fields[row][coli].getText();
}
// Convert to lowercase
inputWord = inputWord.toLowerCase();
// Now, compare words
int matches = 0;
for (int i = 0; i < 5; i++) {
char real = word.charAt(i);
char input = inputWord.charAt(i);
if (real == input) {
// Set field to green
matches++;
fields[row][i].setStyle("-fx-background-color: green;");
} else {
// if the letter is in the word, set background to yellow, if not, set to gray
if (word.indexOf(input) >= 0) {
fields[row][i].setStyle("-fx-background-color: yellow;");
} else {
fields[row][i].setStyle("-fx-background-color: darkgray;");
}
}
}
if (matches == 5) {
// all chars matched, user won
infoLabel.setText("Congratulations! You've guessed the word!");
gameEnded = true;
} else {
row++;
col = 0;
if (row > 5) { // no more guessings left
infoLabel.setText("Game over. The word was " + word + ".");
gameEnded = true;
}
}
} else {
displayMustFillRowAlert();
}
} else if (event.getCode().equals(KeyCode.BACK_SPACE)) {
if (row > 5) {
return;
}
// Find last filled field
int lastCol = -1;
; for (int coli = 0; coli < 5; coli++) {
if (!fields[row][coli].getText().isEmpty()) {
lastCol = coli;
}
}
if (lastCol != -1) {
fields[row][lastCol].setText("");
col = lastCol--;
if (col < 0) {
col = 0;
}
}
}
});
titleLabel.setAlignment(Pos.TOP_CENTER);
titleLabel.setFont(Font.font("Verdana", FontWeight.BOLD, 25));
infoLabel.setAlignment(Pos.BOTTOM_LEFT);
mainPane.getChildren().add(titleLabel);
StackPane.setAlignment(titleLabel, Pos.TOP_CENTER);
mainPane.getChildren().add(infoLabel);
StackPane.setAlignment(infoLabel, Pos.BOTTOM_LEFT);
mainPane.getChildren().add(restartBtn);
StackPane.setAlignment(restartBtn, Pos.BOTTOM_CENTER);
mainPane.getChildren().add(instructionsBtn);
StackPane.setAlignment(instructionsBtn, Pos.BOTTOM_RIGHT);
primaryStage.setScene(scene);
primaryStage.show();
}
/**
* Main method of the program.
* @param args Command line arguments
* @throws Exception Exception
*/
public static void main(String[] args) throws Exception {
launch(args);
}
}