381 lines
8.9 KiB
Java
381 lines
8.9 KiB
Java
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;
|
|
}
|
|
}
|