i have a program that generates a random maze. In the maze a red dot is displayed and the red dot flashes on by each block in the maze. all the blocks in the maze are == 1 and if the red dot goes through that block, it increments ++. the red dot goes in the direction towards the lowest number, that way it wont stay in an infinite loop by a dead end. once it reaches the end, ive solved the maze.
This is where im stumped, im trying to print the red dot to find the optimal route all the way back to the beginning where it started. I used a stack class that i made to record all the y and x components of where the red dot traveled. im able to traceback every where the red dot has gone but that isnt the optimal solution.
My question is how could i print the red dot tracing back in only the optimal path. My idea of solving this would be to check and see if the coordinates of a stack where visited before, if so..find the last case where it was visited and print the red dot up until that point. that way itll never deal with the dead ends it traveled.
the method solve() is what contains the traceback and solving technique for the red dot to travel through the maze and back.
Im not the greatest programmer and im still learning how to use stacks, ive been stumped for hours and dont know how to approach this. Please be kind and explain how you would do it using the stack i made. Thank you
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
import javax.swing.*;
public class mazedfs extends JFrame implements KeyListener
{
/* default values: */
private static int bh = 16; // height of a graphical block
private static int bw = 16; // width of a graphical block
private int mh = 41; // height and width of maze
private int mw = 51;
private int ah, aw; // height and width of graphical maze
private int yoff = 40; // init y-cord of maze
private Graphics g;
private int dtime = 40; // 40 ms delay time
byte[][] M; // the array for the maze
public static final int SOUTH = 0;
public static final int EAST = 1;
public static final int NORTH = 2;
public static final int WEST = 3;
public static boolean showvalue = true; // affects drawblock
// args determine block size, maze height, and maze width
public mazedfs(int bh0, int mh0, int mw0)
{
bh = bw = bh0; mh = mh0; mw = mw0;
ah = bh*mh;
aw = bw*mw;
M = new byte[mh][mw]; // initialize maze (all 0's - walls).
this.setBounds(0,0,aw+10,10+ah+yoff);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{Thread.sleep(500);} catch(Exception e) {} // Synch with system
this.addKeyListener(this);
g = getGraphics(); //g.setColor(Color.red);
setup();
}
public void paint(Graphics g) {} // override automatic repaint
public void setup()
{
g.setColor(Color.green);
g.fill3DRect(0,yoff,aw,ah,true); // fill raised rectangle
g.setColor(Color.black);
// showStatus("Generating maze...");
digout(mh-2,mw-2); // start digging!
// digout exit
M[mh-1][mw-2] = M[mh-2][mw-1] = 1;
drawblock(mh-2,mw-1);
solve(); // this is the function you will write for parts 1 and 2
play(); // for part 3
}
public static void main(String[] args)
{
int blocksize = bh, mheight = 41, mwidth = 41; // need to be odd
if (args.length==3)
{
mheight=Integer.parseInt(args[0]);
mwidth=Integer.parseInt(args[1]);
blocksize=Integer.parseInt(args[2]);
}
mazedfs W = new mazedfs(blocksize,mheight,mwidth);
}
public void drawblock(int y, int x)
{
g.setColor(Color.black);
g.fillRect(x*bw,yoff+(y*bh),bw,bh);
g.setColor(Color.yellow);
// following line displays value of M[y][x] in the graphical maze:
if (showvalue)
g.drawString(""+M[y][x],(x*bw)+(bw/2-4),yoff+(y*bh)+(bh/2+6));
}
void drawdot(int y, int x)
{
g.setColor(Color.red);
g.fillOval(x*bw,yoff+(y*bh),bw,bh);
try{Thread.sleep(dtime);} catch(Exception e) {}
}
/////////////////////////////////////////////////////////////////////
/* function to generate random maze */
public void digout(int y, int x)
{
M[y][x] = 1; // digout maze at coordinate y,x
drawblock(y,x); // change graphical display to reflect space dug out
int dir = (int)(Math.random()*4);
for (int i=0;i<4;i++){
int [] DX = {0,0,2,-2};
int [] DY = {-2,2,0,0};
int newx = x + DX[dir];
int newy = y + DY[dir];
if(newx>=0 && newx<mw && newy>=0 && newy<mh && M[newy][newx]==0)
{
M[y+DY[dir]/2][x+DX[dir]/2] = 1;
drawblock(y+DY[dir]/2,x+DX[dir]/2);
digout(newy,newx);
}
dir = (dir + 1)%4;}
} // digout
/* Write a routine to solve the maze.
Start at coordinates x=1, y=1, and stop at coordinates
x=mw-1, y=mh-2. This coordinate was especially dug out
after the program called your digout function (in the "actionPerformed"
method).
*/
public void solve()
{
int x=1, y=1;
Stack yourstack = null;
drawdot(y,x);
while(y!=mh-2 || x!=mw-2 && M[y][x]!=0){
int min = 0x7fffffff;
int DX = 0;
int DY = 0;
if (y-1>0 && min>M[y-1][x] && M[y-1][x]!=0){
min = M[y-1][x];
DX = 0;
DY = -1;
}//ifNORTH
if (y+1>0 && min>M[y+1][x] && M[y+1][x]!=0){
min = M[y+1][x];
DY = 1;
DX = 0;
}//ifSOUTH
if (x-1>0 && min>M[y][x-1] && M[y][x-1]!=0){
min = M[y][x-1];
DX = -1;
DY = 0;
}//ifWEST
if (x+1>0 && min>M[y][x+1] && M[y][x+1]!=0){
min = M[y][x+1];
DX = 1;
DY = 0;
}//ifEAST
M[y][x]++;
drawblock(y,x);
x = x+DX;
y = y+DY;
drawdot(y,x);
yourstack = new Stack(y,x,yourstack); // creates new stack for each coordinate travelled
}//while
while(yourstack != null){
yourstack = yourstack.tail;
drawdot(yourstack.y,yourstack.x); // this will traceback every box ive been through
}//while
} // solve
class Stack{
int x;
int y;
Stack tail;
public Stack(int a, int b, Stack t){
y = a;
x=b;
tail=t;
}
}//stackclass
///////////////////////////////////////////////////////////////
/// For part three (save a copy of part 2 version first!), you
// need to implement the KeyListener interface.
public void play() // for part 3
{
// code to setup game
}
// for part 3 you may also define some other instance vars outside of
// the play function.
// for KeyListener interface
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public void keyPressed(KeyEvent e) // change this one
{
int key = e.getKeyCode(); // code for key pressed
System.out.println("YOU JUST PRESSED KEY "+key);
}
} // mazedfs
////////////
// define additional classes (stack) you may need here.
when you trace your path back you currently just go back to your stack - but thats not the shortest path...
...whenever you can go back check the values of M around you:
byte valueOfFieldNorthOfXY = M[x][y-1]; //x/y is your current position
byte valueOfFieldWesthOfXY = M[x-1][y];
byte ...;
byte ...; //and so on...
while the first while-loop in your solve-methode simplay solves the maze by flooding it the second while-method is for going back...
and when i say flooding i mean: each time a field has been passed by the 'walker' the value of M[x][y] has been increased by 1 (when the 'walker' has walked 3x over field 5/6 then the value from M[5][6] = 3)
so when you go back from the end (#40/50) to the start (#1/1), you do this algorith:
1) i stand on x/y
2) i check the values north/east/south/west of me
2a) if i come from north, then i ignore the north field
2 ) ... and so on...
2d) if i come from west , then i ignore the west field
3) i pick that direction, where the value is the least
4) put the current field int your packPathStack and walk to
the 'best' direction
5) repeat (go back to Nr.1) until you are #1/1
example
? 4 ? //i'm standing at X (x/y)
2 x f //? are values from walls or not yet considerd
? ? ? //f is where i come from
--> i pick direction WEST(2) because thats less than NORTH(4)
implement this algorithm and you a NEW stack i call it yourPathBackStack
Stack yourPathBackStack = new Stack();
while(x != 1 && y != 1 ){ //x/y = 1/1 = start - do it until you are there (Nr. 5)
// 1) i stand on x/y
int x = yourPathBackStack.x;
int y = yourPathBackStack.y;
// 2) i check the values north/east/south/west of me
byte valueOfFieldNorthOfXY = ... ; //as seen above
// 2a) if i come from north, then i ignore the north field
if (yourstack.tail.x == x && yourstack.tail.y == y-1){
//check - i DO come from north
//make then valueOfFieldNorthOfXY very high
valueOfFieldNorthOfXY = 100; //it's the same as ignoring
}
// 2 ) ... and so on...
// 2d) if i come from west , then i ignore the west field
if (yourstack.tail.x == x-1 && ...// as seen above
// 3) i pick that direction, where the value is the least
int direction = NORTH; //lets simply start with north;
byte maxValue = 100;
if ( valueOfFieldNorthOfXY < maxValue ){ //First north
maxValue = valueOfFieldNorthOfXY;
direction = NORTH;
}
if ( valueOfFieldWestOfXY < maxValue ){ //Then east
maxValue = valueOfFieldWestOfXY ;
direction = WEST;
}
//then the also other directions
if ( value ... //as seen above
// 4) put the current field int your yourPathBackStack and walk to
// the 'best' direction
int newx = x;
int newy = y;
if (direction == NORTH){ //direction has been caclulated above
newy = newy - 1;
}
if (direc ... //with all other direction)
yourPathBackStack = new Stack(newx, newy, yourPathBackStack );
drawdot(yourPathBackStack.y,yourPathBackStack.x);
}
Related
I am looking for some help with some game code i have inherited from a flight sim. The code below simulates bombs exploding on the ground, it works fine but i am trying to refine it.
At the moment it takes a random value for x and y as a start point and then adds another random value between -20 and 20 to this. It works ok, but doesn't simulate bombs dropping very well as the pattern does not lay along a straight line/
What i would like to achieve though is all x and y points after the first random values, to lay along a straight line, so that the effects called for all appear to lay in a line. It doesn't matter which way the line is orientated.
Thanks for any help
slipper
public static class BombUnit extends CandCGeneric
{
public boolean danger()
{
Point3d point3d = new Point3d();
pos.getAbs(point3d);
Vector3d vector3d = new Vector3d();
Random random = new Random();
Aircraft aircraft = War.GetNearestEnemyAircraft(this, 10000F, 9);
if(counter > 10)
{
counter = 0;
startpoint.set(point3d.x + (double)(random.nextInt(1000) - 500), point3d.y + (double)(random.nextInt(1000) - 500), point3d.z);
}
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
World.MaxVisualDistance = 50000F;
counter++;
String s = "weapon.bomb_std";
startpoint.x += random.nextInt(40) - 20;
startpoint.y += random.nextInt(40) - 20;
Explosions.generate(this, startpoint, 7F, 0, 30F, !Mission.isNet());
startpoint.z = World.land().HQ(startpoint.x, startpoint.y);
MsgExplosion.send(this, s, startpoint, getOwner(), 0.0F, 7F, 0, 30F);
Engine.land();
int i = Landscape.getPixelMapT(Engine.land().WORLD2PIXX(startpoint.x), Engine.land().WORLD2PIXY(startpoint.y));
if(firecounter < 100 && i >= 16 && i < 20)
{
Eff3DActor.New(null, null, new Loc(startpoint.x, startpoint.y, startpoint.z + 5D, 0.0F, 90F, 0.0F), 1.0F, "Effects/Smokes/CityFire3.eff", 300F);
firecounter++;
}
super.setTimer(15);
}
return true;
}
private static Point3d startpoint = new Point3d();
private int counter;
private int firecounter;
public BombUnit()
{
counter = 11;
firecounter = 0;
Timer1 = Timer2 = 0.05F;
}
}
The code in the question is a mess, but ignoring this and trying to focus on the relevant parts: You can generate a random position for the first point, and a random direction, and then walk along this direction in several steps.
(This still raises the question of whether the direction is really not important. Wouldn't it matter if only the first bomb was dropped in the "valid" area, and the remaining ones outside of the screen?)
However, the relevant code could roughly look like this:
class Bombs
{
private final Random random = new Random(0);
int getScreenSizeX() { ... }
int getScreenSizeY() { ... }
// Method to drop a single bomb at the given position
void dropBombAt(double x, double y) { ... }
void dropBombs(int numberOfBombs, double distanceBetweenBombs)
{
// Create a random position in the screen
double currentX = random.nextDouble() * getScreenSizeX();
double currentY = random.nextDouble() * getScreenSizeY();
// Create a random step size
double directionX = random.nextDouble();
double directionY = random.nextDouble();
double invLength = 1.0 / Math.hypot(directionX, directionY);
double stepX = directionX * invLength * distanceBetweenBombs;
double stepY = directionY * invLength * distanceBetweenBombs;
// Drop the bombs
for (int i=0; i<numberOfBombs; i++)
{
dropBombAt(currentX, currentY);
currentX += stepX;
currentY += stepY;
}
}
}
I am assuming your startpoint is a StartPoint class with x,y,z coordinates as integers in it.
I hope I have understood your problem correctly. It looks like you either want to create a vertical explosion or a horizontal explosion. Since an explosion always occurs on ground, the z coordinate will be zero. Now you can vary one of x or y coordinate to give you a random explosion along a straight line. Whether you choose x or y could be fixed or could be randomized itself. A potential randomized solution below:
public boolean danger() {
// stuff
int orientation = Random.nextInt(2);
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
// stuff
startPoint = randomizeStartPoint(orientation, startPoint);
// stuff
}
}
StartPoint randomizeStartPoint(int orientation, StartPoint startPoint) {
if(orientation == 0) {
startPoint.x += random.nextInt(40) - 20;
}
else {
startPoint.y += random.nextInt(40) - 20;
}
return startPoint;
}
In response to the image you uploaded, it seems that the orientation of the explosion need not necessarily be horizontal or vertical. So the code I posted above gives a limited solution to your problem.
Since you want any random straight line, your problem boils down to two sub parts:
1. Generate a random straight line equation.
2. Generate random point along this line.
Now, a straight line equation in coordinate geometry is y = mx + c where m is the slope and c is the constant where the line crosses the y-axis. The problem with c is that it gives rise to irrational coordinates. I am assuming you are looking for integer coordinates only, since this will ensure that your points are accurately plotted. (You could do with rational fractions, but then a fraction like 1/3 will still result in loss of accuracy). The best way to get rid of this irrational problem is to get rid of c. So now your straight line always looks like y = mx. So for step one, you have to generate a random m.
Then for step 2, you can either generate a random x or random y. It doesn't matter which one, since either one will result in random coordinates.
Here is a possible code for the solution:
int generateRandomSlope() {
return Random.nextInt(100); // arbitrarily chose 100.
}
int randomizeStartPoint(int m, StartPoint startPoint) { // takes the slope we generated earlier. without the slope, your points will never be on a straight line!
startPoint.x += random.nextInt(40) - 20;
startPoint.y += x * m; // because a line equation is y = mx
return startPoint;
}
public boolean danger() {
// stuff
int m = generateRandomSlope(); // you may want to generate this elsewhere so that it doesn't change each time danger() is called.
if(aircraft != null && (aircraft instanceof TypeBomber) && aircraft.getArmy() != myArmy)
{
// stuff
startPoint = randomizeStartPoint(m, startPoint);
// stuff
}
}
Again, this is not a complete or the best solution.
A program I'm modifying is supposed to use a drawing panel to randomly move a square, starting from the center, either left or right and use an array to tally the position it moves to while the square stays on screen (the panel is 400 x 400 and the square is 10 x 10, so there are only 40 possible positions it can move to) After the square goes off screen, I have to print a histogram that shows how many times the square moved to that index (i.e if the square moved from the x coordinate of 200 to 190, index 19 would get a tally) Here is my code:
import java.awt.*;
import java.util.*;
public class RandomWalkCountSteps {
// DrawingPanel will have dimensions HEIGHT by WIDTH
public static final int HEIGHT = 100;
public static final int WIDTH = 400;
public static final int CENTER_X = WIDTH / 2;
public static final int CENTER_Y = HEIGHT / 2;
public static final int CURSOR_DIM = 10;
public static final int SLEEP_TIME = 25; // milliseconds
public static void main( String[] args ) {
DrawingPanel panel = new DrawingPanel( WIDTH, HEIGHT );
Random rand = new Random();
walkRandomly( panel, rand );
}
public static void walkRandomly( DrawingPanel panel, Random rand ) {
Graphics g = panel.getGraphics();
int[] positionCounts = new int[ WIDTH / CURSOR_DIM ];
// start in center of panel
int x = CENTER_X;
int y = CENTER_Y;
// Draw the cursor in BLACK
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
// randomly step left, right, up, or down
while ( onScreen( x, y ) ) {
panel.sleep( SLEEP_TIME );
// Show a shadow version of the cursor
g.setColor(Color.GRAY);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
if ( rand.nextBoolean() ) { // go left
x -= CURSOR_DIM;
}
else { // go right
x += CURSOR_DIM;
}
positionCounts[ x / CURSOR_DIM ]++;
histogram(positionCounts, x, y);
// draw the cursor at its new location
g.setColor(Color.BLACK);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
}
}
public static boolean onScreen( int x, int y ) {
return 0 <= x && x < WIDTH
&& 0 <= y && y < HEIGHT;
}
public static void histogram(int[] positionCounts, int x, int y) {
if (onScreen(x, y) == false) {
for (int i = 0; i < WIDTH / CURSOR_DIM; i++) {
System.out.print(i + ": ");
for (int j = 1; j <= positionCounts[i]; j++) {
System.out.print("*");
}
System.out.println();
}
}
}
}
My problem was that I couldn't find a good place to initialize the array so that it wouldn't re-initialize every time I passed the x coordinate to the histogram method. Now that I thought I had it in the right place, I get this error message on both calls to histogram in the method walkRandomly "error: method histogram in class RandomWalkCountSteps cannot be applied to given types;" I'm fairly new to java and programming in general, so there's probably something I'm missing regarding arrays as parameters. Thanks in advance.
histogram takes two parameters, positionCounts of type int[] and x of type int. In walkRandomly, you call histogram twice: once with an argument positionCounts of type int[] and once with an argument x of type int. That’s why the compiler complains that the method ”cannot be applied to given types”: the method histogram(int[], int) can’t be applied to (called with) the given types, i.e., histogram(int[]) and histogram(int).
I’m not sure what you’re trying to do with this code, but I’d guess that you want remove the first call and change the second call (inside of the while loop) to histogram(positionCounts, x).
(You’ve edited your code, so my answer doesn’t make much sense.)
I have most of the code written im just having some difficulty finishing up. I am supposed to create some code that will have a square randomly walk around on the drawing board until it walks off the screen. I can get it to work a little bit but i have a feeling it's not correct. Any help will be appreciate.
Here is an example of what it is supposed to look like
Here is my code so far the problem im most concerned about is the walkingRandom method it has stars by it
public class RandomWalk {
// DrawingPanel will have dimensions DIM by DIM
public static final int DIM = 400;
// Start the random walk in the center of the screen
public static final int CENTER = DIM / 2;
// how big should the cursor appear?
public static final int CURSOR_DIM = 10;
// how long should the cursor saty in one place?
public static final int SLEEP_TIME = 5; // milliseconds
public static void main( String[] args ) {
DrawingPanel panel = new DrawingPanel( DIM, DIM );
Random rand = new Random();
walkRandomly( panel, rand );
}
/**
* Draw a random walk on the panel.
* Stop as soon as you walk off the panel.
* Each random step should go only in one
* of these directions: left, right, up, down.
* #param panel a DrawingPanel to draw the
* random walk on
* #param rand a Java Random object to be
* used to generate random steps
*/
public static void walkRandomly( DrawingPanel panel, Random rand ) {
Graphics g = panel.getGraphics();
// start in center of panel
int x = CENTER;
int y = CENTER;
// Randomly step left, right, up, or down
// until cursor goes off screen.
while ( onScreen( x, y ) ) {
// Draw the cursor in BLACK
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
// Wait a bit.
panel.sleep( SLEEP_TIME );
// Show a shadow version of the cursor
g.setColor(Color.GRAY);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
// Choose a new location for the cursor
//*********************************
if (rand.nextInt() < DIM - 300){
x--;
} else if (rand.nextInt() < DIM / 2){
x++;
} else if (rand.nextInt() < DIM - 100){
y--;
} else if (rand.nextInt() < DIM) {
y++;
}
//*********************************
// draw the cursor at its new location
g.setColor(Color.BLACK);
g.fillRect(x, y, CURSOR_DIM, CURSOR_DIM);
}
}
/**
* determine whether (x, y) is a point on the panel.
* #param x the x-coord of the cursor
* #param y the y-coord of the cursor
* #return true if (x,y) is on the screen,
* false if (x,y) is off the screen
*/
public static boolean onScreen( int x, int y ) {
// x/y high = 400, x/y low = 0
//*********************************
return (x <= DIM && x >= 0 || y <= DIM && y >= 0);
}
}
There's a few issues with your code. You did not quite clarify in your question, but I assume that:
All directions should have the same probability of occurring
The cursor can only move "full steps" i.e. it has to move by CURSOR_DIM at a time, not less (that's what seems to be happening in your example)
The problem is mainly in the method walkRandomly, I suggest that you select the next direction as follows:
// Choose a new location for the cursor
int direction = rand.nextInt(4); //0=left, 1=right, 2=up, 3=down
if (direction == 0){
x -= CURSOR_DIM; //The step should be equal to the cursor width, not 1
} else if (direction == 1){
x += CURSOR_DIM;
} else if (direction == 2){
//you usually subtract to go up, the origin being the upper-left corner
y -= CURSOR_DIM;
} else if (direction == 3) {
y += CURSOR_DIM;
}
There's two other issues:
You are drawing the cursor in black at the beginning and at the end of the loop, this is redundant. You could remove one of them and have the same result.
In the onScreen method, x and y values equaling DIM should return false, since usually the bounds of an image/array are 0 to DIM exclusive. Also you should replace the || by an AND, because the cursor should be within the x AND y range, not OR.
return (x < DIM && x >= 0 && y < DIM && y >= 0);
Hope it helps
I have created a game where the player collects pods on the game board. I need to make an evasive maneuver so that after five turns when the player is one space away from the pod, the pod will transport 10 spaces away from the player. I believe my counter is not working and that is why the evasive maneuver is not working.
public class Pod {
int podPositionX;
int podPositionY;
String podDirection;
int layoutWidth;
int layoutHeight;
boolean podVisable = true;
int playerX;
int playerY;
int count = 0;
public Pod(int x, int y, String direction, int width, int height){
podPositionX = x;
podPositionY = y;
podDirection = direction;
layoutWidth = width;
layoutHeight = height;
count=count+1;
}
//Inspector Methods?
// Will get the the pods positon and will return it
public int getX()
{
return podPositionX;
}
//This method returns the current Y coordinate of the pod.
public int getY()
{
return podPositionY;
}
//This method returns true if the pod is visible, false otherwise. Once the
//pod has been caught, it should always return false.
public boolean isVisible(){
if (playerX == podPositionX && playerY == podPositionY && podVisable == true){
podVisable = false;}
return podVisable;
}
// to move pod diagonally across screen//
public void move(){
//Calling invasive methods!!
while (count>5 && count < 100){
podPositionX=transportX();
podPositionY=transportY();
}
/****************** To make pod move **************/
if (podDirection.equals("NW")|| podDirection.equals("NE")){
podPositionY = podPositionY + 1;}
if (podDirection.equals("SW")|| podDirection.equals("SE")){
podPositionY = podPositionY-1;}
if (podDirection.equals("NE")|| podDirection.equals("SE")){
podPositionX = podPositionX+1;}
if(podDirection.equals("NW")|| podDirection.equals("SW")){
podPositionX = podPositionX-1;}
/****************To make Pod bounce off wall******************/
//make pod bounce off left wall
if (podPositionX <= 1){
if (podDirection.equals("SW")){
podDirection = "SE";}
if (podDirection.equals("NW")){
podDirection = "NE";}
}
//make pod bounce off top
if (podPositionY >= layoutHeight-1){
if (podDirection.equals("NW")){
podDirection = "SW";}
if (podDirection.equals("NE")){
podDirection = "SE";}
}
//make pod bounce off right wall
if (podPositionX >= layoutWidth-1){
if (podDirection.equals("NE")){
podDirection = "NW";}
if (podDirection.equals("SE" )){
podDirection = "SW";}
}
//make pod bounce off bottom wall
if (podPositionY <= 1){
if (podDirection.equals("SW")){
podDirection = "NW";}
if (podDirection.equals("SE")){
podDirection = "NE";}
}
}
// to get player x and y positions
public void playerAt(int x, int y){
playerX = x;
playerY = y;
}
//envasive maneuver so that after 5 turns the pod can be transported away from the player if it is 1 spot away from the player.
//then the count is set to 100 so it will exit the loop and not be able to transport the pod again.
public int transportX(){
if (podPositionX == playerX -1 || podPositionX == playerX +1){
podPositionX= playerX +10;
count = 100;}
return podPositionX;
}
public int transportY(){
if (podPositionY == playerY -1 || podPositionY == playerY +1){
podPositionY= playerY +10;
count=100;}
return podPositionY;
}
}
the code my teacher provided us. Can no be touched so i can not put a counter in this file.
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class Project1 extends JFrame implements ActionListener {
// Member variables for visual objects.
private JLabel[][] board; // 2D array of labels. Displays either # for player,
// * for pod, or empty space
private JButton northButton, // player presses to move up
southButton, // player presses to move down
eastButton, // player presses to move right
westButton; // player presses to move left
// Current width and height of board (will make static later).
private int width = 15;
private int height = 9;
// Current location of player
private int playerX = 7;
private int playerY = 4;
// Pod object stored in array for efficiency
private Pod[] pods;
int podCount = 4;
public Project1() {
// Construct a panel to put the board on and another for the buttons
JPanel boardPanel = new JPanel(new GridLayout(height, width));
JPanel buttonPanel = new JPanel(new GridLayout(1, 4));
// Use a loop to construct the array of labels, adding each to the
// board panel as it is constructed. Note that we create this in
// "row major" fashion by making the y-coordinate the major
// coordinate. We also make sure that increasing y means going "up"
// by building the rows in revers order.
board = new JLabel[height][width];
for (int y = height-1; y >= 0; y--) {
for (int x = 0; x < width; x++) {
// Construct a label to represent the tile at (x, y)
board[y][x] = new JLabel(" ", JLabel.CENTER);
// Add it to the 2D array of labels representing the visible board
boardPanel.add(board[y][x]);
}
}
// Construct the buttons, register to listen for their events,
// and add them to the button panel
northButton = new JButton("N");
southButton = new JButton("S");
eastButton = new JButton("E");
westButton = new JButton("W");
// Listen for events on each button
northButton.addActionListener(this);
southButton.addActionListener(this);
eastButton.addActionListener(this);
westButton.addActionListener(this);
// Add each to the panel of buttons
buttonPanel.add(northButton);
buttonPanel.add(southButton);
buttonPanel.add(eastButton);
buttonPanel.add(westButton);
// Add everything to a main panel attached to the content pane
JPanel mainPanel = new JPanel(new BorderLayout());
getContentPane().add(mainPanel);
mainPanel.add(boardPanel, BorderLayout.CENTER);
mainPanel.add(buttonPanel, BorderLayout.SOUTH);
// Size the app and make it visible
setSize(300, 200);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// Auxiliary method to create game setup
createGame();
}
// Auxiliary method used to create board. Sets player, treasure, and walls.
public void createGame() {
// Construct array of Pod objects
pods = new Pod[podCount];
// Construct each Pod in the array, passing it its initial location,
// direction of movement, and the width and heigh of board. This will
// later be modified to be done at random.
pods[0] = new Pod(1, 5, "NE", width, height);
pods[1] = new Pod(2, 1, "SW", width, height);
pods[2] = new Pod(12, 2, "NW", width, height);
pods[3] = new Pod(13, 6, "SE", width, height);
// Call method to draw board
drawBoard();
}
// Auxiliary method to display player and pods in labels.
public void drawBoard() {
// "Erase" previous board by writing " " in each label
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
board[y][x].setText(" ");
}
}
// Get location of each pod and write * into that label. We only
// do this for pods not yet caught.
for (int p = 0; p < podCount; p++) {
if (pods[p].isVisible()) {
board[pods[p].getY()][pods[p].getX()].setText("*");
}
}
// Write the player onto the board.
board[playerY][playerX].setText("#");
}
public void actionPerformed(ActionEvent e) {
// Determine which button was pressed, and move player in that
// direction (making sure they don't leave the board).
if (e.getSource() == southButton && playerY > 0) {
playerY--;
}
if (e.getSource() == northButton && playerY < height-1) {
playerY++;
}
if (e.getSource() == eastButton && playerX < width-1) {
playerX++;
}
if (e.getSource() == westButton && playerX > 0) {
playerX--;
}
// Move the pods and notify the pods about player location.
for (int p = 0; p < podCount; p++) {
pods[p].move();
pods[p].playerAt(playerX, playerY);
}
// Redraw the board
drawBoard();
}
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
Project1 a = new Project1();
}
}
I am looking at this quickly now. You said the problem is with the count variable. I see that you are incrementing it in the constructor i.e
public Pod(int, int, String, int, int){
count = count + 1;
}
why not put it in the move method. That way every time the move method is used the count variable will be incremented by one.
public void move(){
this.count++;
}
Also it is very hard to see exactly what you think your code is doing. I tried to run it and nothing happens. Sometimes it is good to print something to the console.
I have a project to have a red dot inside the first box of a maze i randomly generated and the dot is supposed to follow its way through the boxes and find the end of the maze. Now if it hits a dead end, its supposed to go back to where its path started and not go back down that path, that leads to a dead end. i made it so each box represents the #1, this way when the red dot travels over the box, it increments by 1, so it can realize where its been. its always supposed to go to the lowest number possible so it can never go back to the dead ends its already been to. i am able to reach the end of the maze but i come into 2 problems.
the method i wrote that does all this work is the solve() function. I cant understand why 2 things happen...
1st thing is that when the red dot comes to a branch of dead ends, sometimes itll just go to one dead end, to a different dead end , back to the same dead end.. traveling to the same 'numbers' when im trying to have it only go towards the boxes that have 1's or just the lower numbers.
2nd thing is that once it inevitably reaches the end of the maze.. the red dot goes into the green area, where i specifically say in the while loop, it can not be in a green box.
if M[y][x] = 0, its a green box and if its = 1 its a black box. anything higher than 1 will also be inside the box.
your help is highly appreciated as ive been stuck on this problem for hours and cant seem to find out the problem.
the problem persists in the solve() method
import java.awt.*;
import java.awt.event.*;
import java.awt.Graphics;
import javax.swing.*;
public class mazedfs extends JFrame implements KeyListener
{
/* default values: */
private static int bh = 16; // height of a graphical block
private static int bw = 16; // width of a graphical block
private int mh = 41; // height and width of maze
private int mw = 51;
private int ah, aw; // height and width of graphical maze
private int yoff = 40; // init y-cord of maze
private Graphics g;
private int dtime = 40; // 40 ms delay time
byte[][] M; // the array for the maze
public static final int SOUTH = 0;
public static final int EAST = 1;
public static final int NORTH = 2;
public static final int WEST = 3;
public static boolean showvalue = true; // affects drawblock
// args determine block size, maze height, and maze width
public mazedfs(int bh0, int mh0, int mw0)
{
bh = bw = bh0; mh = mh0; mw = mw0;
ah = bh*mh;
aw = bw*mw;
M = new byte[mh][mw]; // initialize maze (all 0's - walls).
this.setBounds(0,0,aw+10,10+ah+yoff);
this.setVisible(true);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
try{Thread.sleep(500);} catch(Exception e) {} // Synch with system
this.addKeyListener(this);
g = getGraphics(); //g.setColor(Color.red);
setup();
}
public void paint(Graphics g) {} // override automatic repaint
public void setup()
{
g.setColor(Color.green);
g.fill3DRect(0,yoff,aw,ah,true); // fill raised rectangle
g.setColor(Color.black);
// showStatus("Generating maze...");
digout(mh-2,mw-2); // start digging!
// digout exit
M[mh-1][mw-2] = M[mh-2][mw-1] = 1;
drawblock(mh-2,mw-1);
solve(); // this is the function you will write for parts 1 and 2
play(); // for part 3
}
public static void main(String[] args)
{
int blocksize = bh, mheight = 41, mwidth = 41; // need to be odd
if (args.length==3)
{
mheight=Integer.parseInt(args[0]);
mwidth=Integer.parseInt(args[1]);
blocksize=Integer.parseInt(args[2]);
}
mazedfs W = new mazedfs(blocksize,mheight,mwidth);
}
public void drawblock(int y, int x)
{
g.setColor(Color.black);
g.fillRect(x*bw,yoff+(y*bh),bw,bh);
g.setColor(Color.yellow);
// following line displays value of M[y][x] in the graphical maze:
if (showvalue)
g.drawString(""+M[y][x],(x*bw)+(bw/2-4),yoff+(y*bh)+(bh/2+6));
}
void drawdot(int y, int x)
{
g.setColor(Color.red);
g.fillOval(x*bw,yoff+(y*bh),bw,bh);
try{Thread.sleep(dtime);} catch(Exception e) {}
}
/////////////////////////////////////////////////////////////////////
/* function to generate random maze */
public void digout(int y, int x)
{
M[y][x] = 1; // digout maze at coordinate y,x
drawblock(y,x); // change graphical display to reflect space dug out
int dir = (int)(Math.random()*4);
for (int i=0;i<4;i++){
int [] DX = {0,0,2,-2};
int [] DY = {-2,2,0,0};
int newx = x + DX[dir];
int newy = y + DY[dir];
if(newx>=0 && newx<mw && newy>=0 && newy<mh && M[newy][newx]==0)
{
M[y+DY[dir]/2][x+DX[dir]/2] = 1;
drawblock(y+DY[dir]/2,x+DX[dir]/2);
digout(newy,newx);
}
dir = (dir + 1)%4;}
} // digout
public void solve() // This is the method i need help with.
{
int x=1, y=1;
drawdot(y,x);
while(y!=mh-1 || x!=mw-1 && M[y][x]!=0){
int min = 0x7fffffff;
int DX = 0;
int DY = 0;
if (y-1>0 && min>M[y-1][x] && M[y-1][x]!=0){
min = M[y-1][x];
DX = 0;
DY = -1;
}//ifNORTH
if (y+1>0 && min>M[y+1][x] && M[y+1][x]!=0){
min = M[y+1][x];
DY = 1;
DX = 0;
}//ifSOUTH
if (x-1>0 && min>M[y][x-1] && M[y][x-1]!=0){
min = M[y][x-1];
DX = -1;
DY = 0;
}//ifWEST
if (x+1>0 && min>M[y][x+1] && M[y][x+1]!=0){
min = M[y][x+1];
DX = 1;
DY = 0;
}//ifEAST
M[y][x]++;
drawblock(y,x);
x = x+DX;
y = y+DY;
drawdot(y,x);
}//while
// modify this function to move the dot to the end of the maze. That
// is, when the dot reaches y==mh-2, x==mw-2
} // solve
///////////////////////////////////////////////////////////////
/// For part three (save a copy of part 2 version first!), you
// need to implement the KeyListener interface.
public void play() // for part 3
{
// code to setup game
}
// for part 3 you may also define some other instance vars outside of
// the play function.
// for KeyListener interface
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
public void keyPressed(KeyEvent e) // change this one
{
int key = e.getKeyCode(); // code for key pressed
System.out.println("YOU JUST PRESSED KEY "+key);
}
} // mazedfs
////////////
// define additional classes (stack) you may need here.
The issue causing the second problem you are facing (dot moving to green box) lies in the while loop conditiony!=mh-1 || x!=mw-1 && M[y][x]!=0 . The condition evaluates to y!=mh-1 ||(x!=mw-1 && M[y][x]!=0) since && has higher precedence over the || and || just needs one of its operand to be true. In your case, y!=mh-1 is still ture at the end of maze. Hence the loop continues and the dot moves into green area. To fix the issue modify the condition as (y!=mh-1 || x!=mw-1) && M[y][x]!=0. Hope this helps.