迷宫小游戏

文章目录

  • 迷宫小游戏
  • 一、项目概述
  • 二、项目初步设计
    • 1.项目总体框架
    • 2.类关系图
    • 3.程序流程图
  • 三、实验准备
    • 1.迷宫生成算法了解
    • 2.了解A*寻路算法
    • 3.学习二叉树的三种深度优先遍历
    • 4.学习使用Swing组件
    • 5.类划分
  • 四、具体代码(代码后有功能解释)
  • 五、程序运行结果分析

一、项目概述

(1)项目目标和主要内容
<1>迷宫游戏是非常经典的游戏,在该题中要求随机生成一个迷宫,并求解迷宫;
<2>要求查找并理解迷宫生成的算法,并尝试用两种不同的算法来生成随机的迷宫。
<3>要求游戏支持玩家走迷宫,和系统走迷宫路径两种模式。玩家走迷宫,通过键盘 方向键控制,并在行走路径上留下痕迹;系统走迷宫路径要求基于 A*算法实现,输出走迷宫的最优路径并显示。设计交互友好的游戏图形界面。
(2)项目的主要功能
<1>迷宫游戏可以锻炼我们对数据结构中图的更好的理解
<2>迷宫游戏可以通过键盘控制方向,输出走的方向。

二、项目初步设计

1.项目总体框架

2.类关系图

3.程序流程图

三、实验准备

1.迷宫生成算法了解

Depth First Search Algorithm(深度优先搜索算法)
将起点作为当前迷宫单元并标记为已访问
当还存在未标记的迷宫单元,进行循环
如果当前迷宫单元有未被访问过的的相邻的迷宫单元
随机选择一个未访问的相邻迷宫单元
将当前迷宫单元入栈
移除当前迷宫单元与相邻迷宫单元的墙
标记相邻迷宫单元并用它作为当前迷宫单元
如果当前迷宫单元不存在未访问的相邻迷宫单元,并且栈不空
栈顶的迷宫单元出栈
令其成为当前迷宫单元
Depth First Search Algorithm生成的迷宫极度扭曲,有着一条明显的主路。
Randomized Prim’s Algorithm(随机普利姆算法)
让迷宫全是墙.
随机选一个单元格作为迷宫的通路,然后把它的邻墙放入列表
当列表里还有墙时
从列表里随机选一个墙,如果这面墙分隔的两个单元格只有一个单元格被访问过
那就从列表里移除这面墙,即把墙打通,让未访问的单元格成为迷宫的通路
把这个格子的墙加入列表
如果墙两面的单元格都已经被访问过,那就从列表里移除这面墙
相对于深度优先的算法,Randomized Prim’s Algorithm不是优先选择最近选中的单元格,而是随机的从所有的列表中的单元格进行选择,新加入的单元格和旧加入的单元格同样概率会被选择,新加入的单元格没有优先权。因此其分支更多,生成的迷宫更复杂,岔路更多,难度更大,也更自然。
Recursive Division Algorithm(递归分割算法)
让迷宫全是迷宫单元
随机选择一偶数行和一偶数列让其全部变为墙,通过这两堵墙将整个迷宫分为四个子迷宫
在3面墙上各挖一个洞(为了确保连通)
如果子迷宫仍可分割成四个子迷宫,返回继续分割子迷宫
Recursive Division Algorithm十分高效,生成的迷宫较为简单,有点像四叉树,直路多且不扭曲。

本实验我采用了深度优先搜索算法生成迷宫,所以生成的迷宫看似复杂,其实走最靠边的一条路肯定是正确的。。。

2.了解A*寻路算法

找了两篇文章,链接1 链接2
算法有点复杂,我优先考虑使用二叉树的深度优先遍历的逆推方法。

3.学习二叉树的三种深度优先遍历

我找了两篇文章,虽然文章1是爬虫的教程,但算法讲的很清楚,文章2是java的教程。
文章1 文章2
还有实现队列的讲解:java实现队列
看完之后,总结一下,这个算法一共有四个步骤。
首先实现一颗二叉树,要对二叉树进行遍历,需要先创建一棵二叉树,然后进行先序遍历,中序遍历,后序遍历。详细代码在下一部分。

4.学习使用Swing组件

JFrame组件、JPanel组件、JOptionPane组件是我们这个实验需要使用的。详细教程链接在下
JFrame组件
Jpanel组件
JOptionPane组件

5.类划分

我把该项目的实现分为以下八类

分别控制迷宫小球的创建,迷宫的大小控制及建造,按钮功能模块按钮功能模块,生成迷宫算法,键位控制,迷宫主界面模块迷宫主界面模块,时间和步数的检测,找到出口算法,屏幕刷新率控制。

四、具体代码(代码后有功能解释)

Ball类:

