I have a Computer Science project due Monday. We have to make a game and use GUI in order to ensure ourselves a good score. I decided to make Hang Man. The class reads in a txt file of common SAT words (I'm a sophomore in high school, so I need to start studying these words).

Some background on my progress: I've had to make several new files for my classes because my old ones got all corrupt and messed up. Like whenever I wanted to add changes after running a successful program, the class wouldn't read any of my edits at all. Like if I had set my JFrame size from 600 x 600 to 300 x 300, the size would remain 600 x 600, even if my parameters for setSize() would be (300,300). So I had to do lots of copy-pasting here and there on new files, and then there were no problems. They began to act normally.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;

public class HangMan extends JFrame implements ActionListener{
	
	private ArrayList <Vocab> satWords = new ArrayList <Vocab>();
	private boolean gameOver;
	private boolean empty;
	private Label error = new Label ("",1);
	private Label info = new Label ("", 1);
	private JButton slots [] = new JButton [0]; //initial state has 0 slots.
	
	private JButton a = new JButton("A");
	private JButton b = new JButton("B");
	private JButton c = new JButton("C");
	private JButton d = new JButton("D");
	private JButton e = new JButton("E");
	private JButton f = new JButton("F");
	private JButton g = new JButton("G");
	private JButton h = new JButton("H");
	private JButton i = new JButton("I");
	private JButton j = new JButton("J");
	private JButton k = new JButton("K");
	private JButton l = new JButton("L");
	private JButton m = new JButton("M");
	private JButton n = new JButton("N");
	private JButton o = new JButton("O");
	private JButton p = new JButton("P");
	private JButton q = new JButton("Q");
	private JButton r = new JButton("R");
	private JButton s = new JButton("S");
	private JButton t = new JButton("T");
	private JButton u = new JButton("U");
	private JButton v = new JButton("V");
	private JButton w = new JButton("W");
	private JButton x = new JButton("X");
	private JButton y = new JButton("Y");
	private JButton z = new JButton("Z");
	
	private JPanel buttonPanel = new JPanel();
	private JPanel slotPanel = new JPanel();
	private JPanel cluePanel = new JPanel();
	
	private String winner;
	private String clueDef;
	private int numLetters;
	
	public HangMan(){
	   setLayout(new BorderLayout());
	   setSize(600,600);
	   
	   add(buttonPanel, BorderLayout.SOUTH);
		a.addActionListener(this);
		buttonPanel.add(a);
		b.addActionListener(this);
		buttonPanel.add(b);
		c.addActionListener(this);
		buttonPanel.add(c);
		d.addActionListener(this);
		buttonPanel.add(d);
		e.addActionListener(this);
		buttonPanel.add(e);
		f.addActionListener(this);
		buttonPanel.add(f);
		g.addActionListener(this);
		buttonPanel.add(g);
		h.addActionListener(this);
		buttonPanel.add(h);
		i.addActionListener(this);
		buttonPanel.add(i);
		j.addActionListener(this);
		buttonPanel.add(j);
		k.addActionListener(this);
		buttonPanel.add(k);
		l.addActionListener(this);
		buttonPanel.add(l);
		m.addActionListener(this);
		buttonPanel.add(m);
		n.addActionListener(this);
		buttonPanel.add(n);
		o.addActionListener(this);
		buttonPanel.add(o);
		p.addActionListener(this);
		buttonPanel.add(p);
		q.addActionListener(this);
		buttonPanel.add(q);
		r.addActionListener(this);
		buttonPanel.add(r);
		s.addActionListener(this);
		buttonPanel.add(s);
		t.addActionListener(this);
		buttonPanel.add(t);
		u.addActionListener(this);
		buttonPanel.add(u);
		v.addActionListener(this);
		buttonPanel.add(v);
		w.addActionListener(this);
		buttonPanel.add(w);
		x.addActionListener(this);
		buttonPanel.add(x);
		y.addActionListener(this);
		buttonPanel.add(y);
		z.addActionListener(this);
		buttonPanel.add(z);
       			
		try{
			Scanner inFile = new Scanner(new File("SAT.txt"));
			int numWords = inFile.nextInt();
			
			inFile.nextLine(); //needed to flush EOL	
			
			while(inFile.hasNext()){
				String randomWord = inFile.nextLine();
				String def = inFile.nextLine();
				satWords.add(new Vocab(randomWord, def));
			}
			
		}catch(Exception e){
			System.out.println("Error: " + e.getMessage());
		}
		
		Random chooser = new Random();
		int pick = chooser.nextInt(satWords.size());
		
		winner = satWords.get(pick).getWord();
		//THE WINNING WORD!
		//must be kept hidden!
		clueDef = satWords.get(pick).getDefinition();
		//Definition used as a clue.
		numLetters = satWords.get(pick).getNumLetters();
				
		getSlots();
		
		add(error, BorderLayout.SOUTH);
		
	}
	
	private void getSlots(){
		add(cluePanel, BorderLayout.NORTH);
		add(slotPanel, BorderLayout.CENTER);
		
		JLabel visibleDefinition = new JLabel(clueDef);
		cluePanel.add(visibleDefinition);
		//add the selected vocab definition as a Label.
		//definition given as a clue to help player figure out what the word is.
		
		slots = new JButton[numLetters];
		
		for(int i = 0; i < numLetters; i++){
			slots[i] = new JButton("__");
			slots[i].addActionListener(this);
			slotPanel.add(slots[i]);
		} //based on the number of letters
		
	}
	
	private boolean isWrong(JButton choice){
		char [] correctLetters = new char[winner.length()];
			for(int i = 0; i < winner.length(); i++){
				correctLetters[i] = winner.charAt(i);
		}
		for(int i = 0; i < correctLetters.length; i++){
		if(!(choice.getLabel().equals(correctLetters[i]))){
			return true;
		}
		}
		return false;
	}
	
	public void actionPerformed(ActionEvent e){
		
		for(int i = 0; i < slots.length; i++){
			if(e.getSource() == slots[i]){
				if(slots[i].getLabel().equals("")){ //if the slot chosen is empty
					slots[i].setBackground(Color.yellow);
					
					if(e.getSource() == a){
						if(!(isWrong(a))){
							slots[i].setLabel("A");
						}else{
							error.setText("Wrong guess!");
						}
						
					}
					if(e.getSource() == b){
					slots[i].setLabel("B");
					}								
					if(e.getSource() == c){
					slots[i].setLabel("C");
					}
					if(e.getSource() == d){
					slots[i].setLabel("D");
					}
					if(e.getSource() == e){
					slots[i].setLabel("E");
					}
					if(e.getSource() == f){
					slots[i].setLabel("F");
					}
					if(e.getSource() == g){
					slots[i].setLabel("G");
					}
					if(e.getSource() == h){
					slots[i].setLabel("H");
					}
					
				}
			}
		}
	
	}
   
    
    public static void main(String[] args) {
    	JFrame frame = new HangMan();
		frame.setVisible(true);
    }
}

Anyways, my current problem is that my JButtons to make the letters aren't showing up on my buttonPanel JPanel (it isn't showing up on my JFrame at least when I run it). The JButtons to make empty slots appeared very nicely (look at method getSlots()), but the letter buttons seem to be invisible. O.o On the old files that had to be replaced, they initially read my JButtons fine and put all of them up, including the letters. Just for some reason now the letters aren't appearing on the current file I'm using.

