cs2440-lab2/src/solution/MazeGame.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;
}
}