Possible Duplicate:
Java hangman game with gui, problems with incrementing/decrementing numbers
So the problem is that I suck at swing, have no idea how to work with the keylistener, which starts listening to the keys too many times (2 keys recorded after 2nd game, 3 keys after 3rd and so on). I do not know how to work with the Event Dispatch Thread properly or should I even use it, and the won/lost count increments wrongly. Moreover, when i want the frame to listen to keyboard input i request its focus in window, but I don’t know how to unfocus it when I dont want the frame to read keyboard input. Any help is welcome. This is my second time asking this question, and hopefully I have made the program and the problem a bit more comprehensible this time. EDIT: game now works, also with added bufferedwriter that writes a log file. Sorry, was too lazy to change some naming parts of the code to English, as they are in Lithuanian.
import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.*;
public class Hangman {
static int won = 0;
static int lost = 0;
static String key = "";
static String word = null;
static int no = 0;
static StringBuffer toguess;
static KeyboardFocusManager manager;
static Runnable hangman;
static ArrayList<String> tried;
static int gamecount = 0;
@SuppressWarnings("resource")
public static void main(String[] args) throws IOException {
FileWriter filewriter = new FileWriter("rezultatai.txt", true);
final BufferedWriter writer = new BufferedWriter(filewriter);
final DateFormat dateFormat = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
final Date date = new Date();
hangman = new Runnable() {
public void run() {
final JFrame frame = new JFrame();
frame.setLayout(new GridLayout(4, 1));
final JLabel label = new JLabel();
label.setFont(new Font("Serif", Font.BOLD, 48));
label.setForeground(Color.GREEN);
label.setText("Kaledines kartuves");
final JPanel panel1 = new JPanel();
final JPanel panel2 = new JPanel();
final JPanel panel3 = new JPanel();
final JPanel panel4 = new JPanel();
final JLabel label3 = new JLabel();
panel1.add(label);
panel4.add(label3);
final JLabel label2 = new JLabel();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
final JButton button = new JButton("Pradeti");
panel2.add(button);
frame.add(panel1);
frame.add(panel2);
frame.add(panel3);
frame.setSize(800, 600);
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
gamecount = gamecount + 1;
no = 0;
label3.setText("6 tries left");
frame.add(panel4);
frame.setFocusable(true);
frame.requestFocusInWindow();
label2.setText("won " + won + ", lost " + lost);
panel3.add(label2);
button.setText("Sekantis");
BufferedReader reader = null;
try {
reader = new BufferedReader(new FileReader("hangeng.txt"));
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
int lineno = (int) (Math.random() * 167);
for (int i = 0; i < lineno; i++) {
try {
reader.readLine();
} catch (IOException e1) {
e1.printStackTrace();
}
}
word = null;
try {
word = reader.readLine().replace(" ", "");
} catch (IOException e1) {
e1.printStackTrace();
}
String missing = "";
for (int u = 0; u < (word.length() - 2); u++) {
missing = missing + "*";
}
final String guess = word.charAt(0) + missing
+ word.charAt((word.length() - 1));
toguess = new StringBuffer(guess);
label.setText(toguess.toString());
tried = new ArrayList<String>();
}
});
frame.addKeyListener(new KeyListener() {
@Override
public void keyPressed(KeyEvent e) {
}
@Override
public void keyReleased(KeyEvent e) {
}
@Override
public void keyTyped(KeyEvent e) {
if ((no == 6) && (!(toguess.toString().equals(word)))) {
frame.setFocusable(false);
button.requestFocusInWindow();
label.setText("Deja, bet zodis buvo " + word);
lost = lost + 1;
}
key = String.valueOf(e.getKeyChar());
String guessing = key;
Boolean k = false;
if ((no < 6)) {
k = false;
if (!(tried.contains(guessing))) {
tried.add(guessing);
for (int length = 1; length < (word.length()
- 1); length++) {
if (guessing.equals(word.substring(length,
(length + 1)))) {
toguess.replace(length, (length + 1),
String.valueOf(word.charAt(length)));
k = true;
}
}
if (k == false) {
no = no + 1;
}
}
label.setText(toguess.toString());
if (toguess.toString().equals(word)) {
label.setText("Teisingai! Zodis buvo " + word);
frame.setFocusable(false);
button.requestFocusInWindow();
no = 6;
won = won + 1;
}
}
label3.setText((6 - no) + " tries left");
}
});
frame.addWindowListener(new java.awt.event.WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent windowEvent) {
try {
writer.write(System.getProperty("line.separator")
+ dateFormat.format(date)
+ System.getProperty("line.separator")
+ (gamecount - 1) + " games played, "
+ lost + " lost " + won + " won");
} catch (IOException e) {
e.printStackTrace();
}
try {
writer.flush();
} catch (IOException e) {
e.printStackTrace();
}
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
});
}
};
hangman.run();
}
}
Some hints to get you on the right track:
You’re adding a key listener to the frame in the
actionPerformed()method. This means that each time the button is clicked, a new key listener is added to the frame. The key listener should be added once, and only once, when the frame is initialized.If you don’t want to listen on key presses, then you could just set a
keyTypedIgnoredflag to true. In the key listener, if this flag is true, you ignore the event. And if it’s set to false, then you do something.Regarding the EDT, yes, all swing interactions should be done on the EDT. The Runnable should be invoked using
SwingUtilities.invokeLater(runnable), as explained in the Swing tutorial.And finally, maybe the most important advice, don’t do everything in a single giant method. Separate the code in objects and methods doing a specifc task. Add some blank lines to make the code readable. Indent the code properly.