Text Mode Pacman in Java Homework Sample

You need to write code to play a simplified game of Pacman (text mode only). You need to read a map that represents the initial board position. The ghosts should move towards Pacman, and Pacman should move according the the key pressed (w,a,s,d for moving, or q for quit). You also need to accept command line parameters for setting the size of the board, for input and output files (all these are optional). For more Java programming assignments contact us for a quote.

Solution:

Board.java

import java.lang.StringBuilder;
import java.util.*;
import java.io.*;

/**
* @author Firstname Lastname <address @ example.com>
*/
public class Board {

// FIELD
public final int GRID_SIZE;

// Exception string that is thrown whenever an I/O exception occurs
public static final String IO_EXCEPTION = “I/O Exception!”;

private char[][] grid; // String Representation of Pac-man Game Board
private boolean[][] visited; // Record of where Pac-man has visited
private PacCharacter pacman; // Pac-man that user controls
private PacCharacter[] ghosts; // 4 Ghosts that controlled by the program
private int score; // Score Recorded for the gamer

/**
* Constructor
*
* <p> Description: Creates an instance of Pacman game board with the specified size
*
* @param: size of Pacman game board
* @return: an instance of Pacman game board
*/
public Board(int size) {

// Initialize instance variables
GRID_SIZE = size;
grid = new char[GRID_SIZE][GRID_SIZE];
visited = new boolean[GRID_SIZE][GRID_SIZE];
score = 0;

pacman = new PacCharacter(GRID_SIZE/2, GRID_SIZE/2, ‘P’);
ghosts = new PacCharacter[4];
ghosts[0] = new PacCharacter( 0, 0, ‘G’);
ghosts[1] = new PacCharacter( 0, GRID_SIZE-1, ‘G’);
ghosts[2] = new PacCharacter(GRID_SIZE-1, 0, ‘G’);
ghosts[3] = new PacCharacter(GRID_SIZE-1, GRID_SIZE-1, ‘G’);

setVisited(GRID_SIZE/2, GRID_SIZE/2);

refreshGrid();
}

/**
* Constructor
*
* <p> Description: Creates an instance of Pacman game board, loaded from given input file
*
* @param inputBoard input file, containing game save
* @throws Exception with IO_EXCEPTION message, in case error occurred during input file opening
*/
public Board(String inputBoard) throws Exception {
try {
Scanner scanner = new Scanner(new File(inputBoard));
GRID_SIZE = Integer.parseInt(scanner.nextLine());
score = Integer.parseInt(scanner.nextLine());
grid = new char[GRID_SIZE][GRID_SIZE];
visited = new boolean[GRID_SIZE][GRID_SIZE];
ghosts = new PacCharacter[4];
int ghostNum = 0;

for (int row = 0; row < GRID_SIZE; row++) {
char[] rowChar = scanner.nextLine().toCharArray();
for (int column = 0; column < GRID_SIZE; column++) {
switch (rowChar[column]) {
case ‘P’:
pacman = new PacCharacter(row, column, ‘P’);
visited[row][column] = true;
break;
case ‘G’:
ghosts[ghostNum] = new PacCharacter(row, column, ‘G’);
ghostNum++;
visited[row][column] = false;
break;
case ‘ ‘:
visited[row][column] = true;
break;
case ‘*’:
visited[row][column] = false;
break;
}
}
}

// If two or more ghosts were ‘united’, we define all the other ghosts as the last found
if (ghostNum < 4) {
for (int i = ghostNum; i<4; i++) {
ghosts[i] = new PacCharacter(ghosts[ghostNum-1].getRow(), ghosts[ghostNum-1].getCol(), ‘G’);
}
}
scanner.close();
refreshGrid();
} catch (IOException ioe) {
throw new Exception(IO_EXCEPTION);
}
}

public void setVisited(int x, int y) {
if (x < 0 || y < 0 || x >= GRID_SIZE || y > GRID_SIZE) return;
visited[x][y] = true;
}

public void refreshGrid() {

for (int i = 0; i < GRID_SIZE; i++)
for (int j = 0; j < GRID_SIZE; j++) {
if (!visited[i][j])
grid[i][j] = ‘*’;
else
grid[i][j] = ‘ ‘;
}

grid[pacman.getRow()][pacman.getCol()] = pacman.getAppearance();
for (PacCharacter ghost : ghosts) {
if (pacman.getRow() == ghost.getRow() && pacman.getCol() == ghost.getCol())
grid[ghost.getRow()][ghost.getCol()] = ‘X’;
else grid[ghost.getRow()][ghost.getCol()] = ghost.getAppearance();
}

}

public boolean canMove(Direction direction) {
if (direction == null) return false;
// Calculate Coordinate after Displacement
int pacmanRow = pacman.getRow() + direction.getY();
int pacmanCol = pacman.getCol() + direction.getX();

return pacmanRow >= 0 && pacmanRow < GRID_SIZE && pacmanCol >= 0 && pacmanCol < GRID_SIZE;
}

public void move(Direction direction) {
// Calculate Coordinate after Displacement
int pacmanRow = pacman.getRow() + direction.getY();
int pacmanCol = pacman.getCol() + direction.getX();

pacman.setPosition(pacmanRow, pacmanCol);
if (!visited[pacmanRow][pacmanCol]) {
score += 10;
visited[pacmanRow][pacmanCol] = true;
}

for (PacCharacter ghost : ghosts) {
ghostMove(ghost);
}

refreshGrid();
}

public boolean isGameOver() {
int pacmanRow = pacman.getRow();
int pacmanCol = pacman.getCol();

for (PacCharacter ghost : ghosts)
if (ghost.getRow() == pacmanRow && ghost.getCol() == pacmanCol)
return true;

return false;

}

// Monster always move towards Pac-man
public Direction ghostMove(PacCharacter ghost) {
int pacmanRow = pacman.getRow();
int pacmanCol = pacman.getCol();

int ghostRow = ghost.getRow();
int ghostCol = ghost.getCol();

int rowDist = Math.abs(ghostRow – pacmanRow);
int colDist = Math.abs(ghostCol – pacmanCol);

if (rowDist == 0 && colDist > 0) {
if (ghostCol – pacmanCol > 0) {
ghost.setPosition(ghostRow, ghostCol – 1);
return Direction.LEFT;
} else { // ghostCol – pacmanCol < 0
ghost.setPosition(ghostRow, ghostCol + 1);
return Direction.RIGHT;
}
}
else if (rowDist > 0 && colDist == 0 ) {
if (ghostRow – pacmanRow > 0) {
ghost.setPosition(ghostRow – 1, ghostCol);
return Direction.UP;
} else { // ghostRow – pacmanRow < 0
ghost.setPosition(ghostRow + 1, ghostCol);
return Direction.DOWN;
}
}
else if (rowDist == 0 && colDist == 0) {
return Direction.STAY;
}
else {
if (rowDist < colDist) {
if (ghostRow – pacmanRow > 0) {
ghost.setPosition(ghostRow – 1, ghostCol);
return Direction.UP;
} else { // ghostRow – pacmanRow < 0
ghost.setPosition(ghostRow + 1, ghostCol);
return Direction.DOWN;
}
} else {
if (ghostCol – pacmanCol > 0) {
ghost.setPosition(ghostRow, ghostCol – 1);
return Direction.LEFT;
} else { // ghostCol – pacmanCol < 0
ghost.setPosition(ghostRow, ghostCol + 1);
return Direction.RIGHT;
}
}
}

}

public void saveBoard(String outputBoard) throws Exception
{
try {
PrintWriter pw = new PrintWriter(new File(outputBoard));
pw.println(GRID_SIZE);
pw.println(score);
StringBuilder builder = new StringBuilder();
for (int row = 0; row < GRID_SIZE; row++) {
for (int column = 0; column < GRID_SIZE; column++) {
builder.append(grid[row][column]);
}
builder.append(System.lineSeparator());
}
pw.print(builder.toString());
pw.close();
}
catch (IOException ioe) {
throw new Exception(IO_EXCEPTION);
}
}

public String toString(){

StringBuilder outputString = new StringBuilder();
outputString.append(String.format(“Score: %d\n”, this.score));

for (int row = 0; row < GRID_SIZE; row++)
{
for (int column = 0; column < GRID_SIZE; column++) {
outputString.append(” “);
outputString.append(grid[row][column]);
}

outputString.append(“\n”);
}
return outputString.toString();

}
}

