我正在尝试打印一个迷宫,并且还打印正方形的星星,这是迷宫解决方案的一部分(使用堆栈“ LLStack”)。我有两个文件: Maze.java-负责从给定文件中加载迷宫数据,打印出迷宫,并打印出其解决方案。包含一个私有内部类MazeSquare,该类将txt数据文件中的每个字符都移到嵌套的迷宫行的ArrayList中。 LLStack.java-这是我用来执行堆栈算法并为整个LLStack解决方案添加潜在平方的堆栈类。包含Stack ADT中描述的方法,并在Maze.java中使用这些方法。
由于某种原因,我的代码可以正确打印迷宫,但不会打印出解决方案(星星)。我认为问题在于该程序认为迷宫的第一个正方形有右墙,而该文本不在我的txt数据文件中。这是我在Maze.Java中的代码:
import java.io.*;
import java.util.*;
/**
* Maze.java
*/
public class Maze {
private ArrayList<ArrayList<MazeSquare>> rowList;
private int w, h;
private int startRow, startCol, endRow, endCol;
// MazeSquare is implemented as an inner class
// to simplify the file structure a little bit.
private class MazeSquare {
private int r, c;
private boolean top, bottom, left, right,
start, end, visited;
private MazeSquare(int r, int c,
boolean top, boolean bottom, boolean left, boolean right,
boolean start, boolean end) {
this.r = r;
this.c = c;
this.top = top;
this.bottom = bottom;
this.left = left;
this.right = right;
this.start = start;
this.end = end;
this.visited = false;
}
boolean hasTopWall() {
return top;
}
boolean hasBottomWall() {
return bottom;
}
boolean hasLeftWall() {
return left;
}
boolean hasRightWall() {
return right;
}
boolean isStart() {
return start;
}
boolean isEnd() {
return end;
}
int getRow() {
return r;
}
int getCol() {
return c;
}
boolean visit() { // changes visit instance variable to true.
return this.visited = true;
}
boolean isVisited() { // checks to see if MazeSquare has been visited.
if (this.visited == true) {
return true;
}
return false;
}
}
/**
* Construct a new Maze
*/
public Maze() {
rowList = new ArrayList<ArrayList<MazeSquare>>();
}
/**
* Load Maze in from given file
*
* @param fileName the name of the file containing the Maze structure
*/
public void load(String fileName) {
// Create a scanner for the given file
Scanner scanner = null;
try {
scanner = new Scanner(new File(fileName));
} catch (FileNotFoundException e) {
System.err.println(e);
System.exit(1);
}
// First line of file is "w h"
String[] lineParams = scanner.nextLine().split(" ");
w = Integer.parseInt(lineParams[0]);
h = Integer.parseInt(lineParams[1]);
// Second line of file is "startCol startRow"
lineParams = scanner.nextLine().split(" ");
startCol = Integer.parseInt(lineParams[0]);
startRow = Integer.parseInt(lineParams[1]);
// Third line of file is "endCol endRow"
lineParams = scanner.nextLine().split(" ");
endCol = Integer.parseInt(lineParams[0]);
endRow = Integer.parseInt(lineParams[1]);
// Read the rest of the lines (L or | or _ or -)
String line;
int rowNum = 0;
boolean top, bottom, left, right;
boolean start, end;
while (scanner.hasNextLine()) {
line = scanner.nextLine();
rowList.add(new ArrayList<MazeSquare>());
// Loop through each cell, creating MazeSquares
for (int i = 0; i < line.length(); i++) {
// For top, check row above, if there is one
if (rowNum > 0) {
top = rowList.get(rowNum-1).get(i).hasBottomWall();
} else {
top = true;
}
// For right, check cell to the right, if there is one
if (i < line.length() - 1 ) {
char nextCell = line.charAt(i+1);
if (nextCell == 'L' || nextCell == '|') {
right = true;
} else {
right = false;
}
} else {
right = true;
}
// For left and bottom, switch on the current character
switch (line.charAt(i)) {
case 'L':
left = true;
bottom = true;
break;
case '_':
left = false;
bottom = true;
break;
case '|':
left = true;
bottom = false;
break;
case '-':
left = false;
bottom = false;
break;
default:
left = false;
bottom = false;
}
// Check to see if this is the start or end spot
start = startCol == i && startRow == rowNum;
end = endCol == i && endRow == rowNum;
// Add a new MazeSquare
rowList.get(rowNum).add(new MazeSquare(rowNum, i, top, bottom, left, right, start, end));
}
rowNum++;
}
}
/**
* Print the Maze to the Console
*/
public void print() {
ArrayList<MazeSquare> currRow;
MazeSquare currSquare;
LLStack<MazeSquare> solution = getSolution();
// Print each row of text based on top and left
for (int r = 0; r < rowList.size(); r++) {
currRow = rowList.get(r);
// First line of text: top wall
for (int c = 0; c < currRow.size(); c++) {
System.out.print("+");
if (currRow.get(c).hasTopWall()) {
System.out.print("-----");
} else {
System.out.print(" ");
}
}
System.out.println("+");
// Second line of text: left wall then space
for (int c = 0; c < currRow.size(); c++) {
if (currRow.get(c).hasLeftWall()) {
System.out.print("|");
} else {
System.out.print(" ");
}
System.out.print(" ");
}
System.out.println("|");
// Third line of text: left wall, then space, the nstart/end/sol, then space
for (int c = 0; c < currRow.size(); c++) {
currSquare = currRow.get(c);
if (currSquare.hasLeftWall()) {
System.out.print("|");
} else {
System.out.print(" ");
}
System.out.print(" ");
if (currSquare.isStart() && currSquare.isEnd()) {
System.out.print("SF ");
} else if (currSquare.isStart() && !currSquare.isEnd()) {
System.out.print("S ");
} else if (!currSquare.isStart() && currSquare.isEnd()) {
System.out.print("F ");
} else if (solution.contains(currSquare) == true) {
System.out.print("* ");
} else {
System.out.print(" ");
}
}
System.out.println("|");
// Fourth line of text: same as second
for (int c = 0; c < currRow.size(); c++) {
if (currRow.get(c).hasLeftWall()) {
System.out.print("|");
} else {
System.out.print(" ");
}
System.out.print(" ");
}
System.out.println("|");
}
// Print last row of text as straight wall
for (int c = 0; c < rowList.get(0).size(); c++) {
System.out.print("+-----");
}
System.out.println("+");
}
public LLStack<MazeSquare> getSolution() {
ArrayList<MazeSquare> currRow;
MazeSquare currSquare = null;
int rowIndex = -1;
int columnIndex = -1;
LLStack<MazeSquare> solutionStack = new LLStack<MazeSquare>();
MazeSquare startSquare;
for (int r = 0; r < rowList.size(); r++) {
currRow = rowList.get(r);
for (int c = 0; c < currRow.size(); c++) {
currSquare = currRow.get(c);
boolean startCondition = currSquare.isStart();
if (startCondition == true) {
rowIndex = r;
columnIndex = c;
solutionStack.push(currSquare);
startSquare = currSquare;
currSquare.visit();
}
}
}
MazeSquare T = solutionStack.peek();
while (solutionStack.size() > 0 && T.isEnd() != true) {
currRow = rowList.get(rowIndex);
if (currSquare.hasTopWall() == false && rowIndex != 0) {
MazeSquare neighborTop = getNeighbor(T, "top");
if (neighborTop.isVisited() == false) {
neighborTop.visit();
solutionStack.push(neighborTop);
rowIndex--;
}
} else if (currSquare.hasBottomWall() == false && rowIndex != rowList.size()) {
MazeSquare neighborBottom = getNeighbor(T, "bottom");
if (neighborBottom.isVisited() == false) {
neighborBottom.visit();
solutionStack.push(neighborBottom);
rowIndex++;
}
} else if (currSquare.hasRightWall() == false && columnIndex != currRow.size()) {
System.out.println("no right wall");
MazeSquare neighborRight = getNeighbor(T, "right");
if (neighborRight.isVisited() == false) {
neighborRight.visit();
solutionStack.push(neighborRight);
columnIndex++;
}
} else if (currSquare.hasLeftWall() == false && columnIndex != 0) {
MazeSquare neighborLeft = getNeighbor(T, "left");
if (neighborLeft.isVisited() == false) {
neighborLeft.visit();
solutionStack.push(neighborLeft);
columnIndex--;
}
}
solutionStack.pop();
}
return solutionStack;
}
public MazeSquare getNeighbor(MazeSquare s, String direction) {
// takes in a given MazeSquare and direction and returns a reference
// to the MazeSquare in that direction in the maze.
MazeSquare newSquare = null;
for (int r = 0; r < rowList.size(); r++) {
ArrayList<MazeSquare> currentRow = rowList.get(r);
int indexOfS = currentRow.indexOf(s);
if (indexOfS == -1) {
r++;
} else {
System.out.println(r);
if (direction == "right") {
newSquare = currentRow.get(indexOfS + 1);
break;
}
else
if (direction == "left") {
newSquare = currentRow.get(indexOfS - 1);
break;
}
else
if (direction == "top") {
System.out.println(r);
ArrayList<MazeSquare> previousRow = rowList.get(r-1);
if (previousRow == null) {
break;
} else {
newSquare = previousRow.get(indexOfS);
break;
}
}
else
if (direction == "bottom") {
ArrayList<MazeSquare> nextRow = rowList.get(r+1);
newSquare = nextRow.get(indexOfS);
break;
}
}
}
return newSquare;
}
// This main program acts as a simple unit test for the
// load-from-file and print-to-System.out Maze capabilities.
public static void main(String[] args) {
if (args.length != 1) {
System.err.println("Usage: java Maze mazeFile");
System.exit(1);
}
Maze maze = new Maze();
maze.load(args[0]);
maze.print();
}
}
这是LLStack.java,我在其中实现堆栈方法以找到给定迷宫的解决方案:
import java.util.*;
/**
* LLStack.java
* A simple linked-list implementation of a Stack.
*/
public class LLStack<E> {
private Node<E> top;
private int numItems;
/**
* Private Node class for internal linked list
*/
private static class Node<E> {
private E data;
private Node<E> next;
private Node(E item) {
data = item;
next = null;
}
private Node(E item, Node nextNode) {
data = item;
next = nextNode;
}
}
/**
* Construct an empty LLStack
*/
public LLStack() {
top = null;
numItems = 0;
}
/**
* Push an item to the top of the LLStack
*
* @param item the item to be pushed
*/
public void push(E item) {
if (numItems == 0) {
top = new Node(item);
} else {
top = new Node(item, top);
}
numItems++;
}
/**
* Return the item at the top of the LLStack
*
* @return the top item
* @throws EmptyStackException if the stack is empty
*/
public E peek() {
if (numItems == 0) {
throw new EmptyStackException();
}
return top.data;
}
/**
* Return and remove the item at the top of the LLStack
*
* @return the top item (or null if there isn't one)
* @throws EmptyStackException if the stack is empty
*/
public E pop() {
if (numItems == 0) {
throw new EmptyStackException();
}
E temp = top.data;
top = top.next;
numItems--;
return temp;
}
/**
* Return the number of items in the LLStack
*
* @return the number of items contained in the LLStack
*/
public int size() {
return numItems;
}
/**
* Return whether or not the LLStack is empty
*
* @return true if LLStack is empty, false otherwise
*/
public boolean isEmpty() {
return numItems == 0;
}
/**
* Get a String representation of LLStack
* with the top at the left-most spot
*
* @return String representation of LLStack
*/
public String toString() {
StringJoiner sj = new StringJoiner(", ", "[ ", " ]");
Node<E> currNode = top;
for (int i = 0; i < numItems; i++) {
sj.add(currNode.data.toString());
currNode = currNode.next;
}
return sj.toString();
}
/**
* Check to see whether a given item is contained in the LLStack
*
* @param item the item to look for in the LLStack
* @return true if item is in the LLStack, false otherwise
*/
public boolean contains(E item) {
// Traverse list, looking for item
Node temp = top;
while (temp != null) {
if (temp.data.equals(item)) {
return true;
}
temp = temp.next;
}
// If we get here without returning, we didn't find it
return false;
}
// Tester code: Remember, this main method won't run
// unless LLStack is run with the command java LLStack
public static void main(String[] args) {
LLStack<String> fab = new LLStack<String>();
fab.push("John");
System.out.println(fab);
fab.push("Ringo");
fab.push("George");
fab.push("Paul");
System.out.println(fab);
System.out.format("Peek: %s\n", fab.peek());
System.out.format("Pop: %s\n", fab.pop());
System.out.println(fab);
if (fab.contains("Paul")) {
System.out.println("Found Paul!");
}
if (fab.contains("John")) {
System.out.println("Found John!");
}
}
}
这是我的数据文件的样子:
6 5
0 0
0 4
L-_|_-
|L--|_
|-_-|_
|L|L||
L__L__
L应该是具有左壁和底壁的MazeSquare,-应该是没有左和底壁的MazeSquare,_应该是具有底壁而不是左壁的MazeSquare ,和|应该是具有左墙而不是底墙的MazeSquare。这就是在Maze.java的load方法中如何处理信息。数据的第一行是列数,行数。数据的第二行是起始正方形的从0开始的坐标(在此打印“ S”,也首先将其压入堆栈,以及问题所在)。数据的第三行是完成正方形的从0开始的坐标。 迷宫应该在控制台中输出如下内容:
+-----+-----+-----+-----+-----+-----+
| | |
| S * | |
| | |
+-----+ +-----+ +-----+ +
| | | |
| | * * * | |
| | | |
+ +-----+ + + +-----+
| | |
| * * * * | |
| | |
+ + +-----+ + +-----+
| | | | | | |
| * | | | | | |
| | | | | | |
+ +-----+ +-----+ + +
| | |
| F | |
| | |
+-----+-----+-----+-----+-----+-----+
...除了我的也没有印刷任何星星(我想是因为这个第一平方有右墙的问题)。我为此花了几个小时,无济于事。任何帮助表示赞赏。