For loop and if statements acting odd - java

I am making a chess game and so far everything is good and I am writing the rules of each piece now. The problem is that a for loop is acting oddly. Its for the bishop so x is going down and y is going up. At this point it acts oddly whenever I try to add the point to a possible move
for (int i = 0; i < 8; i++) {
Point newLoc = new Point(x-i, y+i);
if(team.equals("white")) {
if(containsPiece(newLoc)) {
if(ChessBoard.black.containsKey(newLoc)) {
possibilities.put(newLoc, rating);
break;
}
else {
break;
}
} else
possibilities.put(newLoc, rating);
}
containsPiece() is working just fine and possibilities is the HashMap I am storing the possible moves in.
The way I see it it should be working perfect because if the tile at newLoc is white it shouldn't add it to the possible moves and stop getting any moves after it in that direction. Does anyone see why it seems to abandon all the previous possible moves added to possibilities

i should start in 1, not 0, since when i==0, newLoc is the position of the bishop ((x-0,y+0)), so you break from the loop, since the bishop is a white tile.

Related

how do i organise this function so it works as i intend it to

im new to android studio and i want this function to loop and create an infinite ball falling loop which will be scored until the two integers do not match but when i try to run it, it will only loop once and if i change streak = 2 in the else statement the app crashes
public void mainGameLoop(){
do {
//sets Balls integer
setColourint();
ball.setVisibility(View.VISIBLE);
//ball fall
float bottomOfScreen = getResources().getDisplayMetrics()
.heightPixels - (ball.getHeight() * 4);
//fall animation
ball.animate()
.translationY(bottomOfScreen)
.setInterpolator(new AccelerateInterpolator())
.setInterpolator(new BounceInterpolator())
.setDuration(9000);
//once animation is complete compares balls variable with current variable
if (colourint == ranint){
//if they are same then +1 score
score = score+1;
scr.setText(Integer.parseInt(String.valueOf(score)));
} else {
//else game is over
streak = 2;
}
//repeat until game is over
} while (streak == 1);
}
once the balls reached the bottom of the relative layout i want the function to check if the setcoulour int and the ran int are the same and then if the are score = score + 1, ball goes back to the top, the setColourInt function is called and the ball falls again(and so on and so on) but if not loop ends and it's game over...i apologise for my blatant incompetence but I can't imagine you guys don't remember when you too, were this naive when it came to coding. many thanks Tom
You have to give the UI a chance to draw what you're doing. The way you have it coded, whichever method (onStart, onCreate, etc) that calls your mainGameLoop will never return because it's stuck in an infinite loop. This is an error.
One way to do this is to create a View and implement your game draw logic in the onDraw method. The UI thread will call your onDraw method when it is time to draw. Here's an article that talks about this approach: http://cjds.github.io/2014/04/28/Creating-a-simple-android-game/

Game logic - Add score only once after passing obstacle

I'm creating a game with a score system similar to the one in Flappy Bird.
if you didn't get it
When the player successfully passes the right and left
obstacle I want my score variable to increase by 1. I don't know the logic behind it though.
Right now I have (this is inside a for loop checking every obstacle in an update method):
'over' making sure the score only increases by 1.
if (bird.getPosition().y > obstacle.getPosLeft().y) {
if (!over) {
over = true;
score++;
}
and when the obstacle gets off the screen (yes, y is 0 at the bottom, not the top):
if (obstacle.getPosLeft().y + Obstacle.OBSTACLE_HEIGHT < 0){
obstacle.reposition(obstacle.getPosLeft().y + (OBSTACLE_SPACING + Obstacle.OBSTACLE_HEIGHT)* OBSTACLE_COUNT);
over = false;
}
The problem is that you can pass 2 obstacle pairs before the first one gets re-positioned which means that you only get the 2nd point after reposition() is called for obstacle 1.
How would you fix this problem?
Just make a "obstacle.over" boolean so that each has its own state.

Java - Loop gets executed, but header doesnt fit condition

This function should check if the explosion hit a box and should be canceled on the first box it hits.
For example bsp.getBomb().getStrength() is currently 2, when a box is hit i=3, but the loop is executed one more time even if the condition isn't met, why is that?
public void detectBomb(BombSpritePair bsp) {
for(int i = 0; i <= bsp.getBomb().getStrength(); i++) {
if(bd.detect(bsp.getBomb().getX(), bsp.getBomb().getY()+i)) {
Sprite sprite = new Sprite(new Texture("gras.png"));
sprite.setPosition(bsp.getBomb().getX()*16, (bsp.getBomb().getY()+i)*16);
// i = bsp.getBomb().getStrength()+1;
sprites.add(sprite);
System.out.println("RIP"+i);
System.out.println(bsp.getBomb().getStrength());
break;
}
}
}
Try adding break to the loop:
public void detectBomb(BombSpritePair bsp) {
for(int i = 0; i <= bsp.getBomb().getStrength(); i++) {
if(bd.detect(bsp.getBomb().getX(), bsp.getBomb().getY() + i)) {
Sprite sprite = new Sprite(new Texture("gras.png"));
sprite.setPosition(bsp.getBomb().getX()*16, (bsp.getBomb().getY()+i)*16);
sprites.add(sprite);
System.out.println("RIP"+i);
System.out.println(bsp.getBomb().getStrength());
break;
}
}
}
You may be seeing duplicate print statements if you are calling the detectBomb method multiple times. Putting a breakpoint or print statement at the beginning of this method will help determine what the problem is.
Another thing to keep in mind is that you are creating a new Texture for the Sprite every time the method get executed - it would be wise to only instantiate the Texture once and share it with all subsequent Sprite instances that require it.

Java Rectangle Collision Intersection (Not always working)

I'm currently working on a tile collision system for an RPG style game and it mostly working except for some inconsistency with rectangle intersection.
protected void tileCollision()
{
AnimatedSprite player = findPlayer();
for(int i = 0; i < _sprites.size(); i++)
{
AnimatedSprite spr = _sprites.get(i);
for(int j = 0; j < tileWithinRange.length; j++)
{
Tile tile = tileWithinRange[j];
if(tile != null)
{
if(tile.getBounds().intersects(player.getBounds()))
{
player.setCollided(true);
tileCollision(player, tile, -1, -1);
} else
{
player.setCollided(false);
}
}
}
}
}
When I first collide with a tile upon launching the game, it always returns true, but if I move along a column of tiles, I start getting false returns and then after a while I only get false returns.
Here is an image of the player intersecting with a tile
There is an obvious intersection here, yet in this scenario, the variable collided returned false.
What is going wrong that the intersection isn't always registering?`
There is too little info here to really know what's happening, but something looks fishy here:
if(tile.getBounds().intersects(player.getBounds()))
{
player.setCollided(true);
tileCollision(player, tile, -1, -1);
} else
{
player.setCollided(false);
}
Since you are checking multiple tiles against the player in a loop, what if the player collides with the first tile, but doesn't collide with the second tile? You'd end up calling player.setCollided(false); even though he collided with a former tile, overwriting that true collision state with a false one. That might explain the behavior you're getting where you're getting only false returns after a while (perhaps because of the order in which you are checking the tiles makes it so you keep overwriting true states with false states).
I'm not sure if that's desirable or not to have these kinds of side effects, but it is a bit confusing at the very least to have this kind of collision state first being turned on and then overwritten with off within the same loop. If that's undesirable behavior, perhaps what you're after needs you to break out of the loop if a collision occurs. Or perhaps what you want is something more like this:
player.setCollided(false);
for(int j = 0; j < tileWithinRange.length; j++)
{
Tile tile = tileWithinRange[j];
if(tile != null && tile.getBounds().intersects(player.getBounds()))
{
player.setCollided(true);
tileCollision(player, tile, -1, -1);
}
}
}
Or maybe your bounds/intersection function is genuinely malfunctioning -- it's too hard to tell with so little code/info (we don't know how these are implemented).
It's good to be able to isolate your code and learn how to construct test cases to test out individual functions in little pieces independently. You want to eliminate suspects through a process of elimination with a testing procedure that allows you to figure out, "Okay, this part works perfectly in every case, let's move on to the next thing." Otherwise it becomes a guessing game trying to figure out what went wrong. One of the easiest ways to lose a time of time/productivity in development is to write a bunch of code first and then try to narrow down what went wrong in hindsight, instead of testing each little babystep. Mistakes get more expensive the later you discover them and the more suspects you have to go through in an investigation.
I ended up rewriting the method into a boolean which made it return true when colliding and false when not. Here is the new code.
public boolean tileCollision() {
AnimatedSprite player = findPlayer();
for(int j = 0; j < tileWithinRange.length; j++) {
Tile tile = tileWithinRange[j];
if(tile != null) {
if(tile.getTileBounds().intersects(player.getBounds()) ) {
return true;
}
}
}
return false;
}

