Reputation: 2207
So, I know this question has been asked before, but thoes answers will not work for the current structure of my program. I have a game of tic-tac-toe. In the games algorithm, when its time for a users turn I have it call a method to get the X & Y coords of a Mouse Click. However, I would like this method to first prompt a user for a click, then wait for the user to click, THEN get the x & y of the click for the game algorithm to use. Currently, it is just pulling the x & y of the last click giving no time for the user to click when their turn starts. The only thought I had to fix this problem was running the game and user code on 2 threads and having one sleep. But, this seems overly complex and I'd prefer not to do this. The whole situation seems like a very fundamental problem, waiting for a mouseclick before executing code. How do I do this?
void takeTurn() {
//turnCount++;
while(gameOver == false) {
if (turn == 'O') {
O.getInput();
if(board[O.x][O.y] != '\u0000') continue;
board[O.x][O.y] = 'O';
}
else if (turn == 'X') {
X.getInput();
if(board[X.x][X.y] != '\u0000') continue;
board[X.x][X.y] = 'X';
}
printBoard();
if (checkWinner(turn) == turn) {
System.out.println("Winner: " + turn);
}
if (turn == 'O') turn = 'X';
else if (turn == 'X') turn = 'O';
}
}
EDIT: getInput() is the method that gets the x & y.
public void getInput() {
System.out.println("Click on your tile");
//wait for click here
//then get x & y of click
}
EDIT: Okay, so using an ActionListener, how do I have a thread wait until an action is preformed?
Upvotes: 1
Views: 1631
Reputation: 285440
The key is not to "wait" for the mouse input, but rather, to change the behavior of the program to mouse press depending on its state. For instance, if you're doing tic-tac-toe, you'll want to give the program a variable to let it know whose turn it is, and this could be a simple boolean variable, say
private boolean xTurn = true;
When this variable is true, it's X's turn, when false, it is O's turn.
Then in your MouseListener (if a Swing application), use the variable to help decide what to do, and then after using it, toggle the boolean to the next state. For example:
// within mouse listener
if (xTurn) {
label.setForeground(X_COLOR);
label.setText("X");
} else {
label.setForeground(O_COLOR);
label.setText("O");
}
// toggle value held by boolean variable.
xTurn = !xTurn;
For example:
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
@SuppressWarnings("serial")
public class TicTacToePanel extends JPanel {
private static final int ROWS = 3;
private static final int MY_C = 240;
private static final Color BG = new Color(MY_C, MY_C, MY_C);
private static final int PTS = 60;
private static final Font FONT = new Font(Font.SANS_SERIF, Font.BOLD, PTS);
public static final Color X_COLOR = Color.BLUE;
public static final Color O_COLOR = Color.RED;
private JLabel[][] labels = new JLabel[ROWS][ROWS];
private boolean xTurn = true;
public TicTacToePanel() {
setLayout(new GridLayout(ROWS, ROWS, 2, 2));
setBackground(Color.black);
MyMouse myMouse = new MyMouse();
for (int row = 0; row < labels.length; row++) {
for (int col = 0; col < labels[row].length; col++) {
JLabel label = new JLabel(" ", SwingConstants.CENTER);
label.setOpaque(true);
label.setBackground(BG);
label.setFont(FONT);
add(label);
label.addMouseListener(myMouse);
}
}
}
private class MyMouse extends MouseAdapter {
@Override // override mousePressed not mouseClicked
public void mousePressed(MouseEvent e) {
JLabel label = (JLabel) e.getSource();
String text = label.getText().trim();
if (!text.isEmpty()) {
return;
}
if (xTurn) {
label.setForeground(X_COLOR);
label.setText("X");
} else {
label.setForeground(O_COLOR);
label.setText("O");
}
// information to help check for win
int chosenX = -1;
int chosenY = -1;
for (int x = 0; x < labels.length; x++) {
for (int y = 0; y < labels[x].length; y++) {
if (labels[x][y] == label) {
chosenX = x;
chosenY = y;
}
}
}
// TODO: check for win here
xTurn = !xTurn;
}
}
private static void createAndShowGui() {
TicTacToePanel mainPanel = new TicTacToePanel();
JFrame frame = new JFrame("Tic Tac Toe");
frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationByPlatform(true);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGui();
}
});
}
}
Upvotes: 2
Reputation: 6816
You have it backwards it not that you need to wait for the input. What you need to do is an action when the mouse is clicked. Saying that all other questions still answers what you want to do. You can follow https://docs.oracle.com/javase/tutorial/uiswing/events/mouselistener.html and come up with a solution. Another good example is Java MouseListener
Upvotes: 1