Here is my VERY WORK IN PROGRESS code for now. Alot of it is empty, but I'll fill them in later once I can figure out the issues. I am not a bright programmer; I've been taking a class for almost a year and I still don't understand alot of stuff.


I appreciate anyone's help. :D I am also open to suggestions to change/add/remove anything. Again, this needs to be done by Monday.

Recommended Answers

All 11 Replies

The posted code needs a definition for the Vocab class.

Two problems so far: You are reusing the Southern borderlayout slot.
The flowlayout manager doesn't work for the 2 letter buttons.

Alright, fixed those problems (at least I hope I did it correctly!)

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;

public class HangMan extends JFrame implements ActionListener{
	
	private ArrayList <Vocab> satWords = new ArrayList <Vocab>();
	private boolean gameOver;
	private boolean empty;
	private Label error = new Label ("",1);
	private Label info = new Label ("", 1);
	private JButton slots [] = new JButton [0]; //initial state has 0 slots.
	
	private JButton a = new JButton("A");
	private JButton b = new JButton("B");
	private JButton c = new JButton("C");
	private JButton d = new JButton("D");
	private JButton e = new JButton("E");
	private JButton f = new JButton("F");
	private JButton g = new JButton("G");
	private JButton h = new JButton("H");
	private JButton i = new JButton("I");
	private JButton j = new JButton("J");
	private JButton k = new JButton("K");
	private JButton l = new JButton("L");
	private JButton m = new JButton("M");
	private JButton n = new JButton("N");
	private JButton o = new JButton("O");
	private JButton p = new JButton("P");
	private JButton q = new JButton("Q");
	private JButton r = new JButton("R");
	private JButton s = new JButton("S");
	private JButton t = new JButton("T");
	private JButton u = new JButton("U");
	private JButton v = new JButton("V");
	private JButton w = new JButton("W");
	private JButton x = new JButton("X");
	private JButton y = new JButton("Y");
	private JButton z = new JButton("Z");
	
