how to find the shortest path in a matrix - java

I have a question in JAVA I can't solve no matter how long I try to think about the solution:
There's a matrix and I need to find the shortest path possible to get from Mat[0][0] to the bottom right of the matrix and I can only proceed to the adjacent square (no diagonals) if the number in it is bigger than the one I'm on right now.
For example:
0 1 2 3 4
0 { 5 13 2 5 2
1 58 24 32 3 24
2 2 7 33 1 7
3 45 40 37 24 70
4 47 34 12 25 2
5 52 56 68 76 100}
So a valid solution would be:
(0,0)->(0,1)->(1,1)->(2,1)->(2,2)->(2,3)->(3,1)->(3,0)->(0,4)->(0,5)->(5,1)->(5,2)->(5,3)->(5,4)
And the method will return 14 because that's the shortest possible path.
I have to use a recursive method only (no loops).
This is what I came up with so far but I don't know how to figure out which is the shortest one.
Public static int shortestPath(int[][]mat)
{
int length=0;
int i=0;
int j=0;
shortestPath(mat, length, i, j);
}
Private static int shortestPath(int[][]math, int length, int i, int j)
{
if((i==mat.length)||(j==mat[i].length))
return length;
if(shortestPath(mat, length, i+1, j) > shortestPath(mat, length, i, j))
return length +1;
if(shortestPath(mat, length, i, j+1) > shortestPath(mat, length, i, j))
return length +1;
if shortestPath(mat, length, i-1, j) > shortestPath(mat, length, i, j))
return length +1;
if shortestPath(mat, length, i, j-1) > shortestPath(mat, length, i, j))
return length +1;
}
I'm not sure if that's the way to do it, and if it is: how do I know which is the shortest way, because right now it would return all possible ways and will add them together (I think).
Also, I think I should add something about reaching the bottom right of the matrix.
The code shouldn't be too complicated.

im not sure if the approach of going to the next smallest value is the shortest, but anyway:
public class Pathfinder {
private int[][] matrix;
private int matrixLenghtI;
private int matrixLenghtJ;
public Pathfinder(int[][] matrix, int matrixLenghtI, int matrixLenghtJ) {
this.matrix = matrix;
this.matrixLenghtI = matrixLenghtI;
this.matrixLenghtJ = matrixLenghtJ;
}
public static void main(String[] args) {
int matrixLenghtI = 6;
int matrixLenghtJ = 5;
int[][] matrix1 = { { 3, 13, 15, 28, 30 }, { 40, 51, 52, 29, 30 }, { 28, 10, 53, 54, 54 },
{ 53, 12, 55, 53, 60 }, { 70, 62, 56, 20, 80 }, { 80, 81, 90, 95, 100 } };
int[][] matrix2 = { { 5, 13, 2, 5, 2 }, { 58, 24, 32, 3, 24 }, { 2, 7, 33, 1, 7 }, { 45, 40, 37, 24, 70 },
{ 47, 34, 12, 25, 2 }, { 52, 56, 68, 76, 100 } };
Pathfinder finder1 = new Pathfinder(matrix1, matrixLenghtI, matrixLenghtJ);
finder1.run();
Pathfinder finder2 = new Pathfinder(matrix2, matrixLenghtI, matrixLenghtJ);
finder2.run();
}
private void run() {
int i = 0;
int j = 0;
System.out.print("(" + i + "," + j + ")");
System.out.println("\nLength: " + find(i, j));
}
private int find(int i, int j) {
int value = matrix[i][j];
int[] next = { i, j };
int smallestNeighbour = 101;
if (i > 0 && matrix[i - 1][j] > value) {
smallestNeighbour = matrix[i - 1][j];
next[0] = i - 1;
next[1] = j;
}
if (j > 0 && matrix[i][j - 1] < smallestNeighbour && matrix[i][j - 1] > value) {
smallestNeighbour = matrix[i][j - 1];
next[0] = i;
next[1] = j - 1;
}
if (i < matrixLenghtI - 1 && matrix[i + 1][j] < smallestNeighbour && matrix[i + 1][j] > value) {
smallestNeighbour = matrix[i + 1][j];
next[0] = i + 1;
next[1] = j;
}
if (j < matrixLenghtJ - 1 && matrix[i][j + 1] < smallestNeighbour && matrix[i][j + 1] > value) {
smallestNeighbour = matrix[i][j + 1];
next[0] = i;
next[1] = j + 1;
}
System.out.print("->(" + next[0] + "," + next[1] + ")");
if (i == matrixLenghtI - 1 && j == matrixLenghtJ - 1)
return 1;
return find(next[0], next[1]) + 1;
}
}
Output:
(0,0)->(0,1)->(0,2)->(0,3)->(1,3)->(1,4)->(2,4)->(3,4)->(4,4)->(5,4)->(5,4)
Length: 10
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)->(3,2)->(3,1)->(3,0)->(4,0)->(5,0)->(5,1)->(5,2)->(5,3)->(5,4)->(5,4)
Length: 14

Position class:
/**
* Represents a position in the matrix.
*/
public class Position {
final private int x;
final private int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
#Override
public String toString() {
return "(" + x + ", " + y + ')';
}
#Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Position position = (Position) o;
if (x != position.x) return false;
return y == position.y;
}
#Override
public int hashCode() {
int result = x;
result = 31 * result + y;
return result;
}
}
Board class:
/**
* A board represents all of the locations in the matrix. It provides a simple interface to getting
* the value in a position, and tracking the height and width of the matrix.
*/
public class Board {
final int [][] board;
public Board(int[][] board) {
this.board = board;
}
final int positionValue(Position position) {
return this.board[position.getY()][position.getX()];
}
final int getWidth() {
return board[0].length;
}
final int getHeight() {
return board.length;
}
}
PathFinder class:
import java.util.ArrayList;
import java.util.List;
/**
* Find the shortest path from a starting point to ending point in a matrix, assuming you can
* only move to a position with a greater value than your current position.
*/
public class PathFinder {
final private Board board;
final private Position start;
final private Position end;
public PathFinder(Board board, int startX, int startY, int endX, int endY) {
this.board = board;
this.start = new Position(startX, startY);
this.end = new Position(endX, endY);
}
/**
* Gets the shortest path from the start to end positions. This method
* takes all of the paths, then determines which one is shortest and returns that.
*
* #return the shortest path from the start to end positions.
*/
public List<Position> shortestPath() {
List<List<Position>> allPaths = this.getAllPaths();
System.out.println("Paths found: " + allPaths.size());
List<Position> shortestPath = null;
for (List<Position> path : allPaths) {
if (shortestPath == null) {
shortestPath = path;
}
else if (shortestPath.size() > path.size()) {
shortestPath = path;
}
}
return shortestPath;
}
/**
* Convenience method for starting the getAllPaths process.
*
* #return all of the paths from the start to end positions
*/
private List<List<Position>> getAllPaths() {
List<List<Position>> paths = new ArrayList<List<Position>>();
return this.getAllPaths(paths, new ArrayList<Position>(), start);
}
/**
* Gets all of the paths from the start to end position. This is done recursively by visiting every
* position, while following the rules that you can only move to a position with a value greater
* than the position you're currently on. When reaching the end position, the path is added to
* the list of all found paths, which is returned.
*
* #param paths the current list of all found paths.
* #param path the current path
* #param position the current position
* #return all paths from the start to end positions
*/
private List<List<Position>> getAllPaths(List<List<Position>> paths, List<Position> path, Position position) {
path.add(position);
if (position.equals(end)) {
paths.add(path);
return paths;
}
//x+
if (position.getX() + 1 < board.getWidth()) {
Position xp = new Position(position.getX() + 1, position.getY());
if (board.positionValue(position) < board.positionValue(xp)) {
getAllPaths(paths, new ArrayList<Position>(path), xp);
}
}
//x-
if (position.getX() - 1 >= 0) {
Position xm = new Position(position.getX() - 1, position.getY());
if (board.positionValue(position) < board.positionValue(xm)) {
getAllPaths(paths, new ArrayList<Position>(path), xm);
}
}
//y+
if (position.getY() + 1 < board.getHeight()) {
Position yp = new Position(position.getX(), position.getY() + 1);
if (board.positionValue(position) < board.positionValue(yp)) {
getAllPaths(paths, new ArrayList<Position>(path), yp);
}
}
//y-
if (position.getY() - 1 >= 0) {
Position ym = new Position(position.getX(), position.getY() - 1);
if (board.positionValue(position) < board.positionValue(ym)) {
getAllPaths(paths, new ArrayList<Position>(path), ym);
}
}
return paths;
}
/**
* Run the example then print the results.
*
* #param args na
*/
public static void main(String[] args) {
int [][] array = {{5, 13, 2, 5, 2},
{14, 24, 32, 3, 24},
{15, 7, 33, 1, 7},
{45, 40, 37, 24, 70},
{47, 34, 12, 25, 2},
{52, 56, 68, 76, 100}
};
final Board board = new Board(array);
final Position end = new Position(board.getWidth()-1, board.getHeight() - 1);
final PathFinder pathFinder = new PathFinder(board, 0, 0, board.getWidth()-1, board.getHeight()-1);
final List<Position> path = pathFinder.shortestPath();
System.out.println("Shortest Path: ");
for (Position position : path) {
if (!position.equals(end)) {
System.out.print(position + " -> ");
}
else {
System.out.println(position);
}
}
System.out.println();
}
}

