Reputation: 139
I am a beginner at Java, and was required to throw together an application for a Java final project. I wanted to do hangman (Seemed easy at the time). This is EXTREMELY DIFFICULT for me. Here is my code so far. (it's really an abomination of about 10 open source hangman games thrown together). See bottom for my question.
import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.util.ArrayList;
public class Hangman implements ActionListener {
JFrame frame;
private String[] wordList = {"computer","java","activity","alaska","appearance","article",
"automobile","basket","birthday","canada","central","character","chicken","chosen",
"cutting","daily","darkness","diagram","disappear","driving","effort","establish","exact",
"establishment","fifteen","football","foreign","frequently","frighten","function","gradually",
"hurried","identity","importance","impossible","invented","italian","journey","lincoln",
"london","massage","minerals","outer","paint","particles","personal","physical","progress",
"quarter","recognise","replace","rhythm","situation","slightly","steady","stepped",
"strike","successful","sudden","terrible","traffic","unusual","volume","yesterday" };
public String mysteryWord;
public int lives;
private boolean finished = false;
private boolean won = false;
private Button a[];
public boolean used[] = new boolean[26];
public static void main (String[] args) {
Hangman gui = new Hangman();
gui.go();
}
class myDrawPanel extends JPanel {
public void paintComponent(Graphics g) {
setBackground(Color.white);
g.setColor(Color.gray);
g.fillRect(50, 200, 150, 20);
g.fillRect(90,20,10,200);
g.fillRect(90,20,60,10);
g.setColor(Color.black);
g.fillRect(145,20,5,25);
g.setColor(Color.green);
if (lives < 6 )
g.drawOval(132,45,30,30);
if (lives < 5 )
g.drawLine(147,75,147,100);
if (lives < 4 )
g.drawLine(147,100,167,133);
if (lives < 3 )
g.drawLine(147,100,127,133);
if (lives < 2 )
g.drawLine(147,75,167,85);
if (lives < 1 )
g.drawLine(147,75,127,85);
StringBuffer guessed = new StringBuffer();
for (int cl = 0; cl < mysteryWord.length(); cl++) {
if (used[(int)mysteryWord.charAt(cl)-65])
guessed.append(mysteryWord.charAt(cl));
else
guessed.append(".");
}
g.drawString(guessed.toString(),75,230);
//currentWordLA.setText("Current word: " + mysteryWord);
if (lives < 1) {
g.setColor(Color.white);
g.fillRect(70, 200, 200, 30);
g.setColor(Color.black);
g.drawString(mysteryWord.toString(),75,230);
Font fff = new Font("Helvetica",Font.BOLD,36);
g.setFont(fff);
g.setColor(Color.red);
g.drawString("You lose!",200,100);
finished = true;
}
if (won) {
Font fff = new Font("Helvetica",Font.BOLD,36);
g.setFont(fff);
// Color red=new Color.red
g.setColor(Color.red);
g.drawString("You Win!",200,100);
finished = true;
}
}
}
public void go() {
///////////////////////DESIGN BEGIN//////////////////////////////////////////////
frame = new JFrame("Hangman");
JPanel topPanel = new JPanel();
myDrawPanel noosePanel = new myDrawPanel();
JPanel bottomPanel = new JPanel();
JPanel scorePanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout( new GridLayout( 2, 0) );
bottomPanel.setLayout( new GridLayout( 0, 2) );
scorePanel.setSize(20,100);
noosePanel.setBorder(BorderFactory.createTitledBorder("Your progress."));
topPanel.setBorder(BorderFactory.createTitledBorder("Your arsenal."));
scorePanel.setBorder(BorderFactory.createTitledBorder("Your score."));
frame.add(topPanel);
frame.add(bottomPanel);
bottomPanel.add(scorePanel);
bottomPanel.add(noosePanel);
//Just the stats panel.
JPanel stats = new JPanel();
JLabel currentWordLA = new JLabel("Current word:");
JLabel triedLettersLA = new JLabel("Tried letters:");
JLabel triesLeftLA = new JLabel("Tries remaining:");
JButton restart = new JButton("Reset");
currentWordLA.setFont(new Font("Verdana", Font.PLAIN, 10));
currentWordLA.setForeground(Color.black);
triedLettersLA.setFont(new Font("Verdana", Font.PLAIN, 10));
triedLettersLA.setForeground(Color.black);
triesLeftLA.setFont(new Font("Verdana", Font.PLAIN, 10));
triesLeftLA.setForeground(Color.black);
restart.setFont(new Font("Verdana", Font.PLAIN, 16));
restart.setForeground(Color.red);
stats.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.insets = new Insets(20,0,0,0);
c.anchor = GridBagConstraints.LINE_START;
stats.add(currentWordLA, c);
c.gridx = 0;
c.gridy = 1;
c.anchor = GridBagConstraints.LINE_START;
stats.add(triedLettersLA, c);
c.gridx = 0;
c.gridy = 2;
c.anchor = GridBagConstraints.LINE_START;
stats.add(triesLeftLA, c);
c.gridx = 0;
c.gridy = 3;
c.anchor = GridBagConstraints.LINE_START;
stats.add(restart, c);
scorePanel.add(stats);
///////////////////////DESIGN END//////////////////////////////////////////////
///////////////////////ALPHABET BEGIN//////////////////////////////////////////
int i;
StringBuffer buffer;
a = new Button[26];
topPanel.setLayout( new GridLayout( 4,0, 10, 10) );
for (i = 0; i <26; i++) {
buffer = new StringBuffer();
buffer.append((char)(i+65));
a[i] = new Button(buffer.toString());
a[i].setSize(100,100);
a[i].addActionListener( this );
topPanel.add(a[i]);
}
///////////////////////ALPHABET END//////////////////////////////////////////
//Just shows the entire window.
frame.setSize(500, 500);
frame.setResizable(false);
frame.setVisible(true);
//////////////////////GAMEPLAY BEGIN////////////////////////////////////////
lives = 6;
mysteryWord = wordGen();
}
//Returns a random word from the wordList bank.
private String wordGen() {
return wordList[0 + (int)(Math.random() * ((63 - 0) + 1)) ]; //Make sure to set these to nonprinted chars eventually
}
public void consultWord(int letter) {
if (finished == false) {
boolean found = false;
boolean www = false;
if (used[letter] = false) {
for (int cl = 0 ; cl < mysteryWord.length(); cl++) {
if (mysteryWord.charAt(cl)==((char)(letter+65))) found = true;
}
if (found == false)
lives = lives - 1;
}
used[letter] = true;
for (int cl = 0; cl < mysteryWord.length(); cl++) {
if (!used[(int)(mysteryWord.charAt(cl)) - 65]) www = true;
}
if (www = false) won = true;
frame.repaint();
}
}
public void actionPerformed( ActionEvent e) {
int i;
for (i = 0; i < 26; i++) {
if (e.getSource() == a[i]) {
consultWord(i); }
}
}
}
At the moment this doesn't work. I run it, and tons of thread exeption errors come up. (It compiles beautifully). The first line it takes me to is
if (used[(int)mysteryWord.charAt(cl)-65])
I'm not sure what the issue is with this line. Also, the original author used the number 65. I tweaked my code and used my own variables so that I understood how it worked. But the number 65 and where it came from, I can't figure out for the life of me. Any ideas?
And I need to know what is causing all the thread exceptions. The GUI builds nicely. It's just all the math and triggers that mess things up. (The GUI I built all by myself! :) )
Exception
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: 34
at Hangman$myDrawPanel.paintComponent(Hangman.java:55)
at javax.swing.JComponent.paint(JComponent.java:1054)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
at javax.swing.JComponent.paint(JComponent.java:1063)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:585)
at javax.swing.JComponent.paintChildren(JComponent.java:887)
Upvotes: 1
Views: 783
Reputation: 719396
This is mostly not a direct answer to your question, but it is relevant to the larger issue of learning to write software ... which is your overall goal. (And there's a real answer at the bottom.)
You write:
(it's really an abomination of about 10 open source hangman games thrown together)
Taking a bunch of existing programs (of dubious quality *) and mashing them together is NOT a good way to create software.
Code reuse can be a good thing, but you need to be disciplined and selective:
(* The fact that you are seeing obscure numbers like 65 embedded in the code is a sign of poor code quality. The author could and should have written that as 'A'
.)
In fact, this might be the root of your bug, since it looks like your "mystery" words are in lowercase. 'a' - 'A'
is 32
, and that is larger than the bounds of your used
array.
And this brings us back to my main point. Because, apparently, in your code mashing you have failed to understand the implied invariants of the code you copied ... and broken them. The problematic statement that is throwing the exception is designed to work with uppercase-only words ... but you've changed that.
Upvotes: 6
Reputation: 21912
65 is ASCII for 'A', but your words are all in lowercase. So instead of (int)mysteryWord.charAt(cl)-65
, you should do (int)mysteryWord.charAt(cl)-'a'
Upvotes: 1
Reputation: 23186
change
if (used[(int)mysteryWord.charAt(cl)-65])
guessed.append(mysteryWord.charAt(cl));
else
guessed.append(".");
}
to
if (used[(int)mysteryWord.charAt(cl)-97])
guessed.append(mysteryWord.charAt(cl));
else
guessed.append(".");
}
The code at line 55, when converting to ASCII, is ending up with a value larger than the size of the used array.
Upvotes: 0
Reputation: 18252
The 65 is the ASCII character code for the letter 'A'. The line in question is converting from the ASCII ordinal value to something in the range 0-25, which allows the used
array to store whether each letter of the alphabet has been checked.
Upvotes: 1