Can anyone lend a fresh pair of eyes for debugging? - java

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.

Related

When the player hits the food make it disapear

I am new to programing, so bare with me lol. Our teacher has given us a game in which we need to add some elements to it. It's a game where we have a player, some enemies and some food made out of rectangles. If the player hits the food i want the food to spawn somewhere else in the window. Heres is the code where im trying to make it happen:
private void updateFood(){
for(int i = 0; i < food.length; ++i)
{
//Should we follow or move randomly?
//2 out of 3 we will follow..
if(rnd.nextInt(3) < 2)
{
//We follow
int dx = player.getX() - food[i].getX();
int dy = player.getY() - food[i].getY();
if(abs(dx) > abs(dy))
{
if(dx > 0)
{
//Player is to the right - opiste
food[i].moveLeft();
}
else
{
//Player is to the left - opiste
food[i].moveRight();
}
}
else if(dy > 0)
{
//Player is down; - opiste
food[i].moveUp();
}
else
{//Player is up; - opiste
food[i].moveDown();
}
}
else
{
//We move randomly
int move = rnd.nextInt(4);
if(move == 0)
{
//Move right
food[i].moveRight();
}
else if(move == 1)
{
//Move left
food[i].moveLeft();
}
else if(move == 2)
{
//Move up
food[i].moveUp();
}
else if(move == 3)
{
//Move down
food[i].moveDown();
}
}
if(food[i].getX() == player.getX() && food[i].getY() == player.getY()){
food[i].getX() = random(0,width);
food[i].getY() = random(0,height);
}
}
}
the last 10 lines (or so) is where im having the problem.
if(food[i].getX() == player.getX() && food[i].getY() == player.getY()){
food[i].getX() = random(0,width);
food[i].getY() = random(0,height);
With limited info on what methods your food[index] objects have, I'm going to guess .getX() is read-only, meaning you can't set a value to it. Either find a .setX(number) method, or use the existing .moveLeft/Right/Up/Down(number) with a bit of maths.

Java change long if statement into for loop

I have an if statement that looks like this:
if (pan[x + 1][y + 1].getBackground() == TeamColor &&
pan[x + 1][y].getBackground() == TeamColor &&
pan[x + 1][y -1].getBackground() == TeamColor &&
pan[x][y - 1].getBackground() == TeamColor &&
pan[x - 1][y - 1].getBackground() == TeamColor &&
pan[x - 1][y].getBackground() == TeamColor &&
pan[x - 1][y + 1].getBackground() == TeamColor &&
pan[x][y + 1].getBackground() == TeamColor) {
// do something
}
The goal is to check every item (in a 2d array) around the current x and y values and make sure they are the correct color.
I assume there is a simple way to do such. I would assume creating a for loop would solve the problem by iterating through each item but unfortunately was not able to think of a way to do this because the items are not all in sequence.
NOTE: i found many other posts on stackoverflow that where titled "solution for very long if statement" unfortunately they were in different programing languages (such as python, android and javascript)
NOTE 2: this is Not a duplicate of this post. It was a question of strings and regex and unfortunately not the solution to my problem
Hopefully someone will have an answer!
Try something like this:
boolean match = true;
for (int dx = -1; match && (dx < 2); ++dx) {
for (int dy = -1; match && (dy < 2); ++dy) {
if (dx != 0 || dy != 0) {
match = pan[x+dx][y+dy].getBackground() == TeamColour;
}
}
}
if (match) {
// do something
}
Basically, you want to check offsets -1, 0 and 1 in each direction, so we have two for loops, each producing those offsets in one dimension. We then check the array element corresponding to each offset, and keep track using the match variable.
Note though that, like the original code, this will fail near boundaries (e.g. if x == 0). This can be fixed if necessary.
It is possible, of course, to instead have the loops run over the actual indices to check (e.g. for (int x2 = x-1; x2 < x+2; ++x)). It's much the same in the end.
for (int a = x-1;a <= x+1;a++)
{
if (a < 0 || a >= pan.length) continue;
for (int b = y-1; b <= y+1; b++)
{
if (b < 0 || b >= pan[a].length) continue;
if (a == x && b == y) continue;
if (pan[a][b].getBackground() != TeamColor)
return false;
}
}
return true;
I can propose two ways :
1) Full object way
You could introduce a custom class Coordinate that holds two values : the x and y coordinates.
Create a List of Coordinate where you had the Coordinate element you want to test and iterate on it to achieve your need.
public class Coordinate{
private final int x;
private final int y;
public Coordinate(int x, int y){
this.x = x;
this.y = y;
}
public getX(){
return x;
}
public getY(){
return y;
}
}
And you can use it :
List<Coordinate> coordinates = new ArrayList<>();
coordinates.add(new Coordinate(1,1));
coordinates.add(new Coordinate(1,0));
coordinates.add(new Coordinate(1,-1));
coordinates.add(new Coordinate(0,-1));
coordinates.add(new Coordinate(-1,-1));
coordinates.add(new Coordinate(-1,0));
coordinates.add(new Coordinate(-1,1));
coordinates.add(new Coordinate(0,1));
// you can also init them with a loop
boolean isMatched = true;
for (Coordinate coordinate : coordinates){
if (pan[x + coordinate.getX()][y + coordinate.getY()].getBackground() != TeamColor){
isMatched = false;
break;
}
}
The object way is more verbose but it has the advantage to expose rules.
So you can read and change it easily.
Suppose, the rules to check become more complex, it becomes very valuable.
2) Shorter code way
It is the same logical even by inlining values of Coordinate and by ignoring the specific case that you don't want to test (no change case).
boolean isMatched = true;
for (int xDelta = -1; xDelta <=1; xDelta++){
for (int yDelta = -1; yDelta <=1; yDelta++){
// as you don't want to test if no change
if (yDelta == 0 && xDelta ==0){
continue;
}
if (pan[x + xDelta][y + yDelta ].getBackground() != TeamColor){
isMatched = false;
break;
}
}

Room placement in a maze using Prim's algorithm

I am attempting to place rooms on an ASCII screen, and then use Prim's algorithm to "fill" the space between rooms with maze, but without actually breaking into the rooms. I have been tinkering for a few hours, and I can't figure out a way to stop my algorithm from breaking into my rooms.
Can anyone help me? I'm pretty lost. I'm practicing map generation techniques, and this is my 5th one I'm on. No, I don't want to do it another way, I simply want to do it this way - but right.
Below is both a photo of my current output with rooms, my current output without rooms, and a link to the relevant source code (AKA the Prim's algorithm section). Thanks again if you can actually help me!
Note: All the opposite method does is figure out which cell the "parent" cell is, and determine direction based off of that. So if parent cell's x value is 7, and the child's x value is 6, then it know that's the new child.
start = new Point(x,y, null);
map[start.x][start.y] = Tile.STAIRS_DOWN;
for(int nx = -1; nx <= 1; nx++){
for(int ny = -1; ny <= 1; ny++){
if((nx == 0 && ny == 0) || (nx != 0 && ny != 0)){
continue;
}
try{
if(map[start.x + nx][start.y + ny] == Tile.FLOOR){
continue;
}
frontier.add(new Point(start.x+nx, start.y + ny, start));
}
catch(Exception e){
continue;
}
}
}
Point last = null;
while(!frontier.isEmpty()){
Point cu = frontier.remove(RandomGen.rand(0, frontier.size() - 1));
Point op = cu.opposite();
try{
if((map[cu.x][cu.y] == Tile.WALL) && (map[op.x][op.y] == Tile.WALL)){
for (int bx = -1; bx <= 1; bx++)
for (int by = -1; by <= 1; by++) {
boolean failed = false;
if (bx == 0 && by == 0 || bx != 0 && by != 0)
continue;
try {
if(map[op.x + bx][op.y + by] == Tile.FLOOR){
break;
}
last = op;
if(!failed){
map[cu.x][cu.y] = Tile.FLOOR;
map[op.x][op.y] = Tile.FLOOR;
frontier.add(new Point(op.x + bx, op.y + by, op));
}
}
catch(Exception e){
continue;
}
}
}
}
catch(Exception e){}
}
Without Rooms
With Rooms
Solved: I needed to check my forward facing corners for open spaces. So if I'm going "east" then I need to check Northeast and Southeast tiles as well, or else I will potentially burrow into the rooms.

Draw stops working after if

I'm trying to create a maze with Union Find, but am unable to remove walls.
This is what I have got so far.
private void createMaze (int cells, Graphics g) {
s = new int[cells*cells]; //No unions yet setting all to -1
for(int i = 0; i < cells*cells; ++i){
s[i] = -1;
}
g.setColor(Color.yellow);
random = new Random();
while(breaker){
g.setColor(Color.yellow);
int innerWall = random.nextInt(4)+0;
int randomCellX = random.nextInt(cells-1)+0;
int randomCellY = random.nextInt(cells)+0;
if(randomCellX==cells&&innerWall==2||
randomCellX==0&&innerWall==0||
randomCellY==cells-1&&innerWall==3||
randomCellY==0&&innerWall==1){
continue;
}
else{
int location = randomCellX+(randomCellY*cells);
int neighbour = 0;
if(innerWall==0){
neighbour =location-1;
}
else if(innerWall==1){
neighbour =location-cells;
}
else if(innerWall==2){
neighbour =location+1;
}
else if(innerWall==3){
neighbour =location+cells;
}
int locationRoot =find(location);
int neighbourRoot =find(neighbour);
if(locationRoot==neighbourRoot){
breaker = checkIfDone(s);
}
union(location,neighbour);
drawWall(randomCellX,randomCellY,innerWall,g);
}
}
}
If I remove the
if(randomCellX==cells&&innerWall==2||
randomCellX==0&&innerWall==0||
randomCellY==cells-1&&innerWall==3||
randomCellY==0&&innerWall==1){
continue;
}
It removes the lines fine,but when it is added the walls are not removed. The method is called but doesn't do anything.
It seems some logical mistake have been done obviously. But can not spot specifically as you haven't given the explanation of the logic you have done. Only can help showing the path where the problem might be happening.
Since you can not reach the else block anyway, it is obvious that one or more of these conditions in if are always true.
(randomCellX == cells && innerWall == 2)
(randomCellX == 0 && innerWall == 0)
(randomCellY == cells - 1 && innerWall == 3)
(randomCellY == 0 && innerWall == 1)
That's why you are getting true for the if condition and continuing the loop without doing anything. Ensure the conditions are okay.
If these conditions are right, the next suspect might be these lines:
int innerWall = random.nextInt(4)+0;
int randomCellX = random.nextInt(cells-1)+0;
int randomCellY = random.nextInt(cells)+0;
Check whether these random values range are exactly what you want or not. For example: you are taking random values for randomCellX from 0 to cells-2, but for randomCellY the range is 0 to cells-1.

How to get variables from for loop

I'm trying to make a for loop, which makes me 1000 objects and places those to a randomly generated spot (x, y). So here is the code. I have been struggling with this many hours and I have also been searching from the net but haven't found out any way to do that. After that loop I try to add those objects into some kind of radar.
Here's the code (so the problem is that I can't figure out how to take variables from the loop and make it appear outside the loop):
case "look": {
System.out.print("You are at: " +px +", " +py);
System.out.println("");
StringBuilder objects = new StringBuilder(); //That's something i found out form the net..
while (objnum>=0){ objnum--; //Creates randomly 1000objects around the map
int objid = (int)(Math.random() * 11 + 1); //int objnum is 1000, told above
int objx = (int)(Math.random() * 10000 + 1);
int objy = (int)(Math.random() * 10000 + 1);}
board.spawnObject(new BoardObject(objectid, objx, //That's something i found out form the net..
objy, objnum));
for(int x=px-2 ; x< px+3 ; x++ ){ //px=player position
for(int y=py-2 ; y< py+3 ; y++ ){ //this is how radar is created
if(objid==1 && x==objx && y==objy){board[x][y]=1;}
else if(objid==2 && x==objx && y==objy){board[x][y]=2;}
else if(objid==3 && x==objx && y==objy){board[x][y]=3;} //That's where i need info from the loop..
else if(objid==4 && x==objx && y==objy){board[x][y]=4;}
else if(objid==5 && x==objx && y==objy){board[x][y]=5;}
else if(objid==6 && x==objx && y==objy){board[x][y]=-1;}
else if(objid==7 && x==objx && y==objy){board[x][y]=-2;}
else if(objid==8 && x==objx && y==objy){board[x][y]=-3;}
else if(objid==9 && x==objx && y==objy){board[x][y]=-4;}
else if(objid==10 && x==objx && y==objy){board[x][y]=-5;}
if(x==px && y==py){
board[x][y]=6;}//<- this shows players position on radar
if(board[x][y]==-1){
System.out.print("[sto]");
}else if(board[x][y]==0){
System.out.print("[___]");//<- This works well..
}else if(board[x][y]==-2){
System.out.print("[box]");
}
else if(board[x][y]==-3){
System.out.print("[ppl]");
}
else if(board[x][y]==-4){
System.out.print("[pit]");
}
else if(board[x][y]==-5){
System.out.print("[brk]");
} //That's how radar shows dots/objects
else if(board[x][y]==1){
System.out.print("[kid]");
}
else if(board[x][y]==2){
System.out.print("[tre]");
}
else if(board[x][y]==3){
System.out.print("[pet]");
}
else if(board[x][y]==4){
System.out.print("[bus]");
}
else if(board[x][y]==5){
System.out.print("[???]");
}
else if(board[x][y]==6){
System.out.print("[You]");} //<- This works well..
}
System.out.println();
}; }break;
Simply use Collection interface class like Vector for storing objects and then, access them from outside the loop.Follow this link: http://docs.oracle.com/javase/6/docs/api/java/util/Collection.html
You have to create a variable outside the scope and if a condition is true, than change the value of the variable outside the loop, so:
class example {
int number = 0;
.....
for (int i = 0; i < 10; i++) {
if (i == 5) {
number = 5;
}
}
If the condition is true, then number becomes 5, to get this data, you can create getters and setters.
But if you want to store all those 1000 objects in 1 object, i would recommend to use an array(list), so:
class Example {
ArrayList<Integer> object = new ArrayList<Integer>();
case.....
object.add(objx)
object.add(objy)
}

Categories

Resources