I have been working on creating a Checkers game in Eclipse using Gridworld. So far I have been only modifying red pieces. My goal is to be able to move() pieces and have them choose whether to jump or to step. Obviously, jumping (i.e. when the piece moves over a piece of the opposite color and then removing that piece from the grid) takes precedence over stepping. My problem is that whenever I try to move pieces that are either in the first two or last two columns I get an Illegal Out of Bounds error. Can anyone help me solve this? Please and thank you.
import java.awt.Color;
import info.gridworld.actor.Actor;
import info.gridworld.actor.Bug;
import info.gridworld.actor.Critter;
import info.gridworld.actor.Flower;
import info.gridworld.grid.Grid;
import info.gridworld.grid.Location;
public class RedPieces extends Bug {
boolean jumped;
public RedPieces() {
setColor(Color.red);
setDirection(180);
jumped = false;
}
public boolean canMove() {
Grid<Actor> gr = getGrid();
if (gr == null)
return false;
Location loc1 = getLocation();
if (getGrid().get(new Location(loc1.getRow() + 1, loc1.getCol() - 1)) == null ||
getGrid().get(new Location(loc1.getRow() + 1, loc1.getCol() - 1)).getColor() == Color.black ||
getGrid().get(new Location(loc1.getRow() + 1, loc1.getCol() + 1)) == null ||
getGrid().get(new Location(loc1.getRow() + 1, loc1.getCol() + 1)).getColor() == Color.black) {
return true;
}
return false;
}
public boolean jump2(Location loc){
Grid<Actor> gr = getGrid();
if (gr == null)
return false;
Location jump1 = new Location(loc.getRow() + 2, loc.getCol() - 2);
Location jump2 = new Location(loc.getRow() + 2, loc.getCol() + 2);
if( (gr.isValid(jump1)) &&
(gr.get(jump1) == null) &&
(gr.get(jump2) == null) &&
(gr.get(new Location(loc.getRow() + 1, loc.getCol() -1)) instanceof BlackPieces) &&
((gr.get(new Location(loc.getRow() + 1, loc.getCol() + 1)) == null) ||
(gr.get(new Location(loc.getRow() + 1, loc.getCol() + 1))) instanceof RedPieces))
{
gr.get(new Location(loc.getRow() + 1, loc.getCol() -1)).removeSelfFromGrid();
moveTo(jump1);
return true;
}
else if( (gr.isValid(jump2)) &&
(gr.get(jump2) == null) &&
(gr.get(jump1) == null) &&
(gr.get(new Location(loc.getRow() + 1, loc.getCol() +1)) instanceof BlackPieces) &&
((gr.get(new Location(loc.getRow() +1, loc.getCol() - 1)) == null) ||
(gr.get(new Location(loc.getRow() + 1, loc.getCol() -1)) instanceof RedPieces)))
{
gr.get(new Location(loc.getRow() + 1, loc.getCol() +1)).removeSelfFromGrid();
moveTo(jump2);
return true;
}
else if((gr.isValid(jump1) && gr.get(jump1) == null) &&
(gr.isValid(jump2) && gr.get(jump2) != null))
{
if(gr.get(new Location(loc.getRow() + 1, loc.getCol() -1)) instanceof BlackPieces)
{
gr.get(new Location(loc.getRow() + 1, loc.getCol() -1)).removeSelfFromGrid();
moveTo(jump1);
return true;
}
}
else if((gr.isValid(jump2) && gr.get(jump2) == null) &&
(gr.isValid(jump1) && gr.get(jump1) != null))
{
if(gr.get(new Location(loc.getRow() + 1, loc.getCol() +1)) instanceof BlackPieces)
{
gr.get(new Location(loc.getRow() + 1, loc.getCol() +1)).removeSelfFromGrid();
moveTo(jump2);
return true;
}
}
return false;
}
public void move() {
Grid<Actor> gr = getGrid();
if (gr == null)
return;
Location loc = getLocation();
Location next1 = new Location(loc.getRow() + 1, loc.getCol() - 1);
Location next2 = new Location(loc.getRow() + 1, loc.getCol() + 1);
if (jump2(loc) == false) {
if (gr.isValid(next2) && gr.get(next2) == null &&
gr.isValid(next1) && gr.get(next1) != null)
{
moveTo(next2);
}
else if (gr.isValid(next1) && gr.get(next1) == null &&
gr.isValid(next1) && gr.get(next2) != null)
{
moveTo(next1);
}
else if (gr.isValid(next1) && gr.get(next1) == null &&
gr.isValid(next2) && gr.get(next2) == null)
{
moveTo(randomLoc(next1, next2));
}
else
return;
}
}
public static Location randomLoc(Location loc1, Location loc2) {
double num = Math.random();
if (num < 0.5)
return loc1;
else
return loc2;
}
public void act() {
if(canMove()) move();
}
}
Had to reformat your code for better readability. By doing so, I have found a few potential bugs.
In the jump2()
method, the second if
statement does not check the validity of jump2
. It might be the cause of exception at gr.get(jump2 == null)
condition in that if
statement.
The same logic applies to the subsequent else if
statement. This time, you are not checking the validity of jump1
.
In the move()
method, the first else if
, you only check the validity of next1
twice which seems a bug. Please find it in the reformatted code in your question.
Overall, I think you need to modify the if
conditions as simple(readable) as possible. Reformatting will help, too.
[Added] Two minor things.
In the canMove()
method, you use gr
only at the first if
statement. You are using getGrid()
instead of gr
in the second if
statement.
Can you not avoid doing new Location
everytime you get grid in the if
statements? You are using those grids without checking their validity. Are you sure they are valid? You might create them at the beginning of the method, check their validity, and use them in the if
statements. It might help the readability of the if
statements, too.
[Added more] jump2()
method simplification sample
The following code ignores the other side of column (being invalid, null or red piece). It is on my assumption that it doesn't matter what the condition of other sides when one side is valid for jumping over a black piece.
public boolean jump2(Location loc){
Grid<Actor> gr = getGrid();
if (gr == null)
return false;
Location jump1 = new Location(loc.getRow() + 2, loc.getCol() - 2);
Location jump2 = new Location(loc.getRow() + 2, loc.getCol() + 2);
Location adjacent1 = new Location(loc.getRow() + 1, loc.getCol() - 1);
Location adjacent2 = new Location(loc.getRow() + 1, loc.getCol() + 1);
// try one column
if( gr.isValid(jump1))
{
if( (gr.get(jump1) == null) &&
(gr.get(adjacent1) instanceof BlackPieces))
{
gr.get(adjacent1).removeSelfFromGrid();
moveTo(jump1);
return true;
}
}
// try the other column
if( gr.isValid(jump2))
{
if( (gr.get(jump2) == null) &&
(gr.get(adjacent2) instanceof BlackPieces))
{
gr.get(adjacent2).removeSelfFromGrid();
moveTo(jump2);
return true;
}
}
return false;
}