Direction.java

/**
* Direction.java
*
* @author Brandon Williams
* @version 2.0
* @since 1/17/15
*
* Modified by Xinwei Wang at 1/27/19
*/

/** DO NOT MODIFY THIS FILE */

/**
* enum Direction
*
* Enumeration Type used to represent a Movement Direction.
* Each Direction object includes the vector of Direction.
*
*/
public enum Direction {

// The Definitions for UP, DOWN, LEFT, and RIGHT
UP(0, -1), DOWN(0, 1), LEFT(-1, 0), RIGHT(1, 0), STAY(0, 0);

// FIELD
private final int x;
private final int y;

/*
* Constructor
*
* @param int x – Displacement on X dimension
* @param int y – Displacement on Y dimension
*/
Direction(int x, int y)
{
this.x = x;
this.y = y;
}

/*
* Getter of x
*
* Retrieve the X component of direction
*
* @return int X component of this direction
*/
public int getX()
{
return x;
}

/*
* Getter of x
*
* Retrieve the Y component of direction
*
* @return int Y component of this direction
*/
public int getY()
{
return y;
}

/*
* toString
*
* Format and return the name of the enum
*
* @return String the string representation of this direction
*/
@Override
public String toString()
{
// Close the x and y components with parenthesis.
return name() + “(” + x + “, ” + y + “)”;
}

}

