我有一个用Java编写的游戏,可以在命令行上完美运行。但是,我一直在为它构建一个GUI,并且一直在改变它,因此它在GUI上运行,但我遇到了问题。这是一个刽子手游戏,允许玩家猜字母,试图猜测刽子手的话。如果玩家做出正确的猜测,游戏会显示某个消息,如果玩家猜错,游戏会显示不同的消息。虽然我已经使用GUI版本进行了两次猜测,但游戏停止了工作...我已经尝试修复它几天但没有运气......我试过调用javax.swing.SwingUtilities.invokeLater
但它是仍然给我问题。
任何帮助将不胜感激,下面是代码(p.s.我仍在将命令行中的东西移动到GUI):
import java.util.ArrayList;
import java.util.Scanner;
public class HangmanTwo {
private String[] wordList = {"apple", "orange"};
private String chosenWord;
private String playerGuess;
private int numberOfIncorrectGuesses = 0;
private boolean playerWon = false;
private boolean playerPlaying = false;
public static String uInput1;
private boolean start = false;
private ArrayList<String> lettersOfChosenWord;
private ArrayList<String> incorrectGuessArrayList2 = new ArrayList<String>();
private ArrayList<String> underScores;
private boolean showHangman = false;
HangmanGuiGui hh = new HangmanGuiGui();
//Print game instructions to player
void printGameInstructions() {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
hh.buildGui();
hh.textFieldSouth.requestFocus();
hh.textAreaCenter.append("Welcome to Hangman! \n");
hh.textAreaCenter.append("To play, type in a letter as your guess, then press ENTER! \n");
hh.textAreaCenter.append("If you think you know the word, type in the whole word and see if you got it right! \n");
hh.textAreaCenter.append("But be careful! Guessing the word incorrectly will cost you a limb! \n");
hh.textAreaCenter.append("To start playing, type 'start' and press ENTER. \n");
}
});
}
//Ask player if they want to start the game
void askToStart() {
uInput1 = "waitingforinput";
while (!start) {
if(uInput1.equals("waitingforinput")) {
} else if ((uInput1).equals("start")) {
start = true;
uInput1 = "waitingforInput";
} else {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
hh.textAreaCenter.append("Please type the word 'start' then press the ENTER key to begin playing. \n");
}
});
uInput1 = "waitingforinput";
}
}
}
//Game picks random word from word list
void pickRandomWord() {
int lengthOfWordList = wordList.length;
int pickRandomWord = (int) (Math.random() * lengthOfWordList);
chosenWord = wordList[pickRandomWord];
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
hh.textAreaCenter.append("The word is " + chosenWord.length() + " letters long\n");
}
});
}
//Make an arraylist to hold each letter of the chosen word at each index
void makeArrayListOfChosenWord(){
lettersOfChosenWord = new ArrayList<String> ();
for (int i = 0; i < chosenWord.length(); i++) {
lettersOfChosenWord.add(chosenWord.substring(i, i+1));
}
}
//Make an arraylist of underscores that holds as
//many underscores as letters in the chosen word
void makeArrayListUnderScore(){
underScores = new ArrayList<String>();
for (int i = 0; i < chosenWord.length(); i++) {
underScores.add("_");
}
for (int i = 0; i < underScores.size(); i++) {
//hh.textAreaWest.append((underScores.get(i)).toString());
//show the underscores in the text area
}
}
//get a guess from the player
void getPlayerGuess() {
boolean getGuess = true;
uInput1 = "waitingforinput";
while (getGuess) {
if (uInput1.equals("")) {
//javax.swing.SwingUtilities.invokeLater(new Runnable() {
//public void run() {
hh.textAreaCenter.append("Please guess a letter\n");
//}
//});
uInput1 = "waitingforinput";
} else if (uInput1.equals("waitingforinput")) {
} else {
playerGuess = uInput1;
//javax.swing.SwingUtilities.invokeLater(new Runnable() {
//public void run() {
hh.textAreaCenter.append(playerGuess + "\n");
//}
//});
getGuess = false;
}
}
}
//if the player wins, set the variable playerWon to true
void setPlayerWon(boolean a) {
playerWon = a;
}
//start the game and play it
void playGame() {
playerPlaying = true;
while (playerPlaying && !playerWon) {
getPlayerGuess();
if (playerGuess.equals(chosenWord)) {
playerPlaying = false;
wordWasGuessed();
}else if (numberOfIncorrectGuesses < 6) {
checkPlayerGuess();
if (playerWon) {
playerPlaying = false;
wordWasGuessed();
} else if (numberOfIncorrectGuesses == 6) {
playerPlaying = false;
gameOver();
}
}
}
}
//check the player's guess and see if its correct or not
void checkPlayerGuess(){
//update number of incorrect guesses
if (lettersOfChosenWord.contains(playerGuess)) {
System.out.println("Correct guess!");
if (!showHangman) {
displayNoose();
}
displayHangman();
replaceUnderScoreWithLetter();
if (!underScores.contains("_")) {
setPlayerWon(true);
}
} else if (!lettersOfChosenWord.contains(playerGuess)) {
checkIncorrectGuessArrayList();
}
}
//check the incorrectguess array list and add incorrect letters to it
void checkIncorrectGuessArrayList() {
if (incorrectGuessArrayList2.contains(playerGuess)) {
System.out.printf("You already guessed %s, try again!", playerGuess);
} else if (!incorrectGuessArrayList2.contains(playerGuess)) {
if (numberOfIncorrectGuesses < 6) {
System.out.println("You guessed wrong, try again!");
incorrectGuessArrayList2.add(playerGuess);
++numberOfIncorrectGuesses;
displayHangman();
printArrayListUnderScore();
}
}
}
//replace the underscores with a letter
void replaceUnderScoreWithLetter() {
while (lettersOfChosenWord.contains(playerGuess)) {
int indexOfPlayerGuess = lettersOfChosenWord.indexOf(playerGuess);
underScores.set(indexOfPlayerGuess, playerGuess);
lettersOfChosenWord.set(indexOfPlayerGuess, "_");
incorrectGuessArrayList2.add(playerGuess);
}
printArrayListUnderScore();
}
//show the underscores to the player
void printArrayListUnderScore() {
for (int j = 0; j < underScores.size(); j++) {
System.out.print((underScores.get(j)).toString());
}
}
void resetAllValues(int resetNumberIncorrectGuesses, boolean hangmanshow) {
numberOfIncorrectGuesses = resetNumberIncorrectGuesses;
lettersOfChosenWord.removeAll(lettersOfChosenWord);
incorrectGuessArrayList2.removeAll(incorrectGuessArrayList2);
underScores.removeAll(underScores);
showHangman = hangmanshow;
}
void displayNoose(){
System.out.println(" ___,");
System.out.println(" l ");
System.out.println(" l");
System.out.println("_l_");
}
//Display a growing hangman with each incremental wrong guess
void displayHangman(){
switch (numberOfIncorrectGuesses) {
case 1: firstWrongGuess();
showHangman = true;
break;
case 2: secondWrongGuess();
break;
case 3: thirdWrongGuess();
break;
case 4: fourthWrongGuess();
break;
case 5: fifthWrongGuess();
break;
case 6: sixthWrongGuess();
break;
}
}
void firstWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l");
System.out.println("_l_");
}
void secondWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l l");
System.out.println("_l_");
}
void thirdWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l");
System.out.println("_l_");
}
void fourthWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l\\");
System.out.println("_l_");
}
void fifthWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l\\");
System.out.println("_l_/");
}
void sixthWrongGuess(){
System.out.println(" ___,");
System.out.println(" l o ");
System.out.println(" l /l\\");
System.out.println("_l_/ \\");
}
//what happens if the chosenWord was guessed
void wordWasGuessed() {
hh.textAreaCenter.append("******\n");
hh.textAreaCenter.append("GOOD JOB! YOU GUESSED THE WORD!\n");
hh.textAreaCenter.append("You wanna play again? (y/n)\n");
resetGame(0, false, false);
boolean playAgain = false;
while (!playAgain) {
Scanner s = new Scanner(System.in);
String userInput = s.next();
if (userInput.equals("y")) {
playAgain = true;
resetAllValues(0, false);
startGame();
} else if (userInput.equals("n")) {
playAgain = true;
System.out.println("Ok...See you next time!");
} else {
System.out.println("please type y or n, then press enter!");
}
}
}
//what happens when the player loses and game is over
void gameOver() {
System.out.println("Aww you lost... the word was " + chosenWord);
System.out.println("You wanna play again? (y/n)");
resetGame(0, false, false);
boolean playAgain = false;
while (!playAgain) {
Scanner s = new Scanner(System.in);
String userInput = s.next();
if (userInput.equals("y")) {
playAgain = true;
resetAllValues(0, false);
startGame();
} else if (userInput.equals("n")) {
playAgain = true;
System.out.println("Ok...See you next time!");
} else {
System.out.println("please type y or n, then press enter!");
}
}
}
//reset the game
void resetGame(int resetNumberIG, boolean resetPlayerWon, boolean resetPlayerPlaying) {
numberOfIncorrectGuesses = resetNumberIG;
playerWon = resetPlayerWon;
playerPlaying = resetPlayerPlaying;
}
void startGame() {
pickRandomWord();
makeArrayListOfChosenWord();
makeArrayListUnderScore();
}
public static void main(String[] args) throws InterruptedException {
HangmanTwo h = new HangmanTwo();
h.printGameInstructions();
h.askToStart();
if (h.start == true) {
h.startGame();
h.playGame();
}
}
}
和GUI
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class HangmanGuiGui {
TextFieldSouthHandler tfsHandler = new TextFieldSouthHandler();
ButtonEnterHandler beHandler = new ButtonEnterHandler();
JFrame frame = new JFrame("Hangman");
JLabel label = new JLabel("Welcome to Hangman");
public JTextArea textAreaCenter = new JTextArea();
JTextField textFieldSouth = new JTextField();
JScrollPane scrollPane = new JScrollPane();
JPanel panelWest = new JPanel(new BorderLayout());
JPanel subPanelWest = new JPanel();
JTextArea textAreaWest = new JTextArea();
JPanel panelSouth = new JPanel(new BorderLayout());
JButton buttonEnter = new JButton("Enter");
//Icon aba = new ImageIcon(getClass().getResource("hangman1.jpg"));
//JLabel picLabel = new JLabel(aba);
JPanel panelEast = new JPanel();
void buildGui() {
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
textAreaCenter.setEditable(false);
textFieldSouth.addKeyListener(tfsHandler);
textAreaWest.setEditable(false);
buttonEnter.addActionListener(beHandler);
panelSouth.add(BorderLayout.CENTER, textFieldSouth);
panelSouth.add(BorderLayout.EAST, buttonEnter);
//subPanelWest.add(picLabel);
JPanel panelwesteast = new JPanel();
JPanel panelwestwest = new JPanel();
JPanel panelwestsouth = new JPanel();
panelWest.add(BorderLayout.SOUTH, panelwestsouth);
panelWest.add(BorderLayout.EAST, panelwesteast);
panelWest.add(BorderLayout.WEST, panelwestwest);
panelWest.add(BorderLayout.NORTH, subPanelWest);
panelWest.add(BorderLayout.CENTER, textAreaWest);
scrollPane.getViewport().setView (textAreaCenter);
frame.getContentPane().add(BorderLayout.NORTH, label);
frame.getContentPane().add(BorderLayout.CENTER, scrollPane);
frame.getContentPane().add(BorderLayout.SOUTH, panelSouth);
frame.getContentPane().add(BorderLayout.WEST, panelWest);
frame.getContentPane().add(BorderLayout.EAST, panelEast);
frame.setSize(800, 600);
frame.setVisible(true);
}
private class TextFieldSouthHandler implements KeyListener {
public void keyPressed(KeyEvent event) {
if (event.getKeyCode()==KeyEvent.VK_ENTER) {
//boolean bee = javax.swing.SwingUtilities.isEventDispatchThread();
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
HangmanTwo.uInput1 = textFieldSouth.getText();
textFieldSouth.setText("");
}
});
}
}
public void keyTyped(KeyEvent event) {
}
public void keyReleased(KeyEvent event) {
}
}
private class ButtonEnterHandler implements ActionListener {
public void actionPerformed(ActionEvent event) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
HangmanTwo.uInput1 = textFieldSouth.getText();
textFieldSouth.setText("");
textFieldSouth.requestFocus();
}
});
}
}
}
/*javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
}
}); */
答案 0 :(得分:4)
为了避免重大问题,您应该重新设计应用程序的控制权。
如果没有GUI,您可以直接控制流程:等待输入,处理,显示结果,重复。
使用GUI,您将显示一个窗口,然后不执行任何操作。当用户输入内容时,GUI会调用您的一种回调方法,并根据您当前的状态做出反应。
所以:不要试图拥有一个控制线程,很容易遇到很多线程问题。设置一些变量,告诉你当前游戏状态是什么(等待“START”关键字,等待猜测,完成......),并在用户做某事时更新它们。
答案 1 :(得分:3)
你已经完全翻译了一个主循环结构,它非常适合于命令行应用程序。然后,您将自己沉浸在主线程中的无限循环中,寻找共享变量的变化。这与Swing管理事物的方式相冲突,应用程序的主线程对于Swing管理其重新绘制及其事件处理至关重要,并且您的代码正在与处理器竞争。我认为我们可以为Swing应用程序考虑更好的设计。
你有2个可能性:
顺便说一句,无论你做出什么决定,我都强烈建议你删除所有invokeLater(new Runnable()...),这是不必要的,也许是危险的(你可以通过这样做来介绍你的事件处理程序之间的竞争条件)