My program is coded in Java. I have an IF() check in run() method (in a Thread). In the IF check, if the condition is satisfied, it shows a Window dialog (using JOptionPane.showMessageDialog) with OK button. However, it shows infinitely. When I click OK it pops up again and again. How can I end the if check after the user click OK. Or when the condition is met, it only shows once ?
This is my method()
public void danhHoiWumpus()
{
if ((GameScreen.bg[x[0] + 1][y[0]] == 2) || (GameScreen.bg[x[0] + 2][y[0]] == 2) || (GameScreen.bg[x[0] + 3][y[0]] == 2) || (GameScreen.bg[x[0]][y[0]+1] == 2) || (GameScreen.bg[x[0]][y[0]+2] == 2) || (GameScreen.bg[x[0]][y[0]+3] == 2))
{
JOptionPane.showMessageDialog(this, "Có mùi wumpus ! \n Bạn được học bổng 40%");
}
}
This is my run() method
public void run()
{
while(true)
{
hunter.update();
hunter.danhHoiWumpus();
// i++;
repaint();
// System.out.println("Gia tri cua y la " +i);
try {
thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
The idea of this action is. When the RED square is going near the YELLOW square, it will pop up a dialog "I smell Wumpus". When the user click OK. They will choose to shot the wumpus (I will do this later).
And here is my full source code (for reference):
https://www.mediafire.com/?wkp6hyq32nq23mp
Thank you in advance.
Your code is executing in an infinite while loop
while(true)
// I am infinite
}
The term you are looking for is hit detection. There are a myriad of ways to achieve it. Look up hit detection in Java for some pointers.
What you have isn't necessarily wrong though.
while (true) // I'm not always bad!
is used in a lot of applications. However, while your code isn't completely posted, I don't see anywhere you break from this. You may be interested in the
java.util.Timer
and the
java.util.TimerTask
Both of those have wide application in Java game development
Your sleep time is too low (20 nanoseconds). Increase the time, otherwise it will happen too quick for you to understand it.
You are potentially triggering this if condition many many times.
You need some 'rising edge trigger' logic in order to only trigger when the new value goes from false to true, instead of triggering whenever it's true.
currentValue = bigLongLogicCheck;
if(!oldvalue&¤tValue) {alert()}
oldvalue = currentValue
Related
I'm aware or the Thread.sleep() and postDelayed() function in java/androidStudio.
But here is the issue, I'm creating a replicate of Simon says game.
I created a generateSequence() function that puts number of 1-9 randomly into an array called sequence. After that, I need to display these sequence, which basically changes the background of a textView for a second and then back to its original background using the postDelayed() function.
Here is my code:
private void displaySequence(){
for(int i = 0; i < sequence.size(); i++) {
if(sequence.get(i) == 1) {
viewCard11.setBackgroundResource(R.drawable.text_view_circle4);
proceed = false;
handler.postDelayed(() -> {
viewCard11.setBackgroundResource(R.drawable.text_view_circle3);
proceed = true;
}, 1000);
}
else if(sequence.get(i) == 2) {}
else if(sequence.get(i) == 3) {}
else if(sequence.get(i) == 4) {}
else if(sequence.get(i) == 5) {}
else if(sequence.get(i) == 6) {}
else if(sequence.get(i) == 7) {}
else if(sequence.get(i) == 8) {}
else if(sequence.get(i) == 9) {}
while(!proceed) {}
}
}
But the problem with postDelayed() is that only whatever is inside the function is delayed. Meaning if this sequence had 2 element, it will simultaneously blink the background. The for loop doesn't wait for the postDelayed to finish whatever it is suppose to do, but instead it increments and proceed to put the next postDelayed.
To solve this issue, I tried to use a proceed boolean variable as a delay. What I do is that, before we call the postDelayed, I set proceed as false. Since it will not wait for postDelayed(), it will go to the next line of code which is the while loop.
By setting the proceed as false, I use it to create a infinite loop. But this infinite loop will be broken by the completed postDelayed() as proceed will be set to true in it, then the code can continues the for loop.
But I not sure why it simply doesn't work. When I run the code, it just displayed a blank screen. It seemed like the problem resides within the infitine while loop and postDelayed() can't update the proceed variable.
I tried using Thread.sleep(1000) as a replacement of postDelayed, but during startup, the program simply shows a white background for however long the parameter is passed to Thread.sleep()
I have exhausted my option and I hope someone has a better idea.
Thank you.
The loop does not wait for the postDelayed because what's inside the postDelayed happens async. This means that it works independently from the UI thread, on a second thread. What you want to accomplish is to make the UIthread wait for a period of time, and not start another thread after a specific period.
You could try to use the handler in this way:
Handler handler=new Handler()
{
public void handleMessage(Message msg)
{
if(msg.what==0)
{
viewCard11.setBackgroundResource(R.drawable.text_view_circle3);
proceed = true;
}
}
};
and then you may use the handler like this:
handler.postDelayed(() ->
{
//does nothing just waits 1 second and then send empty message
handler.sendEmptyMessage(0)
}, 1000);
I am developing a small game, (Java, LibGdx) where the player fills cloze-style functions with predefined lines of code. The game would then compile the code and run a small test suite to verify that the function does the stuff it is supposed to.
Compiling and running the code already works, but I am faced with the problem of detecting infinite loops. Consider the following function:
// should compute the sum of [1 .. n]
public int foo(int n) {
int i = 0;
while (n > 0) {
i += n;
// this is the place where the player inserts one of many predefined lines of code
// the right one would be: n--;
// but the player could also insert something silly like: i++;
}
return i;
}
Please note that the functions actually used may be more complex and in general it is not possible to make sure that there cannot be any infinite loops.
Currently I am running the small test suite (provided for every function) in a Thread using an ExecutorService, setting a timeout to abort waiting in case the thread is stuck. The problem with this is, that the threads stuck in an endless loop will run forever in the background, which of course will at some point have a considerable impact on game performance.
// TestClass is the compiled class containing the function above and the corresponding test suite
Callable<Boolean> task = new Callable<Boolean>() {
#Override
public Boolean call() throws Exception {
// call the test suite
return new TestClass().test();
}
};
Future<Boolean> future = executorService.submit(task);
try {
Boolean result = future.get(100, TimeUnit.MILLISECONDS);
System.out.println("result: " + (result == null ? "null" : result.toString()));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
future.cancel(true);
}
My question is now: How can I gracefully end the threads that accidentally spin inside an endless loop?
*EDIT To clarify why in this case, preventing infinite loops is not possible/feasable: The functions, their test suite and the lines to fill the gaps are loaded from disk. There will be hundrets of functions with at least two lines of code that could be inserted. The player can drag any line into any gap. The effort needed to make sure no combination of function gap/code line produces something that loops infinitely or even runs longer than the timeout grows exponentially with the number of functions. This quickly gets to the point where nobody has the time to check all of these combinations manually. Also, in general, determining, whether a function will finish in time is pretty much impossible because of the halting problem.
There is no such thing as "graceful termination" of a thread inside the same process. The terminated thread can leave inconsistent shared-memory state behind it.
You can either organize things so that each task is started in its own JVM, or make do with forceful termination using the deprecated Thread.stop() method.
Another option is inserting a check into the generated code, but this would require much more effort to implement properly.
The right way is to change the design and avoids never ending loops.
For the time being, inside your loop you could check if the thread is interrupted some way by: isInterrupted() or even isAlive().
And if it is you just exit.
It is not normal to have a never ending loop if it not wanted.
To solve the problem You can add a counter in the loop and if you reach a limit you can exit.
int counter = 0;
while (n > 0) {
counter++;
if (counter > THRESHOLD) {
break;
}
i += n;
// this is the place where the player inserts one of many predefined lines of code
// the right one would be: n--;
// but the player could also insert something silly like: i++;
}
I am making an Image Detection bot using the Sikuli API and I was wondering if anyone knows how I can make it constantly scan for an image, then click on it? At the moment it will scan then click, but I want it to be constantly scanning.
how about:
int mil = MaxMillis;
boolean flagIsFound = false;
while (mil > 0 && flagIsFound != true)
{
Thread.sleep(1000);
mil -= 1000;
System.out.println("wait for the image a sec");
if (screen.exists(image) != null)
{
// found
flagIsFound = true;
}
}
if(flagIsFound == false)
{
throw new SikuliException(image + " not found for " + MaxMillis + " milliseconds");
}
Do you need it to scan until it appears and then click on the image, or will the image recur, and you need it to click on the image every time it pops up? Either way, I think your solution is simple--
For scanning until it pops up, then clicking on it once, then no more scanning--
while not exists(yourImage):
wait(1) #can also use sleep()
click(yourImage)
for continuing to scan and click again and again, wrap it in another 'while' statement, for example--
while True:
while not exists(yourImage):
wait(1)
click(yourImage)
if (someConditionIsMet):
break
I am using AndEngine to develop my game, though I'm thinking this problem is unrelated to AndEngine.
I have two possible dialogs that fire if:
User touches down in an incorrect area or
Users lifts up from an incorrect area.
Unfortunately, if a user touches down in an incorrect area, when they lift up they are also satisfying error 2--lifting up from an incorrect area.
Here's my code in a nutshell:
public boolean onSceneTouchEvent(Scene pScene, TouchEvent pSceneTouchEvent) {
float y = pSceneTouchEvent.getY();
int dialog_count = 0;
if (pSceneTouchEvent.isActionDown() && y < 1000) {
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
AlertDialog Code
..............
}
}
dialog_count ++;
Log.d("Dialog Count", "Count is " + dialog_count);
} else if (dialog_count < 1 && pSceneTouchEvent.isActionUp() && y > 105) {
Log.d("Dialog Count", "Count is still " + dialog_count);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
Second AlertDialog Code
.................
}
}
}
return false;
}
Now, my first log for dialog_count shows a value of 1. However when I lift up the second log shows a value of 0. Somehow this value is either getting reset or my Else statement just can't see the updated value of dialog_count because I get the second dialog popping on top of my first.
Any ideas?
Your code initializes
int dialog_count = 0;
each time it runs.
To keep the value you saw the last time, make dialog_count an instance variable in the class.
Notice that you will be seeing two events, one for "down" and one for "up".
If you want to show only one then you need to use a flag to check if the user has touched down and then if you want not to show the touch up dialog just check from the flag. But the Touch down will always follow the Touch Up. You can use the Touch Move method if you want to show the dialog when the user has moved a bit.
If I understand correctly, what you are trying to do
dialogCount is function local (garbage collected, after you exit the method). So it will be 0 on each new run of the method. (Make it private class variable).
If you are referring to your dialogCount in multiple threads, dialogCount must be thread safe, so use concurrent primitives - AtomicInteger
Hi I have been trying for the past hour to break from this loop and continue since already met my condition once. My application pretty much reads a serie of lines and analyzes it and then prints the variable stated. An example of how the lines look like (the . are not included):
10 c = 9+3
20 a = c+1
30 print c
40 goto 20
50 end
It does everything right, when it gets to line 40 goes to line 20 as expected, but i want it to go to line 50 since already went to line 40 once. Here is my code for this part:
while(booleanValue)
{
if(aString.substring(0, 4).equals("goto"))
{
int chosenLine = Integer.parseInt(b.substring(5));
if(inTheVector.contains(chosenLine))
{
analizeCommands(inTheVector.indexOf(chosenLine));
i++;
}
else
{
System.ou.println("Line Was Not Found");
i++;
}
}
else if(aString.substring(0, 3).equals("end"))
{
System.out.println("Application Ended");
booleanValue = false;
}
}
Use the break statement to break out of a loop completely once your condition has been met. Pol0nium's suggestion to use continue would not be correct since that stops the current iteration of the loop only.
while(foo)
{
if(baz)
{
// Do something
}
else
{
// exit condition met
break;
}
}
All this having been said, good form dictates that you want clean entry and exit points so that an observer (maybe yourself, revisiting the code at a later date) can easily follow its flow. Consider altering the boolean that controls the while loop itself.
while(foo)
{
if(baz)
{
// Do something
}
else
{
// Do something else
foo = false;
}
}
If, for some reason, you can't touch the boolean that controls the while loop, you need only compound the condition with a flag specifically to control your while:
while(foo && bar)
{
if(baz)
{
// Do something
}
else
{
// Do something else
bar = false;
}
}
You could keep the code using booleanValue as-is and switch to a do-while loop.
do {
// ... existing code
} while (booleanValue);
However, to answer your specific question - you can always use the java break keyword. The continue keyword is more for skipping the remainder of the loop block and entering another loop iteration.
if you put this before your check for anything else, you would exit the loop immediately.
if(aString.substring(0, 3).equals("end")) {
break;
}
As an additional tip, you may want to use String.contains("end") or String.endsWith("end") instead of substring(). This way if a 1 or 3 digit (or more) number is used your code will still work.