package solution; import java.util.Scanner; import java.io.File; import java.io.FileNotFoundException; /** * A maze game. * * @author Thom Dickson * @version 2021-01-27 * */ public class MazeGame { /** * The size of each side of the game map. */ private final static int HEIGHT = 19; private final static int WIDTH = 39; /** * The game map, as a 2D array of ints. */ private boolean[][] blocked; /** * The map of bread crumbs. */ private boolean[][] bc; /** * The current location of the player vertically. */ private int userRow; /** * The current location of the player horizontally. */ private int userCol; /** * The scanner from which each move is read. */ private Scanner moveScanner; /** * The row and column of the goal. */ // TODO: add fields here. private int goalCol; private int goalRow; /** * The row and column of the start. */ // TODO: add fields here. private int[] start = {0, 0}; /** * Constructor initializes the maze with the data in 'mazeFile'. * @param mazeFile the input file for the maze */ public MazeGame(String mazeFile) { this.loadMaze(mazeFile); this.moveScanner = new Scanner(System.in); } /** * Constructor initializes the maze with the 'mazeFile' and the move * scanner with 'moveScanner'. * @param mazeFile the input file for the maze * @param moveScanner the scanner object from which to read user moves */ public MazeGame(String mazeFile, Scanner moveScanner) { // TODO this.loadMaze(mazeFile); this.moveScanner = moveScanner; } /** * getMaze returns a copy of the current maze for testing purposes. * * @return the grid */ public boolean[][] getMaze() { if (blocked == null) { return null; } boolean[][] copy = new boolean[HEIGHT][WIDTH]; for (int i = 0; i < HEIGHT; i++) { for (int j = 0; j < WIDTH; j++) { copy[i][j] = blocked[i][j]; } } return copy; } /** * setMaze sets the current map for testing purposes. * * @param maze * another maze. */ public void setMaze(boolean[][] maze) { this.blocked = maze; } /** * Function loads the data from the maze file and creates the 'blocked' * 2D array. * * @param mazeFile the input maze file. */ private void loadMaze(String mazeFile) { // Set field width and height final int WIDTH = 39; final int HEIGHT = 19; // Create empty field to load data into // TODO Remove magic numbers this.blocked = new boolean[HEIGHT][WIDTH]; this.bc = new boolean[HEIGHT][WIDTH]; this.bc[0][0] = true; // Load file try { File inputData = new File(mazeFile); Scanner dataReader = new Scanner(inputData); for (int i = 0; i < this.blocked.length; i++) { for (int j = 0; j < this.blocked[i].length; j++) { String iData = dataReader.next(); switch (iData) { case "1": this.blocked[i][j] = true; break; case "S": this.userRow = i; this.userRow = j; this.start[0] = i; this.start[1] = j; break; case "G": this.goalRow = i; this.goalCol = j; break; default: this.blocked[i][j] = false; } } } } catch (FileNotFoundException e) { System.out.println(e); } } /** * Actually plays the game. */ public void playGame() { String input = ""; boolean won = false; do { input = this.moveScanner.next(); this.makeMove(input); this.printMaze(); won = this.playerAtGoal(); } while (!input.equals("quit") && !won); } /** * Checks to see if the player has won the game. * @return true if the player has won. */ public boolean playerAtGoal() { return this.userCol == this.goalCol && this.userRow == this.goalRow; } /** * Makes a move based on the String. * * @param move * the direction to make a move in. * @return whether the move was valid. */ public boolean makeMove(String move) { int[] curLoc = {this.userCol, this.userRow}; int[] newLoc = curLoc; switch (move) { case "up": newLoc[1] = this.userRow - 1; break; case "down": newLoc[1] = this.userRow + 1; break; case "left": newLoc[0] = this.userCol - 1; break; case "right": newLoc[0] = this.userCol + 1; break; default: break; } if (newLoc[0] < 0 || newLoc[0] > this.blocked[0].length - 1 || newLoc[1] < 0 || newLoc[1] > this.blocked.length - 1 || this.blocked[newLoc[1]][newLoc[0]]) { return false; } else { this.userRow = newLoc[1]; this.userRow = newLoc[1]; this.userCol = newLoc[0]; this.userCol = newLoc[0]; this.bc[newLoc[1]][newLoc[0]] = true; return true; } } /** * Prints the map of the maze. */ public void printMaze() { System.out.print("*"); for (int i = 0; i < this.blocked[0].length; i++) { System.out.print("-"); } System.out.print("*"); System.out.println(); for (int i = 0; i < this.blocked.length; i++) { System.out.print("|"); for (int j = 0; j < this.blocked[i].length; j++) { if (this.blocked[i][j]) { System.out.print("X"); } else if (this.userRow == i && this.userCol == j) { System.out.print("@"); } else if (this.start[0] == i && this.start[1] == j) { System.out.print("S"); } else if (this.goalRow == i && this.goalCol == j) { System.out.print("G"); } else if (this.bc[i][j]) { System.out.print("."); } else { System.out.print(" "); } } System.out.print("|\n"); } System.out.print("*"); for (int i = 0; i < this.blocked[0].length; i++) { System.out.print("-"); } System.out.print("*\n"); } /** * Creates a new game, using a command line argument file name, if one is * provided. * * @param args the command line arguments */ public static void main(String[] args) { String mapFile = "data/easy.txt"; Scanner scan = new Scanner(System.in); MazeGame game = new MazeGame(mapFile, scan); game.printMaze(); game.playGame(); } /** * returns the userCol field * * @return userCol */ public int getUserCol() { return this.userCol; } /** * returns the userRow field * * @return userRow */ public int getUserRow() { return this.userRow; } /** * returns the blocked field * * @return blocked */ public boolean[][] getBlocked() { return this.blocked; } /** * returns the moveScanner field * * @return moveScanner */ public Scanner getMoveScanner() { return this.moveScanner; } /** * set the userCol field * * @param col new userCol field */ public void setUserCol(int col) { this.userCol = col; } /** * set the userRow field * * @param row new userRow field */ public void setUserRow(int row) { this.userRow = row; } /** * set the blocked field * * @param blocked new blocked field */ public void setBlocked(boolean[][] blocked) { this.blocked = blocked; } /** * set the moveScanner field * * @param scn new moveScanner field */ public void setMoveScanner(Scanner scn) { this.moveScanner = scn; } }