Map rotated 90 degrees? - java
I have a class Grid, which manages all map functions. The issue is, the pacman map is rotated by 90 degrees anticlockwise.
How it looks
How it should look
I got the 'fixed' version by swapping out grid[x][y] to be grid[y][x] inside isWall() (an untidy, incorrect method)
Here is the whole code for the Grid class;
package com.jackwilsdon.pacman.game;
import org.newdawn.slick.Graphics;
public class Grid {
public static final int BLOCK_SIZE = 20;
public int[][] grid = null;
public Grid()
{
grid = new int[][] { {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0},
{0,1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,0,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,0,1,0},
{0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0},
{0,1,1,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,1,1,0},
{0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0},
{0,0,0,0,1,0,1,0,1,1,0,1,1,0,1,0,1,0,0,0,0},
{0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0},
{0,0,0,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,0,0,0},
{0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0,1,0,0,0,0},
{0,1,1,1,1,0,1,0,1,1,1,1,1,0,1,0,1,1,1,1,0},
{0,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,0},
{0,1,0,1,1,0,1,1,1,0,1,0,1,1,1,0,1,1,0,1,0},
{0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0},
{0,1,1,0,1,0,1,0,1,1,1,1,1,0,1,0,1,0,1,1,0},
{0,1,0,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,0,1,0},
{0,1,0,1,1,1,1,1,1,0,1,0,1,1,1,1,1,1,0,1,0},
{0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0},
{0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0} };
}
public boolean isWall(int x, int y)
{
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length)
{
return grid[y][x] == 1;
}
return true;
}
public void draw(Graphics g)
{
for (int cX = 0; cX < grid.length; cX++)
{
for (int cY = 0; cY < grid[cX].length; cY++)
{
if (this.isWall(cX, cY))
{
g.fillRect(cX*Grid.BLOCK_SIZE, cY*Grid.BLOCK_SIZE, Grid.BLOCK_SIZE, Grid.BLOCK_SIZE);
}
}
}
}
}
Have I made a silly mistake in my code?
I don't want to switch x and y, as that is no longer the proper format for the 2d array.
The problem I see with your code is that the bounds check is incorrect. In other words, this piece of code:
if (x >= 0 && x < grid.length && y >= 0 && y < grid[0].length)
{
return grid[y][x] == 1;
}
should actually be
if (x >= 0 && x < grid[0].length && y >= 0 && y < grid.length)
{
return grid[y][x] == 1;
}
Your current code works only because the dimensions are equal (the map is square).
You have the same error in draw function. In other words, it should be
for (int cY = 0; cY < grid.length; cY++)
{
for (int cX = 0; cX < grid[cY].length; cX++)
{
if (this.isWall(cX, cY))
{
g.fillRect(cX*Grid.BLOCK_SIZE, cY*Grid.BLOCK_SIZE, Grid.BLOCK_SIZE, Grid.BLOCK_SIZE);
}
}
}
In any case, grid[y][x] is correct and not grid[x][y] because grid[i] refers to the row at index i of the 2D array, not column.
This is just a symptom of the fact that grid[i][j] refers to the jth element in the ith sub-array, which is actually the position at the jth column and the ith row in your formatted grid.
Since you want x to represent the column and y to represent the row, grid[y][x] is the correct way to access a position in your array.
Related
How to find circumference and area of a 2D shape whose indices are given as 0 or 1 in a 2D array?
Given a 2D array of size 20x20 whose values resemble a 2D shape, for example a square or rectangle: public static int[][] rectangle= { {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0}, {0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} }; I would like to find its circumference and area in an algorithm that does the following: Finds the nearest (1) point starting from the center (point[10][10]). Uses the nearest (1) point as a starting point to iterate over all the remaining 1s to count the circumference. calculates the number of zeros enclosed by the circumference to calculate the area Now below is where I am currently at; the "guess" method calculates the nearest (1) point and executes the "count" method which then calculates the circumference. public static void guess() { boolean found = false; if(!found) { int y = 10; for(int x = 10; x <= 20; x++) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y++]==1) { rectangle[x][y] = 2; found = true; break; } } } if(!found) { int y = 10; for(int x = 10; x >= 0; x--) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y--]==1) { rectangle[x][y] = 2; found = true; break; } } } if(!found) { int x = 10; for(int y = 10; y <= 20; y++) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y++]==1) { rectangle[x][y] = 2; found = true; break; } } } if(!found) { int x = 10; for(int y = 10; y >= 0; y--) { if(rectangle[x][y]==1) { rectangle[x][y] = 2; found = true; break; }else if(rectangle[x][y--]==1) { rectangle[x][y] = 2; found = true; break; } } } for(int i = 0; i < 20; i++) { for(int j = 0; j < 20; j++) { if(rectangle[i][j] == 2) { Count(i, j); break; } } } } public static void Count(int x, int y) { public int circumf; int tx = x; int ty = y; for(int c = 40; c >=0; c--) { if((c/2)-1<0 || x>=20 || x<0 || y>=20 || y<0) break; if(rectangle[x][(int) (c/2)-1]==1 || rectangle[(int) (c/2)-1][y]==1 || rectangle[x++][y]==1 || rectangle[x][y++]==1 || rectangle[x--][(int) (c/2)-1]==1 || rectangle[(int) (c/2)-1][y--]==1 || rectangle[x--][y]==1 || rectangle[x][y--]==1) { circumf++; } } x = tx; y = ty; for(int c = 0; c <=40; c++) { if((c/2)>=20 || x>=20 || x<0 || y>=20 || y<0) break; if(rectangle[x][(int) (c/2)]==1 || rectangle[(int) (c/2)][y]==1 || rectangle[x++][y]==1 || rectangle[x][y++]==1 || rectangle[x--][(int) (c/2)]==1 || rectangle[(int) (c/2)] [y--]==1 || rectangle[x--][y]==1 || rectangle[x][y--]==1) { circumf++; } } System.out.print(circumf); Now, the guess method calculates the nearest point correctly, however the count method doesn't correctly counts the circumference which is close to 70 in the above example. As for the area calculating algorithm, I still didn't quite figure it out. The above code isn't the most brilliant or organized thing I know, but any help would be really appreciated!
Suppose you find the nearest one at index [i][j]. You need to check the nearest values in a cross pattern since your object is a rectangle. For example you are in the middle one in the left edge of the rectangle: 0 1 0 0 1 0 0 1 0 You check were the 1's "continue" finding thus the edge direction. There are 2 possible outcomes either [x-1][y]=[x][y]=[x+1][y] or [x][y-1]=[x][y]=[x][y+1]==1 So,you found that the edge is vertical. Continue iterating through this verical line until the condition [x][y-1]==1 is false. Then do the same thing for the horizontal line. Now for the 0's count you could store the index i,j of all the corners while you are doing the above check.If you know their positions and the size of the array is fixed you can calculate the 0's like: 0's area = [(DL_corner_index - 1) - (UL_corner_index + 1)] x [(UR_corner_index - 1) - (UL_corner_index + 1)] int rectangle[10][10] ={ {0,0,0,0,0,0,0,0,0,0}, {0,1,1,1,1,1,1,1,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,0,0,0,0,0,0,1,0}, {0,1,1,1,1,1,1,1,1,0}, {0,0,0,0,0,0,0,0,0,0} }; //calculating area of zeros with known corner coordinates //you have stored the coordinates in variables like this int UL_X=1,UR_X=8; int UL_Y=1,DL_Y=8; int area = ((UR_X-1) - UL_X)*((DL_Y-1)-UL_Y); cout<<area; //36 }
How to add a class that prints to the console on to a JPanel
I have this class that randomly creates rooms next to each other, and prints brackets (which represent the rooms) to the console. But I wanted to know how to add something like that to a JPanel for a GUI. Here is the room generator class: public class Rooms { static final int width = 15, height = 10; static final int rooms = 19; static boolean[][] room = new boolean[width][height]; static int neighborCount(int x, int y) { int n = 0; if (x > 0 && room[x-1][y]) n++; if (y > 0 && room[x][y-1]) n++; if (x < width-1 && room[x+1][y]) n++; if (y < height-1 && room[x][y+1]) n++; return n; } public void Rooms() { room[width/2][height/2] = true; Random r = new Random(); int x, y, nc; for (int i = 0; i < rooms; i++) { while (true) { x = r.nextInt(width); y = r.nextInt(height); nc = neighborCount(x, y); if (!room[x][y] && nc == 1) break; } room[x][y] = true; } for (y = 0; y < height; y++) { for (x = 0; x < width; x++) System.out.print(room[x][y] ? "[]" : " "); System.out.print(); } } } Thanks for the help!
You probably want to use java.awt.Graphics. It lets you draw primitive shapes like lines, rectangles, circles, etc. This might get you started. Section 2 also covers how to draw on a JPanel.
Calculating next frame in conways game of life using java
trying to create a Conways Game of life, but apparently the shapes are not like they have to be. Perhaps someone can help me find the issue. For example the glider : - X - - - - - - X X - - - X X - - - - - - - - - becomes this - - X X - - - X - - - - X X X - - - - X X X - - but should be like this : - - X - - - - - - X - - - X X X - - - - - - - - And my code looks like this public Frame(int x, int y) { setWidth(x); setHeight(y); if (x<1) frame = null; else if (y<1) frame = null; else { frame = new String [x][y]; for (int i=0; i<frame.length; i++) { for (int j=0; j<frame[i].length; j++) { frame [i][j] = DEAD; } } } // else } // construktor public Integer getNeighbourCount(int x, int y) { Frame cell = new Frame(getHeight(), getWidth()); int counter = 0; if(frame[x][y].equals(ALIVE)) { counter = counter - 1; } for(int i=x-1; i<=x+1;i++){ if(i<frame.length && i>0){ for(int j=y-1; j<=y+1;j++){ if(j<frame[i].length && j>0){ if (frame[i][j]==ALIVE) { counter++; } } } } } return counter; } public Frame nextFrame() { // Returns next frame Frame cell = new Frame(getWidth(), getHeight()); //cell.frame = new String[getWidth()][getHeight()]; for(int i = 0; i < frame.length; i++){ for(int j =0; j <frame[i].length;j++){ int n = getNeighbourCount(i,j); if(cell.frame[i][j]==null) { cell.frame[i][j] = DEAD; } if (isAlive(i, j) && n < 2 || n > 3) { cell.frame[i][j] = DEAD; } if (isAlive(i, j) && n == 3 || n == 2){ cell.frame[i][j] = ALIVE; } if(!isAlive(i, j) && n == 3) { cell.frame[i][j] = ALIVE; } if(isAlive(i, j) && n > 3){ cell.frame[i][j] = DEAD; } frame[i][j] = cell.frame[i][j]; } } cell.toString(); return cell; } ` Full code http://pastebin.com/LMwz724H
Here's a solution that works - using an enum for each cell and getting the i/j and x/y stuff right (I think). It certainly generates the correct first iteration: static class GameOfLife { final int w; final int h; State[][] frame; enum State { Dead, Alive; } public GameOfLife(int w, int h) { this.w = w; this.h = h; frame = new State[h][w]; } public void alive(int x, int y) { frame[y][x] = State.Alive; } public void tick() { frame = nextGeneration(); } private int surroundingPopulation(int x, int y) { int pop = 0; for (int i = y - 1; i <= y + 1; i++) { for (int j = x - 1; j <= x + 1; j++) { // On frame - vertically. if ((i >= 0 && i < h) // On frame horizontally. && (j >= 0 && j < w) // Alive && (frame[i][j] == State.Alive) // Not the center. && (i != y || j != x)) { pop += 1; } } } return pop; } private State[][] nextGeneration() { State[][] next = new State[h][w]; for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { int pop = surroundingPopulation(x, y); // Any live cell if (frame[y][x] == State.Alive) { if (pop < 2) { // ... with fewer than two live neighbours dies, as if caused by under-population. next[y][x] = State.Dead; } else if (pop > 3) { // ... with more than three live neighbours dies, as if by overcrowding. next[y][x] = State.Dead; } else { // ... with two or three live neighbours lives on to the next generation. next[y][x] = State.Alive; } } else { // Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. if (pop == 3) { next[y][x] = State.Alive; } } } } return next; } #Override public String toString() { StringBuilder s = new StringBuilder(); for (State[] row : frame) { for (State c : row) { s.append(c == State.Alive ? "X" : " "); } s.append("\r\n"); } return s.toString(); } } public void test() { GameOfLife g = new GameOfLife(6, 6); g.alive(1, 0); g.alive(2, 1); g.alive(3, 1); g.alive(1, 2); g.alive(2, 2); System.out.println("Before:\r\n" + g); g.tick(); System.out.println("After:\r\n" + g); }
I believe the problem is that you are copying the new value as you iterate through the loop. This means neighbours are using the value from the next tick rather than the current one. You can fix this by waiting until you calculated all new values in your new frame: cell.frame and then iterate through the frame again and copy from cell.frame to frame. An alternative (better in my view) is to have away of cloning a frame during construction. Then you could change your nextFrame method to create a clone of frame and use the clone to set the new values in frame.
You are changing the DEAD and ALIVE frames while you iterate through the grid. You need to store the coordinates which should die or become alive and perform that afterwards. Store the coordinates in two ArrayLists (dead, alive). The first and second position is the x and y axis, and change those coordinates according to whether they should become alive or not.
Here's a snippet from a simple test I wrote a while back. As others have mentioned, don't change values on an active board while still reading them. Instead, clone the board and make changes to the copy while reading the current board. Another problem I bumped into a few times was iterating over y, then x for each y, but referring to x,y when accessing a point. It feels back to front :) // Rules: // 1) Any live cell with fewer than two live neighbours dies, as if caused by under-population. // 2) Any live cell with two or three live neighbours lives on to the next generation. // 3) Any live cell with more than three live neighbours dies, as if by overcrowding. // 4) Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction. void mutateGrid() { // Copy existing grid into the next generation's grid boolean[][] mutatedGrid = new boolean[gridXWidth][gridYHeight]; for (int i = 0; i < gridXWidth; i++) { System.arraycopy(grid[i], 0, mutatedGrid[i], 0, gridYHeight); } // Start mutation rules for (int y = 0; y < gridYHeight; y++) { for (int x = 0; x < gridXWidth; x++) { int liveNeighbours = countLiveNeighbours(x,y); if (liveNeighbours < 2 || liveNeighbours > 3) { mutatedGrid[x][y] = false; } else if (liveNeighbours == 3) { mutatedGrid[x][y] = true; } } } grid = mutatedGrid; } int countLiveNeighbours(int x, int y) { int count = 0; for (int j = y-1; j <= y+1; j++) { for (int i = x-1; i <= x+1; i++) { if (i < 0 || j < 0 || i >= gridXWidth || j >= gridYHeight){ continue; } if (grid[i][j]) { count++; } } } count -= grid[x][y]?1:0; // remove self from count return count; }
Algorithm for counting number of paths in an X by Y grid
I'd like to create a program in Java that calculates the number of paths a robot can take from top left of a grid T(x, y) to bottom left.. Using each square in the grid only once and using ALL the squares in the grid. The robot can move up down left and right, making it more complicated. I know it's a recursive program I just don't know how to implement it.
You need to keep track of the number of free squares and when you reach the bottom left you check if you used up all squares. static int countPaths(boolean[][] grid) { int freeSquares = 0; for(int y = 0; y < grid.length; y++) { for(int x = 0; x < grid[y].length; x++) { if(grid[y][x]) freeSquares++; } } return _countPaths(grid, 0, 0, freeSquares); } static int _countPaths(boolean[][] grid, int x, int y, int freeSquares) { if(!grid[y][x]) return 0; if(y == grid.length-1 && x == 0) { // bottom left if(freeSquares == 1) return 1; else return 0; } int sum = 0; grid[y][x] = false; for(int dy = -1; dy <= 1; dy++) { for(int dx = -1; dx <= 1; dx++) { int newX = x+dx, newY = y+dy; if(newX < 0 || newY < 0 || newY >= grid.length || newX >= grid[y].length) continue; if((dx == 0 && dy == 0) || (dx != 0 && dy != 0)) continue; sum += _countPaths(grid, x+dx, y+dy, freeSquares-1); } } grid[y][x] = true; return sum; } public static void main (String args[]) { boolean[][] grid = {{true, true, true, false}, {true, true, true, false}, {true, true, true, true}, {true, true, true, true}}; System.out.println(countPaths(grid)); }
So, what do you need to know? You need to know the current state of the board, and where the robot is. From that, you can explore each of the adjacent cells which haven't been visited yet. As you explore each cell, apply the algorithm recursively to explore their adjacent cells. Eventually, each exploration will either find the goal, or run out of opportunities. The basic algorithm will look something like this: explore(board, position) { if (position == goal) { count++ return } board.mark(position) for cell in position.neighbors if not board.ismarked(cell) explore(board, cell) board.unmark(position) }
Implementing flood fill to check for group - Java
I have been looking over this flood fill implementation for some time now and keep running into the dreaded stack overflow. I am dropping pieces randomly on a 12x10 grid and calling the checkMatches method after each random piece drop to check for groups of three or more, hence the flood fill use. EDIT: See comment public void checkMatches(int x, int y, int type) { if (x < 0 || x >= PIECES_WIDE || y < 0 || y >= PIECES_TALL || type == 0) return; if (grid[x][y].getType() != type) return; int checkL = x; while (checkL >= 0 && grid[checkL][y].getType() == type) { grid[checkL][y].setDestroy(true); numMatches++; checkL--; } checkL++; int checkR = x; while (checkR < PIECES_WIDE - 1 && grid[checkR][y].getType() == type) { grid[checkR][y].setDestroy(true); numMatches++; checkR++; } checkR--; for (int i = checkL; i <= checkR; i++) { if (y > 0 && grid[i][y - 1].getType() == type) checkMatches(i, y - 1, type); if (y < PIECES_TALL - 1 && grid[i][y + 1].getType() == type) checkMatches(i, y + 1, type); } } Then the relevant code to call the method and destroy the pieces if there have been three matched pieces: checkMatches(x, y, type); if (numMatches >= 3) { for (int i = 0; i < PIECES_WIDE; i++) { for (int j = 0; j < PIECES_TALL; j++) { if (grid[i][j].isDestroy()) destroyPiece(grid[i][j]); } } } else { numMatches = 0; for (int i = 0; i < PIECES_WIDE; i++) { for (int j = 0; j < PIECES_TALL; j++) { grid[i][j].setDestroy(false); } } } My eyes and brain hurt. I know that the recursion is causing the overflow, but I also know that this implementation is possible in some form. Therefore I'm doing something wrong. Thanks in advance.
You need to put a mark on the pieces that you have already found matching. Then you can make a loop to extend your matchings, until you notice that no more pieces have been marked. Then you can stop.