package maze;import java.awt.Color;class Ball {private int x;//横坐标private int y;//纵坐标private Color color;//小球颜色public Ball(int x,int y) {setX(x);setY(y);setColor(Color.GREEN);}public int getX() {return x;}public void setX(int x) {this.x = x;}public int getY() {return y;}public int setY(int y) {this.y = y;return y;}public Color getColor() {return color;}public void setColor(Color color) {this.color = color;}}

Creatmaze类:

package maze;import java.awt.Point;
import java.util.LinkedList;
import java.util.List;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;abstract class AbstractCreateMaze {// 验证横纵坐标是否超界protected boolean isOutofBorder(int x, int y, int colNumber, int rowNumber) {if ((x == 0 && y == 1) || (x == colNumber + 1 && y == rowNumber))return false;elsereturn (x > colNumber || y > rowNumber || x < 1 || y < 1) ? true : false;}abstract void createMaze(Lattice[][] mazeLattice, int colNumber, int rowNumber);
}class DepthFirstSearchCreateMaze extends AbstractCreateMaze {// 随机选择一个p点未访问的相邻迷宫单元 ,并移除两者之间的墙,为createMaze()函数调用protected Point ArroundPoint(Lattice[][] mazeLattice, Point p, Stack<Point> s, Random rand, int colNumber,int rowNumber) {final int[] arroundPoint = { -2, 0, 2, 0, -2 };// 一个点周围四个点的坐标变化,顺序为左上右下int r = rand.nextInt(4);for (int i = 0; i < 4; ++i) {int j = r % 4;int x = p.x + arroundPoint[j];int y = p.y + arroundPoint[j + 1];++r;if (!isOutofBorder(x, y, colNumber, rowNumber) && !mazeLattice[y][x].isPassable()) {mazeLattice[y][x].setPassable(true);mazeLattice[p.y + arroundPoint[j + 1] / 2][p.x + arroundPoint[j] / 2].setPassable(true);return new Point(x, y);}}return null;}@Overridepublic void createMaze(Lattice[][] mazeLattice, int colNumber, int rowNumber) {// TODO Auto-generated method stubRandom rand = new Random();Point currentPoint = new Point(2 * rand.nextInt(colNumber / 2) + 1, 2 * rand.nextInt(rowNumber / 2) + 1);mazeLattice[currentPoint.y][currentPoint.x].setPassable(true);Stack<Point> pathStack = new Stack<Point>();pathStack.push(currentPoint);currentPoint = ArroundPoint(mazeLattice, currentPoint, pathStack, rand, colNumber, rowNumber);while (true) {Point p = ArroundPoint(mazeLattice, currentPoint, pathStack, rand, colNumber, rowNumber);if (p != null) {pathStack.push(currentPoint);currentPoint = p;} else if (!pathStack.isEmpty())currentPoint = pathStack.pop();elsebreak;}}
}class RandomizedPrimCreateMaze extends AbstractCreateMaze {// 将点p的邻墙放入列表中protected void pushArroundWallToList(Lattice[][] mazeLattice, Point p, List<Point> list, int colNumber,int rowNumber) {final int[] arroundWall = { -1, 0, 1, 0, -1 };// 一个点周围四个墙的坐标变化,顺序为左上右下for (int i = 0; i < 4;) {int x = p.x + arroundWall[i];int y = p.y + arroundWall[++i];if (!isOutofBorder(x, y, colNumber, rowNumber) && !mazeLattice[y][x].isPassable()) {list.add(new Point(x, y));}}}// 找到墙wall未被访问过的点,如果没有返回Nullprotected Point findPoint(Point wall, Lattice[][] mazeLattice) {final int[] arroundWall = { -1, 0, 1, 0, -1 };// 顺序为左上右下Point p = null;for (int i = (wall.y + 1) % 2; i < 2; i += 2) {boolean add = mazeLattice[wall.y + arroundWall[i + 1]][wall.x + arroundWall[i]].isPassable(),sub = mazeLattice[wall.y - arroundWall[i + 1]][wall.x - arroundWall[i]].isPassable();if (add && !sub) {p = new Point(wall.x - arroundWall[i], wall.y - arroundWall[i + 1]);break;}if (!add && sub) {p = new Point(wall.x + arroundWall[i], wall.y + arroundWall[i + 1]);break;}}return p;}@Overridepublic void createMaze(Lattice[][] mazeLattice, int colNumber, int rowNumber) {// TODO Auto-generated method stubRandom rand = new Random();Point currentPoint = new Point(2 * rand.nextInt(colNumber / 2) + 1, 2 * rand.nextInt(rowNumber / 2) + 1);mazeLattice[currentPoint.y][currentPoint.x].setPassable(true);List<Point> listWall = new LinkedList<Point>();pushArroundWallToList(mazeLattice, currentPoint, listWall, colNumber, rowNumber);while (!listWall.isEmpty()) {int k = rand.nextInt(listWall.size());Point wall = listWall.remove(k);currentPoint = findPoint(wall, mazeLattice);if (currentPoint != null) {mazeLattice[wall.y][wall.x].setPassable(true);mazeLattice[currentPoint.y][currentPoint.x].setPassable(true);pushArroundWallToList(mazeLattice, currentPoint, listWall, colNumber, rowNumber);}}}}class RecursiveDivisionCreateMaze extends AbstractCreateMaze {// 随机在给定墙壁上开一个门protected void openAdoor(Lattice[][] mazeLattice, Point p1, Point p2, Random r) {if(p1.y==p2.y&&p1.x==p2.x){mazeLattice[p1.y][p1.x].setPassable(true);return;}if (p1.y == p2.y) {int pos = p1.x + r.nextInt((p2.x - p1.x) / 2 ) * 2;// 在奇数位置开门mazeLattice[p1.y][pos].setPassable(true);} else if (p1.x == p2.x) {int pos = p1.y + r.nextInt((p2.y - p1.y) / 2 ) * 2;mazeLattice[pos][p1.x].setPassable(true);}}// 递归生成迷宫private void recursiveCreateMaze(Lattice[][] mazeLattice, Point start, int height, int width, Random rand) {if (height <= 2 || width <= 2)return;// 在偶数行建立一条墙壁int drawx = start.y + rand.nextInt(height / 2) * 2 + 1;for (int i = start.x; i < start.x + width; ++i)mazeLattice[drawx][i].setPassable(false);// 在偶数列建立一条墙壁int drawy = start.x + rand.nextInt(width / 2) * 2 + 1;for (int i = start.y; i < start.y + height; ++i)mazeLattice[i][drawy].setPassable(false);// 从左侧墙壁开始按逆时针顺序随机在四个墙壁上开三个门,左侧墙壁记为1int opendoor =  rand.nextInt(4)+ 1;switch (opendoor) {case 1:openAdoor(mazeLattice, new Point(drawy, drawx + 1), new Point(drawy, start.y + height - 1), rand);// 2openAdoor(mazeLattice, new Point(drawy + 1, drawx), new Point(start.x + width - 1, drawx), rand);// 3openAdoor(mazeLattice,new Point(drawy, start.y), new Point(drawy, drawx - 1) , rand);// 4break;case 2:openAdoor(mazeLattice, new Point(drawy + 1, drawx), new Point(start.x + width - 1, drawx), rand);// 3openAdoor(mazeLattice,new Point(drawy, start.y), new Point(drawy, drawx - 1) , rand);// 4openAdoor(mazeLattice, new Point(start.x, drawx), new Point(drawy - 1, drawx), rand);// 1break;case 3:openAdoor(mazeLattice,new Point(drawy, start.y), new Point(drawy, drawx - 1) , rand);// 4openAdoor(mazeLattice, new Point(start.x, drawx), new Point(drawy - 1, drawx), rand);// 1openAdoor(mazeLattice, new Point(drawy, drawx + 1), new Point(drawy, start.y + height - 1), rand);// 2break;case 4:openAdoor(mazeLattice, new Point(start.x, drawx), new Point(drawy - 1, drawx), rand);// 1openAdoor(mazeLattice, new Point(drawy, drawx + 1), new Point(drawy, start.y + height - 1), rand);// 2openAdoor(mazeLattice, new Point(drawy + 1, drawx), new Point(start.x + width - 1, drawx), rand);// 3break;default:break;}// 左上角recursiveCreateMaze(mazeLattice, start,drawx-start.y, drawy-start.x, rand);// 右上角recursiveCreateMaze(mazeLattice, new Point(drawy+1,start.y),drawx-start.y, width-drawy+start.x-1, rand);// 左下角recursiveCreateMaze(mazeLattice, new Point(start.x,drawx+1),height - drawx + start.y - 1, drawy-start.x, rand);// 右下角recursiveCreateMaze(mazeLattice,new Point(drawy+1,drawx+1),height - drawx + start.y - 1, width-drawy+start.x-1, rand);}@Overridepublic void createMaze(Lattice[][] mazeLattice, int colNumber, int rowNumber) {// TODO Auto-generated method stubRandom rand = new Random();for (int i = 1; i < colNumber + 1; ++i)for (int j = 1; j < rowNumber + 1; ++j)mazeLattice[j][i].setPassable(true);Point start = new Point(1, 1);recursiveCreateMaze(mazeLattice, start, rowNumber, colNumber, rand);}}

lattice类:

package maze;import java.awt.Point;class Lattice {private boolean Passable;// 小球是否能通过private Point Father;//是否遍历过public Lattice() {setPassable(false);setFather(null);}public boolean isPassable() {return Passable;}public void setPassable(boolean isPassable) {this.Passable = isPassable;}/*** @return the father*/public Point getFather() {return Father;}/*** @param father the father to set*/public void setFather(Point father) {Father = father;}
}

Maze类:

package maze;import java.applet.Applet;
import java.applet.AudioClip;
import java.awt.BasicStroke;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.Stack;import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.border.EtchedBorder;class Maze extends JPanel {private Point entrance = null;private Point exit = null;private int rowNumber;// 行数private int colNumber;// 列数private int LatticeWidth;// 格子的宽度private Ball ball;private Lattice[][] mazeLattice;private boolean startTiming = false;private JPanel panel = new JPanel();private JTextField timeText = new Timers(), stepNumberText = new JTextField("0");private boolean computerDo = false;private Thread thread = null;private Thread audioThread = null;private int stepNmber;private static final char DepthFirstSearchSolveMaze = 0;private static final char BreadthFirstSearchSolveMaze = 1;private char solveMaze = DepthFirstSearchSolveMaze;private static final char DepthFirstSearchCreateMaze = 0;private static final char RandomizedPrimCreateMaze = 1;private static final char RecursiveDivisionCreateMaze = 2;private char createMaze = DepthFirstSearchCreateMaze;private boolean promptSolveMaze = false;public Maze(int row, int col) {this.setRowNumber(row);this.setColNumber(col);this.LatticeWidth = 15;mazeLattice = new Lattice[getRowNumber() + 2][getColNumber() + 2];setLayout(new BorderLayout(0, 0));stepNumberText.setEnabled(false);Label timeLabel = new Label(""), stepLabel = new Label("StepNumber:");timeLabel.setAlignment(Label.RIGHT);stepLabel.setAlignment(Label.RIGHT);panel.setLayout(new GridLayout(1, 4));add(panel, BorderLayout.NORTH);panel.add(timeLabel);panel.add(getTimeText());panel.add(stepLabel);panel.add(getStepNumberText());panel.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));this.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if (!isComputerDo()) {requestFocus();}}});setKeyListener();createMaze();}public void init() {mazeLattice = new Lattice[getRowNumber() + 2][getColNumber() + 2];setPromptSolveMaze(false);setComputerDo(false);setThreadStop();resetStepNumber();resetTimer();for (int i = 1; i < getRowNumber() + 1; ++i)for (int j = 1; j < getColNumber() + 1; ++j) {mazeLattice[i][j] = new Lattice();}for (int i = 0; i < getRowNumber() + 2; ++i) {mazeLattice[i][0] = new Lattice();mazeLattice[i][getColNumber() + 1] = new Lattice();}for (int j = 0; j < getColNumber() + 2; ++j) {mazeLattice[0][j] = new Lattice();mazeLattice[getRowNumber() + 1][j] = new Lattice();}ball = new Ball(0, 1);setEntrance(new Point(0, 1));setExit(new Point(getColNumber() + 1, getRowNumber()));mazeLattice[getEntrance().y][getEntrance().x].setPassable(true);mazeLattice[getExit().y][getExit().x].setPassable(true);}// 是否已经走出迷宫public boolean isWin() {if (getExit().x == ball.getX() && getExit().y == ball.getY()) {return true;}return false;}// 如果已经走出迷宫即跳出游戏结束对话框private void GameOverMessage() {((Timers) getTimeText()).stop();try {// 读取当前java工程项目下的yy.wav文件File file1 = new File("media//win.wav");AudioClip sound = Applet.newAudioClip(file1.toURI().toURL());sound.play();} catch (Exception e) {e.printStackTrace();}JOptionPane.showMessageDialog(null,"恭喜通过!\n" + ""+ timeText.getText() + "\n "+ stepNmber,"GameOver", JOptionPane.INFORMATION_MESSAGE);}// 验证横纵坐标是否超界private boolean isOutofBorder(int x, int y) {if ((x == 0 && y == 1) || (x == getColNumber() + 1 && y == getRowNumber()))return false;elsereturn (x > getColNumber() || y > getRowNumber() || x < 1 || y < 1) ? true : false;}// 绘制迷宫@Overrideprotected void paintComponent(Graphics g) {super.paintComponent(g);for (int i = 0; i < getRowNumber() + 2; ++i)for (int j = 0; j < getColNumber() + 2; ++j) {g.drawRect((j + 1) * LatticeWidth, (i + 1) * LatticeWidth + 30, LatticeWidth, LatticeWidth);if (mazeLattice[i][j].isPassable())g.setColor(Color.WHITE);elseg.setColor(Color.BLACK);g.fillRect((j + 1) * LatticeWidth, (i + 1) * LatticeWidth + 30, LatticeWidth, LatticeWidth);}g.setColor(Color.RED);g.fillRect((getColNumber() + 2) * LatticeWidth, (getRowNumber() + 1) * LatticeWidth + 30, LatticeWidth,LatticeWidth);g.setColor(ball.getColor());g.drawOval((ball.getX() + 1) * LatticeWidth, (ball.getY() + 1) * LatticeWidth + 30, LatticeWidth, LatticeWidth);g.fillOval((ball.getX() + 1) * LatticeWidth, (ball.getY() + 1) * LatticeWidth + 30, LatticeWidth, LatticeWidth);if (isPromptSolveMaze()) {Stack<Point> pathStack = promptsolveMaze();g.setColor(Color.GREEN);Point start = pathStack.pop();while (!pathStack.isEmpty()) {Point end = pathStack.pop();Graphics2D g2 = (Graphics2D) g;g2.setStroke(new BasicStroke(3.0f));g2.drawLine((int) (start.getX() + 1) * LatticeWidth + LatticeWidth / 2,(int) (start.getY() + 1) * LatticeWidth + 30 + LatticeWidth / 2,(int) (end.getX() + 1) * LatticeWidth + LatticeWidth / 2,(int) (end.getY() + 1) * LatticeWidth + 30 + LatticeWidth / 2);start = end;}}}// 设置键盘监听器synchronized private void move(int c) {int tx = ball.getX(), ty = ball.getY();switch (c) {case KeyEvent.VK_LEFT:--tx;break;case KeyEvent.VK_RIGHT:++tx;break;case KeyEvent.VK_UP:--ty;break;case KeyEvent.VK_DOWN:++ty;break;case KeyEvent.VK_ESCAPE:System.exit(0);break;default:// 防止按键盘上其他键仍然产生键盘音效、使计步器递增tx = 0;ty = 0;break;}if (!isOutofBorder(tx, ty) && mazeLattice[ty][tx].isPassable()) {try {File file1 = new File("media//keyPressed.wav");AudioClip sound = Applet.newAudioClip(file1.toURI().toURL());sound.play();} catch (Exception e) {e.printStackTrace();}ball.setX(tx);ball.setY(ty);++stepNmber;stepNumberText.setText(Integer.toString(stepNmber));if (!isStartTiming()) {setStartTiming(!isStartTiming());((Timers) getTimeText()).start();}}}private void setKeyListener() {this.addKeyListener(new KeyAdapter() {@Overridepublic void keyPressed(KeyEvent e) {if (!isWin()) {int c = e.getKeyCode();move(c);repaint();if (isWin() && !isComputerDo())GameOverMessage();}}});}// 将计时器归零public void resetTimer() {setStartTiming(false);getTimeText().setText("0");((Timers) timeText).restart();}// 将计步器归零public void resetStepNumber() {setStepNmber(0);stepNumberText.setText(Integer.toString(stepNmber));}// 设置小球的位置public void setBallPosition(Point p) {ball.setX(p.x);ball.setY(p.y);repaint();}// 建立一个迷宫public void createMaze() {init();AbstractCreateMaze c = null;if (getCreateMaze() == DepthFirstSearchCreateMaze)c = new DepthFirstSearchCreateMaze();else if (getCreateMaze() == RandomizedPrimCreateMaze)c = new RandomizedPrimCreateMaze();else if (getCreateMaze() == RecursiveDivisionCreateMaze)c = new RecursiveDivisionCreateMaze();c.createMaze(mazeLattice, getColNumber(), getRowNumber());repaint();}// 找出走出迷宫的路径private Stack<Point> solveMaze(Point p) {AbstractSolveMaze a = null;if (getSolveMaze() == BreadthFirstSearchSolveMaze)a = new BreadthFirstSearchSolveMaze();else if (getSolveMaze() == DepthFirstSearchSolveMaze)a = new DepthFirstSearchSolveMaze();return a.solveMaze(mazeLattice, p, getExit(), getColNumber(), getRowNumber());}// 找出小球位于给定位置时走出迷宫的路径private Stack<Point> promptsolveMaze() {AbstractSolveMaze a = null;if (getSolveMaze() == BreadthFirstSearchSolveMaze)a = new BreadthFirstSearchSolveMaze();else if (getSolveMaze() == DepthFirstSearchSolveMaze)a = new DepthFirstSearchSolveMaze();return a.solveMaze(mazeLattice, new Point(ball.getX(), ball.getY()), getExit(), getColNumber(), getRowNumber());}// 将处于给定位置的小球走出迷宫的路径显示在迷宫上显示给定时间长,仅为computerSolveMazeForBallPosition()调用private void computerSolveMazeForBallPositionForTime(int time) {if (getThread() == null)setThread(new Thread() {@Overridepublic void run() {while (!isInterrupted())try {setPromptSolveMaze(true);repaint();Thread.sleep(time);setPromptSolveMaze(false);repaint();setThreadStop();} catch (InterruptedException e) {// TODO Auto-generated catch blockbreak;}}});getThread().start();}// 以time时间显示处于给定位置小球走出迷宫的路径public boolean computerSolveMazeForBallPosition() {setThreadStop();((Timers) getTimeText()).stop();int time = 0;Object[] selections = { "forever", "10s", "5s", "3s", "1s" };Object select = JOptionPane.showInputDialog(null, "Please select the speed of which the ball runs","迷宫游戏", JOptionPane.INFORMATION_MESSAGE, null, selections, selections[2]);if (select != null) {switch ((String) select) {case "forever":time = 2000000000;break;case "10s":time = 10000;break;case "5s":time = 5000;break;case "3s":time = 3000;break;case "1s":time = 1000;break;default:break;}computerSolveMazeForBallPositionForTime(time);((Timers) getTimeText()).proceed();return true;} elsereturn false;}// 以speed速度由计算机将处于初始位置的小球走出迷宫,仅为computerSolveMaze()函数调用private void computerSolveMazeForSpeed(int speed) {setComputerDo(true);Point p = null;if (isWin())p = getEntrance();elsep = new Point(ball.getX(), ball.getY());Stack<Point> stack = solveMaze(p);resetTimer();resetStepNumber();if (getThread() == null)setThread(new Thread() {@Overridepublic void run() {while (!isInterrupted())try {while (!stack.isEmpty()) {Point p = stack.pop();setBallPosition(p);++stepNmber;stepNumberText.setText(Integer.toString(stepNmber));Thread.sleep(speed);}} catch (InterruptedException e) {// TODO Auto-generated catch blockbreak;}}});getThread().start();}// 由计算机将处于初始位置的小球走出迷宫public boolean computerSolveMaze() {int speed = 0;setThreadStop();Object[] selections = { "lower seed", "low speed", "medium speed", "high speed", "higher speed" };Object select = JOptionPane.showInputDialog(null, "Please select the speed of which the ball runs","迷宫游戏", JOptionPane.INFORMATION_MESSAGE, null, selections, selections[2]);if (select != null) {switch ((String) select) {case "lower seed":speed = 400;break;case "low speed":speed = 300;break;case "medium speed":speed = 200;break;case "high speed":speed = 100;break;case "higher speed":speed = 20;break;default:break;}computerSolveMazeForSpeed(speed);return true;} elsereturn false;}public int getLatticeWidth() {return LatticeWidth;}public void setLatticeWidth(int latticeWidth) {LatticeWidth = latticeWidth;}public JTextField getTimeText() {return timeText;}/*** @return the startTiming*/public boolean isStartTiming() {return startTiming;}/*** @param startTiming the startTiming to set*/public void setStartTiming(boolean startTiming) {this.startTiming = startTiming;}/*** @return the entrance*/public Point getEntrance() {return entrance;}/*** @param entrance the entrance to set*/public void setEntrance(Point entrance) {this.entrance = entrance;}/*** @return the exit*/public Point getExit() {return exit;}/*** @param exit the exit to set*/private void setExit(Point exit) {this.exit = exit;}/*** @return the computerDo*/public boolean isComputerDo() {return computerDo;}/*** @param computerDo the computerDo to set*/public void setComputerDo(boolean computerDo) {this.computerDo = computerDo;}/*** @return the thread*/public Thread getThread() {return thread;}/*** @param thread the thread to set*/private void setThread(Thread thread) {this.thread = thread;}public void setThreadStop() {if (getThread() != null) {if (isPromptSolveMaze())setPromptSolveMaze(false);thread.interrupt();setThread(null);}}/*** @return the stepNumberText*/public JTextField getStepNumberText() {return stepNumberText;}/*** @return the stepNmber*/public int getStepNmber() {return stepNmber;}/*** @param stepNmber the stepNmber to set*/public void setStepNmber(int stepNmber) {this.stepNmber = stepNmber;}/*** @return the rowNumber*/public int getRowNumber() {return rowNumber;}/*** @param rowNumber the rowNumber to set*/public void setRowNumber(int rowNumber) {this.rowNumber = rowNumber;}/*** @return the colNumber*/public int getColNumber() {return colNumber;}/*** @param colNumber the colNumber to set*/public void setColNumber(int colNumber) {this.colNumber = colNumber;}/*** @return the solveMaze*/public char getSolveMaze() {return solveMaze;}/*** @param solveMaze the solveMaze to set*/public void setSolveMaze(char solveMaze) {this.solveMaze = solveMaze;}/*** @return the createMaze*/public char getCreateMaze() {return createMaze;}/*** @param createMaze the createMaze to set*/public void setCreateMaze(char createMaze) {this.createMaze = createMaze;}/*** @return the promptSolveMaze*/public boolean isPromptSolveMaze() {return promptSolveMaze;}/*** @param promptSolveMaze the promptSolveMaze to set*/public void setPromptSolveMaze(boolean promptSolveMaze) {this.promptSolveMaze = promptSolveMaze;}/*** @return the audioThread*/private Thread getAudioThread() {return audioThread;}/*** @param audioThread the audioThread to set*/private void setAudioThread(Thread audioThread) {this.audioThread = audioThread;}public void setAudioThreadStart() {if (getAudioThread() == null) {setAudioThread(new Thread() {@Override@SuppressWarnings("restriction")// private AudioStream as = null;// @SuppressWarnings("restriction")public void run() {AudioClip sound = null;while (!isInterrupted())try {// 读取当前java工程项目下的yy.wav文件File file1 = new File("media//background.wav");sound = Applet.newAudioClip(file1.toURI().toURL());sound.play();Thread.sleep(24000);} catch (Exception e) {break;}sound.stop();}});getAudioThread().start();}}public void setAudioThreadStop() {if (getAudioThread() != null) {getAudioThread().interrupt();setAudioThread(null);}}
}

MazeFrame类:

package maze;import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;import javax.swing.ButtonGroup;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFormattedTextField;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JSpinner;
import javax.swing.SpinnerNumberModel;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;class MazeFrame extends JFrame {private static final char DepthFirstSearchSolveMaze = 0;private static final char BreadthFirstSearchSolveMaze = 1;private char solveMaze = 0;private static final char DepthFirstSearchCreateMaze = 0;private static final char RandomizedPrimCreateMaze = 1;private static final char RecursiveDivisionCreateMaze = 2;private char createMaze = 0;private JPanel contentPane;private Maze maze;private boolean isPause = false;private boolean bgmStart = true;private JPanel panel_1;private JPanel panel_2;private Panel panel;private JButton button;private JButton button_1;private JButton button_2;private JButton button_3;private JButton prompt;private JButton bgm;private JPanel panel_3;private JLabel label;private JPanel panel_4;private JButton button_4;private JButton btnQuit;private JPanel panel_5;private JPanel panel_6;private JLabel label_1;private JPanel panel_8;private JLabel label_2;private JSpinner spinner;private JPanel panel_9;private JLabel lblLatticesWidth;private JSpinner spinner_1;private JPanel panel_10;private JPanel panel_7;private JPanel panel_11;private JPanel panel_12;private JLabel label_4;private JSpinner spinner_2;private JPanel panel_13;private JLabel lblPleaseSelectThe;private JPanel panel_14;private JLabel lblPleaseSelectThe_1;private JPanel panel_15;private JRadioButton rdbtnNewRadioButton;private JRadioButton rdbtnNewRadioButton_1;private JRadioButton rdbtnNewRadioButton_2;private ButtonGroup createMazeButton = new ButtonGroup();private JPanel panel_16;private JRadioButton rdbtnDepthFirstSearch;private JRadioButton rdbtnBreadthFirstSearch;private ButtonGroup solveMazeButton = new ButtonGroup();/*** Create the frame.*/public MazeFrame(int rowNumber, int colNumber) {setTitle("迷宫");setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);setSize(500, 500);setVisible(true);contentPane = new JPanel();contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));contentPane.setLayout(new BorderLayout(0, 0));setContentPane(contentPane);panel_1 = new JPanel();contentPane.add(panel_1, BorderLayout.WEST);panel_1.setLayout(new BorderLayout(0, 0));panel_3 = new JPanel();panel_3.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));panel_1.add(panel_3);panel_3.setLayout(new BorderLayout(0, 0));label = new JLabel("迷宫设置\r\n");label.setFont(new Font("Lucida Handwriting", Font.PLAIN, 16));panel_3.add(label, BorderLayout.NORTH);panel_4 = new JPanel();panel_4.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));panel_3.add(panel_4, BorderLayout.SOUTH);button_4 = new JButton("GO");button_4.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if (getSolveMaze() != maze.getSolveMaze())maze.setSolveMaze(getSolveMaze());maze.setPromptSolveMaze(false);button_1.setEnabled(true);button_2.setEnabled(false);button_3.setEnabled(true);prompt.setEnabled(true);int col = Integer.parseInt(spinner_2.getValue().toString());int row = Integer.parseInt(spinner.getValue().toString());if (maze.getColNumber() == col && maze.getRowNumber() == row) {if (getCreateMaze() != maze.getCreateMaze()) {maze.setCreateMaze(getCreateMaze());maze.createMaze();} else {maze.setComputerDo(false);maze.resetStepNumber();maze.resetTimer();maze.setThreadStop();maze.setBallPosition(maze.getEntrance());}maze.requestFocus();maze.repaint();} else {maze.setColNumber(col);maze.setRowNumber(row);if (getCreateMaze() != maze.getCreateMaze()) {maze.setCreateMaze(getCreateMaze());}maze.createMaze();maze.requestFocus();}}});button_4.setFont(new Font("Lucida Handwriting", Font.PLAIN, 12));button_4.setActionCommand("GO");panel_4.add(button_4);btnQuit = new JButton("Quit");btnQuit.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {System.exit(0);}});btnQuit.setFont(new Font("Lucida Handwriting", Font.PLAIN, 12));btnQuit.setActionCommand("Cancel");panel_4.add(btnQuit);panel_5 = new JPanel();panel_3.add(panel_5, BorderLayout.CENTER);panel_5.setLayout(new GridLayout(0, 1, 0, 0));panel_6 = new JPanel();panel_6.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));panel_5.add(panel_6);panel_6.setLayout(new BorderLayout(0, 0));label_1 = new JLabel("size:");label_1.setFont(new Font("SimSun-ExtB", Font.PLAIN, 14));panel_6.add(label_1, BorderLayout.NORTH);panel_7 = new JPanel();panel_6.add(panel_7, BorderLayout.CENTER);panel_7.setLayout(new GridLayout(0, 1, 0, 0));panel_8 = new JPanel();panel_7.add(panel_8);label_2 = new JLabel("ROWS:");panel_8.add(label_2);spinner = new JSpinner();spinner.setModel(new SpinnerNumberModel(11, 11, 99, 2));JSpinner.NumberEditor editor = new JSpinner.NumberEditor(spinner, "0");spinner.setEditor(editor);JFormattedTextField textField = ((JSpinner.NumberEditor) spinner.getEditor()).getTextField();textField.setEditable(false);spinner.addChangeListener(new ChangeListener() {@Overridepublic void stateChanged(ChangeEvent e) {}});panel_8.add(spinner);panel_11 = new JPanel();panel_7.add(panel_11);panel_12 = new JPanel();panel_11.add(panel_12);label_4 = new JLabel("COLS:");panel_12.add(label_4);spinner_2 = new JSpinner();spinner_2.setModel(new SpinnerNumberModel(11, 11, 99, 2));// ��������editor = new JSpinner.NumberEditor(spinner_2, "0");spinner_2.setEditor(editor);textField = ((JSpinner.NumberEditor) spinner_2.getEditor()).getTextField();textField.setEditable(false);panel_12.add(spinner_2);panel_10 = new JPanel();panel_7.add(panel_10);panel_9 = new JPanel();panel_10.add(panel_9);lblLatticesWidth = new JLabel("width: ");panel_9.add(lblLatticesWidth);spinner_1 = new JSpinner();spinner_1.addChangeListener(new ChangeListener() {@Overridepublic void stateChanged(ChangeEvent e) {maze.setLatticeWidth(Integer.parseInt(spinner_1.getValue().toString()));maze.repaint();}});spinner_1.setModel(new SpinnerNumberModel(15, 5, 30, 1));panel_9.add(spinner_1);panel_14 = new JPanel();panel_14.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));panel_5.add(panel_14);panel_14.setLayout(new BorderLayout(0, 0));panel_15 = new JPanel();panel_14.add(panel_15);panel_15.setLayout(new GridLayout(0, 1, 0, 0));rdbtnNewRadioButton = new JRadioButton("1");rdbtnNewRadioButton.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {setCreateMaze(DepthFirstSearchCreateMaze);}});panel_15.add(rdbtnNewRadioButton);rdbtnNewRadioButton_1 = new JRadioButton("2");rdbtnNewRadioButton_1.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {setCreateMaze(RandomizedPrimCreateMaze);}});panel_15.add(rdbtnNewRadioButton_1);rdbtnNewRadioButton_2 = new JRadioButton("3");rdbtnNewRadioButton_2.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {setCreateMaze(RecursiveDivisionCreateMaze);}});panel_15.add(rdbtnNewRadioButton_2);panel_13 = new JPanel();panel_13.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));panel_5.add(panel_13);panel_13.setLayout(new BorderLayout(0, 0));lblPleaseSelectThe = new JLabel(" ");lblPleaseSelectThe.setFont(new Font("SimSun-ExtB", Font.PLAIN, 14));panel_13.add(lblPleaseSelectThe, BorderLayout.NORTH);panel_16 = new JPanel();panel_13.add(panel_16);panel_16.setLayout(new GridLayout(0, 1, 0, 0));rdbtnDepthFirstSearch = new JRadioButton("");rdbtnDepthFirstSearch.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {setSolveMaze(DepthFirstSearchSolveMaze);}});panel_16.add(rdbtnDepthFirstSearch);rdbtnBreadthFirstSearch = new JRadioButton("");rdbtnBreadthFirstSearch.addActionListener(new ActionListener() {@Overridepublic void actionPerformed(ActionEvent e) {setSolveMaze(BreadthFirstSearchSolveMaze);}});panel_16.add(rdbtnBreadthFirstSearch);panel_2 = new JPanel();panel_2.setBorder(new EtchedBorder(EtchedBorder.LOWERED, null, null));contentPane.add(panel_2, BorderLayout.CENTER);panel_2.setLayout(new BorderLayout(0, 0));maze = new Maze(rowNumber, colNumber);panel_2.add(maze);panel = new Panel();panel_2.add(panel, BorderLayout.NORTH);button = new JButton("复位");button.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if (isBgmStart())maze.setAudioThreadStart();maze.init();maze.createMaze();button_1.setEnabled(true);button_1.setText("Pause");setPause(false);button_2.setEnabled(false);button_3.setEnabled(true);prompt.setEnabled(true);maze.requestFocus();}});panel.add(button);button_1 = new JButton("暂停");button_1.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if (!maze.isWin()) {if (!isPause() && maze.isStartTiming() && button_1.isEnabled()) {button_1.setText("继续");((Timers) maze.getTimeText()).stop();setPause(true);} else if (isPause() && maze.isStartTiming() && button_1.isEnabled()) {button_1.setText("暂停");((Timers) maze.getTimeText()).proceed();setPause(false);maze.requestFocus();}}}});panel.add(button_1);button_3 = new JButton("启动");button_3.addMouseListener(new MouseAdapter() {@Overridepublic void mouseClicked(MouseEvent e) {if (button_3.isEnabled() && !maze.isComputerDo() && maze.computerSolveMaze()) {button_2.setEnabled(true);button_3.setEnabled(false);button_1.setEnabled(false);prompt.setEnabled(false);}}});panel.add(button_3);solveMazeButton.add(rdbtnDepthFirstSearch);solveMazeButton.add(rdbtnBreadthFirstSearch);rdbtnDepthFirstSearch.setSelected(true);createMazeButton.add(rdbtnNewRadioButton);createMazeButton.add(rdbtnNewRadioButton_1);createMazeButton.add(rdbtnNewRadioButton_2);rdbtnNewRadioButton.setSelected(true);maze.requestFocus();}/*** Launch the application.*/public static void main(String[] args) {try {MazeFrame mazeFrame = new MazeFrame(11, 11);Toolkit tool = mazeFrame.getToolkit(); // �õ�һ��Toolkit����Image myimage = tool.getImage(System.getProperty("user.dir") + "/media//maze.jpg"); // ��tool��ȡͼ��mazeFrame.setIconImage(myimage);mazeFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);mazeFrame.setVisible(true);mazeFrame.setSize(1000, 500);mazeFrame.maze.setAudioThreadStart();} catch (Exception e) {e.printStackTrace();}}/*** @return the isPause*/public boolean isPause() {return isPause;}/*** @param isPause the isPause to set*/public void setPause(boolean isPause) {this.isPause = isPause;}/*** @return the solveMaze*/public char getSolveMaze() {return solveMaze;}/*** @param solveMaze the solveMaze to set*/public void setSolveMaze(char solveMaze) {this.solveMaze = solveMaze;}/*** @return the createMaze*/public char getCreateMaze() {return createMaze;}/*** @param createMaze the createMaze to set*/public void setCreateMaze(char createMaze) {this.createMaze = createMaze;}/*** @return the bgmStart*/public boolean isBgmStart() {return bgmStart;}/*** @param bgmStart the bgmStart to set*/public void setBgmStart(boolean bgmStart) {this.bgmStart = bgmStart;}
}

