I am having issues setting up a computer vs computer loop in my java game applet. I have been trying for 3 days now to effectively add a one second delay between the two computer-player turns, while also repainting the board. I have tried try/catch/thread.sleep and wait and a few other tricks, however none have been successful. In the program's current state, when a computer vs computer game is initiated, the program freezes for the duration of the game (with one second delays between moves) and then displays the final board when the game has finished. How can I make it so the program repaints/delays after each move? From all of the reading I have done, I am aware that the following implementation will not work but my issue is I cannot figure out how to do it any other way.
Thanks in advance!
The following code is inside my actionPerformed listener method
if (event.getSource() == startAIvAI)
{
drawing.clear();
while (drawing.hasWon() == -1 && !drawing.isFull())
{
go1();
repaint();
try {
Thread.sleep(1000);
} catch (Exception e) {}
go2();
repaint();
try {
Thread.sleep(1000);
} catch (Exception e) {}
}
}
When you invoke Thread.sleep(1000); which Thread do you think you're pausing? Probable the one handling event given your code start with if (event.getSource() == startAIvAI).
You should read this to understand what to do: Sleep method locks my GUI
Related
Okay so, I'm trying to make a tic tac toe that has a network option. I've wrote this code but I'm having a little problem.
public void actionPerformed(ActionEvent e)
{
JButton temp=(JButton)e.getSource();
//temp.setText("X");
if(turn%2==0)
{
temp.setText("X");
temp.setIcon(gui.imgX);
temp.setDisabledIcon(gui.imgX);
gui.repaint();
gui.revalidate();
turn++;
try {
for(int i=0;i<gui.buttons.length;i++)
if(temp==gui.buttons[i])
out.write(i);
} catch (IOException e1) {
e1.printStackTrace();
}
}
if(turn%2==1)
{
try {
System.out.println(turn);
gui.buttons[in.read()].setText("O");
gui.revalidate();
System.out.println(turn);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
turn++;
}
}
Okay so, whenever I click on a button, it runs inside the next if condition(turn%2==0), but doesn't set the button icon or text. However, it actually sets it somehow in the background, so I icon and text come visible ONLY when it finishes the whole actionPerformed and reads an int from the other pc. So basically, it displays "X" and "O" together after finishing the whole actionPerformed method. How can I fix that so it shows "X" when a button gets pressed without waiting to read from the other pc. Note that it successfully write the int in the other pc and the button text/icon get changed there without waiting the other if condition.
At present you are mixing the UI things with the logic/ controller. I think it would be helpful, if you split it. I.e. while processing the ActionEvent you are waiting for the response from the "remote player", blocking all the other UI things.
I would try to move the control (whos turn it is and reading from remote station) into a background thread and then update the UI only if my turn was executed or I received the information from the remote player.
So I have a little puzzle made in Java, and let's just say there are buttons too on this puzzle which represent the puzzle. There is a solving method where a series of buttons are clicked to find a "solution", and it takes around 1 minute to solve it, so that is 1 minute of just clicking buttons
During this one minute, you notice the buttons being clicked by the computer as it changes color and shape during the program flow, I was wondering if there was a way to freeze the jframe before the solving() method is invoked and then unfreezes into the solution when the method is over?
I am a little confused to exactly what you are asking, but I would suggest using this code to do what I believe you are asking for
private static boolean solveDone = false; //This should go in a the class, not here.
//Create a new thread to handle processes while the JFrame is frozen
SwingUtilities.invokeLater(new Thread(){
public void run(){
//Code to run while the JFrame is frozen should be put here.
main.solveDone = true;
}
});
//Sleep the program until the process is done.
try{
while(!solveDone) {
Thread.sleep(10); //Interval in milliseconds to check if the puzzle is done goes here.
}
solveDone = false;
}catch(InterruptedException e){
e.printStackTrace();
System.exit(-1);
}
//Code to run after solving goes here.
Now, this isn't the cleanest way to do this type of thing, but I believe it should work.
On the other hand, if you know exactly how much time it is going to take, you could do this.
SwingUtilities.invokeLater(new Thread(){
public void run(){
//Code to run while the JFrame is frozen should be put here.
}
});
try{
Thread.sleep(1000); //The time in milliseconds to sleep the JFrame
}catch(InterruptedException e){
e.printStackTrace();
System.exit(-1);
}
//Code to run after solving goes here.
so Im doing a project of a tic tac toe using artificial intelligence, and I wanted to make an option so you could replay the game to see what happend in the last round, My intentions were to make the replay as its actually playing right now, which means after each move will be shown there wil lbe a delay and then the next one will occur.And instead of working as expected the delay jsut goes all at a time without anything happening until suddenyl the whole game just shows up without beinge displayed as a game but as a finishing screen' anyway here is the code:
replayMode=true;
setStatus("Replay Playing...");
ifButtonsEnabled(true);
initBoard();
int turn=0;
Move current;
for(int i=0;i<replayer.getSizeOfVect();i++)
{
current=replayer.getMoveAt(i);
if(i%2==0)
{
buttons[current.getI()][current.getJ()].setText("X");
}
else
{
buttons[current.getI()][current.getJ()].setText("O");
}
try {
Thread.sleep(650);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
setStatus("Replay ended.");
replayMode=false;
Usually when you see this kind of effect in a GUI program, it's because you need to yield control back to the GUI thread's event loop for any drawing to happen. Rather than Thread.sleep I recommend using a timer with a 650ms interval and doing one "step" of the animation with each tick of the timer.
Here is my loop code (This is the only code relating to my loop):
while(true)
{
try {
Thread.sleep(20);
System.out.println("1");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
When I launch the applet, it white screens and I cannot close it unless I press the "Terminate" button in eclipse.
You're blocking the UI Thread with an infinite while loop. You don't say whether you're using an AWT or Swing applet, either way the result will be the same. If you're using a Swing applet, use a Swing Timer. If you're using the old heavyweight AWT, convert it to Swing and follow the previous advice.
As said you made an infinity loop with:
while(true){
//something
}
There is no break; So why or what should stop the loop except of a thrown exception?
To see when a InterruptedException is thrown you should read the JavaDoc:
http://docs.oracle.com/javase/7/docs/api/java/lang/InterruptedException.html
You are hogging the applets EDT. You need to run your loop in another thread. Try adding Thread gameThread; as a variable and use
gameThread = new Thread() {
public void run() {
while (condition) {
//code here
}
}
}
and then gameThread.start() both in your applet start method and gameThread.join() in your applet stop method.
I'm having some trouble with an assignment I'm working on.
Part of it is to "animate" the rolling of a pair of die. I have 6 JPEGS, one of each of the sides. Instead of rolling, I want it to cycle through the images. I'm trying to use setIcon over and over in a loop, and use Thread.sleep() for a delay. This, among other things, all happens when the user hits a button (the event). Instead of displaying the images, it waits the correct amount of time and displays only the last image. Here's the function I'm calling to perform the loop:
private void aniRoll(){
for(int i = 0; i < 10; i++){
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
try{
Thread.sleep(1000); // Sleep for 1 sec
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face3.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face4.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face5.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face6.jpg")));
try{
Thread.sleep(1000);
}
catch(InterruptedException e){}
}
}
die1Disp is the name of my JLabel, aniRoll() is the function I'm calling to perform the loop (made private because I don't want anything outside of my GUI class to call it), and the faceX.jpg are my images.
What I can't understand is no matter where I put the Thread.sleep() it delays the program first, and then only displays the last image. For example:
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face1.jpg")));
die1Disp.setIcon(new javax.swing.ImageIcon(getClass().getResource("/face2.jpg")));
//bunch of extra code
try{
Thread.sleep(10000); // Sleep for 10 sec
}
catch(InterruptedException e){}
This will wait for 10 seconds and then display only the second image. It doesn't blip the first quickly, display the second, then wait, it waits and only displays the second image. This quirk really has me baffled, and I'm not sure how to correct it. I'm using NetBeans IDE 7.01 as my editor and for the basic layout and code generation I'm using a Component Palette.
--Thanks
First you must make the changes on the gui thread. See
SwingUtils.invokeLater.
Also Thread.sleep isn't going to cut it, you should be using a javax.swing.Timer to specify when to switch icons.
There's a single UI thread managing events and repainting (updating the screen). You put it to sleep. Doing so means that nothing else was going to happen (in regard to the UI) until it wakes up.
In your actionPerformed method, start a new Thread that will do the repainting. That should fix it.