📄 newmap.java
字号:
package src;
import java.util.Random;
import java.util.LinkedList;
public class NewMap {
/*
* 以下数据不带int参数的的构造函数
*/
private int forChange = -3;// 调整页面布局
public void setforChange(int forChange) {
this.forChange = forChange;
}
public int getforChange() {
return forChange;
}
/*
* 构造函数(不带int参数),用生成一张地图
*/
public NewMap(Canvas canvas) {
/*
* 重新生成
*/
for (int i = 0; i < canvas.getRows(); i++)
for (int j = 0; j < canvas.getCols(); j++) {
canvas.getBox(i, j).setState(Enums.colors.BACK);
}
/*
* 以下边框,终点end,开始点nowBox
*/
for (int i = 0; i < canvas.getRows(); i++) {
canvas.getBox(i, 0).setState(Enums.colors.STOCK);
canvas.getBox(i, canvas.getCols() - 1).setState(Enums.colors.STOCK);
}
for (int i = 0; i < canvas.getCols(); i++) {
canvas.getBox(0, i).setState(Enums.colors.STOCK);
canvas.getBox(canvas.getRows() - 1, i).setState(Enums.colors.STOCK);
}
canvas.getBox(canvas.getRows() - 2, canvas.getCols() - 1).setState(
Enums.colors.END);
MazeGame.setnowBox(canvas.getBox(1, 1));
/*
* 以下初步构造地图内部
*/
int xRan, yRan;// 用于存放随机生成的坐标
Random rand = new Random();// 随机数种子
for (int i = 0; i < ((canvas.getRows() * canvas.getCols()) / 2 - forChange
* canvas// 此处可调节以改变布局
.getCols()); i++) {
MazeBox box = new MazeBox(Enums.colors.BACK);
xRan = rand.nextInt(canvas.getRows() - 2) + 1;
yRan = rand.nextInt(canvas.getCols() - 2) + 1;
box = canvas.getBox(xRan, yRan);
if (Judges.isCrossable(box)) { // 当前位置未设为墙
box.setState(Enums.colors.STOCK);
} else
// 当前位置为墙
i--;
}
canvas.getBox(canvas.getRows() - 2, canvas.getCols() - 2).setState(
Enums.colors.BACK);// 此点必通
MoreBetter.moreBetter(canvas);
for (int i = 1; i < canvas.getRows(); i++)
for (int j = 1; j < canvas.getCols(); j++) {
if (canvas.getBox(i, j).getState() != Enums.colors.STOCK) {
canvas.getBox(i, j).setsysState(Enums.colors.WAY); // 如果不为砖块,标记为空
}
}
}
/*
* 以下使用图遍历法生成地图的构造函数 NewMap(Canvas canvas, int markforthis)
* markforthis的作用仅仅是标记,别无它用
*/
public NewMap(Canvas canvas, int markforthis) {
int[][] pointArray = new int[canvas.getRows()][canvas.getCols()];// 用于存放图的节点
/*
* 以下将canvas里所有的块都初始化为墙
*/
for (int i = 0; i < canvas.getRows(); i++)
for (int j = 0; j < canvas.getCols(); j++)
canvas.getBox(i, j).setState(Enums.colors.STOCK);
/*
* 以下将pointArray里所有的点都初始化为未被访问
*/
for (int i = 0; i < pointArray.length; i++)
for (int j = 0; j < pointArray[i].length; j++)
pointArray[i][j] = 0; // 0代表该点未被访问,1代表该点已被访问
/*
* 以下初始化必可达点,即行和列都为奇数的点
*/
for (int i = 0; i < canvas.getRows(); i++)
for (int j = 0; j < canvas.getCols(); j++)
if (i % 2 != 0 && j % 2 != 0) {// 行和列都为奇数的点
canvas.getBox(i, j).setState(Enums.colors.BACK);
}
/*
* 以下递归尝试优先遍历地图 用户选择了地图生成方式 1为从第一点开始,2为从东北方向开始,3为从最后一点开始
*/
switch (markforthis) {
case 2:
Dfs.dfs(canvas, pointArray, new MyPoint(canvas.getRows() - 2,
canvas.getCols() - 2));// 从最后一行开始生成的迷宫难度为中
break;
case 3:
Dfs.dfs(canvas, pointArray, new MyPoint(1, canvas.getCols() - 2));// 东北方向难度最大
break;
case 1:
Dfs.dfs(canvas, pointArray, new MyPoint(1, 1));// 第一点开始难度最小
break;
}
/*
* 以下边框,终点end,开始点nowBox
*/
for (int i = 0; i < canvas.getRows(); i++) {
canvas.getBox(i, 0).setState(Enums.colors.STOCK);
canvas.getBox(i, canvas.getCols() - 1).setState(Enums.colors.STOCK);
}
for (int i = 0; i < canvas.getCols(); i++) {
canvas.getBox(0, i).setState(Enums.colors.STOCK);
canvas.getBox(canvas.getRows() - 1, i).setState(Enums.colors.STOCK);
}
canvas.getBox(canvas.getRows() - 2, canvas.getCols() - 2).setState(
Enums.colors.BACK);
canvas.getBox(canvas.getRows() - 2, canvas.getCols() - 1).setState(
Enums.colors.END);
MazeGame.setnowBox(canvas.getBox(1, 1));
}
}
/*
* 以下类提供不带标记参数的构造方法所需要的函数
*/
class MoreBetter {
protected static void moreBetter(Canvas canvas) {
int row = canvas.getRows(), col = canvas.getCols() / 10;// 要求是偶数
Random rand = new Random();// 随机数种子,产生两组随机必可达点
XandY[][] xandy = new XandY[2][col];
for (int i = 0; i < xandy[0].length; i++) {
int xtem = rand.nextInt(row / 4 - 1) + 1, ytem = rand.nextInt(9)
+ (10 * i) + 1;
if (xtem >= (row - 2) || ytem >= (10 * col - 2)) {
i--; // 越界
continue;
}
xandy[0][i] = new XandY(xtem, ytem);// 在当前块当中产生一个随机坐标
}
for (int i = 0; i < xandy[1].length; i++) {
int xtem = rand.nextInt(row / 4 - 1) + (row / 4) + 1, ytem = rand
.nextInt(9)
+ (10 * i) + 1;
if (xtem >= (row - 2) || ytem >= (10 * col - 2)) {
i--; // 越界
continue;
}
xandy[1][i] = new XandY(xtem, ytem);// 在当前块当中产生一个随机坐标
}
for (int i = 0; i < xandy.length; i++)
for (int j = 0; j < xandy[i].length; j++) {// 将必可达点设定为可通,并将系统标记为way
canvas.getBox(xandy[i][j].getX(), xandy[i][j].getY()).setState(
Enums.colors.BACK);
canvas.getBox(xandy[i][j].getX(), xandy[i][j].getY())
.setsysState(Enums.colors.WAY);
}
XandY[][] xandyan = new XandY[2][col];
for (int i = 0; i < xandyan[0].length; i++) {
int xtem = rand.nextInt(row / 4 - 1) + 2 * (row / 4) + 1, ytem = rand
.nextInt(9)
+ (10 * i) + 1;
if (xtem >= (row - 2) || ytem >= (10 * col - 2)) {
i--; // 越界
continue;
}
xandyan[0][i] = new XandY(xtem, ytem);// 在当前块当中产生一个随机坐标
}
for (int i = 0; i < xandyan[1].length; i++) {
int xtem = rand.nextInt(row / 4 - 1) + 3 * (row / 4) + 1, ytem = rand
.nextInt(9)
+ (10 * i) + 1;
if (xtem >= (row - 2) || ytem >= (10 * col - 2)) {
i--; // 越界
continue;
}
xandyan[1][i] = new XandY(xtem, ytem);// 在当前块当中产生一个随机坐标
}
for (int i = 0; i < xandyan.length; i++)
for (int j = 0; j < xandyan[i].length; j++) {// 将必可达点设定为可通,并将系统标记为way
canvas.getBox(xandyan[i][j].getX(), xandyan[i][j].getY())
.setState(Enums.colors.BACK);
canvas.getBox(xandyan[i][j].getX(), xandyan[i][j].getY())
.setsysState(Enums.colors.WAY);
}
/*
* 下面按遍历顺序将各点接通
*/
/*
* 连接始点和随机产生的第一点
*/
Connect(canvas.getBox(1, 1), canvas.getBox(xandy[0][0].getX(),
xandy[0][0].getY()), canvas);
ConnectG(xandy, canvas);
ConnectG(xandyan, canvas);
/*
* 连接终点和随机产生的最后一点
*/
Connect(canvas.getBox(xandyan[1][xandyan[1].length - 1].getX(),
xandyan[1][xandyan[1].length - 1].getY()), canvas.getBox(canvas
.getRows() - 2, canvas.getCols() - 2), canvas);
/*
* 以下连接上下两组
*/
int temsOfUpandDown = rand.nextInt(xandy[1].length);
Connect(canvas.getBox(xandy[1][temsOfUpandDown].getX(),
xandy[1][temsOfUpandDown].getY()), canvas.getBox(
xandyan[0][temsOfUpandDown].getX(), xandyan[0][temsOfUpandDown]
.getY()), canvas);
}
private static void ConnectG(XandY[][] xandy, Canvas canvas) {
/*
* 以下组横排相连
*/
for (int i = 0; i < xandy[0].length - 1; i++) {
Random rand = new Random();// 随机数种子
if (rand.nextInt(2) == 0) {
Connect(canvas.getBox(xandy[0][i].getX(), xandy[0][i].getY()),
canvas.getBox(xandy[0][i + 1].getX(), xandy[0][i + 1]
.getY()), canvas);
} else {
Connect(canvas.getBox(xandy[1][i].getX(), xandy[1][i].getY()),
canvas.getBox(xandy[1][i + 1].getX(), xandy[1][i + 1]
.getY()), canvas);
}
}
/*
* 连接每一排上下
*/
for (int i = 0; i < xandy[0].length; i++) {
Connect(canvas.getBox(xandy[0][i].getX(), xandy[0][i].getY()),
canvas.getBox(xandy[1][i].getX(), xandy[1][i].getY()),
canvas);
}
}
private static void Connect(MazeBox boxA, MazeBox boxB, Canvas canvas) {
Random rand = new Random();// 随机数种子
int xTem = boxB.getboxX() - boxA.getboxX();
int yTem = boxB.getboxY() - boxA.getboxY();
if (!Judges.isConnected(boxA, boxB, canvas, 1)) {// 两点间不通则强行打通
while ((xTem * xTem + yTem * yTem) != 0) {
if (rand.nextInt(2) == 0) {// 随机数为0,对xTem操作
if (xTem < 0)
xTem++;
else if (xTem > 0)
xTem--;
} else {// 随机数为1,对yTem操作
if (yTem < 0)
yTem++;
else if (yTem > 0)
yTem--;
}
canvas.getBox(boxA.getboxX() + xTem, boxA.getboxY() + yTem)
.setState(Enums.colors.BACK);
}
}
}
}
/*
* 以下类提供带 mark参数的构造函数所需要的函数
*/
class Dfs {
static LinkedList<MyPoint> pointStack = new LinkedList<MyPoint>();
static int xTem, yTem;
static MyPoint topreventDeleteTooMuch = new MyPoint();// 防止退栈时退晕了头而产生连接两个不相邻点的假象而设定的全局变量
/*
* 深度优先遍历函数
*/
public static void dfs(Canvas canvas, int[][] pointArray, MyPoint now) {// 一般来说,第一次引用此函数时now应该为(1,1)入口
xTem = now.getX();
yTem = now.getY();
pointArray[xTem][yTem] = 1;// 标记此点已经被访问
pointStack.addLast(new MyPoint(xTem, yTem)); // 将此点入栈
now = findNextPoint(canvas, pointArray, now); // 获得下一个点
if (!(now.getX() == 0 && now.getY() == 0)) {// 此处一定要进行判断是否能真正找到下一点即判断是否返回了一个(0,0)的假坐标
if (!(((xTem - now.getX()) * (xTem - now.getX()) + (yTem - now
.getY())
* (yTem - now.getY())) == 4)) {// 如果两点间的坐标差的平方不等于4则说明发生了退栈事件
/*
* 为了防止调用findNextPoint函数时有退栈现象而 出现连接两个并不相邻的点的事情,这几句是十分必要的
* 此处说明发生了退栈事件
*/
xTem = topreventDeleteTooMuch.getX();
yTem = topreventDeleteTooMuch.getY();
}
canvas.getBox((xTem + now.getX()) / 2, (yTem + now.getY()) / 2)
.setState(Enums.colors.BACK);// 将此点标记为可通过
/* System.out.println("接通(" + (xTem + 1) + "," + (yTem + 1) + ")和("
+ (now.getX() + 1) + "," + (now.getY() + 1) + ")");
//实现显示地图生成的过程
*/
dfs(canvas, pointArray, now);// 深度优先递归运算
} else
// 如果没有找到下一点则退出
return;
}
/*
* 寻找下一点函数
*/
private static MyPoint findNextPoint(Canvas canvas, int[][] pointArray,
MyPoint point) {
Random rand = new Random();// 随机数种子
MyPoint pointtemp = new MyPoint();
int mark = 0;// 标记,如果等于0则表示找数成功
while (!pointStack.isEmpty() && mark == 0) {
/*
* 下面判断当前点是不是前后左右都不可行,只要有一个可行就运行switch语句里里面的内容 否则退栈并开始新一轮的循环
*/
if (((point.getX() - 2) > 0 && pointArray[point.getX() - 2][point
.getY()] == 0)
|| ((point.getX() + 2) < (canvas.getRows()) && pointArray[point
.getX() + 2][point.getY()] == 0)
|| ((point.getY() - 2) > 0 && pointArray[point.getX()][point
.getY() - 2] == 0)
|| ((point.getY() + 2) < (canvas.getCols()) && pointArray[point
.getX()][point.getY() + 2] == 0)) {// 上下左右至少有一个可行
switch (rand.nextInt(4)) {// 随机决定应该是向上下左右探测,以便生成不同的地图
case 0: // 得到0向上探测
if ((point.getX() - 2) > 0
&& pointArray[point.getX() - 2][point.getY()] == 0) {// 向上探测成功
pointtemp = new MyPoint(point.getX() - 2, point.getY());
mark = 1;// 找到,标记以便退出循环
break;
}
case 1: // 得到1向下探测
if ((point.getX() + 2) < (canvas.getRows())
&& pointArray[point.getX() + 2][point.getY()] == 0) {// 向下探测成功
pointtemp = new MyPoint(point.getX() + 2, point.getY());
mark = 1;// 找到,标记以便退出循环
break;
}
case 2:// 得到2向左探测
if ((point.getY() - 2) > 0
&& pointArray[point.getX()][point.getY() - 2] == 0) {// 向左探测成功
pointtemp = new MyPoint(point.getX(), point.getY() - 2);
mark = 1;// 找到,标记以便退出循环
break;
}
case 3: // 得到3向右探测
if ((point.getY() + 2) < (canvas.getCols())
&& pointArray[point.getX()][point.getY() + 2] == 0) {// 向右探测成功
pointtemp = new MyPoint(point.getX(), point.getY() + 2);
mark = 1;// 找到,标记以便退出循环
break;
}
}
} else {// 该点上下左右均无未被访问过的点,退栈
point = pointStack.pollLast();// 获取并删除最后一个元素
topreventDeleteTooMuch = point;
}
}
return pointtemp;
/*
* 对此返回值的解释:因为while循环有可能在栈为空的情况下跳出,从而返回的点为(0,0),
* 帮引用此返回值之前一定要先判断此点是否为(0,0),如果是,则说明遍历已经结束 因为正常 的点从上下左右因条件控制都得不到(0,0)这个点
*/
}
}
class MyPoint {
private int x, y;
public MyPoint() {
this(0, 0);
}
public MyPoint(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public int getY() {
return y;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -