I'm working on an app, where I show a question and a person can answer by using the arrow keys for yes/no, which loads a new question and so on. This works well, but I'm trying to implement a multiplayer mode aswell, where another person can use the a and d keys, which is causing problems.
Basically, if the two people answer very quickly one after another, the first input gets counted as the answer for the current question, which causes a new question to load and the second input gets counted as the answer for that new question, even though the person hadn't even seen that question when they answered.
I've tried updating the question later, but it still always remembered the second KeyPress and processes them one after another.
I've also tried working with boolean variables to indicate that a person has already pressed and that the other person's input shouldn't be counted, but it either didn't work as expected or created a deadlock.
I think it's probably because of the way Java handles the KeyEvents that the code that handles the events is processed in parallel, so the boolean variables weren't set in time for it to block from processing the second KeyEvent aswell.
My goal is that if two people answer while one question is showing, only the first person to answer can get the points for that (if both answered at exactly the same time, both would ideally get the points), then a new question is loaded and so on.
Minimal reproducable example:
public class Test extends JFrame{
int right_score;
int left_score;
JLabel r_score = new JLabel();
JLabel l_score = new JLabel();
boolean answer;
boolean clicked = false;
JLabel answer_label = new JLabel();
public static void main(String[] args) {new Test();}
public Test() {
addKeyBindings();
r_score.setText("Right: 0");
l_score.setText("Left: 0");
answer_label.setText("" + answer);
this.setLayout(new FlowLayout(FlowLayout.CENTER));
this.setMinimumSize(new Dimension(100, 100));
this.add(answer_label);
this.add(l_score);
this.add(r_score);
newQuestion();
this.setVisible(true);
}
private void newQuestion() {
Random rand = new Random();
answer = rand.nextBoolean();
answer_label.setText("" + answer);
}
public void r_pressed_yes() {
if (answer && !clicked) {
clicked = true;
right_score += 1;
r_score.setText("Right: " + right_score);
newQuestion();
clicked = false;
}
else if (!clicked){
clicked = true;
right_score -= 1;
r_score.setText("Right: " + right_score);
newQuestion();
clicked = false;
}
};
public void r_pressed_no() {
if (!answer && !clicked) {
clicked = true;
right_score += 1;
r_score.setText("Right: " + right_score);
newQuestion();
clicked = false;
}
else if (!clicked){
clicked = true;
right_score -= 1;
r_score.setText("Right: " + right_score);
newQuestion();
clicked = false;
}
};
public void l_pressed_yes() {
if (answer && !clicked) {
clicked = true;
left_score += 1;
l_score.setText("Left: " + left_score);
newQuestion();
clicked = false;
}
else if (!clicked){
clicked = true;
left_score -= 1;
l_score.setText("Left: " + left_score);
newQuestion();
clicked = false;
}
};
public void l_pressed_no() {
if (!answer && !clicked) {
clicked = true;
left_score += 1;
l_score.setText("Left: " + left_score);
newQuestion();
clicked = false;
}
else if (!clicked){
clicked = true;
left_score -= 1;
l_score.setText("Left: " + left_score);
newQuestion();
clicked = false;
}
};
private void addKeyBindings() {
Action r_pressed_yes = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
r_pressed_yes();
}};
Action r_pressed_no = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
r_pressed_no();
}};
Action l_pressed_yes = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
l_pressed_yes();
}};
Action l_pressed_no = new AbstractAction() {
public void actionPerformed(ActionEvent e) {
l_pressed_no();
}};
r_score.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("LEFT"), "r_pressed_yes");
r_score.getActionMap().put("r_pressed_yes", r_pressed_yes);
r_score.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("RIGHT"), "r_pressed_no");
r_score.getActionMap().put("r_pressed_no", r_pressed_no);
r_score.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("A"), "l_pressed_yes");
r_score.getActionMap().put("l_pressed_yes", l_pressed_yes);
r_score.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(KeyStroke.getKeyStroke("D"), "l_pressed_no");
r_score.getActionMap().put("l_pressed_no", l_pressed_no);
}
}