	private JPanel buttonPanel = new JPanel();
	private JPanel slotPanel = new JPanel();
	private JPanel cluePanel = new JPanel();
	
	private String winner;
	private String clueDef;
	private int numLetters;
	
	public HangMan(){
	   setLayout(new BorderLayout());
	   setSize(750,400);
	   
	   buttonPanel.setLayout(new GridLayout(2,2));
	   add(buttonPanel, BorderLayout.SOUTH);
		a.addActionListener(this);
		buttonPanel.add(a);
		b.addActionListener(this);
		buttonPanel.add(b);
		c.addActionListener(this);
		buttonPanel.add(c);
		d.addActionListener(this);
		buttonPanel.add(d);
		e.addActionListener(this);
		buttonPanel.add(e);
		f.addActionListener(this);
		buttonPanel.add(f);
		g.addActionListener(this);
		buttonPanel.add(g);
		h.addActionListener(this);
		buttonPanel.add(h);
		i.addActionListener(this);
		buttonPanel.add(i);
		j.addActionListener(this);
		buttonPanel.add(j);
		k.addActionListener(this);
		buttonPanel.add(k);
		l.addActionListener(this);
		buttonPanel.add(l);
		m.addActionListener(this);
		buttonPanel.add(m);
		n.addActionListener(this);
		buttonPanel.add(n);
		o.addActionListener(this);
		buttonPanel.add(o);
		p.addActionListener(this);
		buttonPanel.add(p);
		q.addActionListener(this);
		buttonPanel.add(q);
		r.addActionListener(this);
		buttonPanel.add(r);
		s.addActionListener(this);
		buttonPanel.add(s);
		t.addActionListener(this);
		buttonPanel.add(t);
		u.addActionListener(this);
		buttonPanel.add(u);
		v.addActionListener(this);
		buttonPanel.add(v);
		w.addActionListener(this);
		buttonPanel.add(w);
		x.addActionListener(this);
		buttonPanel.add(x);
		y.addActionListener(this);
		buttonPanel.add(y);
		z.addActionListener(this);
		buttonPanel.add(z);
       			
		try{
			Scanner inFile = new Scanner(new File("SAT.txt"));
			int numWords = inFile.nextInt();
			
			inFile.nextLine(); //needed to flush EOL	
			
			while(inFile.hasNext()){
				String randomWord = inFile.nextLine();
				String def = inFile.nextLine();
				satWords.add(new Vocab(randomWord, def));
			}
			
		}catch(Exception e){
			System.out.println("Error: " + e.getMessage());
		}
		
		Random chooser = new Random();
		int pick = chooser.nextInt(satWords.size());
		
		winner = satWords.get(pick).getWord();
		//THE WINNING WORD!
		//must be kept hidden!
		clueDef = satWords.get(pick).getDefinition();
		//Definition used as a clue.
		numLetters = satWords.get(pick).getNumLetters();
				
		getSlots();
		
		add(error, BorderLayout.WEST);
		
	}
	