solvemaze类:

package maze;import java.awt.Point;
import java.util.*;abstract class AbstractSolveMaze {protected Stack<Point> pathStack = null;// 验证横纵坐标是否超界protected boolean isOutofBorder(int x, int y, int colNumber, int rowNumber) {if ((x == 0 && y == 1) || (x == colNumber + 1 && y == rowNumber))return false;elsereturn (x > colNumber || y > rowNumber || x < 1 || y < 1) ? true : false;}abstract Stack<Point> solveMaze(Lattice[][] mazeLattice, Point entrance, Point exit, int colNumber, int rowNumber);
}class DepthFirstSearchSolveMaze extends AbstractSolveMaze {// 按深度优先搜索的方式选择一个p点未访问的相邻迷宫单元 ,并将选择的这一单元的visited置true,为solveMaze()函数调用protected Point ArroundPointDepthFirst(Lattice[][] mazeLattice, Point p, int colNumber, int rowNumber) {final int[] arroundPoint = { -1, 0, 1, 0, -1 };// 一个点周围四个点的坐标变化,顺序为左上右下for (int i = 0; i < 4;) {int x = p.x + arroundPoint[i];int y = p.y + arroundPoint[++i];if (!isOutofBorder(x, y, colNumber, rowNumber) && mazeLattice[y][x].isPassable()&& mazeLattice[y][x].getFather() == null) {p = new Point(x, y);mazeLattice[y][x].setFather(p);return p;}}return null;}@Overridepublic Stack<Point> solveMaze(Lattice[][] mazeLattice, Point entrance, Point exit, int colNumber, int rowNumber) {// TODO Auto-generated method stubpathStack = new Stack<Point>();Deque<Point> pathDeque = new ArrayDeque<Point>();Point judge = new Point(0, 0);Point end = new Point(exit.x - 1, exit.y);for (int i = 0; i < rowNumber + 2; ++i)for (int j = 0; j < colNumber + 2; ++j)mazeLattice[i][j].setFather(null);mazeLattice[entrance.y][entrance.x].setFather(judge);pathDeque.addLast(entrance);Point currentPoint = entrance;while (!currentPoint.equals(end)) {currentPoint = ArroundPointDepthFirst(mazeLattice, currentPoint, colNumber, rowNumber);if (currentPoint == null) {pathDeque.removeLast();if (pathDeque.isEmpty())break;currentPoint = pathDeque.getLast();} else {pathDeque.addLast(currentPoint);}}mazeLattice[exit.y][exit.x].setFather(end);pathDeque.addLast(exit);while (!pathDeque.isEmpty())pathStack.push(pathDeque.removeLast());return pathStack;}
}class BreadthFirstSearchSolveMaze extends AbstractSolveMaze {protected Point[] ArroundPointBreadthFirst(Lattice[][] mazeLattice, Point p, int colNumber, int rowNumber) {final int[] arroundPoint = { -1, 0, 1, 0, -1 };// 一个点周围四个点的坐标变化,顺序为左上右下Point[] point = { null, null, null, null };for (int i = 0; i < 4; ++i) {int x = p.x + arroundPoint[i];int y = p.y + arroundPoint[i + 1];if (!isOutofBorder(x, y, colNumber, rowNumber) && mazeLattice[y][x].isPassable()&& mazeLattice[y][x].getFather() == null) {point[i] = new Point(x, y);mazeLattice[y][x].setFather(p);}}return point;}@Overridepublic Stack<Point> solveMaze(Lattice[][] mazeLattice, Point entrance, Point exit, int colNumber, int rowNumber) {// TODO Auto-generated method stubpathStack = new Stack<Point>();Point judge = new Point(0, 0);Deque<Point> pathDeque = new ArrayDeque<Point>();Point end = new Point(exit.x - 1, exit.y);for (int i = 0; i < rowNumber + 2; ++i)for (int j = 0; j < colNumber + 2; ++j)mazeLattice[i][j].setFather(null);mazeLattice[entrance.y][entrance.x].setFather(judge);pathDeque.addLast(entrance);Point currentPoint = entrance;while (!currentPoint.equals(end)) {Point[] p = ArroundPointBreadthFirst(mazeLattice, currentPoint, colNumber, rowNumber);int count = 0;// 对能压入栈中的currentPoint点周围的四个点中的点进行计数for (int i = 0; i < p.length; ++i)if (p[i] != null) {pathDeque.addLast(p[i]);++count;}if (count == 0) {pathDeque.removeLast();if (pathDeque.isEmpty())break;currentPoint = pathDeque.getLast();} else {pathDeque.addLast(currentPoint);}}mazeLattice[exit.y][exit.x].setFather(end);for (currentPoint = exit; !currentPoint.equals(judge); currentPoint = mazeLattice[currentPoint.y][currentPoint.x].getFather()) {pathStack.push(currentPoint);}return pathStack;}
}

times类:

package maze;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import javax.swing.JTextField;
import javax.swing.Timer;public class Timers extends JTextField { private Date now = null;private Timer timer;public Timers() {setEditable(false);Calendar time=Calendar.getInstance();time.set(0, 0, 0, 0, 0, 0);now=time.getTime();timer= new Timer(1000, new ActionListener() {public void actionPerformed(ActionEvent e) {now = new Date(now.getTime() + 1000);SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");setText(formatter.format(now));}});}public void start(){timer.start();}public void stop(){timer.stop();}public void proceed(){timer.restart();}public void restart(){stop();Calendar time=Calendar.getInstance();time.set(0, 0, 0, 0, 0, 0);now=time.getTime();timer= new Timer(1000, new ActionListener() {public void actionPerformed(ActionEvent e) {now = new Date(now.getTime() + 1000);SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");setText(formatter.format(now));}});}
}

