I need to calculate accuracy in my java game. So far, I tried several methods however, everytime it either doesn't work or gives me an error "/ by zero". The initial value for bullets_shot is zero and the formula for accuracy is enemies_downed % bullets_shot. How can I bypass this error while getting an accurate read for accuracy? I tried doing a loop where it sets bullets_shot to 1 if it is 0 but it wouldn't give an accurate reading. Is there a way in which I can set a value in place for it until it has a value greater than 1 and if so how would I do so? Here are some code snippets.
here is the full code:
https://github.com/ms12r/Galaxy-Monkeys
In the tick method of the enemy class:
if(tempObject.getId() == ID.Bullet)
{
if(getBounds().intersects(tempObject.getBounds()))
{
hp -= 50;
bullets_hit += 1;
handler.removeObject(tempObject);
and in the mouseinput class
for (int i = 0; i < handler.object.size(); i++)
{
GameObject tempObject = handler.object.get(i);
if(tempObject.getId() == ID.Player)
{
handler.addObject(new Bullet(tempObject.getX()+16,
tempObject.getY()+24, ID.Bullet, handler, x, y, game));
bullets_shot += 1;
}
in the game class
System.out.println("GAME OVER");
System.out.println("Level Reached: " + game.level);
System.out.println("Accuracy: " + ((Enemy.bullets_hit + Gorilla.bullets_hit) % MouseInput.bullets_shot) + "%");
Game.INSTANCE.stop(); }
If the error you're getting is / by zero, consider looking at your calculation.
System.out.println("Accuracy: " + ((Enemy.bullets_hit + Gorilla.bullets_hit) % MouseInput.bullets_shot) + "%");
Quite simply, MouseInput.bullets_shot has no check on it to prevent the error from happening.
You can fix it with a simple if statement.
The calculation can only happen without a divide by zero error if (in your case) the user shot some bullets. The case in which no shots were fired could be evaluated as 0 accuracy:
...
double accuracy;
if (MouseInput.bullets_shot > 0) {
// your calculation
accuracy = (Enemy.bullets_hit + Gorilla.bullets_hit) % MouseInput.bullets_shot;
} else {
accuracy = 0D;
}
System.out.println("Accuracy: " + accuracy);
...
One question remains: why modulus (%) instead of division (/) for a percent calculation?
You could create a simple method called bulletAcuracy() like the following
public static double bulletAcuracy(int bulletHits, int totalBulletsFired)
{
if(totalBulletsFired == 0)
return 0;
return bulletHits/((double)totalBulletsFired);
}
Then call it in main like so
System.out.println("Accuracy: " + bulletAcuracy(Enemy.bullets_hit + Gorilla.bullets_hit, MouseInput.bullets_shot) + "%");
The last variation of the Frog Jumping is shown at the end of the video.
In short, you have n number of lily pads in a line and one frog on
each one.
In the last variation (the one I want to brute force), the second
first and second last lily pads do not have a frog. Your goal is to
get all frogs to the same lily pad. Each frog can jump right or left
based on the number of frogs on its lily pad, but can't jump on a
empty lily pad.
(pad with 1 frog moves 1 spot, pad with n frogs moves only n spots)
Example of a solution for n=12: (there are no solutions below 12)
[1,0,1,1,1,1,1,1,1,1,0,1] - Starting formation of frogs. (counting
frogs from 0. to 11.) [1,0,1,0,2,1,1,1,1,1,0,1] - Frog 3. jumped
right [1,0,1,0,2,1,2,0,1,1,0,1] - Frog 7. jumped left
[1,0,1,0,4,1,0,0,1,1,0,1] - Frogs 6. jumped left
[5,0,1,0,0,1,0,0,1,1,0,1] - Frogs 4. jumped left
[0,0,1,0,0,6,0,0,1,1,0,1] - Frogs 0. jumped right
[0,0,1,0,0,0,0,0,1,1,0,7] - Frogs 5. jumped right
[0,0,1,0,0,0,0,0,0,2,0,7] - Frogs 8. jumped right
[0,0,1,0,0,0,0,0,0,0,0,9] - Frogs 9. jumped right
[0,0,10,0,0,0,0,0,0,0,0,0] - Frogs 11. jumped left- solved
I want to find solutions for n frogs, if the solution exists. I know by hand that 12,14,15,16,17,18,19,20 have at least one solution and that 1-11 and 13 do not have a solution.
I tried writing a piece of code that would run through all combinations to find a solution for n lily pads.
EDIT: The code works now, thanks to OleV.V., also added logging.
import java.util.ArrayDeque;
import java.util.Arrays;
import java.util.Deque;
// # Brute Force # Brute Force # Brute Force # Brute Force # Brute Force # //
public class Frogger {
/**
* PUBLIC STATIC GLOBAL VARIABLES - Modify these as you wish.
*
* Time Data: Levels < 20 ~ around couple seconds
* Level = 20 ~ around a minute
* Level = 21 ~ around a quarter of an hour
* Level = 22 ~ around a sixth of a minute
* Level = 23 ~ around half an hour
* Level = 24 ~ around a minute
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
public static int Level = 12;
public static boolean LogSolution = true;
public static boolean LogAll = false;
/** * * * * * * * * * * * * * * * * * * * * * * * * * * * */
// used for logging
private static Deque<Jump> solution = new ArrayDeque<>(Level);
private static double time;
public static void main(String[] args) {
// log the time
time = System.currentTimeMillis();
// build the world & start jumping
run(Level);
}
public static void run(int n) {
// create the world
int[] world = new int[n];
for (int i = 0; i < n; i++) {
world[i] = 1;
}
world[1] = 0;
world[n-2] = 0;
// start jumping
if (Level > 11 && Level != 13) jump(world);
else System.out.println("Unsolvable");
}
//////////////////////////////////////////////////////
public static void jump(int[] world) {
for (int i = 0; i < world.length; i++) {
if (world[i] != 0) { // pad has a frog
// check if it is solved at current pad
if (world[i] == Level - 2) {
System.out.println("SOLUTION: " + Arrays.toString(world));
System.out.println(solution);
System.out.println("\n" + (System.currentTimeMillis() - time) / 1000 + " seconds");
System.exit(0);
}
// roll-back var
int temp = 0;
// attempts to make a RIGHT jump
if (world[i] + i < world.length) { // right jump is in bound
if (world[i + world[i]] != 0) { // can't jump on empty pad
temp = world[i];
// jump RIGHT
world[i + world[i]] += world[i];
world[i] = 0;
solution.push(new Jump(temp, i, i + temp)); // log the solution step 1/2
if (LogSolution) if (LogAll) System.out.println( "J: " + Arrays.toString(world)); // log the jump
// continue jumping
jump(world);
// roll-back right jump
world[i] = temp;
world[i + world[i]] -= world[i];
if (LogAll) System.out.println("R: " + Arrays.toString(world)); // log the rollback
if (LogSolution) solution.pop(); // log the solution step 2/2
}
}
// attempts to make a LEFT jump
if (i - world[i] >= 0) { // left jump is in bound
if (world[i - world[i]] != 0) { // can't jump on empty pad
temp = world[i];
// jump LEFT
world[i - world[i]] += world[i];
world[i] = 0;
if (LogSolution) solution.push(new Jump(temp, i, i - temp)); // log the solution step 1/2
if (LogAll) System.out.println("J:" + Arrays.toString(world)); // log the jump
// continue jumping
jump(world);
// roll-back left jump
world[i] = temp;
world[i - world[i]] -= world[i];
if (LogAll) System.out.println("R: " + Arrays.toString(world)); // log the rollback
if (LogSolution) solution.pop(); // log the solution step 2/2
}
}
}
}
}
}
Side note: This problem was mathematically solved for all solvable n (all n > 11, other than 13, have a solution, reachable by a generalized method). This piece of code is just me attempting to do some recursion in java.
Glad you got it to work. I don’t think you need my code now, but I will give at the bottom of this answer in case.
First, how does one log a solution? I guess you’re thinking that knowing that the end result was [0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0] is not that interesting; we’d like to know how it was obtained. I will present two ways.
The easier way is store each step as it is tried and then delete it when backtracking. Then when you get to the solution, you have also stored the steps that lead to it. Use a stack or similar:
private static Deque<Jump> solution = new ArrayDeque<>(Level);
(java.util.ArrayDeque is the recommended class for both stacks and queues; for a stack ArrayList is another option.) Now in your code, where it says log the jump do
solution.push(new Jump(temp, i, i + temp));
At log the rollback do
solution.pop();
Use a simple auxiliary class Jump that could for instance look like this:
public class Jump {
int count;
int from;
int to;
public Jump(int count, int from, int to) {
this.count = count;
this.from = from;
this.to = to;
}
#Override
public String toString() {
return "" + count + " frog/s jump from " + from + " to " + to;
}
}
When I tried it in my solution, one search took 20 % longer. I’d say it’s acceptable. If you are very concerned about performance, only log on your way out from having found the solution. This will require you to return a boolean to indicate success rather than using System.exit() for stopping the search. Now your recursive call becomes:
if (jump(world)) {
solution.push(new Jump(temp, i, i + temp));
return true;
}
You get the elements in your solution stack in the opposite order than before, I expect you to figure that out. Also instead of System.exit(0); do return true;. At the bottom of the method, return false. I have not measured performance impact, but I expect it to be minute compared to logging nothing. Now you can get output like:
1 frog/s jump from 3 to 4
1 frog/s jump from 7 to 6
2 frog/s jump from 6 to 4
4 frog/s jump from 4 to 0
5 frog/s jump from 0 to 5
6 frog/s jump from 5 to 11
1 frog/s jump from 8 to 9
2 frog/s jump from 9 to 11
9 frog/s jump from 11 to 2
Finally here’s how I did, just for the sake of completeness. I haven’t spotted any interesting differences from your code.
public static void jump(int[] world) {
for (int fromIndex = 0; fromIndex < world.length; fromIndex++) { // index of pad to jump from
// any frog/s here?
int frogsJumping = world[fromIndex];
if (frogsJumping > 0) {
// try to jump left; frogsJumping frogs jump frogsJumping places
int targetIndex = fromIndex - frogsJumping;
if (targetIndex >= 0 && world[targetIndex] > 0) { // must not jump to empty pad
performJump(fromIndex, targetIndex, world, frogsJumping);
}
// try a right jump
targetIndex = fromIndex + frogsJumping;
if (targetIndex < world.length && world[targetIndex] > 0) {
performJump(fromIndex, targetIndex, world, frogsJumping);
}
}
}
}
private static void performJump(int fromIndex, int toIndex, int[] world, int frogsJumping) {
solution.push(new Jump(frogsJumping, fromIndex, toIndex));
world[fromIndex] = 0;
world[toIndex] += frogsJumping;
if (world[toIndex] == noOfFrogs) {
System.out.println("Solved: " + Arrays.toString(world));
System.exit(0);
}
jump(world);
// backtrack
world[toIndex] -= frogsJumping;
world[fromIndex] = frogsJumping;
solution.pop();
}
NOTE: I apologize for the text wall, but I'm stuck getting my own code to work. I've dug through the other similar questions, but I'm not seeing why I can't get this code to search through everything. I WILL accept semi-cryptic answers that at least point me in the right direction in thanks.
To practice java, and answer a running question I have about minesweeper, I decided to try to build a minesweeper bot to find out exactly what the best possible winning percentage is for a given game start. I'm still working on getting the right behavior in the game portion of the code though, specifically where I have the game revealing squares that don't have adjacent mines. I end up with 0's on the edge of the revealed space, instead of my code searching the tiles around it, like below:
Printing Field:
-
-
-
-
-
-
-
-
-
- 1 1 2 1
- 0 0 0 0 0 1
- 1 0 0 0 1 2 3
- 1 0 0 0 0 0 0 0
- 2 1 0 0 0 0 0
- 1 0 0 0 0 0
- 1 0 0 0 0 0
I am tracking the actual field in a 2 dimensional Character array, and then tracking the revealed spaces in a same-sized Boolean array. I am including the method below that I am running once another method has found a '0', which marks a space without a bomb. I have another method which handles printing the revealed parts out to the current field, and can share that if anyone is curious.
private void checkAround(int x, int y)
{
//this pattern is used to parse out the comma to get the coordinates.
String regex = "[,]";
Pattern pat = Pattern.compile(regex);
ArrayList<String> to_check = new ArrayList<String>(); //the list of coordinates to check.
to_check.add("" + x + "," + y);
revealed_field[x][y] = true; //marking the coordinates as revealed.
do //iterates through the to_check list until nothing is in it.
{
//these next 2 sections handle pulling the next item from to_check
String temp = to_check.get(0);
to_check.remove(0);
String[] xy = pat.split(temp);
int a = Integer.parseInt(xy[0]); //local declaration of x
int b = Integer.parseInt(xy[1]); //local declaration of y
//if either a or b are outside the bounds of the respective axis, we skip the coordinate and move on.
if (b > height-1 || b < 0) continue;
if (a > width-1 || a < 0) continue;
if (bomb_field[b][a] == '0') //if this is not adjacent to a bomb
{
if (a > 0 && revealed_field[b][a-1] == false) //adds the square above to to_check
{
to_check.add("" + (b) + "," + (a-1));
revealed_field[b][a-1] = true;
}
if (b > 0 && revealed_field[b-1][a] == false) //adds the square left to to_check
{
to_check.add("" + (b-1) + "," + (a));
revealed_field[b-1][a] = true;
}
if (b < height-1 && revealed_field[b+1][a] == false) //adds the square right to to_check
{
to_check.add("" + (b+1) + "," + (a));
revealed_field[b+1][a] = true;
}
if (a < width-1 && revealed_field[b][a+1] == false) //adds the square below to to_check
{
to_check.add("" + (b) + "," + (a+1));
revealed_field[b][a+1] = true;
}
}
}
while (to_check.size() > 0); //ends once we have nothing to check.
}
You are storing b first in the list, then a, in the entries in the list. But you are interpreting the entries as if they contain a first, then b.
For example, if the start point is x=4, y=10:
You add "4,10" to the list.
You remove "4,10" from the list.
You check the cell at x=4, y=10.
You add "11,4", "9,4", "10,5" and "10,3" to the list - instead of "4,11", "4,9", "5,10" and "3,10".
I can't seem to figure out why my for loop is not working. I have been on the for about an hour now and the closest I have come is this. I'm trying to find out how many McNuggets you can buy using the 6, 9, and 20 packs. All I need dopeChecker(x) to do is return a true or a false. I haven't implemented check the next number yet because it wont even find that a 6 pack can be bought yet. I know it's in the loop somewhere but I just can't find out where. This is form the MIT open course ware problem 2. I don't know if you guys have seen it but I'm just letting you know this is where I'm getting my info.
int x = 0, y = 0, z = 0;// These will the the pack of McNuggets that we can buy.
int testFor = 0; //This will be the number of McNuggets we are looking for.
int matches = 0; //This will be the number of consecutive matches we will be looking for.
public void dopeEquation(){
while (matches < 6){//It's 6 Because that is the smallest order of nuggets we can buy.
//Looking for smaller nuggets then we can buy would not make sense.
while (testFor < 6){
testFor++;
}
if (dopeChecker(testFor)){
matches++;
} else{
matches = 0;
System.out.println(x + "," + y +"," + z +"," + testFor + "," + matches);
}
}
}
private boolean dopeChecker(int testFor){
for ( x = 0 ; x*6 <= testFor; x++){
for ( y = 0 ; y*9 <= testFor; y++){
for (z = 0 ; z*20 <= testFor;){
System.out.println(x + "," + y +"," + z +"," + testFor + "," + matches);
if (x*6 + y*9 + z*20 == testFor){
matches++;
System.out.println("match");
return true;
}else{
System.out.println("no match");
}
}
}
}
return false;
}
}
The z variable is always 0, you're not changing it.
Your code goes inside the first while loop:
while (matches < 6){
Then increased testFor to 6 with the following code:
while (testFor < 6){
testFor++;
}
Then goes to dopeChecker:
dopeChecker(int testFor)
Then insde the 3rd loop, for z:
for (z = 0 ; z*20 <= testFor;) {
...
}
z is never incremented, so you need to write this as:
for (z = 0 ; z*20 <= testFor; z++){
}
The following is the innermost for loop. I have commented where the problem is. as you can see, z never gets implemented. therefore, the loop will never terminate, as 0 <= testFor, since TestFor >= 6.
for (z = 0 ; z*20 <= testFor;/* incrementor needed here*/){
System.out.println(x + "," + y +"," + z +"," + testFor + "," + matches);
if (x*6 + y*9 + z*20 == testFor){
matches++;
System.out.println("match");
return true;
}else{
System.out.println("no match");
}
}