	private void getSlots(){
		add(cluePanel, BorderLayout.NORTH);
		add(slotPanel, BorderLayout.CENTER);
		
		JLabel visibleDefinition = new JLabel(clueDef);
		cluePanel.add(visibleDefinition);
		//add the selected vocab definition as a Label.
		//definition given as a clue to help player figure out what the word is.
		
		slots = new JButton[numLetters];
		
		for(int i = 0; i < numLetters; i++){
			slots[i] = new JButton("__");
			slots[i].addActionListener(this);
			slotPanel.add(slots[i]);
		} //based on the number of letters
		
	}
	
	private boolean isWrong(JButton choice){
		char [] correctLetters = new char[winner.length()];
			for(int i = 0; i < winner.length(); i++){
				correctLetters[i] = winner.charAt(i);
		}
		for(int i = 0; i < correctLetters.length; i++){
		if(!(choice.getLabel().equals(correctLetters[i]))){
			return true;
		}
		}
		return false;
	}
	
	public void actionPerformed(ActionEvent e){
		int wrong = 0;
		if(wrong <= 10){
		for(int i = 0; i < slots.length; i++){
			if(e.getSource() == slots[i]){
				if(slots[i].getLabel().equals("__")){ //if the slot chosen is empty
					slots[i].setBackground(Color.yellow);
					
					if(e.getSource() == a){
						a.setEnabled(false);
						if(!(isWrong(a))){
							slots[i].setLabel("A");
						}else{
							wrong++;
							error.setText("Wrong guess!  You have " + (10 - wrong) + " left!");
						}
						
					}
					if(e.getSource() == b){
					slots[i].setLabel("B");
					}								
					if(e.getSource() == c){
					slots[i].setLabel("C");
					}
					if(e.getSource() == d){
					slots[i].setLabel("D");
					}
					if(e.getSource() == e){
					slots[i].setLabel("E");
					}
					if(e.getSource() == f){
					slots[i].setLabel("F");
					}
					if(e.getSource() == g){
					slots[i].setLabel("G");
					}
					if(e.getSource() == h){
					slots[i].setLabel("H");
					}
					
				}
			}
		}
	
	}
	
}
    
    public static void main(String[] args) {
    	JFrame frame = new HangMan();
		frame.setVisible(true);
    }
}

Oh, and here's the Vocab class if anyone wanted to see it.

public class Vocab {
	private String word;
	private String define;
	
	public Vocab(String myWord, String myDef){
		word = myWord;
		define = myDef;
	}
	
	public String getWord(){
		return word;
	}
	
	public String getDefinition(){
		return define;
	}
	
	public int getNumLetters(){
		return word.length();
	}
	
	
}

I also need help with the actionPerformed method in my HangMan class. I'm trying to provide an action for the Letter JButtons and Slot JButtons whenever the user clicks on them. I only set up the 'A' letter button just for now; I'll set up the others later once I know what to do! The user needs to click on an empty slot button(to fill in letters for the random word) and then press a letter button to fill that slot in (IF the letter for that slot is correct, otherwise a a Label message would read "Wrong guess!"). Also, the user cannot press a letter more than once, so I'm gonna need help with trying to set that up.

Some more recommendations:
replace the list of JButton definitions with a loop to create the buttons and add the listeners. The getSource() method in the listener returns a reference to the JButton so you don't need to have all the variables: a,b,c,...z
That should make the actionListener code much simpler.

Use setText() and getText() vs get/set Label.