GameManager.java

import java.util.*;

public class GameManager {

// Instance variables
private Board board; // The actual Pacman board
private String outputFileName = “Pac-Man.board”; // File to save the board to when exiting

/*
* GameManager Constructor
*
* Purpose: Constructs a GameManager to Generate new game
* Parameter: int boardSize – Integer player want to set as board size.
* String outputBoard – the filename the Board will be saved as.
* Random random – the Random generator player wanna use.
*
*/
GameManager(int boardSize, String outputBoard) throws Exception
{
board = new Board(boardSize);
if (outputBoard != null) {
outputFileName = outputBoard;
}
}

/*
* GameManager Constructor
*
* Purpose: Constructs a GameManager to Load a saved game.
* Parameter: String inputBoard – the filename the Board will be inputted.
* String outputBoard – the filename the Board will be saved as.
* Random random – the Random generator player wanna use.
*
*/
GameManager(String inputBoard, String outputBoard) throws Exception
{
board = new Board(inputBoard);
if (outputBoard != null) {
outputFileName = outputBoard;
}
}

// Main play loop
// Takes in input from the user to specify moves to execute
// valid moves are:
// w – Move up
// s – Move Down
// a – Move Left
// d – Move Right
// q – Quit and Save Board
//
// If an invalid command is received then print the controls
// to remind the user of the valid moves.
//
// Once the player decides to quit or the game is over,
// save the game board to a file based on the outputFileName
// string that was set in the constructor and then return
//
// If the game is over print “Game Over!” to the terminal

/*
* Name: play
* Purpose: Takes in input from the user to specify moves to execute.
* Parameter: Null.
* Return: void.
*
*/
public void play() throws Exception
{
Scanner scanner = new Scanner(System.in);
boolean quit = false;
while(!board.isGameOver() && !quit) {
printControls();
System.out.println(board.toString());
String line = scanner.nextLine().trim();
switch (line) {
case “w”:
board.move(Direction.UP);
break;
case “s”:
board.move(Direction.DOWN);
break;
case “a”:
board.move(Direction.LEFT);
break;
case “d”:
board.move(Direction.RIGHT);
break;
case “q”:
quit = true;
break;
default:
System.out.println(“Your input is invalid. Please, try again.”);
printControls();
}
}
if (!quit) {
System.out.println(board.toString());

System.out.println(“GAME OVER”);
}
board.saveBoard(outputFileName);
System.out.println(“Your game has been saved”);
scanner.close();
}

/*
* Name: printControls()
* Purpose: Print the Controls for the Game.
* Parameter: Null.
* Return: void.
*/
private void printControls()
{
System.out.println(” Controls:”);
System.out.println(” w – Move Up”);
System.out.println(” s – Move Down”);
System.out.println(” a – Move Left”);
System.out.println(” d – Move Right”);
System.out.println(” q – Quit and Save Board”);
System.out.println();
}
}