五、程序运行结果分析

运行结果图


总结:
1、项目的难点和关键点
在这个项目中,难点在于代码的编写,在编写代码过程中最难的还是优先级的完成。对深度优先算法和二叉树遍历的学习理解和应用很关键。
2、项目的评价
我的编码存在很多漏洞,比如我的运行结果中,中文乱码但通关后的中文没有乱码如下图:

是我的idea设置问题,其他电脑上可以中文显示,代码功能不够完善,迷宫的大小可以调整,但在行列增加的部分做的不太好,重置功能后不能手动通关等问题。

参考链接:
https://blog.csdn.net/qq_41264674/article/details/80945140
https://www.gamedev.net/reference/articles/article2003.asp
https://blog.csdn.net/jjwwwww/article/details/82891213
https://www.cnblogs.com/maxuewei2/p/4825520.html
https://www.cnblogs.com/demodashi/p/10474104.html
https://www.cnblogs.com/yaowen/p/4479563.html
http://www.doc88.com/p-6791558318524.html

迷宫小游戏Java实现相关推荐

  1. [原创]我的作品:我的迷宫小游戏Java版本

    这个小游戏是我选的第二个数据结构课程设计题目,觉得很有意思,也很有挑战性,对于一个自学Java的人来说写出这个小游戏我觉得无疑是一种鼓励,呵呵呵 实验题目: 随机生成一个迷宫图,迷宫大小为N*N,N预 ...

  2. 基于Java的迷宫小游戏

    一.实验内容: 1)迷宫游戏是非常经典的游戏,在该题中要求随机生成一个迷宫,并求解迷宫: 2) 要求查找并理解迷宫生成的算法,并尝试用两种不同的算法来生成随机的迷宫. 要求迷宫游戏支持玩家走迷宫,和系 ...

  3. 黑马程序员--迷宫小游戏

    ------- android培训.java培训.期待与您交流! ---------- 在黑马ios的基础课视频上,有个迷宫小游戏,感觉挺有趣,然后我就在此基础上,稍稍改了点,记下,留着可以和别人共同 ...

  4. Python游戏开发,pygame模块,Python实现过迷宫小游戏

    前言 今天为大家带来解闷用的过迷宫小游戏分享给大家好了.让我们愉快地开始吧~ 效果展示 开发工具 Python版本: 3.6.4 相关模块: pygame模块: 以及一些Python自带的模块. 环境 ...

  5. c语言自动按键脚本,C语言键盘控制走迷宫小游戏

    本文实例为大家分享了C语言键盘控制走迷宫小游戏的具体代码,供大家参考,具体内容如下 在看了<啊哈C语言>之后想写一个游戏demo 游戏的截图 首先是启动界面 然后是初始化 接下来是键盘操控 ...

  6. python迷宫小游戏大全_Python迷宫小游戏源代码、源程序

    Python迷宫小游戏源程序包括两个文件maze.py和mazeGenerator.py,mazeGenerator.py实现迷宫地图的生成,程序运行截图: mazeGenerator.py impo ...

  7. 一个Python的迷宫小游戏

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 迷宫小游戏 前言 一.python是什么? 二.使用步骤 1.引入库 2.读入数据 2.1.游戏开始 2.2.控制角色移动 2.3.鼠 ...

  8. 分享一个C语言矿井逃生迷宫小游戏【附源码】

    用C语言写的一个迷宫小游戏,游戏玩法是通过鼠标控制帽子上的灯走出迷宫 // 定义常量 #define PI 3.141592653589 // 圆周率 #define UNIT_GROUND 0 // ...

  9. 用 Dev-C++ 编写简单的走迷宫小游戏

    用 Dev-C++ 编写简单的走迷宫小游戏 前言 基础版 优化版 前言 以下是显示效果 B站视频讲解:[小游戏]用 Dev-C++ 编写简单的控制台走迷宫小游戏 [小游戏]用 Dev-C++ 编写简单 ...

  10. UEFI开发探索94 – 迷宫小游戏

    (请保留-> 作者: 罗冰 https://blog.csdn.net/luobing4365) UEFI下的迷宫小游戏 1 Maze程序结构分析 1)定义全局变量 2)设置迷宫 3) 游戏控制 ...

最新文章

  1. 深入理解Semaphore
  2. python调用动态链接库windows_用win从python ctypes调用标准windows.dll的Segfault
  3. ARM中LDR伪指令与LDR加载指令
  4. Android Studio开发第四篇版本管理Git(下)
  5. oracle中创建游标,oracle 存储过程创建游标
  6. 如何向开源软件贡献自己的力量
  7. 软件定义:给你一个更智能的世界
  8. 电脑如何连接蓝牙音箱_蓝牙音箱如何办理SRRC认证
  9. 微信小程序_简单组件使用与数据绑定
  10. PAT乙级1028 人口普查 (20 分)
  11. k阶原点距和k阶中心距各是说明什么数字特征
  12. 骑士资本高频交易系统事故案例分析
  13. DELPHI利用WMI获取主板参数
  14. Python 【问题描述】按照世卫组织的标准: 男性:(身高cm-80)×70%=标准体重 女性:(身高cm-70)×60%=标准体重 标准体重正负10%为正常体重(含10%) 标准体重正负1
  15. 无心剑英译许巍《温暖》
  16. Educational Codeforces Round 62 (Rated for Div. 2) E. Palindrome-less Arrays(DP+瞎搞)
  17. 服务器硬盘分区raid,硬盘分区高手请进!!!
  18. MySQL 高可用之MMM
  19. vue2.0配置代理 api 开发环境、生产环境
  20. Creo5.0结构有限元仿真分析视频教程

热门文章

  1. 串的模式匹配算法之BF算法
  2. LTE中CQI反馈学习笔记
  3. iTOP-4418开发板RS85模块ioctl操作时间间隔修改
  4. S5P4418 使用SD卡启动Android系统
  5. ABAP Enhancement
  6. 使用MySQL进行地理坐标计算
  7. 《大话设计模式 下》
  8. 【linux内核分析与应用-陈莉君】设备驱动概述
  9. R 语言计算卡方检验的P值
  10. 信息编码的运用——如何用二进制改图