IndexOutOf range exception thrown in TimeHandler - java

I'm making a card-like game. The method below handles the opponents' attacks. It is supposed to go through the opponents' cards (with a two second delay between them) and execute their attacks (dealDamage() returns the damage). First it should check if the current opponent is active (i.e. not killed) and if it has already attacked, if so, their attack is executed. After that, the method moved to the next active opponent. After the last one it should stop iterating and change to the next round. Although the in first round everything goes as planned, but then it often crashes during the second or last round (when only one opponent is active). There can be 5 opponents max. I am clearly missing some obvious thing, but I can't get this to work.
EDIT
The error is in while(gm.opponentList.get(i).is available...
it is for examle index out of range: index 4 size 4.
public void opponentAttack(){
this.registerUpdateHandler(new TimerHandler(2f, true, new ITimerCallback() {
int i = 0;
#Override
public void onTimePassed(TimerHandler pTimerHandler) {
if (i < gm.opponentList.size()) {
while (gm.opponentList.get(i).isAvailable == false
|| gm.opponentList.get(i).attacked == true) {
i++;
}
if (gm.opponentList.get(i).isAvailable == true
&& gm.opponentList.get(i).attacked == false) {
gm.negotiationStrength = gm.negotiationStrength - gm.opponentList.get(i).dealDamage();
i++;
}
if (gm.negotiationStrength < 1) {
gm.negotiationEnded = true;
gm.playersTurn = false;
}
i = 0;
}else{
pTimerHandler.setAutoReset(false);
}
}
}));
gm.nextRound();
}

while (gm.opponentList.get(i).isAvailable == false
|| gm.opponentList.get(i).attacked == true) {
i++;
}
if the exit condition is never met, you keep incrementing i, and when it exceed the size of gm.opponentList throws an IndexOutBoundExcetion. You probably want to check i against gm.opponentList.size(), in the while loop

Related

Troubles with variable scope outside the for loop

So, there is a class Hotel, that contains 20 Rooms in form of a matrix 4x5 (4 floors, 5 rooms on every floor). The class Room has the properties:
floorNumber(int),
roomNumber(int),
numberOfBeds(int),
occupation(boolean)
etc.
For occupation, true means busy, and false means free.
One of methods I have to implement in Hotel is the one that reserves a room
reserve(int floorNumber, int roomNumber)
This method should check if occupation is true or false.
If it is true, then reservation fails, and if it is false, I should set occupation to true, with method
setOccupation(boolean t).
Also, method reserve return boolean (true or false), depending on whether reservation succeeded or not.
In that method, you guess, is problem with scope of one variable.
So there it is:
public boolean reserve(int floorNumber, int roomNumber){
boolean flag = false;
for ( int i = 0; i < 5; i++){
if(rooms[floorNumber][i].getRoomNumber() == roomNumber){//every element in matrix rooms has this property: rooms[floorNumber][some_number_from_1_to_5]
if (rooms[floorNumber][i].getOccupancy() == false){
rooms[floorNumber][i].setOccupancy(true);
flag = true;
}
else
flag = false;
}
}
return flag;
}
The problem is, when I set (in first line) flag to true, function returns true, and when I set flag to false, function returns false.
The reason I have to assign some value to flag in first line is because compiler shows:
Error: variable flag might not have been initialized
So, the problem is that it seems like method never executes code with for loop.
I know that variables defined in loop don't exist outside loop, but those defined outside should change their values in loop.
Like in this question here:
Java - Access variable inside and outside of for-loop
There is a simpler way to accomplish what you want to do. You don't need a boolean flag at all; you can just return true immediately on success or return false if the entire loop executed without finding a room.
public boolean reserve(int floorNumber, int roomNumber){
for (int i = 0; i < 5; i++) {
//every element in matrix rooms has this property:
//rooms[floorNumber][some_number_from_1_to_5]
if (rooms[floorNumber][i].getRoomNumber() == roomNumber){
if (rooms[floorNumber][i].getOccupancy() == false){
rooms[floorNumber][i].setOccupancy(true);
return true;
}
}
}
return false;
}
But if you insist on applying your original approach that uses a flag, then: First give it a value of false (in case no room succeeded). When we find an unoccupied room (successful), set it to true. If we find an occupied room, don't touch the flag value.
public boolean reserve(int floorNumber, int roomNumber){
boolean flag = false;
for (int i = 0; i < 5; i++) {
//every element in matrix rooms has this property:
//rooms[floorNumber][some_number_from_1_to_5]
if (rooms[floorNumber][i].getRoomNumber() == roomNumber){
if (rooms[floorNumber][i].getOccupancy() == false){
rooms[floorNumber][i].setOccupancy(true);
flag = true;
} // else DO NOTHING
}
}
return flag;
}
I found what the problem was.
It was actually index floorNumber in matrix rooms[floorNumber][] that goes from 0 to 3 (there are 4 floors), of course.
But in real life, floor numbers go from 1, and I passed argument to
reserve(int floorNumber,int roomNumber)
without considering that.
So, I just decremented floorNumber by 1 in body of method, and it works now.

Wrap Around Grid - errors on east/west only

I have four methods that check whether or not a given grid location is next to an occupied location (value of 1). The grid is assumed to wrap around, ie, if in a 50x50 grid[0][1] is the given location and grid[49][1] is occupied, the method should return true/ My checkNorth and checkEast method are working fine, but I get an ArrayIndexOutofBoundsException: -1 error for either the south or west methods every time I run the program. I checked my math and I think it should work - am I using the modulo incorrectly, or am I missing something else?
EDIT: Clarified the wrapping criterion, word use correction.
boolean checkWest(int indexA, int indexB)
{
if (indexA-1 > 0)
{
if (grid[indexA-1][indexB] == 1)
{
return true;
}
}
if (indexA-1 < 0)
{
if (grid[(indexA-1)%width][indexB] == 1)
{return true;}
else return false;
}
return false;
}
I see a couple problems. First, Java arrays are zero-indexed, which means that the first element is at index 0. So it's okay to check grid[indexA-1][indexB] when indexA-1 is equal to 0. Second, you're not properly handling when indexA equals 0. Here is my implementation. I also simplified the logic a bit.
boolean checkWest(int indexA, int indexB)
{
if (indexA > 0)
return grid[indexA - 1][indexB] == 1;
else
return grid[width + indexA - 2][indexB] == 1;
}
EDIT: I'm pretty sure I butchered the math with the second return statement. It should be right now...

Java help regarding looping (do loops)

I'm trying to make a very basic game where you guess a number between 1-1000 using a do loop. Everything works, except when I finally make the correct guess, I am still prompted to make another guess, and when I enter the same correct guess again, the program terminates like it's suppose to.
Why do I have to make that extra guess to finally get my program to work? Am I looping around an extra time? Also, if I make a correct guess (the compiler will say I am correct then still prompt me), then a wrong guess (the compiler will tell me I'm wrong), then the correct guess again, the program will only terminate after I make the correct guess a second time.
The second do loop at the bottom is what I put in my main method. Everything above is in a method I wrote called play.
public static boolean play()
{
boolean c;
int n = 0;
do {
String input = JOptionPane.showInputDialog("Enter a number between 1-1000");
n = Integer.parseInt(input);
if (n == guess)
{
System.out.println("Correct");
c = true;
}
else if (n < guess)
{
System.out.println("Not Right");
c = false;
}
else
{
System.out.println("Not Right");
c = false;
}
guess++;
} while (c == false);
return c;
}
In main method:
do {
game1.play();
} while (game1.play() != true);
This loop runs the play method twice in each iteration of the loop :
do {
game1.play(); // first call
} while (game1.play()!=true); // second call
You are not testing the value returned by the first call, so even if it returns true, you would still call game1.play() again, which will display "Enter a number between 1-1000" again.
Replace it with:
boolean done = false;
do {
done = game1.play();
} while (!done);
This would only call play() one time in each iteration of the loop.
That said, I'm not sure why you need the outer loop.
You can just replace in with one call to game1.play(), since game1.play() will loop until the correct number is entered.

Trouble with creating Battleship using Java

The following block of code is supposed to check if the coordinates that the user entered are the coordinates of the ship. The ship is located on a two dimensional array at (1,1) and (1,2).
The problem started when I surrounded the getUserGuess method implementation with a while loop. The loop checks if the ship is still alive and will keep asking for the user to enter coordinates until the ship is sunk. However, as soon as the user enters either pair of the correct coordinates, the entire ship is sunk.
I have no idea why this keeps happening. As soon as I comment out the loop, the problem stops, but the loop is necessary.
Here is the method:
public void checkResult(String userGuess) {
while (frigateIsAlive == true) {
if (userGuess.equalsIgnoreCase(board[1][1])){
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][1] = " *";
createBoard();
}
if (userGuess.equalsIgnoreCase(board[1][2])) {
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][2] = " *";
createBoard();
}
else if (numOfHitsOnFrigate == 2) {
System.out.println("Enemy frigate has been sunk!");
frigateIsAlive = false;
break;
}
else {
System.out.println("miss!");
// try again
}
}
}
public String getUserGuess()
{ // takes the users guess
System.out.println("Choose a coordinate on the board to fire at");
int x = input.nextInt();
int y = input.nextInt();
String userGuess = board[x][y];
return userGuess;
}
Let me know if you need to see any other part of the code in order to better assist me.
This method is flawed :
If userGuess matches board[1][1], the loop will make you increment numOfHitsOnFrigate twice, and then you'll change frigateIsAlive to false and exit.
If userGuess matches board[1][2], the loop will make you increment numOfHitsOnFrigate infinite times and you'll never exit.
If userGuess doesn't match, the loop will never terminate, and keep printing miss! without getting new input.
You need to remove the loop, since this method checks a single userGuess, and change the conditions :
public void checkResult(String userGuess) {
if (userGuess.equalsIgnoreCase(board[1][1])){
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][1] = " *";
createBoard();
} else if (userGuess.equalsIgnoreCase(board[1][2])) {
System.out.println("hit!");
numOfHitsOnFrigate++;
board[1][2] = " *";
createBoard();
} else {
System.out.println("miss!");
// try again
}
if (numOfHitsOnFrigate == 2) {
System.out.println("Enemy frigate has been sunk!");
frigateIsAlive = false;
}
}
Based on what you wrote - I surrounded the getUserGuess method implementation with a while loop. - you have another loop which keeps getting input from the user. That other loop, whose code you haven't shown us, is necessary, since without it the game won't progress.
What you probably want (pseudo-code):
start (of a loop)
ask user for a guess
check result for the guess
sunk => stop / not sunk => continue to start
(i.e. you misplaced your while loop)

