Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 days ago.
Improve this question
I am making a uno game for a school project. The code displayed below if giving me some issues, and i dont know why.
The code below is suppose to check if the cpu has any cards that match the players card in the middle. If there is a card that matches, the cpu places it down. If there isnt a card that matches, the code checks to see if the cpu has a wild card, if so it places it down, if not then it draws.
For some reason the draw() method is giving me issues, rather than the cpu drawing just 1 card, sometimes it draws 2, 5, 10,etc.
To be clear, i am pretty sure the issue isnt my draw method, i have tested it out.
I assume the issue stems from a problem with my loops in the gamePlayed subclass.
Here is the code
private void game_played(Canvas canvas, MouseEvent event) {
//Setting the horizontal position of the mouse to x
double x = event.getX();
//Setting the Vertical position of the mouse to x
double y = event.getY();
//Setting the defualt card in the Middle
boolean played = false;
for (int i = 0 ; i < human.getHand().size(); i++) {
if (x > 20+75*(i%10) && x < 20+75*(i%10) + 75
&& y > 400+110*(i/10) && y <400+110*(i/10)+110) {
//C becomes the card we clicked
myCard c = human.getHand().get(i);
//C is placed in the middle of the scene
humanMiddle = c;
//We remove the card clicked from our hand
human.getHand().remove(i);
//Breaking the loop
//My code - checking for color match
//If the card in the middle for the human is red
if (humanMiddle.color == myCard.RED) {
//loop through the cpu hand, and see if you find a red card
for (int r = 0; r < cpu.getHand().size(); r++ ) {
//if you find a red card
if (cpu.getHand().get(r).color == myCard.RED) {
//the cpu middle now becomes that card
cpuMiddle = cpu.getHand().get(r);
//we remove the card from the hand
cpu.getHand().remove(r);
//else if, we have a wild card
} else if (cpu.getHand().get(r).value == -1){
//the cpu middle now becomes the wild card
cpuMiddle = cpu.getHand().get(r);
//we remove the wild card from the hand
cpu.getHand().remove(r);
} else {
cpu.draw();
}
}
}
if (humanMiddle.color == myCard.BLUE) {
for (int b = 0; b < cpu.getHand().size(); b++ ) {
if (cpu.getHand().get(b).color == myCard.BLUE) {
cpuMiddle = cpu.getHand().get(b);
cpu.getHand().remove(b);
} else if (cpu.getHand().get(b).value == -1){
cpuMiddle = cpu.getHand().get(b);
cpu.getHand().remove(b);
} else {
cpu.draw();
}
}
}
if (humanMiddle.color == myCard.YELLOW) {
for (int ye = 0; ye < cpu.getHand().size(); ye++ ) {
if (cpu.getHand().get(ye).color == myCard.YELLOW) {
cpuMiddle = cpu.getHand().get(ye);
cpu.getHand().remove(ye);
} else if (cpu.getHand().get(ye).value == -1){
cpuMiddle = cpu.getHand().get(ye);
cpu.getHand().remove(ye);
} else {
cpu.draw();
}
}
}
if (humanMiddle.color == myCard.GREEN) {
for (int g = 0; g < cpu.getHand().size(); g++ ) {
if (cpu.getHand().get(g).color == myCard.GREEN) {
cpuMiddle = cpu.getHand().get(g);
cpu.getHand().remove(g);
} else if (cpu.getHand().get(g).value == -1){
cpuMiddle = cpu.getHand().get(g);
cpu.getHand().remove(g);
} else {
cpu.draw();
}
}
}
played = true;
break;
}
}
here is the draw method
public void draw() {
int value = (int)(Math.random()*13);
int color = (int)(Math.random()*5);
while (value == 11) value = (int)(Math.random()*13);
if (color == myCard.BLACK) {
value = -1;
}
myCard card = new myCard();
card.value = value;
card.color = color;
hand.add(card);
}
I would appreciet any help
I have tried, adding breaks, to stop the loops at Certain points, but it just makes it worst.
This question already has answers here:
What causes a java.lang.ArrayIndexOutOfBoundsException and how do I prevent it?
(26 answers)
Closed 6 years ago.
I am trying to use stacks to find my way through a maze.
Before I worry about stacks, I am trying to get it so that it comes to a dead-end first.
However, when I run my code I am getting java.lang.ArrayIndexOutofBoundsException: -1. Which does not make sense since I am constantly updating the rows and columns.
Here is part of my code that I am stuck on:
Maze myMaze = new Maze (rows, columns);
MazeDisplay myDisplay = new MazeDisplay (myMaze);
myMaze.buildMaze(10);
myMaze.setSolveAnimationDelay(75);
boolean [][] mazeArray = new boolean [rows][columns];
for (int row=0; row<mazeArray.length; row++)
for (int col=0; col<mazeArray[row].length; col++)
mazeArray[row][col] = false;
mazeArray [myMaze.getCurrentRow()][myMaze.getCurrentCol()] = true;
for (int i = 0; i < 9999999 ; i++) //Temporary for now
{
int arrayRows = myMaze.getCurrentRow();
int arrayCols = myMaze.getCurrentCol();
if (myMaze.isOpen(Maze.Direction.RIGHT) && mazeArray [arrayRows][1 + arrayCols] == false)
{
myMaze.move(Maze.Direction.RIGHT);
//mazeStack.push(Maze.Direction.RIGHT);
mazeArray[arrayRows][arrayCols] = true;
}
else if (myMaze.isOpen(Maze.Direction.UP) && mazeArray [1 + arrayRows][arrayCols] == false)
{
myMaze.move(Maze.Direction.UP);
//mazeStack.push(Maze.Direction.UP);
mazeArray[arrayRows][arrayCols] = true;
}
else if (myMaze.isOpen(Maze.Direction.LEFT) && mazeArray [arrayRows][arrayCols - 1] == false) // <---Getting an error here.
{
myMaze.move(Maze.Direction.LEFT);
//mazeStack.push(Maze.Direction.LEFT);
mazeArray[arrayRows][arrayCols] = true;
}
else if (myMaze.isOpen(Maze.Direction.DOWN) && mazeArray [arrayRows - 1][arrayCols] == false) // <---Getting an error here.
{
myMaze.move(Maze.Direction.DOWN);
//mazeStack.push(Maze.Direction.DOWN);
mazeArray[arrayRows][arrayCols] = true;
}
Is there a way to get around this? What I want is to access the ArrayList's position down or left of the current position.
Here are some of the methods of the Maze class:
//-------- isOpen - returns true if there is no wall in the direction that is passed in
public boolean isOpen(Direction direction)
{
boolean result = false;
if (direction == Direction.UP && mazeArray[currentArrayRow-1][currentArrayCol]==0)
result = true;
else if (direction == Direction.DOWN && mazeArray[currentArrayRow+1][currentArrayCol]==0)
result = true;
else if (direction == Direction.LEFT && mazeArray[currentArrayRow][currentArrayCol-1]==0)
result = true;
else if (direction == Direction.RIGHT && mazeArray[currentArrayRow][currentArrayCol+1]==0)
result = true;
return result;
}
//-------- getCurrentRow - returns the current (real) row
public int getCurrentRow()
{
return currentArrayRow/2;
}
//-------- getCurrentCol - returns the current (real) col
public int getCurrentCol()
{
return currentArrayCol/2;
}
// -------- move - receives a Direction and moves there if OK. Calls the other
// arrayMove to do this
public boolean move(Direction direction)
{
boolean success = false;
if (direction == Direction.UP)
success = arrayMove(currentArrayRow-2, currentArrayCol);
else if (direction == Direction.DOWN)
success = arrayMove(currentArrayRow+2, currentArrayCol);
else if (direction == Direction.LEFT)
success = arrayMove(currentArrayRow, currentArrayCol-2);
else if (direction == Direction.RIGHT)
success = arrayMove(currentArrayRow, currentArrayCol+2);
return success;
}
//This is Maze's enumerated data type: moves can be UP, DOWN, LEFT, RIGHT
public enum Direction
{
UP, DOWN, LEFT, RIGHT
}
//-------- getMazeArray - returns the mazeArray
public int[][] getMazeArray()
{
return mazeArray;
}
Before checking the left cell, you should check that you are not on the left edge. Otherwise mazeArray [arrayRows][arrayCols - 1] will throw an exception, since arrayCols - 1 = -1.
If I understand your code correctly, your algorithm isn't perfect. It gets stuck at dead ends. I think the shortest path algorithm is the easiest one to implement.
I have made a simple puzzle game where you slide a ball either vertically or horizontally on a grid. The level format is just an array with 1 meaning a tile you can be onto and 0 being a wall. It's not possible to stop until the ball meets a wall.
Example level:
map[][] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,1,1,1,0,0,2,0,1,1,1,1,0},
{0,0,1,1,1,1,1,1,1,1,0,1,0},
{0,1,1,1,1,0,1,1,1,1,1,1,0},
{0,1,0,1,1,1,1,1,1,1,1,1,0},
{0,1,0,1,1,1,1,1,0,1,1,1,0},
{0,1,1,0,1,1,1,1,1,1,1,1,0},
{0,1,1,1,0,1,1,0,1,1,1,1,0},
{0,1,1,1,1,0,1,1,1,1,1,1,0},
{0,1,1,1,1,1,0,1,1,0,1,1,0},
{0,1,1,1,1,1,3,1,1,1,1,1,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0}
}
(I know it's a bit troublesome to have Y-axis first)
The problem is how on earth can one make an algorithm that solves all possible routes from the starting point (3) to the goal (2). This made me look up some common algorithms online but they only solved:
a route on a grid with free movement
the most efficient route
I have written this:
//keep track of tiles the player has already been to
List<Integer> beenToX = new ArrayList<Integer>();
List<Integer> beenToY = new ArrayList<Integer>();
beenToX.add(0, 6); //starting x-coordinate
beenToY.add(0, 10); //starting y-coordinate
Boolean solving = true;
while (solving) {
for (int i = 0; i < 4; i++) { //num of directions N=0, E=1, S=2, W=3
for (int j = 1; j < 11; j++) {
if (i == 0) {
if (map[beenToY.get(0)+j][beenToX.get(0)] == 0) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
break;
}
if (map[beenToY.get(0)+j][beenToX.get(0)] == 2) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
solving = false;
break;
}
}
if (i == 1) {
if (map[beenToY.get(0)][beenToX.get(0)+j] == 0) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
break;
}
if (map[beenToY.get(0)][beenToX.get(0)+j] == 2) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
solving = false;
break;
}
}
if (i == 2) {
if (map[beenToY.get(0)-j][beenToX.get(0)] == 0) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
break;
}
if (map[beenToY.get(0)-j][beenToX.get(0)] == 2) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
solving = false;
break;
}
}
if (i == 3) {
if (map[beenToY.get(0)][beenToX.get(0)-j] == 0) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
break;
}
if (map[beenToY.get(0)][beenToX.get(0)-j] == 2) {
beenToX.add(0, currentX);
beenToY.add(0, beenToY.get(0)+j);
solving = false;
break;
}
}
}
}
}
Then I realized I have a problem: How do I deal with the program handling multiple direction possibly at the same time? How about dealing with multiple correct routes?
It's also missing a section to check which tiles the player has already been to, to avoid running in circles.
Your movement rules might be unconventional, but it's still a classic pathfinding problem.
Dijkstra, A-star and all the rest work on any graph representation. So you just need to abstract yout movement away into a graph representation. At the most basic level, it only means each Node (State) links to a few other Nodes.
A pathfinder does not need to know yabout movement rules, it only needs a State representation like so:
public interface State extends Comparable<State>{
List<? extends State> neighbours(); // Alternatively, return a Map<State, Integer> to associate a distance/cost
}
I assume you know how to code a Pathfinder class that matches this interface (otherwise look around on S:O):
public interface Pathfinder(){
List<State> path(State start, State end);
}
In this case, here's what a resonable State implementation would look like for you:
public class RollingBallState extends Point implements State{
private static map[][] map = [...];// This must be available somehow at the start, you decide how (hint: static var like I did is ugly AF)
public RollingBallState(int xStart, int yStart){
super(xStart, yStart);
}
#Override
public List<RollingBallState> neighbours(){
List<RollingBallState> neighbours = new ArrayList<>(4);
int xLeft = getX(); // Where the ball can travel left
for(int x=getX()-1; x>=0; x--){
if(map[x][getY()] == 0){
break;
} else{
xLeft = x;
}
}
if(xLeft < xBall){
neighbours.add(new RollingBallState(xLeft, getY()));
}
[...Get xRight, yUp, yDown, and add them in the same fashion ...]
return neighbours;
}
#Override
public int compareTo(RollingBallState other){
if(getX() == other.getX()){
return getY() - other.getY();
} else {
return getX() - other.getX();
}
}
}
You're all set up, just feed two RollingBallState (start & end) to your Pathfinder, it will give you the path.
The purpose of this assignment was to create a Field and Robot class and objects of those classes.
The single field object is limited to a square of points from (0, 0) to (50, 50), and contains 3 pieces of gold and 3 bombs.
Three robot objects search the field (one after another) for gold from left to right (0, 0) to (0, 50) and descend through the field (1, 0) to 1, 50) and so on.
The robots are destroyed by bombs that are places by input from the user. Once the gold is collected it cannot be picked up by another robot, and one a bomb explodes it does not do so again.
This is my attempt at solving the problem so far, I am continuing to work on it, but would appreciate a second pair of eyes on it to catch something im missing. The program compiles, but the bombs and gold arent being "found" correctly and the output states that the following robots die on the same bomb as the one before it. Also, there are several pieces of code removed by comments, I did this to test different parts of the program. I think this section is where I'm having trouble. The methods field.alreadyFound() and field.alreadyBombed() return a boolean with the value true. My if statements should be saying if the gold/bomb has already been found, ignore it.
while(x <= 50 && y <= 50 && alive2 == true) {
foundGold1 = robot2.look(field.locateGold1());
foundGold2 = robot2.look(field.locateGold2());
foundGold3 = robot2.look(field.locateGold3());
foundBomb1 = robot2.look(field.locateBomb1());
foundBomb2 = robot2.look(field.locateBomb2());
foundBomb3 = robot2.look(field.locateBomb3());
/*gotBomb1 = field.alreadyBombed1();
gotBomb2 = field.alreadyBombed2();
gotBomb3 = field.alreadyBombed3();
gotGold1 = field.alreadyFound1();
gotGold2 = field.alreadyFound2();
gotGold3 = field.alreadyFound3();*/
if (foundGold1 == true){
if (field.alreadyFound1() == true){}
else {robot2.addGold();
field.foundGold1();}
}
if (foundGold2 == true) {
if (field.alreadyFound2() == true){}
else {robot2.addGold();
field.foundGold2();}
}
if (foundGold3 == true) {
if (field.alreadyFound3() == true){}
else {robot2.addGold();
field.foundGold3();}
}
if (foundBomb1 == true) {
if (field.alreadyBombed1() == true){}
else alive2 = false;
}
if (foundBomb2 == true) {
if (field.alreadyBombed2() == true){}
else alive2 = false;
}
if (foundBomb3 == true) {
if (field.alreadyBombed3() == true){}
else alive2 = false;
}
y = y + 1;
robot2.setLocation(x, y);
//System.out.println(y);
if (y == 50)
{x = x + 1;
y = 0;}
}
I don't see where you set that a bomb has exploded, so from what I see here, you're missing that part.
Below is the code reformatted and slightly restructured: I found the code fairly difficult to work with as-is. It may be easier to work with this shorter, more canonical, and IMO more communicative version.
while (x <= 50 && y <= 50 && alive2 == true) {
foundGold1 = robot2.look(field.locateGold1());
foundGold2 = robot2.look(field.locateGold2());
foundGold3 = robot2.look(field.locateGold3());
foundBomb1 = robot2.look(field.locateBomb1());
foundBomb2 = robot2.look(field.locateBomb2());
foundBomb3 = robot2.look(field.locateBomb3());
/*gotBomb1 = field.alreadyBombed1();
gotBomb2 = field.alreadyBombed2();
gotBomb3 = field.alreadyBombed3();
gotGold1 = field.alreadyFound1();
gotGold2 = field.alreadyFound2();
gotGold3 = field.alreadyFound3();*/
if (foundGold1 && !field.alreadyFound1()) {
robot2.addGold();
field.foundGold1();
}
if (foundGold2 && !field.alreadyFound2()) {
robot2.addGold();
field.foundGold2();
}
if (foundGold3 && !field.alreadyFound3()) {
robot2.addGold();
field.foundGold3();
}
if (foundBomb1 && !field.alreadyBombed1()) {
alive2 = false;
}
if (foundBomb2 && !field.alreadyBombed2()) {
alive2 = false;
}
if (foundBomb3 && !field.alreadyBombed3()) {
alive2 = false;
}
y = y + 1;
robot2.setLocation(x, y);
if (y == 50) {
x = x + 1;
y = 0;
}
}
You may also be hampered by the amount of code it takes to do this work: I assume you have essentially identical code for robot1 and robot2, the only difference being which robot you're currently processing.
Rather than repeat the code, consider passing a currentRobot in to a single method. There are a variety of ways to go about dealing with issues like this, but that fits in well with what you've already done. You're likely want to add an isAlive method/property to the robot class.