The getSource() method in the listener returns a reference to the JButton so you don't need to have all the variables: a,b,c,...z

How does that work? I get the for loop part, but can you show me a coding example so that I know how to code for that?

On second thought, since you've already coded it, you could leave it. However you should not reference the variables by name in the actionPerformed() method. You should use the String returned by the getText() method to control the logic.

he user needs to click on an empty slot button(to fill in letters for the random word) and then press a letter button

You'll need to remember which slot was clicked before the letter was clicked. You'll need to test that the clicks are in the right order: slot before letter.
It be better to have two ActionListeners here. One for slots and one for letters.

More comments on your code:
You expect e.getSource() to have two different possible values in the actionPerformed() method. A slot and a button. Not possible. It'll be one or the other.
Use a GridLayout for the panel with the buttons. For example

buttonPanel.setLayout(new GridLayout(5,6));

Here's an example of how you could create the buttons in a loop:

char[] aChar = new char[1]; // use for String constructor
     for(char ltr = 'A'; ltr <= 'Z';  ltr++) {
        aChar[0] = ltr; // setup for below
        JButton jb = new JButton(new String(aChar));
        jb.addActionListener(this);
        buttonPanel.add(jb);
     }
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.util.*;
import java.io.*;

public class HangMan extends JFrame implements ActionListener{
	
	private ArrayList <Vocab> satWords = new ArrayList <Vocab>();
	private boolean gameOver;
	private boolean empty;
	private Label error = new Label ("",1);
	private Label info = new Label ("", 1);
	private JButton slots [] = new JButton [0]; //initial state has 0 slots.
	private JButton ltrs [] = new JButton [26]; //array of buttons to create a button for each leter of the alphabet
	
	private JPanel buttonPanel = new JPanel();
	private JPanel slotPanel = new JPanel();
	private JPanel cluePanel = new JPanel();
	
	private String winner;
	private String clueDef;
	private int numLetters;
	
	public HangMan(){
	   setLayout(new BorderLayout());
	   setSize(750,400);
	   
	   buttonPanel.setLayout(new GridLayout(2,2));
	   add(buttonPanel, BorderLayout.SOUTH);
	   
		char[] aChar = new char[1]; // use for String constructor
		int indexCount = 0; /* needed to designate an index in Array ltrs [] so that 
		each new JButton will be added in that spot.*/
		for(char ltr = 'A'; ltr <= 'Z'; ltr++) {
			aChar[0] = ltr; // setup for below
			ltrs[indexCount] = new JButton(new String(aChar));
			ltrs[indexCount].addActionListener(this);
			buttonPanel.add(ltrs[indexCount]);
			indexCount++;
			}
			
       			
		try{
			Scanner inFile = new Scanner(new File("SAT.txt"));
			int numWords = inFile.nextInt();
			
			inFile.nextLine(); //needed to flush EOL	
			
			while(inFile.hasNext()){
				String randomWord = inFile.nextLine();
				String def = inFile.nextLine();
				satWords.add(new Vocab(randomWord, def));
			}
			
		}catch(Exception e){
			System.out.println("Error: " + e.getMessage());
		}
		
		Random chooser = new Random();
		int pick = chooser.nextInt(satWords.size());
		
		winner = satWords.get(pick).getWord();
		//THE WINNING WORD!  must be kept hidden!
		
		clueDef = satWords.get(pick).getDefinition();
		//Definition used as a clue.
		
		numLetters = satWords.get(pick).getNumLetters();
				
		getSlots();
		
		add(error, BorderLayout.WEST);
		
	}
	
	private void getSlots(){
		add(cluePanel, BorderLayout.NORTH);
		add(slotPanel, BorderLayout.CENTER);
		
		JLabel visibleDefinition = new JLabel(clueDef);
		cluePanel.add(visibleDefinition);
		//adds the selected vocab definition as a Label.
		//definition given as a clue to help player figure out what the word is.
		
		slots = new JButton[numLetters];
		
		for(int i = 0; i < numLetters; i++){
			slots[i] = new JButton("__");
			slots[i].addActionListener(this);
			slotPanel.add(slots[i]);
		} //based on the number of letters
		
	}
	