Repeated Addition

I just got a task asking me to do repeated addition from 1 to 21, as follows :
1,4,6,9,11,14,16,19,21
and get the total.
I tried this code but it returned to be a +2 addition, and it even bypass the prerequisite of bil<=21
public class test
{
public static void main(String[]args)
{
int bil=1;
long total=0;
boolean mult = true;
for(bil=1; bil<=21;bil++)
{
if(mult=true)
{
bil+=1;
mult=false;
}
else if(mult=false)
{
bil+=2;
mult=true;
}
System.out.println(bil);
total=total+bil;
}
System.out.println("----+");
System.out.println(total);
}
}
(if it's TL;DR)
Basically the request is 1+4+6+9+11+14+16+19+21=?
I can't seem to get these code to work, please help me?
EDIT : Thanks guys I got it now :D
You need boolean mult = false; so that the first time the loop runs, bil is incremented by 3 and not 2.
First, you are not comparing your boolean with ==. Therefore, every time the for() loop executes, the first block will be the one that enters since mult = true will always store true in mult... and then qualify that if() block to run.
If this assignment wasn't intentional, then you need to change it to == and also put some logic in your loop to toggle mult appropriately.
Basically when it runs through the first loop it only adds one because of the state of the boolean but also there should be an == operator to check instead of just an =
Try this:
for (bil = 1; bil < 21; bil++) {
if (bil % 2 == 0) { // If bil is divisible by 2, then add 2
bil += 2;
continue;
}
bil += 3;
}

Categories