1

我是 Java 的初学者,需要为 Java 最终项目组合一个应用程序。我想做刽子手(当时看起来很容易)。这对我来说非常困难。到目前为止,这是我的代码。(这真是令人厌恶的大约 10 个开源刽子手游戏拼凑在一起)。我的问题见底部。

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); }
  }
}       
}

目前这不起作用。我运行它,然后出现大量线程异常错误。(它编译得很漂亮)。带我去的第一行是

if (used[(int)mysteryWord.charAt(cl)-65])

我不确定这条线有什么问题。此外,原作者使用了数字 65。我调整了代码并使用了自己的变量,以便了解它是如何工作的。但是数字 65 和它来自哪里,我一辈子都想不通。有任何想法吗?

我需要知道是什么导致了所有线程异常。GUI 构建得很好。只是所有的数学和触发器把事情搞砸了。(我自己构建的GUI!:))

例外

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)
4

4 回答 4

6

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.

  • You inherit the problems of functionality and style in the existing code that you have "harvested".
  • You add a bunch of new functionality and style problems caused by mismatches between the different code bases ... and your conception.

Code reuse can be a good thing, but you need to be disciplined and selective:

  • Do design your own code ... following the design principles that you have been taught.
  • Do reuse at the library level, using well-engineered libraries.
  • Don't reuse by copy-and-pasting.
  • Don't reuse code (or libraries) that looks like a dog's breakfast. (If the author is sloppy with his/her code style and API design, that's a bad sign for other quality issues.)

(* 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.

于 2012-05-07T02:49:47.793 回答
1

65 是字母“A”的 ASCII 字符代码。有问题的行是从 ASCII 序数值转换为 0-25 范围内的值,这允许used数组存储是否已检查字母表的每个字母。

于 2012-05-07T02:11:33.687 回答
1

65 是 'A' 的 ASCII,但你的单词都是小写的。所以,而不是(int)mysteryWord.charAt(cl)-65,你应该做(int)mysteryWord.charAt(cl)-'a'

于 2012-05-07T03:02:57.523 回答
0

改变

if (used[(int)mysteryWord.charAt(cl)-65])
    guessed.append(mysteryWord.charAt(cl));
else
    guessed.append(".");
}

if (used[(int)mysteryWord.charAt(cl)-97])
    guessed.append(mysteryWord.charAt(cl));
else
    guessed.append(".");
}

第 55 行的代码在转换为 ASCII 时,最终的值大于所用数组的大小。

于 2012-05-07T03:00:22.517 回答