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;
// checkIfWon}
- sees if the// userget hasinput wonfrom the gameuser
private boolean checkIfWoncheckUserGuess(String l){
if(l.length() == 1 && for!lettersGuessed.contains(boolean tofl.charAt(0)) :&& lettersRevealedalphabet.contains(l.charAt(0))){
ifsetText(!tofnull)
return false;;
}lettersGuessed.add(l.charAt(0));
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)];
}
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);
}
// 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("_ ");
}
);
}
// 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);
}
}
);
}
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);
}
}
// playAgainreadFile - Allows theread userin towordList
play another game ofprivate hangman
String[] readFile(String loc){
private void playAgain(Stringtry message){
intFile ansf = JOptionPane.showConfirmDialog(f,new message,File(loc);
assert f.exists() : "File doesn't exist";
"Play again?",BufferedReader JOptionPane.YES_NO_OPTION,input JOptionPane.PLAIN_MESSAGE= new BufferedReader(new FileReader(f));
// read in if(ansthe ==stuff JOptionPane.YES_OPTION)into {
an arrayList here
wordList = setUpGameinput.readLine().split(" ");
}else {
// close the input stream
Systeminput.exitclose(0);
}catch(IOException ioException){
} ioException.printStackTrace();
}
return wordList;
}
// readFilesetUpGame - read in wordList
sets up the variables appropriately
private String[]void readFilesetUpGame(String loc){
GuessesRemaining try= {5;
secretWord = chooseSecretWord(wordList);
File f lettersRevealed = new Fileboolean[secretWord.length(loc);];
Arrays.fill(lettersRevealed, false);
lettersGuessed = assertnew f.existsHashSet<Character>(26); : "File doesn't exist";
// 26 letters in alphabet
drawSecretWord();
BufferedReaderdrawLettersGuessed();
input = new BufferedReader(new FileReader drawGuessesRemaining(f));
}
// updateSecretWord - updates which letters of the secret word have //been readrevealed
in the stuff intoprivate anvoid arrayListupdateSecretWord(String herel){
List<Integer> changeBool = new ArrayList<Integer>();
wordList = input.readLine if()secretWord.splitcontains(" "l);){
// Searches through secretWord & notes down all //letters closethat equal the inputuser's streamguess
for(int i=0; inputi<secretWord.closelength(); i++){
}catch if(IOExceptionsecretWord.charAt(i) ioException== l.charAt(0){)
ioException changeBool.printStackTraceadd(i);
}
return wordList;
}
// setUpGame - sets upChanges the variables appropriately
private void setUpGame(){
boolean value for those letters @ GuessesRemainingtheir =corresponding 5;indexes
secretWord = chooseSecretWordfor(wordList);
lettersRevealedInteger =idx new: boolean[secretWord.length(changeBool)];
Arrays.fill(lettersRevealed, false);
lettersGuessedlettersRevealed[idx] = new HashSet<Character>(26); // 26 letters in alphabet
true;
drawSecretWord();}else{
drawLettersGuessed()GuessesRemaining--;
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();
}
);
}
// 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();
}
}
}
}
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();
}
}
}
}
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();
}
}
}
}
Today I wroteHere's an implementation of Hangman (code below) that was originally written to be used on the command-line. I'm in the process of getting it to work on some simple GUI, and I've almost got it to work onwritten that uses a basic GUI, however I'm having difficulty in determining how to get the user input from the JTextField into the appropriate parts of the code (like the userGuess() invoked in the play() method).
I understand that the action listener linked to the JTextField will run on the EDT & so isn't that a separate thread from the thread of that play() is in? Do I need to send the info from the EDT thread to the main thread? I know As I can get the text using .getText() but I'd like for the code to wait for the useram new to make a guess (i.e. block), like how it waits in the command-line when Scanner(System.in) is used.
AlsoJava, 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.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
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
Scanner k = new Scanner(System.in);
boolean keepGoing;
boolean keepPlaying; // allows the player to play another game of hangman
int GuessesRemaining;
// GUI
DocumentJFrame doc;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.play();
}
// appendMessage - appends text to the text area
private void appendMessage(final String message){
SwingUtilities.invokeLater(
new Runnable(){
@Override
public void run(){
try{
doc.insertString(doc.getLengthsetUpGame(), message, null);
}catch(BadLocationException badLocationException){
badLocationExceptionh.printStackTracedrawSecretWord();
}
}
}
);
}
// buildGUI - builds the GUI
private void buildGUI(){
JFrame f = new JFrame("Hangman");
// Text area
JTextArea textArea = new JTextArea();
doc = textArea.getDocument();
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane// jspJLabels
guessesRemainingLabel = new JScrollPaneJLabel(textArea"Guesses remaining: " + String.valueOf(GuessesRemaining));
lettersGuessedLabel = new JLabel("Already guessed: ");
secretWordLabel = new JLabel();
// Text field for user to type letters in
textField = new JTextField(10); // TODO fix the textField's size
JButton checkButton = new JButton("Send""Guess");
// Add listeners to textField & checkButton
TextListener textListener = new TextListener();
checkButton.addActionListener(textListener);
textField.addActionListener(textListener);
// AddPanel everythingfor toall framethe labels
JPanel panellabelPanel = new JPanel();
panellabelPanel.addsetLayout(BorderLayout.WESTnew BoxLayout(labelPanel, textFieldBoxLayout.PAGE_AXIS));
panellabelPanel.add(BorderLayoutguessesRemainingLabel);
labelPanel.EAST,add(lettersGuessedLabel);
checkButton labelPanel.add(secretWordLabel);
f// User panel
JPanel userPanel = new JPanel(new BorderLayout());
userPanel.add(BorderLayout.CENTER, jsptextField);
fuserPanel.add(BorderLayout.SOUTHEAST, panelcheckButton);
labelPanel.add(userPanel);
// Add everything to frame
f.add(BorderLayout.CENTER, labelPanel);
f.setSize(300250, 300100);
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("_ ");
}
}
appendMessage(word + "\n");
System.out.println(word);
}
// play - Initiates a game of hangman
public void play(){
keepPlaying = true;
createAlphabetSet();
while(keepPlaying) {
setUpGame();
appendMessage("Welcome to hangman! You have 5 guesses to guess the secret word.\n");
System.out.println("Welcome to hangman! You have 5 guesses to guess the secret word.");
// user's guess
String guess;
while (GuessesRemaining > 0 && keepGoing) {
drawSecretWord();
// Doesn't output this at the beginning
final String w = if(lettersGuessedword.sizetoString() != 0) {;
appendMessageSwingUtilities.invokeLater("Letters already guessed: ");
new System.out.printRunnable("Letters already guessed: ");{
for (Character el : lettersGuessed) {@Override
public void appendMessagerun(el + " ");{
System.outsecretWordLabel.printsetText(el + " "w);
}
appendMessage("\n");
System.out.println();
}
guess = userGuess("Guess a letter:");
updateSecretWord(guess);
appendMessage("\n");
System.out.println();
if (checkIfWon()) {
keepGoing = false;
appendMessage("Well done! You guessed " + secretWord + " with " + GuessesRemaining + " guesses left!\n");
System.out.println("Well done! You guessed " + secretWord + " with " + GuessesRemaining + " guesses left!");
}
}
// If player runs out of guesses
if (GuessesRemaining == 0) {
appendMessage("Tough luck. The secret word was " + secretWord + "\n");
System.out.println("Tough luck. The secret word was " + secretWord);
}
// loseSequence - when the the user runs out of guesses
playAgain private void loseSequence("Would){
you like to play another game of hangman? for(typeint yesi=0; ori<lettersRevealed.length; noi++)"
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){
appendMessage(messageint +ans "\n");
= JOptionPane.showConfirmDialog(f, message,
System.out.println(message);
String ans"Play =again?", kJOptionPane.next()YES_NO_OPTION, JOptionPane.toLowerCase(PLAIN_MESSAGE);
if(ans == JOptionPane.equals("yes")YES_OPTION) {
appendMessage("Okay! Let's play another game of hangman!\n\n\n");
System.out.printlnsetUpGame("Okay! Let's play another game of hangman!\n\n");
}else if(ans.equals("no")){
keepPlaying = false;
appendMessage("Fair enough. Bye!");
System.out.println("Fair enough. Bye!");
}else{
playAgainexit("Invalid input. Please type in yes or no: "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(){
keepGoing = true;
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--;
appendMessage("Letter not found. You have " + GuessesRemaining + " guesses remaining.\n");
System.out.printlndrawGuessesRemaining("Letter not found. You have " + GuessesRemaining + " guesses remaining.");
}
}
// getwinSequence input- fromwhen the user has correctly guessed the secret word
private Stringvoid userGuesswinSequence(String message){
appendMessageplayAgain(message"Well done! You guessed " + "\n");secretWord + " with " + GuessesRemaining + " guesses left!\n" +
System.out.println(message);
"Would you like to Stringplay lanother =game k.next().toLowerCase(of hangman?");
}
if(l.length() == 0) {
l = userGuess("Nothing has been typed. Please guess a letter:");
}else if(l.length() > 1) {
l = userGuess("More than one letter was typed. Please select only one letter:");
}else if(lettersGuessed.contains(l.charAt(0))){
l = userGuess("Letter already guessed. Please choose another letter:");
}else if(!alphabet.contains(l.charAt(0))){
l = userGuess("Not a letter. Please choose a letter:");
}
lettersGuessed.add(l.charAt(0));
return l;
}
// 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 -- TODO need the input from the the textField to go into userGuess method somehow
private class TextListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ev){
appendMessage(String guess = getText();
if(checkUserGuess(guess)) {
updateSecretWord(guess);
setText drawSecretWord(null);
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();
}
}
}
}
Today I wrote an implementation of Hangman (code below) that was originally written to be used on the command-line. I'm in the process of getting it to work on some simple GUI, and I've almost got it to work on a GUI, however I'm having difficulty in determining how to get the user input from the JTextField into the appropriate parts of the code (like the userGuess() invoked in the play() method).
I understand that the action listener linked to the JTextField will run on the EDT & so isn't that a separate thread from the thread of that play() is in? Do I need to send the info from the EDT thread to the main thread? I know I can get the text using .getText() but I'd like for the code to wait for the user to make a guess (i.e. block), like how it waits in the command-line when Scanner(System.in) is used.
Also, 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.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
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
Scanner k = new Scanner(System.in);
boolean keepGoing;
boolean keepPlaying; // allows the player to play another game of hangman
int GuessesRemaining;
// GUI
Document doc;
JTextField textField;
public static void main(String[] args){
Hangman h = new Hangman();
h.readFile("words.txt");
h.buildGUI();
h.play();
}
// appendMessage - appends text to the text area
private void appendMessage(final String message){
SwingUtilities.invokeLater(
new Runnable(){
@Override
public void run(){
try{
doc.insertString(doc.getLength(), message, null);
}catch(BadLocationException badLocationException){
badLocationException.printStackTrace();
}
}
}
);
}
// buildGUI - builds the GUI
private void buildGUI(){
JFrame f = new JFrame("Hangman");
// Text area
JTextArea textArea = new JTextArea();
doc = textArea.getDocument();
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane jsp = new JScrollPane(textArea);
// Text field for user to type letters in
textField = new JTextField(10); // TODO fix the textField's size
JButton checkButton = new JButton("Send");
// Add listeners to textField & checkButton
TextListener textListener = new TextListener();
checkButton.addActionListener(textListener);
textField.addActionListener(textListener);
// Add everything to frame
JPanel panel = new JPanel();
panel.add(BorderLayout.WEST, textField);
panel.add(BorderLayout.EAST, checkButton);
f.add(BorderLayout.CENTER, jsp);
f.add(BorderLayout.SOUTH, panel);
f.setSize(300, 300);
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;
}
// 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);
}
}
// 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("_ ");
}
}
appendMessage(word + "\n");
System.out.println(word);
}
// play - Initiates a game of hangman
public void play(){
keepPlaying = true;
createAlphabetSet();
while(keepPlaying) {
setUpGame();
appendMessage("Welcome to hangman! You have 5 guesses to guess the secret word.\n");
System.out.println("Welcome to hangman! You have 5 guesses to guess the secret word.");
// user's guess
String guess;
while (GuessesRemaining > 0 && keepGoing) {
drawSecretWord();
// Doesn't output this at the beginning
if(lettersGuessed.size() != 0) {
appendMessage("Letters already guessed: ");
System.out.print("Letters already guessed: ");
for (Character el : lettersGuessed) {
appendMessage(el + " ");
System.out.print(el + " ");
}
appendMessage("\n");
System.out.println();
}
guess = userGuess("Guess a letter:");
updateSecretWord(guess);
appendMessage("\n");
System.out.println();
if (checkIfWon()) {
keepGoing = false;
appendMessage("Well done! You guessed " + secretWord + " with " + GuessesRemaining + " guesses left!\n");
System.out.println("Well done! You guessed " + secretWord + " with " + GuessesRemaining + " guesses left!");
}
}
// If player runs out of guesses
if (GuessesRemaining == 0) {
appendMessage("Tough luck. The secret word was " + secretWord + "\n");
System.out.println("Tough luck. The secret word was " + secretWord);
}
playAgain("Would you like to play another game of hangman? (type yes or no)");
}
}
// playAgain - Allows the user to play another game of hangman
private void playAgain(String message){
appendMessage(message + "\n");
System.out.println(message);
String ans = k.next().toLowerCase();
if(ans.equals("yes")) {
appendMessage("Okay! Let's play another game of hangman!\n\n\n");
System.out.println("Okay! Let's play another game of hangman!\n\n");
}else if(ans.equals("no")){
keepPlaying = false;
appendMessage("Fair enough. Bye!");
System.out.println("Fair enough. Bye!");
}else{
playAgain("Invalid input. Please type in yes or no: ");
}
}
// 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(){
keepGoing = true;
GuessesRemaining = 5;
secretWord = chooseSecretWord(wordList);
lettersRevealed = new boolean[secretWord.length()];
Arrays.fill(lettersRevealed, false);
lettersGuessed = new HashSet<Character>(26); // 26 letters in alphabet
}
// 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--;
appendMessage("Letter not found. You have " + GuessesRemaining + " guesses remaining.\n");
System.out.println("Letter not found. You have " + GuessesRemaining + " guesses remaining.");
}
}
// get input from the user
private String userGuess(String message){
appendMessage(message + "\n");
System.out.println(message);
String l = k.next().toLowerCase();
if(l.length() == 0) {
l = userGuess("Nothing has been typed. Please guess a letter:");
}else if(l.length() > 1) {
l = userGuess("More than one letter was typed. Please select only one letter:");
}else if(lettersGuessed.contains(l.charAt(0))){
l = userGuess("Letter already guessed. Please choose another letter:");
}else if(!alphabet.contains(l.charAt(0))){
l = userGuess("Not a letter. Please choose a letter:");
}
lettersGuessed.add(l.charAt(0));
return l;
}
// 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 -- TODO need the input from the the textField to go into userGuess method somehow
private class TextListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ev){
appendMessage(getText());
setText(null);
}
}
}
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();
}
}
}
}
Implementation of Hangman in Java
Today I wrote an implementation of Hangman (code below) that was originally written to be used on the command-line. I'm in the process of getting it to work on some simple GUI, and I've almost got it to work on a GUI, however I'm having difficulty in determining how to get the user input from the JTextField into the appropriate parts of the code (like the userGuess() invoked in the play() method).
I understand that the action listener linked to the JTextField will run on the EDT & so isn't that a separate thread from the thread of that play() is in? Do I need to send the info from the EDT thread to the main thread? I know I can get the text using .getText() but I'd like for the code to wait for the user to make a guess (i.e. block), like how it waits in the command-line when Scanner(System.in) is used.
Also, 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.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Document;
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
Scanner k = new Scanner(System.in);
boolean keepGoing;
boolean keepPlaying; // allows the player to play another game of hangman
int GuessesRemaining;
// GUI
Document doc;
JTextField textField;
public static void main(String[] args){
Hangman h = new Hangman();
h.readFile("words.txt");
h.buildGUI();
h.play();
}
// appendMessage - appends text to the text area
private void appendMessage(final String message){
SwingUtilities.invokeLater(
new Runnable(){
@Override
public void run(){
try{
doc.insertString(doc.getLength(), message, null);
}catch(BadLocationException badLocationException){
badLocationException.printStackTrace();
}
}
}
);
}
// buildGUI - builds the GUI
private void buildGUI(){
JFrame f = new JFrame("Hangman");
// Text area
JTextArea textArea = new JTextArea();
doc = textArea.getDocument();
textArea.setEditable(false);
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);
JScrollPane jsp = new JScrollPane(textArea);
// Text field for user to type letters in
textField = new JTextField(10); // TODO fix the textField's size
JButton checkButton = new JButton("Send");
// Add listeners to textField & checkButton
TextListener textListener = new TextListener();
checkButton.addActionListener(textListener);
textField.addActionListener(textListener);
// Add everything to frame
JPanel panel = new JPanel();
panel.add(BorderLayout.WEST, textField);
panel.add(BorderLayout.EAST, checkButton);
f.add(BorderLayout.CENTER, jsp);
f.add(BorderLayout.SOUTH, panel);
f.setSize(300, 300);
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;
}
// 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);
}
}
// 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("_ ");
}
}
appendMessage(word + "\n");
System.out.println(word);
}
// play - Initiates a game of hangman
public void play(){
keepPlaying = true;
createAlphabetSet();
while(keepPlaying) {
setUpGame();
appendMessage("Welcome to hangman! You have 5 guesses to guess the secret word.\n");
System.out.println("Welcome to hangman! You have 5 guesses to guess the secret word.");
// user's guess
String guess;
while (GuessesRemaining > 0 && keepGoing) {
drawSecretWord();
// Doesn't output this at the beginning
if(lettersGuessed.size() != 0) {
appendMessage("Letters already guessed: ");
System.out.print("Letters already guessed: ");
for (Character el : lettersGuessed) {
appendMessage(el + " ");
System.out.print(el + " ");
}
appendMessage("\n");
System.out.println();
}
guess = userGuess("Guess a letter:");
updateSecretWord(guess);
appendMessage("\n");
System.out.println();
if (checkIfWon()) {
keepGoing = false;
appendMessage("Well done! You guessed " + secretWord + " with " + GuessesRemaining + " guesses left!\n");
System.out.println("Well done! You guessed " + secretWord + " with " + GuessesRemaining + " guesses left!");
}
}
// If player runs out of guesses
if (GuessesRemaining == 0) {
appendMessage("Tough luck. The secret word was " + secretWord + "\n");
System.out.println("Tough luck. The secret word was " + secretWord);
}
playAgain("Would you like to play another game of hangman? (type yes or no)");
}
}
// playAgain - Allows the user to play another game of hangman
private void playAgain(String message){
appendMessage(message + "\n");
System.out.println(message);
String ans = k.next().toLowerCase();
if(ans.equals("yes")) {
appendMessage("Okay! Let's play another game of hangman!\n\n\n");
System.out.println("Okay! Let's play another game of hangman!\n\n");
}else if(ans.equals("no")){
keepPlaying = false;
appendMessage("Fair enough. Bye!");
System.out.println("Fair enough. Bye!");
}else{
playAgain("Invalid input. Please type in yes or no: ");
}
}
// 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(){
keepGoing = true;
GuessesRemaining = 5;
secretWord = chooseSecretWord(wordList);
lettersRevealed = new boolean[secretWord.length()];
Arrays.fill(lettersRevealed, false);
lettersGuessed = new HashSet<Character>(26); // 26 letters in alphabet
}
// 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--;
appendMessage("Letter not found. You have " + GuessesRemaining + " guesses remaining.\n");
System.out.println("Letter not found. You have " + GuessesRemaining + " guesses remaining.");
}
}
// get input from the user
private String userGuess(String message){
appendMessage(message + "\n");
System.out.println(message);
String l = k.next().toLowerCase();
if(l.length() == 0) {
l = userGuess("Nothing has been typed. Please guess a letter:");
}else if(l.length() > 1) {
l = userGuess("More than one letter was typed. Please select only one letter:");
}else if(lettersGuessed.contains(l.charAt(0))){
l = userGuess("Letter already guessed. Please choose another letter:");
}else if(!alphabet.contains(l.charAt(0))){
l = userGuess("Not a letter. Please choose a letter:");
}
lettersGuessed.add(l.charAt(0));
return l;
}
// 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 -- TODO need the input from the the textField to go into userGuess method somehow
private class TextListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent ev){
appendMessage(getText());
setText(null);
}
}
}