OK so I seem to be getting an Array Index out of Bounds error in a part of my code. Specifically in lines 85-102...
My code: http://www.sosos.pastebin.com/f0JQBWui
I just want it to check for blocked tiles AHEAD of time that way my sprite doesn't move in the direction it can't. This exception only happens when I am on the RIGHT or BOTTOM corners of my map.
My GUESS of why this error happens if because when I am on the corner.. it checks for the tiles to the RIGHT and BOTTOM of it which are not there...
1) The way you implemented blocked(tx,ty), it only accepts legal board coordinates (0<=tx<=12 and 0<=ty<=8). Otherwise it checks an illegal array position, producing an ArrayIndexOutOfBoundsException. Are you sure this is your intention? I think it makes sense to consider off board tiles as blocked.
2) In lines 85-102 there seems to be many errors. I think you meant something like:
if (spawnX == 0 || blocked(spawnX - 1, spawnY)) {
left = false;
System.out.println("You can't go left!");
}
if (spawnX == 12 || blocked(spawnX + 1, spawnY)) {
right = false;
System.out.println("You can't go right!");
}
if (spawnY ==0 || blocked(spawnX, spawnY - 1)) {
up = false;
System.out.println("You can't go up!");
}
if (spawnY == 8 || blocked(spawnX, spawnY + 1)) {
down = false;
System.out.println("You can't go down!");
}
Anyway, if you fix (1) as I suggested, the extra bound condition per direction is unecessary.
3) isInBound(r,c) is implemented incorrectly. It always returns false, due to the conditions on c.
4) There are many other problems with the code, but I will not enter into details. As a principle, try to make your design simple and make sure the code does not repeat itself.
You're going to have to do some bounds-checking in your blocked() function. Make sure that the coordinates they're giving you actually exist and return some "blocked" value if they don't.
The description of getting the error at the bottom or right would seem to suggest that you need to test if the value exceeds the array bounds. Have a look at Array.length
Related
Ok, so I need assistance with an array, I have a 2D array that a player can move through, at the moment I'm randomly generating an entity and a player is supposed to be able to interact with it. I have one decently long if statement that tracks if the player approaches the entity however unable to increase the range at what will trigger a prompt. This if statement is long and was frustrating to wrap my head around at times but is as follows;
if(((getPlayerX() == getEntityX() - getPlayerRange()) || (getPlayerX() == getEntityX() + getPlayerRange()) || (getPlayerX() == getEntityX())) && ((getPlayerY() == getEntityY() - getPlayerRange()) || (getPlayerY() == getEntityY() + getPlayerRange()) || (getPlayerY() == getEntityY()))){
However when the range increase to two (from its default which is one), this no longer works. I want to implement this so a player with higher range can still interact with this entity. Is there an easier way to do this that might be more efficient?
What about something like this:
int xDistance = Math.abs(getPlayerX() - getEntityX());
int yDistance = Math.abs(getPlayerY() - getEntityY());
if (xDistance <= getPlayerRange() && yDistance <= getPlayerRange()){ ... }
Calculate absolute distance and then compare with player range.
Even tho it's more code than your current version, it is more readable even for range of 1 in my opinion.
I'm making a 2d platformer in libgdx with box2d. The below is the update method for one of my enemies. It's an extension of the 'Enemy' class, which is what 'super.update' refers to. I want the enemy to run when the player is behind it or far away and to stop and shoot when the player is close to it and in front of it.
I try to achieve this by setting the speed (velocity.x) initially [depending on the enemy's direction], then setting whether or not it's shooting afterwards.
The problem I have at the moment is that the enemy doesn't run when the player is behind it. As you can see, I printed out a lot of strings to console to see when the velocity.x gets changed back to 0. According to the console, it happens in the last if/else pair of statements which are supposed to check how far away the player is and which direction the enemy is running. However, the console strings within those statements, the ones that say 'Shoot Left' or 'Shoot Right', don't get printed out. Despite this, the line that changes velocity.x must get run because the it's value changes according to the string output in the next line. The if statements at the top which check direction must get run as well because the console outputs within those statements get printed, and the output that says the velocity says the correct velocity (either 2 or -2).
What is going on? It seems like the IDE is running only one of the lines in the if statement. That's impossible so what am I missing here?
Thanks for any help.
public void update (float dt, Player player){
super.update(dt, player);
if (b2body.isActive()){
System.out.println(b2body.getPosition().x - player.b2body.getPosition().x);
System.out.println("After Enemy code: " + velocity.x);
if (getRunningRight()) {
System.out.println("Right");
velocity.x = 2;
}
else if (!getRunningRight()) {
System.out.println("Left");
velocity.x = -2;
}
System.out.println("After checking direction: " + velocity.x);
if ((b2body.getPosition().x - player.b2body.getPosition().x <= 2 &&
b2body.getPosition().x - player.b2body.getPosition().x >= 0) && !getRunningRight()){
velocity.x = 0;
System.out.println("Shoot left");
}
else if ((b2body.getPosition().x - player.b2body.getPosition().x >= -2 &&
b2body.getPosition().x - player.b2body.getPosition().x < 0) && getRunningRight()){
System.out.println("Shoot right");
velocity.x = 0;
}
System.out.println("After shooting: " + velocity.x);
}
}
In your first set of ifs, you evaluate getRunningRight() after you have already determined that it will be false (by the initial if failing), so there is no need to evaluate it again.
If you think you are doing the same thing in the second block, you are not; the expression in the inner if is not the opposite of the first one. That is, (A && B) && C is not the opposite of (!A && !B) && !C. Thus, it is possible for both expressions to be false.
I'm studying for my computer science final and am going back over some of the things that I never quite grasped when we went over them in class. The main thing being recursion. I think I've got the hang of the simple recursion example but am trying to work through one that was on a previous exam and am having trouble figuring out how it should be done.
Here is the question:
Texas numbers (Tx(n)) are defined as follows for non-negative numbers (assume true):
Tx(n) = 10 if n is 0
Tx(n) = 5 if n is 1
Tx(n) = 2*(Tx(n-1) + Tx(n-2) if n >= 2
We are then to write the recursion function for Texas numbers, after making some corrections after the test, here's what I've come up with, I think it's right, but not 100% sure.
public int Tx(int n) {
if(n == 0)
return 10;
else if (n == 1)
return 5;
else
return 2*(Tx(n-1) + Tx(n-2));
}
Then we are asked to computer the value of Tx(5). This is where I'm stuck. If the return statement for the else was simply n-1, I think I'd be able to figure it out, but the n-1 + n-2 is completely throwing me off.
Can anyone explain how this would work, or share some links that have similar examples. I have tried looking this up online and in my textbook but the examples I've found are either so advanced that I have no clue what's going on, or they only deal with something like return n-1, which I already know how to do.
Let's start with Tx(2). n > 1, so we have 2*(Tx(n-1) + Tx(n-2)) which is 2*(Tx(1) + Tx(0)).
But we already know Tx(1) and Tx(0)! So just substitute them in and you get 2*(5 + 10) -> 30. Great, so now we know T(2).
What about T(3)? 2*(Tx(2) + Tx(1)). Nice, we already know these too :) Again, just fill them in to get 2*(30 + 5) -> 70.
You can work forwards to get to Tx(5).
Your code is logically correct, you should just be using == to test equality, a single = is for assignment.
When you run your method, it will work backwards and solve smaller and smaller subproblems until it gets to a point where the answer is known, these are your base cases.
Tx(3)
2* Tx(2) + Tx(1)
2*Tx(1) + Tx(0) (5)
(5) (10)
In order for recursion to work, whatever you are doing each time to break the problem down into smaller problems needs to make some progress towards the base case. If it doesn't, you will just infinitely recurse until your computer runs out of space to store all of the repeated calls to the same function.
public int Tx(int n) {
if(n == 0)
return 10;
else
return Tx(n+1); // n will never reach 0!
}
Tx(1) becomes Tx(2) -> Tx(3) -> Tx(4) -> Tx(5) etc.
Your implementation is good, only one minor mistake - in the conditions you should replace = with == - it's not an assignment - it's a comparison.
By the way, what would you expect your method to return for Tx(-1) ?
You have implemented it right just change = with ==.
If you want to further reduce the time complexity you can store the result in an array global to the function so that your function doesnot compute results again and again for a same number this will only save you some time for large computations.
You can use something like this.
public int tx(int n , int []arr) {
if (arr[n] == 0) {
if (n == 1) {
arr[n] = 10;
}
else if (n == 2) {
arr[n] = 5;
}
else {
arr[n] = 2 * (tx((n - 1), arr) + tx((n - 2), arr));
}
}
return arr[n];
}
See whenever you ask the computer for the value Tx(5) it will call the recursive function and so the program will execute the else part because value of n=5.
Now in the else part 2*(Tx(n-1)+Tx(n-2)) will be executed.
In first iteration it will become 2*((2*(Tx(3)+Tx(2)))+(2*(Tx(2)+Tx(1)))) . The iteration will be continued until the value of n become 0 or 1.
I have looked at other do while issues on StackOverflow, but I could not find the solution to my issue. I have variables initialized outside the do{ and they are being use within, but when the variables reach a certain value, the while method does not jump out.
Here is what I have:
int aiShotHit = 0;
int shotHit = 0;
do{
showBoard(board);
bAi.showAi(ai);
shoot(shoot,ships);
bAi.aiHit(aiShoot);
attempts++;
if(hit(shoot,ships)){
hint(shoot,ships,aiShips,attempts);
shotHit++;
System.out.println("\nShips Left on the Board: " + shotHit);
}
else
hint(shoot,ships,aiShips,attempts);
changeboard(shoot,ships,board);
if(bAi.aiHit(aiShoot,aiShips)){
hint(shoot,ships,aiShips,attempts);
aiShotHit++;
}
else
System.out.print("");
bAi.changeAi(aiShoot,aiShips,ai);
}while(shotHit !=3 || aiShotHit !=3);
if (shotHit == 3){
System.out.println("\n\n\nBattleship Java game finished! You Beat the Computer");
}
System.out.print("You lost! The Ai beat you");
You probably started out by saying, I want this to loop until shotHit is 3 or until aiHShotHit is 3.
That would be
while (!(shotHit == 3 || aiShotHit == 3));
which is "loop while it is not the case that either shotHit or aiShotHit contains the value 3", but it's kind of ugly so you wanted to apply the negation operator to each subexpression and get rid of some parens. The mistake was thinking you can move the negation operator without changing anything else to get
while (shotHit != 3 || aiShotHit != 3);
This exits the loop only in the event that shotHit is 3 at the same time that aiShotHit is 3. Not what you want.
The correct transformation is
while (shotHit != 3 && aiShotHit != 3);
This much was covered in the comments. The guidelines for how to safely transform this kind of expression are De Morgan's rules, which describe how to transform conjunctions and disjunctions in terms of each other. Following those rules lets you can move the negation operator and change the parenthesization without changing the meaning of the expression:
"not (A or B)" is the same as "(not A) and (not B)"
"not (A and B)" is the same as "(not A) or (not B)"
Needing to reorganize an expression to make it more readable comes up a lot in programming and this is a tool you need in order to do it safely. If you want to know more about De Morgan's rules you might want to read this answer.
I am writing a code for a class assignment to get a character through a maze. I have been working on this for hours and I can't figure out what I am doing wrong. The character moves left to right and right to left. Except when I add the code to have the character move around a block if (maze.moveRight() == false), it causes the character to move up and down at the end of each row a bunch of times before it moves the other direction. Also it messes up my count as the character moves across the rows. I feel like I am making it much more complicated than it should be. Can someone help?
Algorithm
The student always starts at the top left corner, that is row and column zero.
The Java logo can be anywhere in the maze, which also contains obstacles shown as "Wrong Way" signs.
You must traverse every row in the maze from top to bottom according to the rules below, until you find the Java logo.
Row and column numbers are zero based, so the first row and column is index 0. the second row and column is index 1, and so on. The number zero is even.
On even rows, you must move left to right using maze.moveRight(), on odd rows, you must move right to left using maze.moveLeft().
After completing each row, use maze.moveDown() to proceed to the next row, until you reach the last row or find the Java logo.
You can detect that you have encountered an obstacle by checking the return value from move methods in the Maze object, true means no obstacle, false means obstacle.
If you run into an obstacle when when moving left to right: Move down, right, right, and up.
Adjustment the loop counter for the extra move right!
If you run into an obstacle when when moving right to left: Move down, left, left, and up. Adjustment the loop counter for the extra move left!
Every time you move left or right, not including when avoiding an obstacle, you must call maze.isDone() to see if you have found the Java logo.
When you find the Java logo, you must immediately break out of all loops, and exit the program.
There are mazes that cannot be solved using the algorithm, but we will not test your program with any of them.
public static void main(String[] args) {
// Create maze
String fileName = args[1];
Maze maze = new Maze(fileName);
System.out.println("Maze name: " + fileName);
// Get dimensions
int mazeWidth = maze.getWidth();
int mazeHeight = maze.getHeight();
// Print maze size
System.out.println("Maze width: " + mazeWidth);
System.out.println("Maze height: " + mazeHeight);
int r = 0;
int c = 0;
// Move commands
while (c < maze.getWidth() - 1 && r % 2 == 0 && maze.isDone() == false)
{
maze.moveRight();
maze.isDone();
c++;
if (maze.moveRight() == false && maze.isDone() == false){
maze.moveDown();
maze.moveRight();
maze.moveRight();
maze.moveUp();
}
if (maze.isDone() == true){
System.exit(1);
}
}
while (c == maze.getWidth() - 1 && r % 2 == 0 && maze.isDone() == false)
{
maze.moveDown();
maze.isDone();
r++;
}
while (c != 0 && c <= maze.getWidth() -1 && r % 2 != 0
&& maze.isDone() == false){
maze.moveLeft();
maze.isDone();
c--;
if (maze.moveLeft() == false && maze.isDone() == false) {
maze.moveDown();
maze.moveLeft();
maze.moveLeft();
maze.moveUp();
}
if (maze.isDone() == true){
System.exit(1);
}
}
}
I'm having a hard time following what your intent is and thus what the problem is. Perhaps it's due to lack of understanding of how this maze is set up. I also don't know the scope of the class so I don't know if this is above your current level or not, but here goes how I would personally implement a maze solver:
For each position in a maze that I find myself, I would create a maze "space" object. This object will keep track of remaining options of directions to be traversed and whether or not I have visited that space. If I can turn left and right, I would create new spaces for both, pick one direction, and mark only that one direction to say I've been there. When I reach a dead end, I will turn around until I find a choice of direction to go. If I've not visited a direction, I'd take that. Otherwise, If I've visited all ways, I would call a recursive function to determine if there are any directions available along down any of the paths I've taken previously.
So it's creating objects, using recursion, and flagging an object for whether or not I've been there. (you'd also need a flag to indicate if your recursive algorithm has checked a square as well lest you find yourself in an infinite loop).
Hopefully that's within the constraints of the assignment! Otherwise, we may need more information as to what the limitations are and the true scope of the assignment.
Ok so a few problems you are only moving down on the right wall.
You aren't updating your row column counters when you are navigating hazards.
You should be testing the results of every move and isDone method call and breaking or updating your counters accordingly.
Also you shouldn't be updating your counters as you do outside an if statement associated with a move test method call.