Value of Variable Keeps Resetting Every Time The Loop Runs (Java) - java

I'm currently working on a homework assignment for my Java OOP class. The assignment is that a mouse is trapped midway in a 30ft long pipe. The mouse needs to move randomly with a 50% chance of going left or right. The mouse can only move a random distance between a min of 3ft and a max distance of 8ft for each move made. The program should keep track of the distance that the mouse is from the left and right ends of the pipe after each move and once it has reached one end of the pipe, the loop should end and it should print out that the mouse has reached whatever end it reached. I'm using the variable fromendL to keep track of the mouse's distance from the left end and fromendR for the other end. The problem i'm encountering is that every time the loop runs it's resetting the values of each variable so and it's never giving me the distance over the course of multiple loops. Everything I believe I have working fine, although it might not be the most efficient way (i'm still fairly new to programming).
I'll attach the code below:
class Main {
public static void main(String[] args)
{
int fromendL;
int fromendR;
int tMin = 3;
int tMax = 8;
int direction;
int travel;
int travelR = 15;
int travelL = 15;
boolean escaped = false;
while (!escaped)
{
direction = (int)(Math.random()* 2 + 1);
travel = (int)(Math.random() * (tMax - tMin) + 3);
if (direction == 1)
{
fromendL = 15 - travel;
fromendR = 30 - 15 + travel;
travelL = travelL - travel;
System.out.println("The mouse has moved: " + travel + " ft to the left" );
System.out.println("The mouse is " + fromendL +" ft from The Left End");
System.out.println("The mouse is " + fromendR +" ft from The Right End\n");
if(travelL == 0 || travelL < 0)
{
escaped = true;
System.out.println("The Mouse has escaped the Left end of the Pipe!");
}
else if (travelR == 30 || travelR > 30)
{
escaped = true;
System.out.println("The Mouse has escaped the Right end of the Pipe!");
}
}
else if (direction == 2)
{
fromendL = 15 + travel;
fromendR = 30 - 15 - travel;
travelR = travelR + travel;
System.out.println("The mouse has moved: " + travel + " ft to the right");
System.out.println("The mouse is " + fromendL +" ft from The Left End");
System.out.println("The mouse is " + fromendR +" ft from The Right End\n");
if(travelR == 30 || travelR > 30)
{
escaped = true;
System.out.println("The Mouse has escaped the Right end of the Pipe!");
}
else if (travelL == 0 || travelL < 0)
{
escaped = true;
System.out.println("The Mouse has escaped the Left end of the Pipe!");
}
}
}
}
}

The following piece of code should solve the original problem. Please analyze it to find some of the improvements compared to your code.
Instead of using two variables to keep the position (fromendLand fromendR), I use a single one (pos). If I know the length of the pipe (which doesn't change) and the position starting from the left side of the pipe, the distance to the right end can be calculated.
Constructs like if (a == 0 || a < 0) are better written like if (a <= 0) in my opinion.
I use the direction as +1 or -1. Just like in mathematics, the negative direction is like going to the left, the positive direction is like going to the right.
The reason that your variables are reset every time lies in
fromendL = 15 - travel;
fromendR = 30 - 15 + travel;
travelL = travelL - travel;
You start from 15 resp 30 over and over again instead of using the last position of the mouse.
My code looks like
(I use tabs for indentation; my eyes are too old to see the subtle 2-character indentations ;) :
class Main {
public static void main(String[] args)
{
static final int tMin = 3;
static final int tMax = 8;
static final int pLength = 30;
int direction;
int travel;
int pos = pLength / 2;
boolean escaped = false;
while (!escaped) {
direction = (int)(Math.random() * 2);
if (direction == 0) direction = -1;
travel = ((int)(Math.random() * (tMax - tMin)) + tMin) * direction;
pos += travel;
System.out.println("The mouse has moved: " + Math.abs(travel) + " ft to the " + (travel > 0 ? "right" : "left"));
System.out.println("The mouse is " + pos +" ft from The Left End");
System.out.println("The mouse is " + (pLength - pos) + " ft from The Right End\n");
if (pos >= pLength || pos <= 0) {
System.out.println("The Mouse has escaped the " + (pos <= 0 ? "Left" : "Right") + " end of the Pipe!");
escaped = true;
}
}
}
}
The ? is a ternary operator. It tests the condition and if true, the expression evaluates to the value directly following the question mark. If false the expression evaluates to the value following the colon. Use it with care, many people don't like it and think it's confusing. And for that reason I've put it between parenthesis so it's clear where the construct starts and ends.
Since pos is either less or equal zero (escaped to the left) or greater or equal 30 (escaped to the right), I only have to test which of both it is. If I know the mouse didn't escape to the left it must have escaped to the right. (The condition of the if already guarantees that the mouse has escaped).

Related

java: how to find a value in which initial value is zero and getting error "/ by zero"

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) + "%");

Brute Force the Frog Jumping Game

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();
}

Minesweeper - revealing all empty tiles instead of only some

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".

While or loop where on or condition is addressed but the other is not?

I am programming a simulation of Monopoly and I wanted to know if there is a way to address a variable if it is over a number but not the other variable?
while (i<=200){
while(Player1.space<41 || Player2.space<41){
roll();
Player1.space=Player1.space+roll();
System.out.println("Player1 "+Player1.space);
i++;
roll();
Player2.space=Player2.space+roll();
System.out.println("Player2 "+Player2.space);
i++;
}
//So here I want to reset the variable that reached 41 back to one.
}
}
I would do this:
int moveTo = Player1.space + roll();
Player1.space = moveTo > 40 ? moveTo - 40 : moveTo;
This assumes that your space numbering starts at 1 (which it seems to if you say that 40 is a valid space, and from your comment that you want to "reset the variable that reached 41 back to one").
You then have no more need for the inner while loop, so you just need
while (i <= 200) {
int moveTo = Player1.space + roll();
Player1.space = moveTo > 40 ? moveTo - 40 : moveTo;
...
It gets shorter still with the modulus operator (divide by 40 and use the remainder as your output):
Player1.space = (Player1.space + roll()) % 40;
This works really well if your space numbering starts at 0, but can be adjusted if it starts at 1 as follows:
Player1.space = 1 + ((Player1.space + roll() - 1) % 40);
You can see the difference between the two with the following:
public static void main(String[] args) {
for (int moveTo = 0; moveTo < 50; moveTo++) {
int space = moveTo > 40 ? moveTo - 40 : moveTo;
System.out.println("" + moveTo + " " + space);
}
for (int moveTo = 0; moveTo < 50; moveTo++) {
int space = moveTo % 40;
System.out.println("" + moveTo + " " + space);
}
}

Can't seem to figure out why my loop wont progress

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");
}
}

Categories

Resources