Here's an implementation of Hangman that I've written that uses a basic GUI. As I am new to Java, please let me know of any improvements I can make to my coding style. Thanks for your help.
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.*;
import java.util.*;
import java.util.List;
import javax.swing.*;
public class Hangman {
String[] wordList;
String secretWord;
Set<Character> alphabet;
Set<Character> lettersGuessed; // letters the user has guessed
boolean[] lettersRevealed; // determines if the letter should be revealed or not
int GuessesRemaining;
// GUI
JFrame f;
JTextField textField;
JLabel guessesRemainingLabel;
JLabel lettersGuessedLabel;
JLabel secretWordLabel;
public static void main(String[] args){
Hangman h = new Hangman();
h.createAlphabetSet();
h.readFile("words.txt");
h.buildGUI();
h.setUpGame();
h.drawSecretWord();
}
// buildGUI - builds the GUI
private void buildGUI(){
f = new JFrame("Hangman");
// JLabels
guessesRemainingLabel = new JLabel("Guesses remaining: " + String.valueOf(GuessesRemaining));
lettersGuessedLabel = new JLabel("Already guessed: ");
secretWordLabel = new JLabel();
// Text field for user to type letters in
textField = new JTextField();
JButton checkButton = new JButton("Guess");
// Add listeners to textField & checkButton
TextListener textListener = new TextListener();
checkButton.addActionListener(textListener);
textField.addActionListener(textListener);
// Panel for all the labels
JPanel labelPanel = new JPanel();
labelPanel.setLayout(new BoxLayout(labelPanel, BoxLayout.PAGE_AXIS));
labelPanel.add(guessesRemainingLabel);
labelPanel.add(lettersGuessedLabel);
labelPanel.add(secretWordLabel);
// User panel
JPanel userPanel = new JPanel(new BorderLayout());
userPanel.add(BorderLayout.CENTER, textField);
userPanel.add(BorderLayout.EAST, checkButton);
labelPanel.add(userPanel);
// Add everything to frame
f.add(BorderLayout.CENTER, labelPanel);
f.setSize(250, 100);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.setVisible(true);
}
// checkIfWon - sees if the user has won the game
private boolean checkIfWon(){
for(boolean tof : lettersRevealed){
if(!tof)
return false;
}
return true;
}
// get input from the user
private boolean checkUserGuess(String l){
if(l.length() == 1 && !lettersGuessed.contains(l.charAt(0)) && alphabet.contains(l.charAt(0))) {
setText(null);
lettersGuessed.add(l.charAt(0));
return true;
}else {
Toolkit.getDefaultToolkit().beep();
}
return false;
}
// chooseSecretWord - selects a word
private String chooseSecretWord(String[] wordList){
return wordList[(int)(Math.random() * wordList.length)];
}
// createAlphabetSet - Creates the alphabet set that's used to ensure that the user's guess not a number nor a special character
private void createAlphabetSet(){
alphabet = new HashSet<Character>(26);
for(Character c = 'a'; c<='z'; c++){
alphabet.add(c);
}
}
// drawGuessesRemaining - Outputs the guesses remaining
void drawGuessesRemaining(){
final String guessesMessage = "Guesses remaining: " + String.valueOf(GuessesRemaining);
SwingUtilities.invokeLater(
new Runnable(){
@Override
public void run(){
guessesRemainingLabel.setText(guessesMessage);
guessesRemainingLabel.setAlignmentX(Component.LEFT_ALIGNMENT);
}
}
);
}
// drawLettersGuessed - Outputs the letters guessed
void drawLettersGuessed(){
StringBuilder lettersBuilder = new StringBuilder();
for (Character el : lettersGuessed) {
String s = el + " ";
lettersBuilder.append(s);
}
final String letters = lettersBuilder.toString();
SwingUtilities.invokeLater(
new Runnable() {
@Override
public void run() {
lettersGuessedLabel.setText("Already guessed: " + letters);
}
}
);
}
// drawSecretWord - draws the secret word with dashes & etc for user to use to guess the word with
private void drawSecretWord(){
StringBuilder word = new StringBuilder();
for(int i=0; i<lettersRevealed.length; i++){
if(lettersRevealed[i]){
String s = secretWord.charAt(i) + " ";
word.append(s);
}else{
word.append("_ ");
}
}
final String w = word.toString();
SwingUtilities.invokeLater(
new Runnable(){
@Override
public void run(){
secretWordLabel.setText(w);
}
}
);
}
// loseSequence - when the the user runs out of guesses
private void loseSequence(){
for(int i=0; i<lettersRevealed.length; i++)
lettersRevealed[i] = true;
drawSecretWord();
playAgain("Tough luck. The secret word was " + secretWord + ".\nWould you like to play another game of hangman?");
}
// playAgain - Allows the user to play another game of hangman
private void playAgain(String message){
int ans = JOptionPane.showConfirmDialog(f, message,
"Play again?", JOptionPane.YES_NO_OPTION, JOptionPane.PLAIN_MESSAGE);
if(ans == JOptionPane.YES_OPTION) {
setUpGame();
}else {
System.exit(0);
}
}
// readFile - read in wordList
private String[] readFile(String loc){
try {
File f = new File(loc);
assert f.exists() : "File doesn't exist";
BufferedReader input = new BufferedReader(new FileReader(f));
// read in the stuff into an arrayList here
wordList = input.readLine().split(" ");
// close the input stream
input.close();
}catch(IOException ioException){
ioException.printStackTrace();
}
return wordList;
}
// setUpGame - sets up the variables appropriately
private void setUpGame(){
GuessesRemaining = 5;
secretWord = chooseSecretWord(wordList);
lettersRevealed = new boolean[secretWord.length()];
Arrays.fill(lettersRevealed, false);
lettersGuessed = new HashSet<Character>(26); // 26 letters in alphabet
drawSecretWord();
drawLettersGuessed();
drawGuessesRemaining();
}
// updateSecretWord - updates which letters of the secret word have been revealed
private void updateSecretWord(String l){
List<Integer> changeBool = new ArrayList<Integer>();
if(secretWord.contains(l)){
// Searches through secretWord & notes down all letters that equal the user's guess
for(int i=0; i<secretWord.length(); i++){
if(secretWord.charAt(i) == l.charAt(0))
changeBool.add(i);
}
// Changes the boolean value for those letters @ their corresponding indexes
for(Integer idx : changeBool)
lettersRevealed[idx] = true;
}else{
GuessesRemaining--;
drawGuessesRemaining();
}
}
// winSequence - when the user has correctly guessed the secret word
private void winSequence(){
playAgain("Well done! You guessed " + secretWord + " with " + GuessesRemaining + " guesses left!\n" +
"Would you like to play another game of hangman?");
}
// GETTERS
private String getText(){
return textField.getText();
}
// SETTERS
private void setText(final String t){
SwingUtilities.invokeLater(
new Runnable(){
@Override
public void run(){
textField.setText(t);
}
}
);
}
// ActionListener
private class TextListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ev){
String guess = getText();
if(checkUserGuess(guess)) {
updateSecretWord(guess);
drawSecretWord();
if(lettersGuessed.size() != 0) // No letters have been guessed by the user at the beginning
drawLettersGuessed();
// Checks if the user has won or lost
if (checkIfWon())
winSequence();
else if (GuessesRemaining == 0)
loseSequence();
}
}
}
}