Random Pac-Man Ghost AI using an 2d array

1.5k views Asked by At

I used a 2d array for the maze of a Pac-Man game clone in Java. I know the ghosts in Pac-Man doesn't move randomly however how would I go about making the ghosts move randomly in the maze? Below is what I tried.

private void randomGhostMovement() {

    // Get the tileX for the 2d array data map.
    int tileX = (int) (this.ghosts.get(0).getCenterX() / Wall.SIZE);

    // Get the tileY for the 2d array data map.
    int tileY = (int) (this.ghosts.get(0).getCenterY() / Wall.SIZE);

    // Get the left corner x position of the ghost.
    double ghostX = this.ghosts.get(0).getCenterX();

    // Get the tile X coordinates where the ghost is at.
    double tileXCoord = tileX * Wall.SIZE;

    // Get the left corner y position of the ghost.
    double ghostY = this.ghosts.get(0).getCenterY();

    // Get the tile Y coordinates where the ghost is at.
    double tileYCoord = tileY * Wall.SIZE;

    // Create a dice to roll [0,3].
    int randomMovement = (int) (Math.random() * 4);

    // Create a flag to check if the ghost is able to move left, right, up, or down.
    boolean moveLeft = false, moveRight= false, moveUp = false, moveDown = false;


    // Check for possible movements and not in the reverse.
    if(!this.ghosts.get(0).isMoveRightFlag() && (this.dataMap[tileY][tileX - 1] == 1 || this.dataMap[tileY][tileX - 1] == -1) && ((tileXCoord/ghostX) >= 0.4 && (ghostX/tileXCoord) <= 1.13) && ((tileYCoord/ghostY) >= 0.4 && (ghostY/tileYCoord) <= 1.13)) {

        moveLeft = true;
    }
    if(!this.ghosts.get(0).isMoveLeftFlag() && (this.dataMap[tileY][tileX + 1] == 1 || this.dataMap[tileY][tileX + 1] == -1) && ((tileXCoord/ghostX) >= 0.4 && (ghostX/tileXCoord) <= 1.13) && ((tileYCoord/ghostY) >= 0.4 && (ghostY/tileYCoord) <= 1.13)) {

        moveRight = true;
    }
    if(!this.ghosts.get(0).isMoveDownFlag() && (this.dataMap[tileY - 1][tileX] == 1 || this.dataMap[tileY - 1][tileX] == -1 ||
            this.dataMap[tileY - 1][tileX] == 15) && ((tileXCoord/ghostX) >= 0.4 && (ghostX/tileXCoord) <= 1.13) && ((tileYCoord/ghostY) >= 0.4 && (ghostY/tileYCoord) <= 1.13)) {

        moveUp = true;
    }
    if(!this.ghosts.get(0).isMoveUpFlag() && (this.dataMap[tileY + 1][tileX] == 1 || this.dataMap[tileY + 1][tileX] == -1) && ((tileXCoord/ghostX) >= 0.4 && (ghostX/tileXCoord) <= 1.13) && ((tileYCoord/ghostY) >= 0.4 && (ghostY/tileYCoord) <= 1.13)) {

        moveDown = true;
    }


    // Roll the dice, and if the ghost is able to move in the direction then move.
    if(moveLeft && randomMovement == 0) {

        this.ghosts.get(0).moveLeft();
    }
    if(moveRight && randomMovement == 1) {

        this.ghosts.get(0).moveRight();
    }
    if(moveUp && randomMovement == 2) {

        this.ghosts.get(0).moveUp();
    }
    if(moveDown && randomMovement == 3) {

        this.ghosts.get(0).moveDown();
    }

}
2

There are 2 answers

0
Michriko On

You can get a Ranom direction when you check for available directions (no wall in those directions) and then select a direction with a random number

//Anywhere in the Movementcontroller declared
const int UP = 0;
const int DOWN = 1;
const int RIGHT = 2;
const int LEFT = 3;
....
//the moveroutine
int directions[] = checkAvailabelDirections(currentPosition);
randomDirection = directions [(int) (Math.random() * directions.length)]
move(randomDirection)
0
Nixxon On

Depends on how you want them to move. I assume you want them to follow a path until it branches and then choose a new path?

Each ghost is an object I assume (otherwise youll have to store information about each ghost in some other way). So keep a field to indicate which direction they just moved from (as to disallow moving back the same way (unless no other path is available)), possibly use an enum, but a number could also used.

For each "round", check where it could possibly go (up, down, left, right).

If only 1 is available go that way.

If 2 options are available, go the opposite of where you come from (exclude the one where you came from).

If 3 or 4 are available, roll() between the ones you did not arrive from.

(Remember to set the direction you moved in so that you will know in the next round, have an int mapped to some direction through the code, or use enums (or even objects that move your object the correct direction when calling something like direction.move(ghostObject)).

public int roll(int possiblePaths) {
   Random random = new Random();
   int d = random.nextInt(possiblePaths);
   return d;
}

If you added some of the code you've already written it would be easier to give more concrete examples