I really like this problem. Unfortunately I haven't worked in Java for many years, so this answer is pseudo-Java and you'll have to fix some of the syntax. Probably some of the function params should be references and not copies; you'll figure it out (update: I've added a TESTED version in python below).
// just a little thing to hold a set of coordinates
class Position
{
// not bothering with private / getters
public int x ;
public int y ;
public constructor (int x, int y)
{
this.x = x ;
this.y = y ;
}
}
class PathFinder
{
public void main (void)
{
// create a path with just the start position
start = new Position(0, 0) ;
path = new Vector() ;
path.add(start) ;
// create an empty path to contain the final shortest path
finalPath = new Vector() ;
findPath(path, finalPath) ;
print ("Shortest Path: ") ;
showPath (finalPath) ;
}
private void showPath (Vector path) {
// print out each position in the path
iter = path.iterator() ;
while (pos = iter.next()) {
print ("(%, %) ", pos.x, pos.y);
}
// print out the length of the path
print (" Length: %\n", path.size()) ;
}
// recursive function to find shortest path
private void findPath (Vector path, Vector finalPath)
{
// always display the current path (it should never be the same path twice)
showPath(path) ;
// where are we now?
here = path.lastElement() ;
// does the current path find the exit (position 4,5)?
if (here.x == 4 && here.y == 5) {
if (finalPath.size() == 0) {
//finalPath is empty, put the current path in finalPath
finalPath = path ;
} else {
// some other path found the exit already. Which path is shorter?
if (finalPath.size() > path.size()) {
finalPath = path ;
}
}
// either way, we're at the exit and this path goes no further
return ;
}
// path is not at exit; grope in all directions
// note the code duplication in this section is unavoidable
// because it may be necessary to start new paths in three
// directions from any given position
// If no new paths are available from the current position,
// no new calls to findPath() will happen and
// the recursion will collapse.
if (here.x > 0 && matrix[here.x-1][here.y] > matrix[here.x][here.y]) {
// we can move left
newPos = new Position(here.x-1, here.y) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
if (here.x < 4 && matrix[here.x+1][here.y] > matrix[here.x][here.y]) {
// we can move right
newPos = new Position(here.x+1, here.y) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
if (here.y > 0 && matrix[here.x][here.y-1] > matrix[here.x][here.y]) {
// we can move up
newPos = new Position(here.x, here.y-1) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
if (here.y < 5 && matrix[here.x][here.y+1] > matrix[here.x][here.y]) {
// we can move down
newPos = new Position(here.x, here.y+1) ;
newPath = path ;
newPath.add (newPos) ;
findPath(newPath, finalPath) ;
}
}
}
Here's a tested version of the same algorithm in python. (I noticed that using x, y as coordinates is kind of misleading. x is actually "vertical" and y is "horizontal" with the array indexed the way it is. I've set up a matrix with four paths to the exit and a couple of dead ends.)
import copy, sys
matrix = [
[5, 13, 17, 58, 2],
[17, 24, 32, 3, 24],
[23, 7, 33, 1, 7],
[45, 40, 37, 38, 70],
[47, 34, 12, 25, 2],
[52, 56, 68, 76, 100]]
def showPath(path):
for position in path:
sys.stdout.write("(" + str(position[0]) + ", " + str(position[1]) + "), ")
sys.stdout.write("\n\n")
sys.stdout.flush()
def findPath(path):
#showPath(path)
global finalPath
x = path[-1][0]
y = path[-1][1]
if x == 5 and y == 4:
showPath(path)
if len(finalPath) == 0 or len(finalPath) > len (path):
finalPath[:] = copy.deepcopy(path)
return
if x > 0 and matrix[x-1][y] > matrix[x][y]:
# we can move up
newPath = copy.deepcopy(path)
newPath.append([x-1, y])
findPath(newPath)
if x < 5 and matrix[x+1][y] > matrix[x][y]:
# we can move down
newPath = copy.deepcopy(path)
newPath.append([x+1, y])
findPath(newPath)
if y > 0 and matrix[x][y-1] > matrix[x][y]:
# we can move left
newPath = copy.deepcopy(path)
newPath.append([x, y-1])
findPath(newPath)
if y < 4 and matrix[x][y+1] > matrix[x][y]:
# we can move right
newPath = copy.deepcopy(path)
newPath.append([x, y+1])
findPath(newPath)
path = []
path.append([0, 0])
finalPath = []
findPath(path)
print "Shortest Path: " + str(len(finalPath)) + " steps.\n"
showPath(finalPath)
If you uncomment the first showPath() call in findPath() you can see every step and see where the dead ends get abandoned. If you only show paths that reach the exit, the output looks like:
(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
(0, 0), (1, 0), (1, 1), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
(0, 0), (0, 1), (1, 1), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (3, 2), (3, 1), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),
Shortest Path: 10 steps.
(0, 0), (1, 0), (2, 0), (3, 0), (4, 0), (5, 0), (5, 1), (5, 2), (5, 3), (5, 4),

here you can build a tree to all possibilities and take then the shortest. There is a loop inside for tracing the result, but you can also get around that with some ugly ifs...
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.TreeMap;
public class BetterPathfinder {
public class Comperator implements Comparator<Path> {
#Override
public int compare(Path o1, Path o2) {
return o1.getValue().compareTo(o2.getValue());
}
}
public class Path {
private Integer lenght;
TreeMap<Integer, String> trace = new TreeMap<>();
public Path(int lenght) {
this.lenght = lenght;
}
public Path(Path find, int i, int j) {
this.lenght = find.getValue() + 1;
this.trace.putAll(find.getTrace());
this.trace.put(lenght, "(" + i + "," + j + ")");
}
private Map<Integer, String> getTrace() {
return trace;
}
public Integer getValue() {
return lenght;
}
#Override
public String toString() {
String res = "end";
for (Entry<Integer, String> is : trace.entrySet()) {
res = is.getValue() + "->" + res;
}
return res;
}
}
private int[][] matrix;
private int matrixLenghtI;
private int matrixLenghtJ;
public BetterPathfinder(int[][] matrix, int matrixLenghtI, int matrixLenghtJ) {
this.matrix = matrix;
this.matrixLenghtI = matrixLenghtI;
this.matrixLenghtJ = matrixLenghtJ;
}
public static void main(String[] args) {
int matrixLenghtI = 6;
int matrixLenghtJ = 5;
int[][] matrix1 = { { 3, 13, 15, 28, 30 }, { 40, 51, 52, 29, 30 }, { 28, 10, 53, 54, 54 },
{ 53, 12, 55, 53, 60 }, { 70, 62, 56, 20, 80 }, { 80, 81, 90, 95, 100 } };
int[][] matrix2 = { { 5, 13, 2, 5, 2 }, { 58, 24, 32, 3, 24 }, { 2, 7, 33, 1, 7 }, { 45, 40, 37, 24, 70 },
{ 47, 34, 12, 25, 2 }, { 52, 56, 68, 76, 100 } };
BetterPathfinder finder1 = new BetterPathfinder(matrix1, matrixLenghtI, matrixLenghtJ);
finder1.run();
BetterPathfinder finder2 = new BetterPathfinder(matrix2, matrixLenghtI, matrixLenghtJ);
finder2.run();
}
private void run() {
int i = 0;
int j = 0;
System.out.println(new Path(find(i, j), i, j));
}
private Path find(int i, int j) {
int value = matrix[i][j];
int[] next = { i, j };
ArrayList<Path> test = new ArrayList<>();
if (i == matrixLenghtI - 1 && j == matrixLenghtJ - 1)
return new Path(1);
if (i > 0 && matrix[i - 1][j] > value) {
next[0] = i - 1;
next[1] = j;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (j > 0 && matrix[i][j - 1] > value) {
next[0] = i;
next[1] = j - 1;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (i < matrixLenghtI - 1 && matrix[i + 1][j] > value) {
next[0] = i + 1;
next[1] = j;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (j < matrixLenghtJ - 1 && matrix[i][j + 1] > value) {
next[0] = i;
next[1] = j + 1;
test.add(new Path(find(next[0], next[1]), next[0], next[1]));
}
if (test.isEmpty()) {
return new Path(100);
}
return Collections.min(test, new Comperator());
}
}
result:
(0,0)->(1,0)->(1,1)->(1,2)->(2,2)->(3,2)->(4,2)->(5,2)->(5,3)->(5,4)->end
(0,0)->(0,1)->(1,1)->(1,2)->(2,2)->(3,2)->(3,1)->(3,0)->(4,0)->(5,0)->(5,1)->(5,2)->(5,3)->(5,4)->end

You want a recursive strategy. A pretty easy, though expensive method, is to simply flood the board. Something like "Try every possible path and compute the distance".
You can do this recursively by imagining moving a pebble around.
public int shortestPath(Point src, Point dest) {
if (src.equals(dest)) {
return 0;
}
// You need to do some bound checks here
int left = shortestPath(new Point(src.x - 1, src.y), dest);
int right = shortestPath(new Point(src.x + 1, src.y), dest);
int up = shortestPath(new Point(src.x, src.y + 1), dest);
int down = shortestPath(new Point(src.x, src.y - 1), dest);
// Decide for the direction that has the shortest path
return min(left, right, up, down) + 1;
}
If you are interested in the path represented by the solution, you may trace the path while creating. For this you simply need to save for which direction min decided.
I needed to solve a similar task ages ago in my computer science studies. We needed to compute the shortest amount of moves a knight on a chess board needs for reaching a given destination. Maybe this also helps you: http://pastebin.com/0xwMcQgj

public class shortestPath{
public static int shortestPath(int[][] mat){
if(mat == null || mat.length == 0 || mat[0].length == 0)
return 0;
else {
int n = shortestPath(mat, 0, 0, 0);
return (n == mat.length*mat.length+1 ) ? 0 : n;
}
}
private static int shortestPath(int[][]mat, int row, int col,int prev){
if (!valid(mat,row,col) || !(mat[row][col] > prev)){
return mat.length*mat.length+1;
} else if(row == mat.length - 1 && col == mat[row].length - 1) {
return 1;
} else {
return minimum(shortestPath(mat,row-1,col, mat[row][col]),
shortestPath(mat,row+1,col, mat[row][col]),
shortestPath(mat,row,col-1, mat[row][col]),
shortestPath(mat,row,col+1, mat[row][col])) + 1;
}
}
private static boolean valid(int[][]mat,int row, int col){
if(row < 0 || col < 0 || col > mat[0].length-1 || row > mat.length-1)
return false;
else
return true;
}
private static int minimum(int x, int y, int t, int z){
int min1 = (x > y)? y : x;
int min2 = (t > z)? z : t;
return (min1 > min2)? min2 : min1;
}
public static void main(String[] args){
int maze[][] = {
{ 3, 13, 15, 28, 30},
{ 40, 51, 52, 29, 30},
{ 28, 10, 53, 54, 53},
{ 53, 12, 55, 53, 60},
{ 70, 62, 56, 20, 80},
{ 81, 81, 90, 95, 100}};
System.out.println(shortestPath(maze));
}
}

Here is how I solved it, note that in your example we should get 16
public static void main(String[] args)
{
int[][] mat =
{
{ 3, 13, 15, 28, 30 },
{ 40, 51, 52, 29, 30 },
{ 28, 10, 53, 54, 53 },
{ 53, 12, 55, 53, 60 },
{ 70, 62, 56, 20, 80 },
{ 80, 81, 90, 95, 100 }
};
System.out.println(shortestPath(mat)); // 10
int[][] mat1 =
{
{0, 1, 2, 3, 4 },
{0, 5, 13, 2, 5, 2},
{1, 58, 24, 32, 3, 24} ,
{2, 2 , 7, 33, 1, 7} ,
{3, 45, 40, 37, 24, 70},
{4, 47, 34, 12, 25, 2},
{5, 52, 56, 68, 76, 100}
};
System.out.println(shortestPath(mat1)); // 16
}
public static int shortestPath(int[][] mat)
{
return shortestPath(mat, 0, 0, mat[0][0] - 1, 0);
}
private static int shortestPath(int[][] mat, int row, int col, int prev, int counter)
{
if (row < 0 || row == mat.length || col < 0 || col == mat[row].length) // boundaries
return Integer.MAX_VALUE;
if (mat[row][col] <= prev || mat[row][col] == -999) // if the sequence is not ascending or if we have been in this cell before
return Integer.MAX_VALUE;
if (row == mat.length - 1 && col == mat[row].length - 1)
return counter + 1;
int temp = mat[row][col];
mat[row][col] = -999;
int up = shortestPath(mat, row - 1, col, temp, counter + 1); // go up and count
int down = shortestPath(mat, row + 1, col, temp, counter + 1);
int left = shortestPath(mat, row, col - 1, temp, counter + 1);
int right = shortestPath(mat, row, col + 1, temp, counter + 1);
mat[row][col] = temp;
return Math.min(Math.min(up, down), Math.min(left, right)); // get the min
}

Related

Finding sum of subarrays using Java

My problem is in the function Sum(int z) which should return the sum of all items in sub-array at index z or returns 0 if invalid index.
My current code is
public int[][] data;
public calculate(int[][] source) {
data = source;
}
public int size() {
return data.length;
}
public boolean isValidSubsetIndex(int z) {
if (z<0 || z>= size())
return false;
return true;
}
public int sum(int z) {
int x=0;
if (isValidSubsetIndex(z) == true) {
for (int i = 0; i < data[z].length;i++) {
for(int j= i; j<i+1; j++)
x = x + data[i][j];
}
return x;
}
return 0;
}
aP = new Analytics(new int[][]{{30, 10, 40},
{50, 20, 80},
{10, 60, 30},
{60, 60, 60}});
aHD = new Analytics(new int[][]{{-30, 10, -40},
{},
{-10, 60},
{-60},
{-20, -20, -20, -20, -20},
{-20, -20},
{-20},
{},
{50},
{10, 30, 20}});
The test that it is failing is given below. My current code only provides the first result correct (sum 80 for sum(0)).
if sum(1) result should be 150,
if sum (2) result should be 100
public void testSumHD() {
testSumD();
int[] sumHD = {-60, 0, 50, -60, -100, -40, -20, 0, 50, 60};
for(int i=0; i < sumHD.length; i++) {
assertEquals(sumHD[i], aHD.sum(i));
}
assertEquals(0, aHD.sum(-1));
assertEquals(0, aHD.sum(10));
}
The solution was x = x + data[z][j];

I am having problems in running my Java programing Game

I have problem with my java game. i write all code no problem and programed JFrame run well but didn't start game. And I used Netbeans. Please find me find this problem.
this is my code
public class Board extends JPanel implements ActionListener{
private Dimension d;
private final Font smallfont = new Font("Helvetica", Font.BOLD, 14);
private Image ii;
private final Color dotcolor = new Color(192,191,0);
private Color mazecolor;
private boolean ingame = false;
private boolean dying = false;
private final int blocksize = 24;
private final int nrofblocks = 15;
private final int scrsize = nrofblocks * blocksize;
private final int pacanimdelay = 2;
private final int pacmananimcount = 4;
private final int maxghosts = 12;
private final int pacmanspeed = 6;
private int pacanimcount = pacanimdelay;
private int pacanimdir = 1;
private int pacmananimpos = 0;
private int nrofghosts = 6;
private int pacsleft, score;
private int[] dx, dy;
private int[] ghostx, ghosty, ghostdx, ghostdy, ghostspeed;
private Image ghost;
private Image pacman1, pacman2up, pacman2left, pacman2right, pacman2down;
private Image pacman3up, pacman3right, pacman3left, pacman3down;
private Image pacman4up, pacman4right, pacman4left, pacman4down;
private int pacmanx, pacmany, pacmandx, pacmandy;
private int reqdx, reqdy, viewdx, viewdy;
private final short leveldata[] = {
19, 26, 26, 26, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 22,
21, 0, 0, 0, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20,
21, 0, 0, 0, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20,
21, 0, 0, 0, 17, 16, 16, 24, 16, 16, 16, 16, 16, 16, 20,
17, 18, 18, 18, 16, 16, 20, 0, 17, 16, 16, 16, 16, 16, 20,
17, 16, 16, 16, 16, 16, 20, 0, 17, 16, 16, 16, 16, 24, 20,
25, 16, 16, 16, 24, 24, 28, 0, 25, 24, 24, 16, 20, 0, 21,
1, 17, 16, 20, 0, 0, 0, 0, 0, 0, 0, 17, 20, 0, 21,
1, 17, 16, 16, 18, 18, 22, 0, 19, 18, 18, 16, 20, 0, 21,
1, 17, 16, 16, 16, 16, 20, 0, 17, 16, 16, 16, 20, 0, 21,
1, 17, 16, 16, 16, 16, 20, 0, 17, 16, 16, 16, 20, 0, 21,
1, 17, 16, 16, 16, 16, 16, 18, 16, 16, 16, 16, 20, 0, 21,
1, 17, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 20, 0, 21,
1, 25, 24, 24, 24, 24, 24, 24, 24, 24, 16, 16, 16, 18, 20,
9, 8, 8, 8, 8, 8, 8, 8, 8, 8, 25, 24, 24, 24, 28
};
private final int validspeeds[] = {1, 2, 3, 4, 6, 8};
private final int maxspeed = 6;
private int currentspeed = 3;
private short[] screendata;
private Timer timer;
public Board(){
loadImages();
initVariables();
addKeyListener(new TAdapter());
setFocusable(true);
setBackground(Color.black);
setDoubleBuffered(true);
}
private void initVariables(){
screendata = new short [nrofblocks * nrofblocks];
mazecolor = new Color(5, 100, 5);
d = new Dimension(400, 400);
ghostx = new int[maxghosts];
ghostdx = new int [maxghosts];
ghosty = new int[maxghosts];
ghostdy = new int [maxghosts];
ghostspeed = new int [maxghosts];
dx = new int[4];
dy = new int[4];
timer = new Timer (40, this);
timer.start();
}
#Override
public void addNotify(){
super.addNotify();
initGame();
}
private void doAnim(){
pacanimcount--;
if(pacanimcount <=0){
pacanimcount = pacanimdelay;
pacmananimpos = pacmananimpos + pacanimdir;
if(pacmananimpos == (pacmananimcount - 1)|| pacmananimpos == 0){
pacanimdir = -pacanimdir;
}
}
}
private void playGame (Graphics2D g2d){
if (dying){
death();
} else{
movePacman();
drawPacman(g2d);
moveGhosts(g2d);
checkMaze();
}
}
private void showIntroScreen(Graphics2D g2d){
g2d.setColor(new Color(0, 32, 48));
g2d.fillRect(50, scrsize /2 -30, scrsize - 100, 50);
g2d.setColor(Color.white);
g2d.drawRect(50, scrsize /2 - 30, scrsize -100, 50);
String s = "Press s to start.";
Font small = new Font ("Helvetica", Font.BOLD, 14);
FontMetrics metr = this.getFontMetrics(small);
g2d.setColor(Color.white);
g2d.setFont(small);
g2d.drawString(s, (scrsize - metr.stringWidth(s)) / 2, scrsize / 2);
}
private void drawScore(Graphics2D g){
int i;
String s;
g.setFont(smallfont);
g.setColor(new Color(96,128,255));
s= "Score:" + score;
g.drawString(s, scrsize / 2 + 96, scrsize + 16);
for (i =0; i<pacsleft; i++){
g.drawImage(pacman3left, i * 28 + 8, scrsize + 1, this);
}
}
private void checkMaze(){
short i = 0;
boolean finished = true;
while (i <nrofblocks * nrofblocks && finished){
if ((screendata[i] & 48) != 0){
finished = false;
}
i++;
}
if (finished){
score += 50;
if(nrofghosts < maxghosts){
nrofghosts++;
}
if(currentspeed <maxspeed){
currentspeed++;
}
initLevel();
}
}
private void death(){
pacsleft--;
if(pacsleft ==0){
ingame = false;
}
continueLevel();
}
private void moveGhosts(Graphics2D g2d){
short i;
int pos;
int count;
for (i = 0; i < nrofghosts; i++){
if (ghostx[i] % blocksize == 0 && ghosty[i] % blocksize ==0){
pos = ghostx[i] / blocksize + nrofblocks * (int) (ghosty[i] / blocksize);
count = 0;
if ((screendata[pos] & 1) == 0 && ghostdx[i] != 1){
dx[count] =-1;
dy[count] = 0;
count++;
}
if ((screendata[pos] & 2) == 0 && ghostdy[i] != 1){
dx[count] = 0;
dy[count] = -1;
count++;
}
if ((screendata[pos] & 4) == 0 && ghostdx[i] != -1){
dx[count] = 1;
dy[count] = 0;
count++;
}
if ((screendata[pos] & 8) == 0 && ghostdy[i] != -1){
dx[count] = 0;
dy[count] = 1;
count++;
}
if(count == 0){
if ((screendata[pos] & 15) == 15){
ghostdx[i] = 0;
ghostdy[i] = 1;
}else {
ghostdx[i] = -ghostdx[i];
ghostdy[i] = -ghostdy[i];
}
}else{
count = (int) (Math.random() * count);
if (count > 3){
count = 3;
}
ghostdx[i] = dx[count];
ghostdy[i] = dy[count];
}
}
ghostx[i] = ghostx[i] + (ghostdx[i] * ghostspeed[i]);
ghosty[i] = ghosty[i] + (ghostdy[i] * ghostspeed[i]);
drawGhost(g2d, ghostx[i] +1, ghosty[i] + 1);
if (pacmanx > (ghostx[i] - 12) && pacmanx < (ghostx[i] + 12)
&& pacmany > (ghosty[i] - 12) && pacmany < (ghosty[i] + 12)
&& ingame) {
dying = true;
}
}
}
private void drawGhost(Graphics2D g2d, int x, int y){
g2d.drawImage(ghost, x, y, this);
}
private void movePacman(){
int pos;
short ch;
if(reqdx == -pacmandx && reqdy == -pacmandy){
pacmandx = reqdx;
pacmandy = reqdy;
viewdx = pacmandx;
viewdy = pacmandy;
}
if (pacmanx % blocksize == 0 && pacmany % blocksize == 0){
pos = pacmanx / blocksize + nrofblocks * (int) (pacmany / blocksize);
ch = screendata[pos];
if ((ch & 16) != 0){
screendata[pos] = (short) (ch & 15);
score++;
}
if (reqdx != 0 || reqdy != 0){
if (!((reqdx == -1 && reqdy == 0 && (ch & 1) !=0)
|| (reqdx == 1 && reqdy == 0 && (ch & 4) != 0)
|| (reqdx == 0 && reqdy == -1 && (ch & 2) != 0)
|| (reqdx == 0 && reqdy == 1 && (ch & 8) != 0))){
pacmandx = reqdx;
pacmandy = reqdy;
viewdx = pacmandx;
viewdy = pacmandy;
}
}
// Check for standstill
if ((pacmandx == -1 && pacmandy == 0 && (ch & 1 )!=0)
|| (pacmandx == 1 && pacmandy == 0 && (ch & 4) != 0)
|| (pacmandx == 0 && pacmandy == -1 && (ch & 2) != 0)
|| (pacmandx == 0 && pacmandy == 1 && (ch & 8) != 0)){
pacmandx = 0;
pacmandy = 0;
}
}
pacmanx = pacmanx + pacmanspeed * pacmandx;
pacmany = pacmany + pacmanspeed * pacmandy;
}
private void drawPacman(Graphics2D g2d){
if (viewdx == -1){
drawPacmanLeft(g2d);
}else if (viewdx == 1){
drawPacmanRight(g2d);
}else if (viewdy == -1){
drawPacmanUp(g2d);
}else {
drawPacmanDown(g2d);
}
}
private void drawPacmanUp(Graphics2D g2d){
switch (pacmananimpos){
case 1:
g2d.drawImage(pacman2up, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3up, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4up, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
private void drawPacmanDown(Graphics2D g2d){
switch (pacmananimpos){
case 1:
g2d.drawImage(pacman2down, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3down, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4down, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
private void drawPacmanRight(Graphics2D g2d){
switch (pacmananimpos){
case 1:
g2d.drawImage(pacman2right, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3right, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4right, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
private void drawPacmanLeft(Graphics2D g2d){
switch (pacmananimpos){
case 1:
g2d.drawImage(pacman2left, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3left, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4left, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
private void drawMaze(Graphics2D g2d){
short i = 0;
int x, y;
for (y = 0; y< scrsize; y += blocksize){
for (x = 0; x<scrsize; x += blocksize){
g2d.setColor(mazecolor);
g2d.setStroke(new BasicStroke(2));
if ((screendata[i] & 1) != 0){
g2d.drawLine (x, y, x, y + blocksize - 1);
}
if ((screendata[i] & 2) != 0){
g2d.drawLine(x, y, x + blocksize -1, y);
}
if ((screendata[i] & 4) != 0){
g2d.drawLine(x + blocksize - 1, y, x + blocksize -1, y + blocksize - 1);
}
if ((screendata[i] & 8) != 0){
g2d.drawLine(x, y + blocksize - 1, x + blocksize -1, y + blocksize -1);
}
if ((screendata[i] & 16) != 0){
g2d.setColor(dotcolor);
g2d.fillRect(x +11, y + 11, 2, 2);
}
i++;
}
}
}
private void initGame(){
pacsleft = 3;
score = 0;
initLevel();
nrofghosts = 6;
currentspeed = 3;
}
private void initLevel(){
int i;
for (i = 0; i<nrofblocks * nrofblocks; i++){
screendata[i] = leveldata[i];
}
continueLevel();
}
private void continueLevel(){
short i;
int dx = 1;
int random;
for (i = 0; i <nrofghosts; i++){
ghosty[i] = 4 * blocksize;
ghostx[i] = 4 * blocksize;
ghostdy[i] = 0;
ghostdx[i] = dx;
dx = -dx;
random = (int) (Math.random() * (currentspeed + 1));
if (random > currentspeed){
random = currentspeed;
}
ghostspeed[i] = validspeeds[random];
}
pacmanx = 7 * blocksize;
pacmany = 11 * blocksize;
pacmandx = 0;
pacmandy = 0;
reqdx = 0;
reqdy = 0;
viewdx = 0;
viewdy = 0;
dying = false;
}
private void loadImages(){
ghost = new ImageIcon("images/ghost.png").getImage();
pacman1 = new ImageIcon("images/pacman.png").getImage();
pacman2up = new ImageIcon("images/up1.png").getImage();
pacman3up = new ImageIcon("images/up2.png").getImage();
pacman4up = new ImageIcon("images/up3.png").getImage();
pacman2down = new ImageIcon("images/down1.png").getImage();
pacman3down = new ImageIcon("images/down2.png").getImage();
pacman4down = new ImageIcon("images/down3.png").getImage();
pacman2left = new ImageIcon("images/left1.png").getImage();
pacman3left = new ImageIcon("images/left2.png").getImage();
pacman4left = new ImageIcon("images/left3.png").getImage();
pacman2right = new ImageIcon("images/right1.png").getImage();
pacman3right = new ImageIcon("images/right2.png").getImage();
pacman4right = new ImageIcon("images/right3.png").getImage();
}
#Override
public void paintComponent(Graphics g){
super.paintComponent(g);
doDrawing(g);
}
private void doDrawing(Graphics g){
Graphics2D g2d = (Graphics2D)g;
g2d.setColor(Color.black);
g2d.fillRect(0, 0, d.width, d.height);
drawMaze(g2d);
drawScore(g2d);
doAnim();
if (ingame){
playGame(g2d);
}else{
showIntroScreen(g2d);
}
g2d.drawImage(ii, 5, 5, this);
Toolkit.getDefaultToolkit().sync();
g2d.dispose();
}
class TAdapter extends KeyAdapter {
#Override
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (ingame) {
if (key == KeyEvent.VK_LEFT) {
reqdx = -1;
reqdy = 0;
} else if (key == KeyEvent.VK_RIGHT) {
reqdx = 1;
reqdy = 0;
} else if (key == KeyEvent.VK_UP) {
reqdx = 0;
reqdy = -1;
} else if (key == KeyEvent.VK_DOWN) {
reqdx = 0;
reqdy = 1;
} else if (key == KeyEvent.VK_ESCAPE && timer.isRunning()) {
ingame = false;
} else if (key == KeyEvent.VK_PAUSE) {
if (timer.isRunning()) {
timer.stop();
} else {
timer.start();
}
}
} else {
if (key == 's' || key == 'S') {
ingame = true;
initGame();
}
}
}
#Override
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == Event.LEFT || key == Event.RIGHT
|| key == Event.UP || key == Event.DOWN) {
reqdx = 0;
reqdy = 0;
}
}
}
#Override
public void actionPerformed(ActionEvent e){
repaint();
}
public class Pacman extends JFrame{
public Pacman(){
initUI();
}
private void initUI(){
add(new Board());
setTitle ("Pacman");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setSize(380, 420);
setLocationRelativeTo(null);
setVisible(true);
}
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable(){
#Override
public void run(){
JFrame ex = new JFrame();
ex.setVisible(true);
}
});
}
}
your game is started by Pacman class which create a jframe and add Board panel to it and etc. so instead of making a new jframe create a new Pacman object in main method and move your Pacman class outside of Board class .this is complete code
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
new Pacman();
}
});
}

LWJGL Inventory Rendering Wrong

So ive been working on a 2D rpg game and ive worked out the inventory quite nicely but ive ran into a problem where when I have an item in a slot the slot directly after it doesnt render; its just a black square.
Here is a visual: http://imgur.com/lLbv0fh
Im using immediate mode rendering.
Rendering inventory method:
public void render(Renderer renderer) {
if (shown == false) {
return;
}
//renderer.renderRectangle(0, x, y, 220, 240, Color4f.BLACK);
renderer.setFont(font);
renderer.renderString("Inventory", x + 24, y + 11, Color4f.WHITE);
renderer.setFont(Renderer.DEFAULT_FONT);
int drawSlotsX = x + 25;
int drawSlotsY = y + 50;
int xPos = 0;
int yPos = 0;
int maxX = 4;
int maxY = 4;
for (int i = 0; i < slots.length; i++) {
int renderX = ((xPos * 32) + drawSlotsX) + 2 * xPos;
int renderY = ((yPos * 32) + drawSlotsY) + 2 * yPos;
renderer.renderTexture(slot, renderX, renderY, 32, 32, 0);
if (collisionBoxs[i] == null) {
collisionBoxs[i] = new Rectangle(renderX, renderY, 32, 32);
}
if (slots[i] != null) {
renderer.renderTexture(slots[i].getItem().getIcon().getIcon(), renderX, renderY, 24, 32, 0);
if (slots[i].getAmount() < 10) {
renderer.renderString("" + slots[i].getAmount(), renderX + 22, renderY + 18, Color4f.BLACK);
} else {
renderer.renderString("" + slots[i].getAmount(), renderX + 18, renderY + 18, Color4f.BLACK);
}
}
if (xPos < maxX) {
xPos++;
} else {
xPos = 0;
if (yPos < maxY) {
yPos++;
}
}
}
if (grabbedItem != null) {
renderer.renderTexture(grabbedItem.getItem().getIcon().getIcon(), Mouse.getX(), (Engine.FRAME_HEIGHT - Mouse.getY()), 32, 32, 0);
}
}
Sorry if you cant see the problem within this method!

Why I'm getting ArrayIndexOutOfBoundsException? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm creating a pacman game, and I'm getting an exception that I can't figure out:
Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: -11
at p.PacBoard.moveGhosts(PacBoard.java:207)
And here is where the logic of my game is (I marked off the line that has thrown the exception):
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Event;
import java.awt.Font;
import java.awt.FontMetrics;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import javax.swing.ImageIcon;
import javax.swing.JPanel;
import javax.swing.Timer;
public class PacBoard extends JPanel implements ActionListener {
Dimension d;
String s = "Press s to start.";;
Font small = new Font("Helvetica", Font.BOLD, 14);
FontMetrics metr = this.getFontMetrics(small);
Image ii;
Color dotcolor = new Color(192, 192, 0);
Color mazecolor;
boolean ingame = false;
boolean dying = false;
final int blocksize = 24;
final int nrofblocks = 15;
final int scrsize = nrofblocks * blocksize;
final int pacanimdelay = 2;
final int pacmananimcount = 4;
final int maxghosts = 6;
final int pacmanspeed = 6;
int pacanimcount = pacanimdelay;
int pacanimdir = 1;
int pacmananimpos = 0;
int nrofghosts = 4;
int pacsleft, score;
int deathcounter;
int[] dx, dy;
int[] ghostx, ghosty, ghostdx, ghostdy, ghostspeed;
Image ghost;
Image pacman1, pacman2up, pacman2left, pacman2right, pacman2down;
Image pacman3up, pacman3down, pacman3left, pacman3right;
Image pacman4up, pacman4down, pacman4left, pacman4right;
int pacmanx, pacmany, pacmandx, pacmandy;
int reqdx, reqdy, viewdx, viewdy;
final short leveldata[] =
{ 3, 19, 18, 18, 18, 18, 18, 18, 18, 18, 18, 22, 3, 10, 6,
1, 25, 24, 16, 16, 16, 16, 16, 16, 16, 16, 20, 5, 15, 5,
1, 0, 0, 17, 16, 16, 16, 16, 16, 16, 16, 20, 9, 10, 12,
19, 18, 18, 16, 16, 16, 24, 16, 24, 16, 16, 24, 18, 18, 22,
17, 16, 16, 16, 16, 28, 0, 21, 0, 17, 20, 0, 17, 16, 20,
17, 16, 16, 16, 28, 0, 19, 20, 0, 25, 28, 0, 17, 16, 20,
17, 16, 16, 28, 0, 19, 16, 20, 0, 0, 0, 0, 17, 16, 20,
17, 16, 20, 0, 27, 16, 16, 16, 18, 18, 22, 0, 17, 16, 20,
17, 16, 16, 22, 0, 25, 16, 16, 16, 16, 20, 0, 17, 16, 20,
17, 16, 16, 16, 22, 0, 25, 16, 16, 16, 20, 0, 17, 16, 20,
17, 16, 16, 16, 16, 22, 0, 17, 16, 16, 20, 0, 17, 16, 20,
25, 16, 24, 16, 16, 16, 18, 16, 16, 16, 16, 18, 24, 24, 28,
1, 21, 0, 17, 16, 16, 16, 16, 16, 16, 16, 20, 0, 8, 12,
9, 29, 0, 17, 16, 16, 16, 16, 16, 16, 16, 20, 0, 10, 14,
9, 15, 27, 24, 24, 24, 24, 24, 24, 24, 24, 28, 8, 10, 14};
final int validspeeds[] = {1, 2, 3, 4, 5, 6};
final int maxspeed = 6;
int currentspeed = 3;
short[] screendata;
Timer timer;
public PacBoard() {
GetImages();
addKeyListener(new TAdapter());
screendata = new short[nrofblocks * nrofblocks];
mazecolor = new Color(255, 0, 5);
setFocusable(true);
d = new Dimension(400, 400);
setBackground(Color.black);
setDoubleBuffered(true);
ghostx = new int[maxghosts];
ghostdx = new int[maxghosts];
ghosty = new int[maxghosts];
ghostdy = new int[maxghosts];
ghostspeed = new int[maxghosts];
dx = new int[4];
dy = new int[4];
timer = new Timer(40, this);
timer.start();
}
public void addNotify() {
super.addNotify();
GameInit();
}
public void DoAnim() {
pacanimcount--;
if (pacanimcount <= 0) {
pacanimcount = pacanimdelay;
pacmananimpos = pacmananimpos + pacanimdir;
if (pacmananimpos == (pacmananimcount - 1) || pacmananimpos == 0)
pacanimdir = -pacanimdir;
}
}
public void PlayGame(Graphics2D g2d) {
if (dying) {
Death();
} else {
MovePacMan();
DrawPacMan(g2d);
moveGhosts(g2d);
CheckMaze();
}
}
public void ShowIntroScreen(Graphics2D g2d) {
g2d.setColor(new Color(0, 32, 48));
g2d.fillRect(50, scrsize / 2 - 30, scrsize - 100, 50);
g2d.setColor(Color.white);
g2d.drawRect(50, scrsize / 2 - 30, scrsize - 100, 50);
g2d.setColor(Color.white);
g2d.setFont(small);
g2d.drawString(s, (scrsize - metr.stringWidth(s)) / 2, scrsize / 2);
}
public void DrawScore(Graphics2D g) {
int i;
String s;
g.setFont(small);
g.setColor(new Color(96, 128, 255));
s = "Score: " + score;
g.drawString(s, scrsize / 2 + 96, scrsize + 16);
for (i = 0; i < pacsleft; i++) {
g.drawImage(pacman3left, i * 28 + 8, scrsize + 1, this);
}
}
public void CheckMaze() {
short i = 0;
boolean finished = true;
while (i < nrofblocks * nrofblocks && finished) {
if ((screendata[i] & 48) != 0)
finished = false;
i++;
}
if (finished) {
score += 50;
if (nrofghosts < maxghosts)
nrofghosts++;
if (currentspeed < maxspeed)
currentspeed++;
LevelInit();
}
}
public void Death() {
pacsleft--;
if (pacsleft == 0)
ingame = false;
LevelContinue();
}
public void moveGhosts(Graphics2D g2d) {
short i;
int pos;
int count;
for (i = 0; i < nrofghosts; i++) {
if (ghostx[i] % blocksize == 0 && ghosty[i] % blocksize == 0) {
pos = ghostx[i] / blocksize + nrofblocks * (int)(ghosty[i] / blocksize);
count = 0;
//line that causes problems below
if ((screendata[pos] & 1) == 0 && ghostdx[i] != 1) {
//line that causes problems above
dx[count] = -1;
dy[count] = 0;
count++;
}
if ((screendata[pos] & 2) == 0 && ghostdy[i] != 1) {
dx[count] = 0;
dy[count] = -1;
count++;
}
if ((screendata[pos] & 4) == 0 && ghostdx[i] != -1) {
dx[count] = 1;
dy[count] = 0;
count++;
}
if ((screendata[pos] & 8) == 0 && ghostdy[i] != -1) {
dx[count] = 0;
dy[count] = 1;
count++;
}
if (count == 0) {
if ((screendata[pos] & 15) == 15) {
ghostdx[i] = 0;
ghostdy[i] = 0;
} else {
ghostdx[i] = -ghostdx[i];
ghostdy[i] = -ghostdy[i];
}
} else {
count = (int)(Math.random() * count);
if (count > 3)
count = 3;
ghostdx[i] = dx[count];
ghostdy[i] = dy[count];
}
}
ghostx[i] = ghostx[i] + (ghostdx[i] * ghostspeed[i]);
ghosty[i] = ghosty[i] + (ghostdy[i] * ghostspeed[i]);
DrawGhost(g2d, ghostx[i] + 1, ghosty[i] + 1);
if (pacmanx > (ghostx[i] - 12) && pacmanx < (ghostx[i] + 12) &&
pacmany > (ghosty[i] - 12) && pacmany < (ghosty[i] + 12) &&
ingame) {
dying = true;
deathcounter = 64;
}
}
}
public void DrawGhost(Graphics2D g2d, int x, int y) {
g2d.drawImage(ghost, x, y, this);
}
public void MovePacMan() {
int pos;
short ch;
if (reqdx == -pacmandx && reqdy == -pacmandy) {
pacmandx = reqdx;
pacmandy = reqdy;
viewdx = pacmandx;
viewdy = pacmandy;
}
if (pacmanx % blocksize == 0 && pacmany % blocksize == 0) {
pos = pacmanx / blocksize + nrofblocks * (int)(pacmany / blocksize);
ch = screendata[pos];
if ((ch & 16) != 0) {
screendata[pos] = (short)(ch & 15);
score++;
}
if (reqdx != 0 || reqdy != 0) {
if (!((reqdx == -1 && reqdy == 0 && (ch & 1) != 0) ||
(reqdx == 1 && reqdy == 0 && (ch & 4) != 0) ||
(reqdx == 0 && reqdy == -1 && (ch & 2) != 0) ||
(reqdx == 0 && reqdy == 1 && (ch & 8) != 0))) {
pacmandx = reqdx;
pacmandy = reqdy;
viewdx = pacmandx;
viewdy = pacmandy;
}
}
// Check for standstill
if ((pacmandx == -1 && pacmandy == 0 && (ch & 1) != 0) ||
(pacmandx == 1 && pacmandy == 0 && (ch & 4) != 0) ||
(pacmandx == 0 && pacmandy == -1 && (ch & 2) != 0) ||
(pacmandx == 0 && pacmandy == 1 && (ch & 8) != 0)) {
pacmandx = 0;
pacmandy = 0;
}
}
pacmanx = pacmanx + pacmanspeed * pacmandx;
pacmany = pacmany + pacmanspeed * pacmandy;
}
public void DrawPacMan(Graphics2D g2d) {
if (viewdx == -1)
DrawPacManLeft(g2d);
else if (viewdx == 1)
DrawPacManRight(g2d);
else if (viewdy == -1)
DrawPacManUp(g2d);
else
DrawPacManDown(g2d);
}
public void DrawPacManUp(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2up, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3up, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4up, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawPacManDown(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2down, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3down, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4down, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawPacManLeft(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2left, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3left, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4left, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawPacManRight(Graphics2D g2d) {
switch (pacmananimpos) {
case 1:
g2d.drawImage(pacman2right, pacmanx + 1, pacmany + 1, this);
break;
case 2:
g2d.drawImage(pacman3right, pacmanx + 1, pacmany + 1, this);
break;
case 3:
g2d.drawImage(pacman4right, pacmanx + 1, pacmany + 1, this);
break;
default:
g2d.drawImage(pacman1, pacmanx + 1, pacmany + 1, this);
break;
}
}
public void DrawMaze(Graphics2D g2d) {
short i = 0;
int x, y;
for (y = 0; y < scrsize; y += blocksize) {
for (x = 0; x < scrsize; x += blocksize) {
g2d.setColor(mazecolor);
g2d.setStroke(new BasicStroke(2));
if ((screendata[i] & 1) != 0) // draws left
{
g2d.drawLine(x, y, x, y + blocksize - 1);
}
if ((screendata[i] & 2) != 0) // draws top
{
g2d.drawLine(x, y, x + blocksize - 1, y);
}
if ((screendata[i] & 4) != 0) // draws right
{
g2d.drawLine(x + blocksize - 1, y, x + blocksize - 1,
y + blocksize - 1);
}
if ((screendata[i] & 8) != 0) // draws bottom
{
g2d.drawLine(x, y + blocksize - 1, x + blocksize - 1,
y + blocksize - 1);
}
if ((screendata[i] & 16) != 0) // draws point
{
g2d.setColor(dotcolor);
g2d.fillRect(x + 11, y + 11, 2, 2);
}
i++;
}
}
}
public void GameInit() {
pacsleft = 3;
score = 0;
LevelInit();
nrofghosts = 4;
currentspeed = 3;
}
public void LevelInit() {
int i;
for (i = 0; i < nrofblocks * nrofblocks; i++)
screendata[i] = leveldata[i];
LevelContinue();
}
public void LevelContinue() {
short i;
int dx = 1;
int random;
for (i = 0; i < nrofghosts; i++) {
ghosty[i] = 4 * blocksize;
ghostx[i] = 4 * blocksize;
ghostdy[i] = 0;
ghostdx[i] = dx;
dx = -dx;
random = (int)(Math.random() * (currentspeed + 1));
if (random > currentspeed)
random = currentspeed;
ghostspeed[i] = validspeeds[random];
}
pacmanx = 7 * blocksize;
pacmany = 11 * blocksize;
pacmandx = 0;
pacmandy = 0;
reqdx = 0;
reqdy = 0;
viewdx = -1;
viewdy = 0;
dying = false;
}
public void GetImages()
{
ghost = new ImageIcon(PacBoard.class.getResource("../pacpix/ghost.gif")).getImage();
pacman1 = new ImageIcon(PacBoard.class.getResource("../pacpix/pacman.png")).getImage();
pacman2up = new ImageIcon(PacBoard.class.getResource("../pacpix/up1.png")).getImage();
pacman3up = new ImageIcon(PacBoard.class.getResource("../pacpix/up2.png")).getImage();
pacman4up = new ImageIcon(PacBoard.class.getResource("../pacpix/up3.png")).getImage();
pacman2down = new ImageIcon(PacBoard.class.getResource("../pacpix/down1.png")).getImage();
pacman3down = new ImageIcon(PacBoard.class.getResource("../pacpix/down2.png")).getImage();
pacman4down = new ImageIcon(PacBoard.class.getResource("../pacpix/down3.png")).getImage();
pacman2left = new ImageIcon(PacBoard.class.getResource("../pacpix/left1.png")).getImage();
pacman3left = new ImageIcon(PacBoard.class.getResource("../pacpix/left2.png")).getImage();
pacman4left = new ImageIcon(PacBoard.class.getResource("../pacpix/left3.png")).getImage();
pacman2right = new ImageIcon(PacBoard.class.getResource("../pacpix/right1.png")).getImage();
pacman3right = new ImageIcon(PacBoard.class.getResource("../pacpix/right2.png")).getImage();
pacman4right = new ImageIcon(PacBoard.class.getResource("../pacpix/right3.png")).getImage();
}
public void paint(Graphics g)
{
super.paint(g);
Graphics2D g2d = (Graphics2D) g;
g2d.setColor(Color.black);
g2d.fillRect(0, 0, d.width, d.height);
DrawMaze(g2d);
DrawScore(g2d);
DoAnim();
if (ingame){
PlayGame(g2d);
}
else{
ShowIntroScreen(g2d);
}
g.drawImage(ii, 5, 5, this);
Toolkit.getDefaultToolkit().sync();
g.dispose();
}
class TAdapter extends KeyAdapter {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (ingame)
{
if (key == KeyEvent.VK_LEFT)
{
reqdx=-1;
reqdy=0;
}
else if (key == KeyEvent.VK_RIGHT)
{
reqdx=1;
reqdy=0;
}
else if (key == KeyEvent.VK_UP)
{
reqdx=0;
reqdy=-1;
}
else if (key == KeyEvent.VK_DOWN)
{
reqdx=0;
reqdy=1;
}
else if (key == KeyEvent.VK_ESCAPE && timer.isRunning())
{
ingame=false;
}
else if (key == KeyEvent.VK_PAUSE) {
if (timer.isRunning())
timer.stop();
else timer.start();
}
}
else
{
if (key == 's' || key == 'S')
{
ingame=true;
GameInit();
}
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == Event.LEFT || key == Event.RIGHT ||
key == Event.UP || key == Event.DOWN)
{
reqdx=0;
reqdy=0;
}
}
}
public void actionPerformed(ActionEvent e) {
repaint();
}
}
Sorry I know that's a lot of code but I'm not sure where the problem is being created. Here is the line that it is being caught at:
if ((screendata[pos] & 1) == 0 && ghostdx[i] != 1) {
I know it has to be increasing or decreasing the size of the array to an illegal number, but where? And why? That's what I don't understand. Oh, and I got the exception in my output window about 10 times, not sure why though. Would this mean it's getting increased in one of my for loops?
Thanks to anyone who will help, and I will provide more information as needed.
To compile:
import javax.swing.JFrame;
public class Pacman extends JFrame
{
public Pacman()
{
add(new PacBoard());
setTitle("Pacman");
setSize(380, 420);
setLocationRelativeTo(null);
setVisible(true);
}
public static void main(String[] args) {
new Pacman();
}
}
I think I know (with the help of other commenters) where your problem is:
We have deduced that either ghostx[i] is negative, or ghosty[i] is negative.
Notice here that you set dx to one, and then set ghostx[i] to dx.
The problem arises when you set dx to be the negative of dx (dx = -dx;)
This means that on the next iteration, dx is negative, and therefore out of bounds.
(It is out of bounds, because pos is calculated based on ghostx[i]. And ghostx[i] is calculated based on dx. If dx is negative, so will ghostx[i] be, and so will pos, causing big problems)
I am not sure what you were trying to do here, but definitely change this line and see if it fixes your problems. Leave a comment with what dx = -dx; is supposed to do, and I'll help you figure it out.
Code which is the culprit:
public void LevelContinue() {
short i;
int dx = 1;
int random;
for (i = 0; i < nrofghosts; i++) {
ghosty[i] = 4 * blocksize;
ghostx[i] = 4 * blocksize;
ghostdy[i] = 0;
ghostdx[i] = dx;
dx = -dx;//Line which kills your code
random = (int)(Math.random() * (currentspeed + 1));
if (random > currentspeed)
random = currentspeed;
ghostspeed[i] = validspeeds[random];
}
To sum it all up, the code I posted above (particularly the "Line which kills your code") sets ghosty[i] to a negative. It will only do this at odd indexes (ghostx[0], and ghostx[2] will be positive, but [1] (which is the index you have stated having issues with) will be negative.
Later down the line, this bit of code here:
pos = ghostx[i] / blocksize + nrofblocks * (int)(ghosty[i] / blocksize);
uses ghostx[] in a division, causing the whole thing to become negative.
You then, at the line of code you stated to be bad, use screendata[pos], which results in you using a negative index.
EDIT: New answer proposal.
Now, the only lines of code I have found so far that modify ghostx or ghosty are:
ghostx[i] = ghostx[i] + (ghostdx[i] * ghostspeed[i]);
ghosty[i] = ghosty[i] + (ghostdy[i] * ghostspeed[i]);
and
ghosty[i] = 4 * blocksize;
ghostx[i] = 4 * blocksize;
We know the latter of the two can't be it, because blocksize and 4 are both positive.
That means that
ghostx[i] = ghostx[i] + (ghostdx[i] * ghostspeed[i]);
ghosty[i] = ghosty[i] + (ghostdy[i] * ghostspeed[i]);
are the problem.
Looking at this, it appears to me that your ghosts are wandering outside your board! I noticed that ghostdx can be negative (ghostdx being ghost delta x right?) This means that when your ghost is traveling in the negative direction, it ends up going so far that it ends up going outside the board.
Right after those lines, I suggest adding these lines:
if (ghostx[i] < 0) ghostx[i] = 0;
if (ghosty[i] < 0) ghosty[i] = 0;
if (ghostx[i] >= WHATEVER_YOUR_MAX_POSITION_IS) ghostx[i] = WHATEVER_YOUR_MAX_POSITION_IS - 1;
if (ghosty[i] >= WHATEVER_YOUR_MAX_POSITION_IS) ghosty[i] = WHATEVER_YOUR_MAX_POSITION_IS - 1;
See if that fixes your problems please!
pos = pacmanx / blocksize + nrofblocks * (int)(pacmany / blocksize);
make sure your assignd value cannot be > nrofblocks*nrofblocks, also make sure that your divisor is allways > 0, as far as i remember in java you can devide by zero but this will result in NaN , pos[NaN] is obviously out of bounds.. ah but i dont think this makes sense for int , which is your variable pos.
Iam just providing some thoughts i would check first, its too late to crunch the numbers, sorry ;)
Btw, why not use vectors for the coordinates ? should be much easier

Shortest path in a 2d array using Dijkstra's algorithm?

This is my first time implementing Dijkstra's algorithm. Okay so here I have a simple 2D 9 by 9 array:
Starting point is 1 and we're trying to get to any green square. Red squares are walls or lava (whatever satisfies your imagination).
How do I implement this in Java?
Computer science is not my field hence I'm not a seasoned programmer so I might not know how to do some stack pushing, only loops and recursion :( please keep it easy as possible and bear with me!
Here's something similiar that should get you started. However, the solution presented below attempts to get to the bottom right corner. You can relax that condition to find the bottom row. You will also need to change the encoding slightly to have a unique value that represents this row.
public class MazeSolver {
final static int TRIED = 2;
final static int PATH = 3;
// #formatter:off
private static int[][] GRID = {
{ 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1 },
{ 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 0, 1 },
{ 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0 },
{ 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1 },
{ 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 1 },
{ 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1 },
{ 1, 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 }
};
// #formatter:off
public static void main(String[] args) {
MazeSolver maze = new MazeSolver(GRID);
boolean solved = maze.solve();
System.out.println("Solved: " + solved);
System.out.println(maze.toString());
}
private int[][] grid;
private int height;
private int width;
private int[][] map;
public MazeSolver(int[][] grid) {
this.grid = grid;
this.height = grid.length;
this.width = grid[0].length;
this.map = new int[height][width];
}
public boolean solve() {
return traverse(0,0);
}
private boolean traverse(int i, int j) {
if (!isValid(i,j)) {
return false;
}
if ( isEnd(i, j) ) {
map[i][j] = PATH;
return true;
} else {
map[i][j] = TRIED;
}
// North
if (traverse(i - 1, j)) {
map[i-1][j] = PATH;
return true;
}
// East
if (traverse(i, j + 1)) {
map[i][j + 1] = PATH;
return true;
}
// South
if (traverse(i + 1, j)) {
map[i + 1][j] = PATH;
return true;
}
// West
if (traverse(i, j - 1)) {
map[i][j - 1] = PATH;
return true;
}
return false;
}
private boolean isEnd(int i, int j) {
return i == height - 1 && j == width - 1;
}
private boolean isValid(int i, int j) {
if (inRange(i, j) && isOpen(i, j) && !isTried(i, j)) {
return true;
}
return false;
}
private boolean isOpen(int i, int j) {
return grid[i][j] == 1;
}
private boolean isTried(int i, int j) {
return map[i][j] == TRIED;
}
private boolean inRange(int i, int j) {
return inHeight(i) && inWidth(j);
}
private boolean inHeight(int i) {
return i >= 0 && i < height;
}
private boolean inWidth(int j) {
return j >= 0 && j < width;
}
public String toString() {
String s = "";
for (int[] row : map) {
s += Arrays.toString(row) + "\n";
}
return s;
}
}
I would suggest you start with writing down a method of applying dijkstras algorithm (assuming you know it in the first place) here in natural language and then start transforming it to your programming language.
The basic questions you will need to answer for that:
What are the nodes?
What are the connections?
What is the weight of each connection?
Once you did this you should be able to find a (probably not efficient) solution.
The optimal solution is indeed to use Dijkstra or AStar with a different finish condition. So you need to write if(targetNodes.contains(u)) break; instead of if(target == u) break;
(see wikipedia: If we are only interested in a shortest path between vertices source and target, we can terminate the search at line 13 if u = target.)
This is already implemented in my project called ... oh is this homework ;) ?

Categories

Resources