I am making a Pac-Man game and I am currently working on the ghosts AI. I am planning on using Dijkstra's algorithm for the pathfinding. My problem is that when my game is loaded the vertices for the graph are stored in a matrix. I am trying to assign each vertex all of its edges like this
for(int x = 0; x<40; x++)
{
for(int y = 0; y<40; y++)
{
Vertex vertex = map[x][y];
vertex.adjacencies = new Edge[]{new Edge(map[x-1][y], 1), new Edge(map[x+1][y], 1), new Edge(map[x][y-1], 1), new Edge(map[x][y+1], 1)};
}
}
the problem is that it sometimes throws an array out of bounds exception. How would I fix this without putting in tons of if statements to check if the current vertex is on the edge of the graph?
One easy way is to include a non-traversable border around the edges.
For example, if your actual map is 40x40, you can declare a 42x42 array. Rows 0 and n would be non-traversable, as would be columns 0 and n.
You'd still need to handle cylindrical travel of the pacman between left and right sides.
You should start your loop with a "border" of 1, like this:
for(int x = 1; x < 39; x++)
because, when you create your edges with map[x-1][y] with a x started to 0, it take -1 as array index, so it throw an Array Out of Bounds exception.
Related
I'm kind of at a roadblock while trying to assign 3D grid points as vertices to Cells.
The Cells should just contain 8 points as corner vertices.
I have created the grid without any issues, but cant seem to figure out how to sort the points to their according cells.
This sketch illustrates how the points are indexed:
One cube with 8 corner points would correspond to a Cell (ex. Cell0 would include points 0,1,3,4,6,7,9,10 as corner points).
The code should be something like this:
public class Cell
{
public int[] Index =new int[8];
}
public void makeCells()
{
numCells = (xSize - 1) * (zSize - 1) * (ySize - 1);
Cells = new Cell[numCells];
for ( int i = 0, j = 0; i < numCells; i++)
{
Cells[i] = new Cell();
for ( int k = 0; k <8; k++, j ++)
{
Cells[i].Index[k] = j;
}
}
}
I can't seem to get how to increment the indices properly so that they coordinate with the correct points.
Any form of help would be appreciated!
I managed to index all of my vertices using the algorithm above. If anyone needs any further explanation please feel free to ask.
Can someone explain this code in detail, I don't understand what the multiplication in q.offer(x*m + y) does and what the while loop is doing. This is the requirements for the program:
Starting from a given location on the grid, experiment explores the grid, expanding and labeling all of the cells in a single colony originating from the starting location. Taking as input a grid, the coordinates of a starting location, and a label, experiment will either label that location and all its neighbors or do nothing, depending on the presence or absence of a cell at the given location, respectively; either way, experiment is required to return the size of the labeled colony.
(c) The program is responsible for ensuring that experiment is called start- ing at every location on the grid storing a 1. The reason is that experiment locates only a single colony.
For example, using the first grid above and calling experiment for the first time on the location at the top row and forth column will modify the grid only at the locations labeled A, leaving all the other locations intact.
Once every grid location storing a 1 has been colonized, the program freezes the grid by replacing the 0s on the grid with s (dashes) .
(d) The program is responsible for creating an initial grid of random number of rows and columns in the range [5-20], and for filling the grid randomly with 0s and 1s.
(e) The program is responsible for generating the labels for experiment to use during exploration. Use the alphabet letters A · · · Z and a · · · z as labels (in that order).
public static Map<Character, Integer> experiment(int n, int m, int x, int y, char[][] matrix, int[][] mark, char colony) {
Queue<Integer> q = new LinkedList<Integer>();
q.offer(x*m + y);
mark[x][y] = 1;
matrix[x][y] = colony;
while(!q.isEmpty()) {
int front = q.peek(); q.remove();
int x1 = front / m, y1 = front % m;
if(x1 != 0)
if(mark[x1-1][y1] == 0 && matrix[x1-1][y1] == '1') {
matrix[x1-1][y1] = colony;
mark[x1-1][y1] = 1;
q.offer((x1-1) * m + y1);
}
I just don't understand this part of code. Can someone please explain it.
one possible explanation could be that
x and y are coordinates of grid,
if you loop over x and y as below
for( int x = 0 ; x < width; x++ ){
for( int y = 0 ; y < height; y++ ){
index_of_one_dimensional_array = x*m+y;//where m = width(i.e number if columns in each row)
}
}
seems like the q.offer() functions somehow uses this concept to set a value depending on value of index_of_one_dimensional_array given by x*m+y;
and loop is used to make sure every cell in the grid is processed which happens when the queue is empty
I have an ArrayList of Vector2 (Vector2 is an object that contains an x and y coordinate) that contains a bunch of vertices that make a shape when drawn. However, the way they were put into the ArrayList are out of order. For example, the starting Vector2 point is index 0 but the closest next point is of index 4. My goal is to have another ArrayList of Vector2 that orders the Vector2's in a way so that the starting point is index 0, the next closest point is index 1, next is index 2, etc. Here is an image of what is happening.
The image shows what is happening but the green arrows show what I want to happen. The green point is the starting point.
So what I need is once the new ArrayList is created and ordered, it should look like this:
So here is the code in which I thought would do it:
public Array<Vector2> orderedVertices;
private void cleanVertices(Array<Vector2> originalVertices){
//This will be the Array containing ordered vertices
orderedVertices = new Array<Vector2>();
//Copy vertices of unsorted Array in a new Array
Array<Vector2> verticesOfImage = originalVertices;
//Add a random vertice to begin with (starting point)
orderedVertices.add(verticesOfImage.get(1));
//For breaking loop
int originalArraySize = originalVertices.size;
for(int i = 0; i < orderedVertices.size; i++){
//Index to be compared, meaning to find closest vertice around this vertice
int indexOfCompare = i;
//Get a distance for reference //Random point to check
double currentDistance = MathFactory.distance(orderedVertices.get(indexOfCompare), verticesOfImage.get(0));
//If we found a closest vertice, add to ordered pair and remove from original
// So we don't go backwards
if(getClosest(verticesOfImage, indexOfCompare, currentDistance) != -1){
orderedVertices.add(verticesOfImage.removeIndex(getClosest(verticesOfImage, indexOfCompare, currentDistance)));
}
//If not, then the original 'currentDistance' check was the closest vertice
else
orderedVertices.add(verticesOfImage.removeIndex(0));
//Stop checks, ordered pair fully populated
if(orderedVertices.size == originalArraySize)
break;
}
}
public int getClosest(Array<Vector2> vertices, int checkedIndex, double currentDistance){
//This is used to find the closest vertice, defaulted to -1 for condition statements
int correctIndex = -1;
for(int k = 0; k < vertices.size; k++){
//Make sure to not check same Vector2
if(vertices.get(k).x == orderedVertices.get(checkedIndex).x && vertices.get(k).y == orderedVertices.get(checkedIndex).y){
continue;
}
if(MathFactory.distance(orderedVertices.get(checkedIndex), vertices.get(k)) < currentDistance){
correctIndex = k;
currentDistance = MathFactory.distance(orderedVertices.get(checkedIndex), vertices.get(k));
}
}
return correctIndex;
}
This code comes very close to working, here is an image explaining what is going wrong.
I understand the one that isn't working doesn't look as smooth, but the only real problem is the fact that the lines freak out at the end and go through the body. I can't seem to figure out why this is happening or how to fix it. Any help at all with this is hugely appreciated! Thank you!
I am loading my level for a game through xml.
I have a loop that test the "name" and adds the sprite accordingly.
I have a map that has tiles that are 80by80 width and height. The maps rows and columns are 6x10.
I am trying to find a way to keep track of which row and column the level loader is on while it is loading the tiles, because i want to do specific things with the coordinates.
I have thought of using a 2d array for this but i am not sure how i would go about doing this in this situation.
Could anyone help me out with this?
EDIT:
Here is what i have tried.
Creating a row and column array
int row[] = new int[6];
int col[] = new int[10];
Now here is where i am stuck, im not sure how i can tell the code when to switch and use a different row. For example..
if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_unwalkable)) {
tile = new Tile(x, y, this.tUnwalkable_tile,
activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(1);
/*
* Body groundBody = PhysicsFactory.createBoxBody(this.mPhysicsWorld,
* tile, BodyType.StaticBody, wallFixtureDef);
*/
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
Log.e("Tile", "Unwalkable_Tile");
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Blue_Tile)) {
tile = new Tile(x, y, this.blue,
activity.getVertexBufferObjectManager());
tile.setTag(0);
this.tileList.add(tile);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Red_Tile)) {
tile = new Tile(x, y, this.red, activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(0);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Pink_Tile)) {
tile = new Tile(x, y, this.pink,
activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(0);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
} else if (name.equals(TAG_ENTITY_ATTRIBUTE_TYPE_Yello_Tile)) {
tile = new Tile(x, y, this.yellow,
activity.getVertexBufferObjectManager());
tileList.add(tile);
tile.setTag(0);
gameScene.getChildByIndex(SECOND_LAYER).attachChild(tile);
return;
}
How do i tell it to stay row[1] until the col[10] is reached?
Then switch to row[2] and stay there until col[10] is reached again?
From a design standpoint, your level loader should just be loading the level. Whatever magical transform you want to do on top of that can and most likely should be handled separately.
So just have your level loader create a 2d array of... whatever it's reading. Are you reading a flat set of tile elements? Then count the number of elements read. At any given point, your offset is:
x = count % 10;
y = count / 6;
If you have each row in an encapsulating element, count the rows, and the columns. Same idea.
Now you've got a 2d array (or some object encapsulating it). And you can do whatever transformations you want on it. If you want this in terms of screen space, instead multiply each count by 80.
Edit: from the edit above, it looks like you're declaring separate row and column arrays, which you probably don't want to do. It would more logically be something like:
int[][] tiles = new int[6][];
for (int i = 0; i < 6; i++) {
tiles[i] = new int[10];
}
Then, in your loader, define a counter somewhere (once).
int counter = 0;
You'll switch rows when:
counter > 0 && (counter++) % 10 == 0
But with a 2d array, you can really just think of it as having coordinates, as I mentioned above:
x = counter % 10;
y = counter / 6;
And in the end, you have one tiles[][] variable that holds all the tile data. So you can say:
tiles[x][y] = <whatever data you need to store>
And remember to increment the counter, once you're done.
I am using adjacency matrix to represent all the vertex of my weighted unidirectional large graph. In this graph no edge connects a vertex to itself. This makes all the diagonal elements of my adjacency matrix null. As my graph is large so in adjacency matrix i need not to save any elements in left triangle. Below is a small sample graph with adjacency matrix.
In an unidirectional graph left triangle is just mirror image of right triangle. i.e. adjacency_matrix[i][j], adjacency_matrix[j][i] are same. so why to store the left triangle. for a large graph this trick can save so much memory. At the same time diagonal elements are also zero since no edge connects a vertex to itself. i.e. adjacency_matrix[i][i] are zero.
But how can i implement this? can 2D array be used here?
Java doesn't really have 2D arrays, although there is syntatic sugar for allocating an array of arrays.
You probably just want:
int[][] weight = new int[N][];
for (int i = 0; i < N; i++) weight[i] = new int[N-1-i];
That will allocate the triangle you want. Then just index row r, col c at weight[r][c-r-1].
The other option is just to use a single array with
int[] weight = new int[N*(N-1)/2];
The indexing can be a bit more complicated to compute, but less allocation and pointer overhead.
You can use a jagged array.
int[][] matrix = new int[N][];
for (int i = 1; i <= N; i++) {
matrix[i] = new int[N - i + 1];
for (int j = 1; j <= N - i + 1; j++)
matrix[i][j] = edgeValue;
}
Basically you allocate for each row as much as you need.
P.S Maybe I messed up some boundaries here, but you should still get the main point:)