GamePacman.java

public class GamePacman {

private static final int DEFAULT_SIZE = 10;

private static String inputBoard;
private static String outputBoard;
private static int boardSize;

public static void main(String[] args) throws Exception {

processArgs(args);

System.out.println(“Welcome to Pac-Man!”);

GameManager game;

if (inputBoard == null) {
System.out.println(“Generating a New Board”);
game = new GameManager(boardSize, outputBoard);
} else {
System.out.println(“Loading Board from ” + inputBoard);
game = new GameManager(inputBoard, outputBoard);
}

game.play();

}

private static void processArgs(String[] args) {

// Arguments must come in pairs
if((args.length % 2) != 0)
{
printUsage();
System.exit(-1);
}

// Setting boards size with default value
// If no parameters was passed, boardSize will stay default
boardSize = DEFAULT_SIZE;

// iterating over each pair of command line arguments
for (int i = 0; i<args.length/2; i++) {
// Getting parameters of current pair
String param1 = args[2*i];
String param2 = args[2*i+1];

// If first parameters is not “-s”, throwing an error
switch (param1) {
case “-s”:
// Trying to parse integer from the second parameter
try {
// Parsing integer
int tryBoardSize = Integer.parseInt(param2);
// If int is less than 3, the default value is set
if (tryBoardSize < 3) {
boardSize = DEFAULT_SIZE;
}
// otherwise boardSize is updated with new param
else {
boardSize = tryBoardSize;
}
} catch (NumberFormatException nfe) {
// If second parameter in pair is invalid, an error is
// thrown
printUsage();
System.exit(-1);
}
break;
case “-i”:
inputBoard = param2;
break;
case “-o”:
outputBoard = param2;
break;
default:
printUsage();
System.exit(-1);
}
}

}

// Print the Usage Message
private static void printUsage()
{
System.out.println(“Pac-Man”);
System.out.println(“Usage: GamePacman [-i|o file …]”);
System.out.println();
System.out.println(” Command line arguments come in pairs of the form: <command> <argument>”);
System.out.println();
System.out.println(” -i [file] -> Specifies a Pacman board that should be loaded”);
System.out.println();
System.out.println(” -o [file] -> Specifies a file that should be used to save the 2048 board”);
System.out.println(” If none specified then the default \”Pac-Man.board\” file will be used”);
System.out.println(” -s [size] -> Specifies the size of the Pac-Man board if an input file hasn’t been”);
System.out.println(” specified. If both -s and -i are used, then the size of the board”);
System.out.println(” will be determined by the input file. If board size declared is less”);
System.out.println(” than 3, the board size will be modified to the default size. The default”);
System.out.println(” size is 10.”);

}
}

PacCharacter.java

public class PacCharacter {

private char appearance;
private int row;
private int col;

public PacCharacter(int row, int col, char appearance) {
this.row = row;
this.col = col;
this.appearance = appearance;
}

public int getRow() {
return row;
}

public int getCol() {
return col;
}

public char getAppearance() {
return appearance;
}

public void setPosition(int row, int col) {
this.row = row;
this.col = col;
}

public void setAppearance(char appearance) {
this.appearance = appearance;
}
}