	public void actionPerformed(ActionEvent e){
		int wrong = 0;
		if(wrong <= 10){
		for(int i = 0; i < slots.length; i++){
			if(e.getSource() == slots[i]){
				if(slots[i].getText().equals("__")){ //if the slot chosen is empty
				processEvent(i);
				slots[i].setBackground(Color.yellow);
				}else{
					error.setText("That slot has already been taken!");
				}
			for(int k = 0; k < ltrs.length; k++){
				if(e.getSource() == ltrs[k]){
					error.setText("You need to pick an empty slot first!");
					}				
				}	
				}
			}
		}
	}

	private void processEvent(int index){
		int wrong = 0;
		if(!gameFinished(wrong)){
			for(int m = 0; m < ltrs.length; m++){
				String ltrPick = ltrs[m].getText();
					if(!isWrong(slots[index])){
						slots[index].setText(ltrs[m].getText());
					}
				}
					}else if(isWrong(slots[index])){
						error.setText("Wrong guess!  You have " + (10 - wrong) + " guesses left!");
						wrong++;
						}
		}
					
	private boolean isWrong(JButton choice){
		char [] correctLetters = new char[winner.length()];
			for(int i = 0; i < winner.length(); i++){
				correctLetters[i] = winner.charAt(i);
			}
		for(int i = 0; i < correctLetters.length; i++){
			if(!(choice.getText().equals(correctLetters[i]))){
			return true;
				}
			}
		return false;
	}
	
	private boolean gameFinished(int numWrong){
		if (numWrong == 10){
			error.setText("GAME OVER!!");
			return true;
			}else if (numWrong > 0 && numWrong < 10){
				//error.setText("Wrong guess!  You have " + (10 - numWrong) + " guesses left!");
				return false;
		}else{
			hasWon();
			return false;
		}
	}
	
	private boolean hasWon(){
		for(int x = 0; x < slots.length; x++){
			if (slots[x].getText().equals("")){
				return false; //if any of the slots are empty, the user still hasn't won yet.
			}
			}
			return true;
	}
    
    public static void main(String[] args) {
    	JFrame frame = new HangMan();
		//frame.setVisible(true);
		frame.show();
    }	
    	
 }

I took most of what you suggested into your account.

But when I want to position slotPanel in the center, it stays north with the Definition (which is North).

it stays north with the Definition

Why do you think that? Try setting the background color of the panels to see where they are.

You expect e.getSource() to have two different possible values in the actionPerformed() method. A slot and a button. Not possible. It'll be one or the other.

public void actionPerformed(ActionEvent e){
		int wrong = 0;
		if(wrong <= 10){
		for(int i = 0; i < slots.length; i++){
			if(e.getSource() == slots[i]){
				if(slots[i].getText().equals("__")){ //if the slot chosen is empty
				error.setText("Now pick a letter!");
				processEvent(slots[i]);
				slots[i].setBackground(Color.yellow);
				}else{
					error.setText("That slot has already been taken!");
				}
			for(int k = 0; k < ltrs.length; k++){
				if(e.getSource() == ltrs[k]){
					error.setText("You need to pick an empty slot first!");
					}				
				}	
				}
			}
		}
	}

Alright, now when error.setText("Now pick a letter!") is called, the label changes. But one of them, error.setText("You need to pick an empty slot first") isn't called whenever I hit a Letter Button first.

I'm sorry if I'm bothering you with all these questions; I'm very new to this GUI stuff! XD

^ignore this post; i figured it out.

i tried running this code but i got


Error: null
Exception in thread "main" java.lang.IllegalArgumentException: n must be positive
at java.util.Random.nextInt(Random.java:250)
at HangMan.<init>(HangMan.java:61)
at HangMan.main(HangMan.java:188)


could someone please help me?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.