LeJOS NXT Programming Sonic Sensor

I am trying to make a NXT Robot that has attached the Ultrasonic Sensor. It has to drive until the distance is 15, and then the engines have to stop. After it stops it has to turn, but it doesn't work.
import lejos.nxt.*;
public class test {
public static void main(String [] args) throws InterruptedException {
UltrasonicSensor ultra = new UltrasonicSensor(SensorPort.S1);
for (int i = 0; i < 5; i++) {
try {
Motor.B.rotate(-1500 , true);
Motor.C.rotate(-1500 , true);
} catch (Exception E){}
while ( ultra.getDistance() < 15 ) {
Motor.B.backward();
Motor.C.backward();
}
LCD.clear();
LCD.drawString("Distance : "+ultra.getDistance(), 0, 0);
}
Button.waitForAnyPress();
}
}
My old code, which also didn't work:
import lejos.nxt.*;
public class test {
public static void main(String [] args) throws InterruptedException {
UltrasonicSensor ultra = new UltrasonicSensor(SensorPort.S1);
try {
Motor.B.rotate(-720);
Motor.C.rotate(-720);
} catch (Exception E){}
for (int i = 0; i < 5; i++)
{
LCD.drawString("Distance : "+ultra.getDistance(), 0, i);
Thread.sleep(2000);
int maxDistance = ultra.getDistance();
if (maxDistance < 15){
Motor.B.stop();
Motor.C.stop();
}
}
Button.waitForAnyPress();
}
}
Assumptions
Okay, from the looks of things, your code is probably not doing what you want. (In the future, when writing a question on Stack Overflow, please clarify in detail what the expected behavior is, as well as what erroneous behavior you're seeing. Those are usually the first two questions we would ask of you, anyway.)
First of all, you're going to want to ensure that your NXT kit has been set up properly, with your two motors on B and C, and your sensor on S1. If this is so, continue reading.
Code Interpretation
The motor commands:
try {
Motor.B.rotate(-1500, true);
Motor.C.rotate(-1500, true);
} catch (Exception E) {}
look like they're valid motor commands... but wait! You're using a two-wheeled robot, with the motors connected to two wheels that point in opposite directions? But you're using the same distance and direction for your motor's limit angle! If your wheels oppose each other, then this will do nothing but make the robot spin in a circle.
NOTE: Since your motors are configured properly, as written in your comments, ignore this part.
If you change the direction of one of the motors by changing the positive to a negative, then you'll have them both working in unison to move your robot forward (or backwards, if you change the wrong one!)
Also, keep in mind that passing true as the second argument in
Motor.B.rotate(-1500, true);
Motor.C.rotate(-1500, true);
makes this function in a very specific fashion, according to the Javadoc (emphasis mine):
If immediateReturn is true, method returns immediately and the motor stops by itself.
If any motor method is called before the limit is reached, the rotation is canceled.
The first sentence means that this does what we want it to: It tells our motor to find the right limit angle by itself, but don't make our program wait for it. However, the second sentence means that if any other motor commands are called, it will stop moving to the given limit angle. Yeah, that's right. Those next few lines make us stop moving the motors and do what they say instead.
Now, this code is problematic for two reasons:
while (ultra.getDistance() < 30) {
Motor.B.backward();
Motor.C.backward();
}
First, these commands will IMMEDIATELY stop our previous two motor commands from executing, which basically means the motors will jump straight to going "backwards" and looping until the distance sensor reads greater than or equal to 30. This is actually what we want, but we need a bit more...
Second, after your sensor reads the distance greater than 30, your motors are never told to stop! So even when your program is showing you the distance, and waiting for your button to be pressed, it'll still be moving!
A Solution
Okay, there's a few things that need to change:
Your initial motor command is being blocked out by the later commands that tell it to move to the correct position.
Your motors don't stop when they're supposed to.
Below is your code, edited to address each of these issues. I've included notes where I've made changes to show you what I've changed.
import lejos.nxt.*;
public class test {
public static void main(String [] args) throws InterruptedException {
UltrasonicSensor ultra = new UltrasonicSensor(SensorPort.S1);
for (int i = 0; i < 5; i++) {
// No initial motor movement (because it did nothing anyway)
// We change this to approach from either direction.
while (ultra.getDistance() != 30) {
// Check whether it's behind or ahead of it.
// Assuming that B- and C- increase distance, and B+ and C+ decrease it (depends on robot configuration).
// This is called a feedback loop, by the way.
if (ultra.getDistance() < 30) { // Move forward (distance+)
Motor.B.backward();
Motor.C.backward();
} else { // Move backward (distance-)
Motor.B.forward();
Motor.C.forward();
}
}
// We only get here when the distance is right, so stop the motors.
Motor.B.stop();
Motor.C.stop();
LCD.clear();
LCD.drawString("Distance : "+ultra.getDistance(), 0, 0);
}
Button.waitForAnyPress();
}
}
Now, this code isn't perfect; it may have a tendency to oscillate between forward and backward on slippery surfaces (which may turn it slightly to the left or right due to differences in applied torque), or if the sensor misses the correct position and the robot overshoots it.
This code also doesn't wait until the robot stabilizes at the given position, just until the sensor first reports the correct one. Again, this may result in sliding around a bit if the wheels don't have decent traction, the motors are set to smooth acceleration, or if the motors run at too high of a speed.
To correct these flaws, you'd need a more advanced type of feedback loop which accounts for acceleration and slip, and you'd need to wait until the robot stabilizes at the correct position for a short period of time before stopping the motors.
However, this should get you moving in the right direction, so to speak.
EDIT Corrected drive motor directionality, as specified in the comments.

Categories

Resources