开发环境:
操作系统Win10。
1.下载Java 15,提取码:soft
2.下载软件 Eclipse 2020-12,提取码:soft
3.生成迷宫第1版

下载本博客的实例工程代码,提取码:soft

画迷宫思路:
        想象着有一个正方形区域,由长宽相等数量的正方形房间构成,房间中间是空的,四周是墙壁。有这么一个工人,他是来到这块区域的某一个房间,开始砸墙。
        规则一:随机砸上下左右其中一个方向的墙,举例这个方向是下,就砸下面的墙和下面房间的上面的墙,然后前往下面的房间,并对上面的房间做个标记,不再砸上面的房间。以此类推,一直砸下去。
        规则二:当工人发现四周所有房间都做了标记,就随机前往一个被标记的房间,继续规则一的步骤。
        规则三:所有房间都做了标记的时候,迷宫就创建完了。
寻路思路:
        规则一:随机生成起点终点,假设有一个玩家站在起点房间,首先随机一个方向,如果这个方向不是墙壁,就前往这个方向的房间,然后记录这个房间的位置,避免走相同的房间。
        规则二:如果玩家当前所在房间有三面墙壁,表示进入死胡同,就后退到那唯一没有墙壁的方向的房间,如果那个房间之前走过,就从记录里删除,如果之前没有走过就增加新的房间位置的记录。后退完毕后,把那个死胡同的房间的唯一没有墙的方向,重新筑墙,然后重复规则一。
        规则三:如果当前玩家所在房间是终点,则寻路完毕,得到走出迷宫的答案。

文章目录

  • 1. 工程目录结构
  • 2. 程序效果
  • 3. 代码内容

1. 工程目录结构

2. 程序效果

3. 代码内容

Constant.java

package maze.view;public class Constant {/** 方向 */public static enum DIRECT {// 上TOP// 下,BOTTOM// 左,LEFT// 右,RIGHT}}

LogUtils.java
这个类,中间调试的时候用了下,最后都删掉了。

package maze.view;public class LogUtils {public static boolean changedLine = true;public static boolean showFlg = true;public static int tryCount = 0;public static void log(String message) {//        try {//            PrintStream out = System.out;// 保存原系统输出流
//            PrintStream ps = new PrintStream("./src/maze/view/maze.log");
//            System.setOut(ps);// 设定新的输出流if (tryCount == 20) {showFlg = false;}if (showFlg) {if (message.contains("try")) {tryCount++;} else {tryCount = 0;}if (changedLine) {System.out.println(message);} else {System.out.print(message);}}
//
//            System.setOut(out);// 恢复原系统输出流
//        } catch (FileNotFoundException e) {//            // TODO Auto-generated catch block
//            e.printStackTrace();
//        }// 创建文件输出流}
}

MainFrame.java

package maze.view;import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JTextField;/*** 用迷宫算法,随机生成迷宫<br>* 思想:生成迷宫的过程就是一个在一个个房间里砸墙的过程<br>* 迷宫算法规则:<br>* &nbsp;&nbsp;&nbsp;&nbsp;1,只有当隔壁房间没去过的时候,墙才可以砸<br>* &nbsp;&nbsp;&nbsp;&nbsp;2, 无墙可砸的时候,就传送到一个去过的房间里<br>* &nbsp;&nbsp;&nbsp;&nbsp;3, 每一个房间都要到达* * @author 见瑞彬**/
public class MainFrame extends JFrame implements ActionListener {/** 序列号 */private static final long serialVersionUID = 1L;private int frameX = 0;private int frameY = 0;private int frameW = 800;private int frameH = 700;/** 迷宫管理员 */private MazeUtils mazeUtils;/** 迷宫区域 */private Rectangle mazeArea;/** 按钮<<生成迷宫>> */private JButton remakeMazeButton;/** 文本<<迷宫长度>> */private JTextField horizontalCountField;/** 标签<<迷宫长度>> */private JLabel horizontalCountLabel;/** 起点 */private Point startPoint;/** 终点 */private Point endPoint;/** 迷宫 */private Room[][] maze;public MainFrame() {// 初始化迷宫工具类mazeUtils = new MazeUtils();// 初始化迷宫区域mazeArea = new Rectangle(20, 80, 600, 600);// 设定窗体控件布局this.setLayout(null);// 添加按钮<<生成迷宫>>remakeMazeButton = new JButton("生成迷宫");remakeMazeButton.setBounds(0, 5, 90, 30);remakeMazeButton.addActionListener(this);this.add(remakeMazeButton);// 设定横排方格数horizontalCountLabel = new JLabel("迷宫长度");horizontalCountLabel.setBounds(100, 5, 50, 30);this.add(horizontalCountLabel);horizontalCountField = new JTextField(6);horizontalCountField.setBounds(160, 5, 40, 30);this.add(horizontalCountField);// 居中Dimension clientSize = Toolkit.getDefaultToolkit().getScreenSize();frameX = (int) ((clientSize.getWidth() - frameW) / 2);frameY = (int) ((clientSize.getHeight() - frameH) / 2);// 窗体属性this.setBounds(frameX, frameY, frameW, frameH);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setResizable(false);this.setVisible(true);this.validate();}/*** 重绘窗体*/@Overridepublic void paint(Graphics g) {super.paint(g);drawMaze(g);}/*** 画迷宫* * @param g*/private void drawMaze(Graphics g) {// 禁止迷宫长度if (mazeUtils.getMazeLength() <= 1) {return;}// 重画迷宫maze = mazeUtils.createMaze(mazeArea, mazeUtils.getMazeLength());// 显示路径mazeUtils.playMazeGame(maze, startPoint, endPoint);// 遍历房间,画房间for (int i = 0; i < mazeUtils.getMazeLength(); i++) {for (int j = 0; j < mazeUtils.getMazeLength(); j++) {// 获得迷宫房间Room room = maze[i][j];// 绘制迷宫房间room.draw(g);}}}@Overridepublic void actionPerformed(ActionEvent e) {// 重新生成迷宫if (e.getSource() == this.remakeMazeButton) {// 修改迷宫的横排方格数量try {mazeUtils.setMazeLength(Integer.parseInt(horizontalCountField.getText()));} catch (Exception e1) {if (mazeUtils.getMazeLength() == 0) {mazeUtils.setMazeLength(10);}}// 画迷宫路径// 随机起点int randX1 = (int) (Math.random() * mazeUtils.getMazeLength());int randY1 = (int) (Math.random() * mazeUtils.getMazeLength());startPoint = new Point(randX1, randY1);// 随机终点int randX2 = 0;int randY2 = 0;while (randX1 == randX2 && randY1 == randY2) {randX2 = (int) (Math.random() * mazeUtils.getMazeLength());randY2 = (int) (Math.random() * mazeUtils.getMazeLength());}endPoint = new Point(randX2, randY2);// 重绘迷宫this.repaint();}}}

MazeUtils.java

package maze.view;import java.awt.Point;
import java.awt.Rectangle;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;/*** 迷宫工具类* * @author 见瑞彬**/
public class MazeUtils {/** 迷宫 */private Room[][] maze;/** 迷宫长度 */private int mazeLength;/** 创建迷宫砸墙工人 */private WallWorker wallWorker;/** 迷宫玩家 完成迷宫任务的人 */private Player player;public MazeUtils() {mazeLength = 0;}/*** 创建迷宫* * @param areaWidth  迷宫区域* @param mazeLength 迷宫宽度* @return*/public Room[][] createMaze(Rectangle area, int mazeLength) {// 取得房间宽度BigDecimal roomWidth = new BigDecimal(area.width).divide(new BigDecimal(mazeLength), 4, RoundingMode.DOWN);// 初始化迷宫的每一个房间maze = new Room[getMazeLength()][getMazeLength()];for (int i = 0; i < getMazeLength(); i++) {for (int j = 0; j < getMazeLength(); j++) {maze[i][j] = new Room(i, j, roomWidth,area.getLocation(),getMazeLength());}}// 初始化砸墙工人,并设定位置wallWorker = new WallWorker(maze);// 迷宫算法规则3, 每一个房间都要到达while (!wallWorker.destroyAllRoom()) {// 迷宫算法规则1,只有当隔壁房间没去过的时候,墙才可以砸boolean pushWallSuccess = destroyStraightRoom();// 迷宫算法规则2, 无墙可砸的时候,就传送到一个去过的房间里if (!pushWallSuccess) {// 跳跃到曾经去过的迷宫房间wallWorker.gotoAnyDestroyedRoom();}}return wallWorker.getMaze();}/*** 规则1:去到相邻的没去过的房间,并砸开与相邻房间之间的墙* * @return*/private boolean destroyStraightRoom() {// 隔壁房间(上下左右)中违法房间的集合List<Integer> illegalRooms = new ArrayList<>();// 遍历隔壁房间while (true) {// 所有隔壁房间都访问失败if (illegalRooms.size() == 4) {return false;}// 随机抽取一个隔壁房间(上下左右)int roomIndex = (int) (Math.random() * 4);// 隔壁房间的合法性的判定if (!illegalRooms.contains(roomIndex)) {// 开始砸墙if (roomIndex == Constant.DIRECT.TOP.ordinal()) {if (wallWorker.destroyTopWall()) {return true;}} else if (roomIndex == Constant.DIRECT.BOTTOM.ordinal()) {if (wallWorker.destroyBottomWall()) {return true;}} else if (roomIndex == Constant.DIRECT.LEFT.ordinal()) {if (wallWorker.destroyLeftWall()) {return true;}} else {if (wallWorker.destroyRightWall()) {return true;}}// 访问失败illegalRooms.add(roomIndex);}}}/*** 开始迷宫游戏* * @param startPoint 起点* @param endPoint   终点* */public Room[][] playMazeGame(Room[][] maze, Point startPoint, Point endPoint) {// 创建玩家player = new Player(maze, startPoint.x, startPoint.y);// 到达终点gotoEndPoint(startPoint, endPoint);List<Point> pointList = player.getPathList();for (int i = 0; i < pointList.size() - 1; i++) {// 当前通路房间位置int v = pointList.get(i).x;int h = pointList.get(i).y;// 下一个通路房间的位置int nextv = pointList.get(i + 1).x;int nexth = pointList.get(i + 1).y;// 设置当前房间为通路房间maze[v][h].getCenterWall().setType(Wall.TYPE.PATH);// 设置当前房间和下一个房间之间的墙体的类型if (v - 1 == nextv) {maze[v][h].getTopWall().setType(Wall.TYPE.PATH);maze[nextv][nexth].getBottomWall().setType(Wall.TYPE.PATH);} else if (v + 1 == nextv) {maze[v][h].getBottomWall().setType(Wall.TYPE.PATH);maze[nextv][nexth].getTopWall().setType(Wall.TYPE.PATH);} else if (h - 1 == nexth) {maze[v][h].getLeftWall().setType(Wall.TYPE.PATH);maze[nextv][nexth].getRightWall().setType(Wall.TYPE.PATH);} else {maze[v][h].getRightWall().setType(Wall.TYPE.PATH);maze[nextv][nexth].getLeftWall().setType(Wall.TYPE.PATH);}}maze[pointList.get(pointList.size() - 1).x][pointList.get(pointList.size() - 1).y].getCenterWall().setType(Wall.TYPE.PATH);return maze;}/*** 从起点走到终点* * @param maze 迷宫*/private void gotoEndPoint(Point startPoint, Point endPoint) {int direct = 0;while (true) {// 如果到达终点,则寻路成功if (player.getVertical() == endPoint.x && player.getHorizontal() == endPoint.y) {break;}// 遍历周围的房间(上下左右)if (direct > 3) {direct = 0;}if (direct == Constant.DIRECT.TOP.ordinal()) {player.walkTopRoom();} else if (direct == Constant.DIRECT.BOTTOM.ordinal()) {player.walkBottomRoom();} else if (direct == Constant.DIRECT.LEFT.ordinal()) {player.walkLeftRoom();} else {player.walkRightRoom();}direct++;}}/*** @return the maze*/public Room[][] getMaze() {return maze;}/*** @param maze the maze to set*/public void setMaze(Room[][] maze) {this.maze = maze;}/*** @return the mazeLength*/public int getMazeLength() {return mazeLength;}/*** @param mazeLength the mazeLength to set*/public void setMazeLength(int mazeLength) {this.mazeLength = mazeLength;}/*** @return the wallWorker*/public WallWorker getWallWorker() {return wallWorker;}/*** @param wallWorker the wallWorker to set*/public void setWallWorker(WallWorker wallWorker) {this.wallWorker = wallWorker;}/*** @return the player*/public Player getPlayer() {return player;}/*** @param player the player to set*/public void setPlayer(Player player) {this.player = player;}}

Player.java

package maze.view;import java.awt.Point;
import java.util.ArrayList;
import java.util.List;/*** 玩家类* * @author 见瑞彬**/
public class Player {/** 玩家水平坐标 */private int horizontal;/** 玩家垂直坐标 */private int vertical;/** 玩家所在的迷宫 */private Room[][] maze;/** 记录玩家走过的轨迹 */List<Point> pathList;/*** 设定玩家默认属性* * @param maze* @param vertical* @param horizontal*/public Player(Room[][] maze, int vertical, int horizontal) {// 迷宫this.maze = new Room[maze.length][maze.length];for (int i = 0; i < maze.length; i++) {for (int j = 0; j < maze.length; j++) {this.maze[i][j] = new Room(maze[i][j].getVertical(), maze[i][j].getHorizontal(), maze[i][j].getWidth(),new Point(maze[i][j].getLeftTopWall().getHorizontalPx().intValue(),maze[i][j].getLeftTopWall().getVerticalPx().intValue()),maze.length);this.maze[i][j].setTopWall(maze[i][j].getTopWall());this.maze[i][j].setBottomWall(maze[i][j].getBottomWall());this.maze[i][j].setLeftWall(maze[i][j].getLeftWall());this.maze[i][j].setRightWall(maze[i][j].getRightWall());}}// 玩家位置this.vertical = vertical;this.horizontal = horizontal;// 轨迹起点pathList = new ArrayList<>();pathList.add(new Point(vertical, horizontal));}/*** 当前位置是否已经不在迷宫* * @param vertical* @param horizontal* @return*/private boolean isOutMaze(int vertical, int horizontal) {if (vertical >= 0 && vertical < maze.length && horizontal >= 0 && horizontal < maze.length) {// 不出界,返回falsereturn false;}// 出界返回truereturn true;}/*** 判断这个点是否走过* * @param vertical* @param horizontal* @return*/private boolean existsPoint(int vertical, int horizontal) {for (int i = 0; i < pathList.size(); i++) {if (pathList.get(i).x == vertical && pathList.get(i).y == horizontal) {return true;}}return false;}/*** 走向上面的房间* * @return*/public void walkTopRoom() {// 下面的位置int nextVertical = vertical - 1;int nextHorizontal = horizontal;Room room = maze[vertical][horizontal];// 如果玩家所在房间的上面有墙,则不能走向到上面的房间if (room.getTopWall().getType() == Wall.TYPE.WALL) {// 如果当前房间上左右有墙if (room.getLeftWall().getType() == Wall.TYPE.WALL && room.getRightWall().getType() == Wall.TYPE.WALL) {// 后面的位置int lastVertical = vertical + 1;int lastHorizontal = horizontal;// 筑墙,防止再次走maze[vertical][horizontal].getBottomWall().setType(Wall.TYPE.WALL);maze[lastVertical][lastHorizontal].getTopWall().setType(Wall.TYPE.WALL);// 已经走过的情况if (existsPoint(lastVertical, lastHorizontal)) {pathList.remove(pathList.size() - 1);} else {// 没有走过的情况pathList.add(new Point(lastVertical, lastHorizontal));}// 更新位置vertical = lastVertical;horizontal = lastHorizontal;}return;}// 如果上面的房间已经走过了,则不能再走if (existsPoint(nextVertical, nextHorizontal)) {return;}// 如果出界了,不能继续走if (isOutMaze(nextVertical, nextHorizontal)) {return;}// 走到上面的房间pathList.add(new Point(nextVertical, nextHorizontal));// 更新位置vertical = nextVertical;horizontal = nextHorizontal;}/*** 走向下面的房间* * @return*/public void walkBottomRoom() {// 下面的位置int nextVertical = vertical + 1;int nextHorizontal = horizontal;Room room = maze[vertical][horizontal];// 如果玩家所在房间的下面有墙,则不能走向到下面的房间if (room.getBottomWall().getType() == Wall.TYPE.WALL) {// 如果当前房间下左右有墙if (room.getLeftWall().getType() == Wall.TYPE.WALL && room.getRightWall().getType() == Wall.TYPE.WALL) {// 后面的位置int lastVertical = vertical - 1;int lastHorizontal = horizontal;// 筑墙,防止再次走maze[vertical][horizontal].getTopWall().setType(Wall.TYPE.WALL);maze[lastVertical][lastHorizontal].getBottomWall().setType(Wall.TYPE.WALL);// 已经走过的情况if (existsPoint(lastVertical, lastHorizontal)) {pathList.remove(pathList.size() - 1);} else {// 没有走过的情况pathList.add(new Point(lastVertical, lastHorizontal));}// 更新位置vertical = lastVertical;horizontal = lastHorizontal;}return;}// 如果上面的房间已经走过了,则不能再走if (existsPoint(nextVertical, nextHorizontal)) {return;}// 如果出界了,不能继续走if (isOutMaze(nextVertical, nextHorizontal)) {return;}// 走到下面的房间pathList.add(new Point(nextVertical, nextHorizontal));// 更新位置vertical = nextVertical;horizontal = nextHorizontal;}/*** 走向左面的房间* * @return*/public void walkLeftRoom() {// 左面的位置int nextVertical = vertical;int nextHorizontal = horizontal - 1;Room room = maze[vertical][horizontal];// 如果玩家所在房间的左面有墙,则不能走向到左面的房间if (room.getLeftWall().getType() == Wall.TYPE.WALL) {// 如果当前房间左上下有墙if (room.getTopWall().getType() == Wall.TYPE.WALL && room.getBottomWall().getType() == Wall.TYPE.WALL) {// 后面的位置int lastVertical = vertical;int lastHorizontal = horizontal + 1;// 筑墙,防止再次走maze[vertical][horizontal].getRightWall().setType(Wall.TYPE.WALL);maze[lastVertical][lastHorizontal].getLeftWall().setType(Wall.TYPE.WALL);// 已经走过的情况if (existsPoint(lastVertical, lastHorizontal)) {pathList.remove(pathList.size() - 1);} else {// 没有走过的情况pathList.add(new Point(lastVertical, lastHorizontal));}// 更新位置vertical = lastVertical;horizontal = lastHorizontal;}return;}// 如果左面的房间已经走过了,则不能再走if (existsPoint(nextVertical, nextHorizontal)) {return;}// 如果出界了,不能继续走if (isOutMaze(nextVertical, nextHorizontal)) {return;}// 走到左面的房间pathList.add(new Point(nextVertical, nextHorizontal));// 更新位置vertical = nextVertical;horizontal = nextHorizontal;}/*** 走向右面的房间* * @return*/public void walkRightRoom() {// 右面的位置int nextVertical = vertical;int nextHorizontal = horizontal + 1;Room room = maze[vertical][horizontal];// 如果玩家所在房间的右面有墙,则不能走向到右面的房间if (room.getRightWall().getType() == Wall.TYPE.WALL) {// 如果当前房间上下右有墙if (room.getTopWall().getType() == Wall.TYPE.WALL && room.getBottomWall().getType() == Wall.TYPE.WALL) {// 后面的位置int lastVertical = vertical;int lastHorizontal = horizontal - 1;// 筑墙,防止再次走maze[vertical][horizontal].getLeftWall().setType(Wall.TYPE.WALL);maze[lastVertical][lastHorizontal].getRightWall().setType(Wall.TYPE.WALL);// 已经走过的情况if (existsPoint(lastVertical, lastHorizontal)) {pathList.remove(pathList.size() - 1);} else {// 没有走过的情况pathList.add(new Point(lastVertical, lastHorizontal));}// 更新位置vertical = lastVertical;horizontal = lastHorizontal;}return;}// 如果右面的房间已经走过了,则不能再走if (existsPoint(nextVertical, nextHorizontal)) {return;}// 如果下面的位置出界了,则不能继续走if (isOutMaze(nextVertical, nextHorizontal)) {return;}// 走到右面的房间pathList.add(new Point(nextVertical, nextHorizontal));// 更新位置vertical = nextVertical;horizontal = nextHorizontal;}/*** @return the thoughPoints*/public List<Point> getPathList() {return pathList;}/*** @return the horizontal*/public int getHorizontal() {return horizontal;}/*** @return the vertical*/public int getVertical() {return vertical;}}

Room.java

package maze.view;import java.awt.Color;
import java.awt.Graphics;
import java.awt.Point;
import java.math.BigDecimal;
import java.math.RoundingMode;public class Room {/** 上面的墙 */private Wall topWall;/** 下面的墙 */private Wall bottomWall;/** 左面的墙 */private Wall leftWall;/** 右面的墙 */private Wall rightWall;/** 左上角墙体 */private Wall leftTopWall;/** 左下角墙体 */private Wall leftBottomWall;/** 右上角墙体 */private Wall rightTopWall;/** 右下角墙体 */private Wall rightBottomWall;/** 中间墙体 */private Wall centerWall;/** 是否墙体被砸过 */private boolean destroyed;/** 水平坐标 */private int horizontal;/** 垂直坐标 */private int vertical;/** 房间宽度(两侧墙体+房间中心) */private BigDecimal width;int mazeLength;/**** 设定房间默认属性* * @param vertical   垂直坐标位置* @param horizontal 水平坐标位置* @param width      房间宽度*/public Room(int vertical, int horizontal, BigDecimal width,Point location,int mazeLength) {this.mazeLength = mazeLength;// 设定房间坐标位置this.vertical = vertical;this.horizontal = horizontal;// ***************** 计算房间在迷宫中的像素位置,并设定各个墙体的位置和宽高 *****************BigDecimal vPx = new BigDecimal(vertical).multiply(width).add(new BigDecimal(location.y));BigDecimal hPx = new BigDecimal(horizontal).multiply(width).add(new BigDecimal(location.x));// 墙体单元宽度BigDecimal unit = width.divide(new BigDecimal(4), RoundingMode.DOWN); // 宽度的1/4BigDecimal unit2 = unit.add(unit); // 宽度的2/4BigDecimal unit3 = unit2.add(unit); // 宽度的3/4BigDecimal one = new BigDecimal(1);BigDecimal two = new BigDecimal(2);// 设定四角的墙体,显示墙体颜色// 设定左上角墙体Wall leftTopWall = new Wall();leftTopWall.setVerticalPx(vPx);leftTopWall.setHorizontalPx(hPx);leftTopWall.setWidthPx(unit);leftTopWall.setHeightPx(unit);leftTopWall.setType(Wall.TYPE.WALL);this.setLeftTopWall(leftTopWall);// 设定左下角墙体Wall leftBottomWall = new Wall();leftBottomWall.setVerticalPx(vPx.add(unit3));leftBottomWall.setHorizontalPx(hPx);leftBottomWall.setWidthPx(unit);if(this.getVertical() == mazeLength - 1) {leftBottomWall.setHeightPx(unit);}else {leftBottomWall.setHeightPx(unit.add(one));}leftBottomWall.setType(Wall.TYPE.WALL);this.setLeftBottomWall(leftBottomWall);// 设定右上角墙体Wall rightTopWall = new Wall();rightTopWall.setVerticalPx(vPx);rightTopWall.setHorizontalPx(hPx.add(unit3));if(this.getHorizontal() == mazeLength - 1) {rightTopWall.setWidthPx(unit2);}else {rightTopWall.setWidthPx(unit.add(one));}rightTopWall.setHeightPx(unit);rightTopWall.setType(Wall.TYPE.WALL);this.setRightTopWall(rightTopWall);// 设定右下角墙体Wall rightBottomWall = new Wall();rightBottomWall.setVerticalPx(vPx.add(unit3));rightBottomWall.setHorizontalPx(hPx.add(unit3));if(this.getHorizontal() == mazeLength - 1) {rightBottomWall.setWidthPx(unit2);}else {rightBottomWall.setWidthPx(unit.add(one));}if(this.getVertical() == mazeLength - 1) {rightBottomWall.setHeightPx(unit);}else {rightBottomWall.setHeightPx(unit.add(one));}rightBottomWall.setType(Wall.TYPE.WALL);this.setRightBottomWall(rightBottomWall);// 设定四边墙体,默认是透明,显示迷宫背景色// 设定上面墙体Wall topWall = new Wall();topWall.setHorizontalPx(hPx.add(unit).subtract(one));topWall.setVerticalPx(vPx);topWall.setWidthPx(unit2.add(two));topWall.setHeightPx(unit);topWall.setType(Wall.TYPE.WALL);this.setTopWall(topWall);// 设定下面墙体Wall bottomWall = new Wall();bottomWall.setHorizontalPx(hPx.add(unit).subtract(one));bottomWall.setVerticalPx(vPx.add(unit3));bottomWall.setWidthPx(unit2.add(two));if(this.getVertical() == mazeLength - 1) {bottomWall.setHeightPx(unit);}else {bottomWall.setHeightPx(unit.add(one));}bottomWall.setType(Wall.TYPE.WALL);this.setBottomWall(bottomWall);// 设定左面墙体Wall leftWall = new Wall();leftWall.setHorizontalPx(hPx);leftWall.setVerticalPx(vPx.add(unit).subtract(one));leftWall.setWidthPx(unit);leftWall.setHeightPx(unit2.add(two));leftWall.setType(Wall.TYPE.WALL);this.setLeftWall(leftWall);// 设定右面墙体Wall rightWall = new Wall();rightWall.setHorizontalPx(hPx.add(unit3));rightWall.setVerticalPx(vPx.add(unit).subtract(one));if(this.getHorizontal() == mazeLength - 1) {rightWall.setWidthPx(unit2);}else {rightWall.setWidthPx(unit.add(one));}rightWall.setHeightPx(unit2.add(two));rightWall.setType(Wall.TYPE.WALL);this.setRightWall(rightWall);// 设定中间墙体Wall centerWall = new Wall();centerWall.setVerticalPx(vPx.add(unit));centerWall.setHorizontalPx(hPx.add(unit));centerWall.setWidthPx(unit2);centerWall.setHeightPx(unit2);centerWall.setType(Wall.TYPE.DESTROYED);this.setCenterWall(centerWall);// 设定房间状态,默认房间的墙体没有被砸this.destroyed = false;// 设定房间宽度this.width = width;}/*** 画房间* * @param g           画笔* @param showPathFlg 是否画路径*/public void draw(Graphics g) {Color color = g.getColor();// 画墙的颜色Color wallColor = Color.RED;g.setColor(wallColor);// 画四角的墙if(this.getVertical() == 0) {g.fillRect(this.getLeftTopWall().getHorizontalPx().intValue(),this.getLeftTopWall().getVerticalPx().subtract(this.getLeftTopWall().getHeightPx()).intValue()+1,this.getLeftTopWall().getWidthPx().intValue(),this.getLeftTopWall().getHeightPx().intValue());g.fillRect(this.getLeftTopWall().getHorizontalPx().intValue(),this.getLeftTopWall().getVerticalPx().intValue(),this.getLeftTopWall().getWidthPx().intValue(),this.getLeftTopWall().getHeightPx().intValue());}else {g.fillRect(this.getLeftTopWall().getHorizontalPx().intValue(),this.getLeftTopWall().getVerticalPx().intValue(),this.getLeftTopWall().getWidthPx().intValue(),this.getLeftTopWall().getHeightPx().intValue());}g.fillRect(this.getLeftBottomWall().getHorizontalPx().intValue(),this.getLeftBottomWall().getVerticalPx().intValue(),this.getLeftBottomWall().getWidthPx().intValue(),this.getLeftBottomWall().getHeightPx().intValue());if(this.getVertical() == 0) {g.fillRect(this.getRightTopWall().getHorizontalPx().intValue(),this.getRightTopWall().getVerticalPx().subtract(this.getRightTopWall().getHeightPx()).intValue()+1,this.getRightTopWall().getWidthPx().intValue(),this.getRightTopWall().getHeightPx().intValue());g.fillRect(this.getRightTopWall().getHorizontalPx().intValue(),this.getRightTopWall().getVerticalPx().intValue(),this.getRightTopWall().getWidthPx().intValue(),this.getRightTopWall().getHeightPx().intValue());}else {g.fillRect(this.getRightTopWall().getHorizontalPx().intValue(),this.getRightTopWall().getVerticalPx().intValue(),this.getRightTopWall().getWidthPx().intValue(),this.getRightTopWall().getHeightPx().intValue());}g.fillRect(this.getRightBottomWall().getHorizontalPx().intValue(),this.getRightBottomWall().getVerticalPx().intValue(),this.getRightBottomWall().getWidthPx().intValue(),this.getRightBottomWall().getHeightPx().intValue());// 画四边的墙if (this.getTopWall().getType() == Wall.TYPE.WALL) {if(this.getVertical() == 0) {g.fillRect(this.getTopWall().getHorizontalPx().intValue(),this.getTopWall().getVerticalPx().subtract(this.getTopWall().getHeightPx()).intValue()+1,this.getTopWall().getWidthPx().intValue(),this.getTopWall().getHeightPx().intValue());g.fillRect(this.getTopWall().getHorizontalPx().intValue(),this.getTopWall().getVerticalPx().intValue(),this.getTopWall().getWidthPx().intValue(),this.getTopWall().getHeightPx().intValue());}else {g.fillRect(this.getTopWall().getHorizontalPx().intValue(),this.getTopWall().getVerticalPx().intValue(),this.getTopWall().getWidthPx().intValue(),this.getTopWall().getHeightPx().intValue());}}if (this.getBottomWall().getType() == Wall.TYPE.WALL) {g.fillRect(this.getBottomWall().getHorizontalPx().intValue(),this.getBottomWall().getVerticalPx().intValue(),this.getBottomWall().getWidthPx().intValue(),this.getBottomWall().getHeightPx().intValue());}if (this.getLeftWall().getType() == Wall.TYPE.WALL) {g.fillRect(this.getLeftWall().getHorizontalPx().intValue(),this.getLeftWall().getVerticalPx().intValue(),this.getLeftWall().getWidthPx().intValue(),this.getLeftWall().getHeightPx().intValue());}if (this.getRightWall().getType() == Wall.TYPE.WALL) {g.fillRect(this.getRightWall().getHorizontalPx().intValue(),this.getRightWall().getVerticalPx().intValue(),this.getRightWall().getWidthPx().intValue(),this.getRightWall().getHeightPx().intValue());}// 画路径的颜色Color pathColor = Color.GREEN;g.setColor(pathColor);BigDecimal unit = this.getCenterWall().getWidthPx().divide(new BigDecimal(4));BigDecimal unit2 = unit.multiply(new BigDecimal(2));BigDecimal unit3 = unit.multiply(new BigDecimal(3));// 画路径if (this.getCenterWall().getType() == Wall.TYPE.PATH) {// 上if (this.getTopWall().getType() == Wall.TYPE.PATH) {// 上面的墙g.fillRect(this.getTopWall().getHorizontalPx().add(unit).intValue(),this.getTopWall().getVerticalPx().intValue()-1,unit2.intValue(),this.getTopWall().getHeightPx().intValue()+2);// 中间的墙g.fillRect(this.getCenterWall().getHorizontalPx().add(unit).intValue(),this.getCenterWall().getVerticalPx().intValue(),unit2.intValue(),unit3.intValue());}// 下if (this.getBottomWall().getType() == Wall.TYPE.PATH) {// 下面的墙g.fillRect(this.getBottomWall().getHorizontalPx().add(unit).intValue(),this.getBottomWall().getVerticalPx().intValue()-1,unit2.intValue(),this.getBottomWall().getHeightPx().intValue()+2);// 中间的墙g.fillRect(this.getCenterWall().getHorizontalPx().add(unit).intValue(),this.getCenterWall().getVerticalPx().add(unit).intValue(),unit2.intValue(),unit3.intValue());}if (this.getLeftWall().getType() == Wall.TYPE.PATH) {// 左面的墙g.fillRect(this.getLeftWall().getHorizontalPx().intValue()-1,this.getLeftWall().getVerticalPx().add(unit).intValue(),this.getLeftWall().getWidthPx().intValue()+2, unit2.intValue());// 中间的墙g.fillRect(this.getCenterWall().getHorizontalPx().intValue(),this.getCenterWall().getVerticalPx().add(unit).intValue(),unit3.intValue(),unit2.intValue());}if (this.getRightWall().getType() == Wall.TYPE.PATH) {// 右面的墙g.fillRect(this.getRightWall().getHorizontalPx().intValue()-1,this.getRightWall().getVerticalPx().add(unit).intValue(),this.getRightWall().getWidthPx().intValue()+2,unit2.intValue());// 中间的墙g.fillRect(this.getCenterWall().getHorizontalPx().add(unit).intValue(),this.getCenterWall().getVerticalPx().add(unit).intValue(),unit3.intValue(),unit2.intValue());}}g.setColor(color);}/*** @return the topWall*/public Wall getTopWall() {return topWall;}/*** @param topWall the topWall to set*/public void setTopWall(Wall topWall) {Wall wall = new Wall();wall.setType(topWall.getType());wall.setHeightPx(topWall.getHeightPx());wall.setHorizontalPx(topWall.getHorizontalPx());wall.setVerticalPx(topWall.getVerticalPx());wall.setWidthPx(topWall.getWidthPx());this.topWall = wall;}/*** @return the bottomWall*/public Wall getBottomWall() {return bottomWall;}/*** @param bottomWall the bottomWall to set*/public void setBottomWall(Wall bottomWall) {Wall wall = new Wall();wall.setType(bottomWall.getType());wall.setHeightPx(bottomWall.getHeightPx());wall.setHorizontalPx(bottomWall.getHorizontalPx());wall.setVerticalPx(bottomWall.getVerticalPx());wall.setWidthPx(bottomWall.getWidthPx());this.bottomWall = wall;}/*** @return the leftWall*/public Wall getLeftWall() {return leftWall;}/*** @param leftWall the leftWall to set*/public void setLeftWall(Wall leftWall) {Wall wall = new Wall();wall.setType(leftWall.getType());wall.setHeightPx(leftWall.getHeightPx());wall.setHorizontalPx(leftWall.getHorizontalPx());wall.setVerticalPx(leftWall.getVerticalPx());wall.setWidthPx(leftWall.getWidthPx());this.leftWall = wall;}/*** @return the rightWall*/public Wall getRightWall() {return rightWall;}/*** @param rightWall the rightWall to set*/public void setRightWall(Wall rightWall) {Wall wall = new Wall();wall.setType(rightWall.getType());wall.setHeightPx(rightWall.getHeightPx());wall.setHorizontalPx(rightWall.getHorizontalPx());wall.setVerticalPx(rightWall.getVerticalPx());wall.setWidthPx(rightWall.getWidthPx());this.rightWall = wall;}/*** @return the leftTopWall*/public Wall getLeftTopWall() {return leftTopWall;}/*** @param leftTopWall the leftTopWall to set*/public void setLeftTopWall(Wall leftTopWall) {this.leftTopWall = leftTopWall;}/*** @return the leftBottomWall*/public Wall getLeftBottomWall() {return leftBottomWall;}/*** @param leftBottomWall the leftBottomWall to set*/public void setLeftBottomWall(Wall leftBottomWall) {this.leftBottomWall = leftBottomWall;}/*** @return the rightTopWall*/public Wall getRightTopWall() {return rightTopWall;}/*** @param rightTopWall the rightTopWall to set*/public void setRightTopWall(Wall rightTopWall) {this.rightTopWall = rightTopWall;}/*** @return the rightBottomWall*/public Wall getRightBottomWall() {return rightBottomWall;}/*** @param rightBottomWall the rightBottomWall to set*/public void setRightBottomWall(Wall rightBottomWall) {this.rightBottomWall = rightBottomWall;}/*** @return the centerWall*/public Wall getCenterWall() {return centerWall;}/*** @param centerWall the centerWall to set*/public void setCenterWall(Wall centerWall) {this.centerWall = centerWall;}/*** @return the destroyed*/public boolean isDestroyed() {return destroyed;}/*** @param destroyed the destroyed to set*/public void setDestroyed(boolean destroyed) {this.destroyed = destroyed;}/*** @return the horizontal*/public int getHorizontal() {return horizontal;}/*** @param horizontal the horizontal to set*/public void setHorizontal(int horizontal) {this.horizontal = horizontal;}/*** @return the vertical*/public int getVertical() {return vertical;}/*** @param vertical the vertical to set*/public void setVertical(int vertical) {this.vertical = vertical;}/*** @return the width*/public BigDecimal getWidth() {return width;}/*** @param width the width to set*/public void setWidth(BigDecimal width) {this.width = width;}}

Start.java

package maze.view;import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileLock;public class Start {private static FileLock lock = null;// 判断该应用是否已启动public static boolean isRunning() {try {// 获得实例标志文件File flagFile = new File(".lock");// 如果不存在就新建一个if (!flagFile.exists())flagFile.createNewFile();// 获得文件锁lock = new FileOutputStream(flagFile).getChannel().tryLock();// 返回空表示文件已被运行的实例锁定if (lock == null)return false;} catch (Exception ex) {ex.printStackTrace();}return true;}public static void main(String[] args) {MainFrame mf = null;// 保证只有一个主窗体运行if (isRunning()) {mf = new MainFrame();mf.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosed(WindowEvent e) {super.windowClosing(e);try {lock.release();} catch (IOException e1) {// TODO Auto-generated catch blocke1.printStackTrace();}}});}}
}

Wall.java

package maze.view;import java.math.BigDecimal;public class Wall {/** 墙体类型 */public static enum TYPE {/** 被砸过的墙,显示迷宫背景色 */DESTROYED/** 正常的墙,显示墙的颜色 */, WALL/** 路,显示路的颜色 */, PATH, START, END}/** 墙体垂直像素位置 */private BigDecimal verticalPx;/** 墙体水平像素位置 */private BigDecimal horizontalPx;/** 墙体像素宽度 */private BigDecimal widthPx;/** 墙体像素高度 */private BigDecimal heightPx;/** 墙的类型 */private TYPE type;public Wall() {// 墙体类型默认是透明,显示迷宫背景色this.type = TYPE.DESTROYED;}/*** @return the verticalPx*/public BigDecimal getVerticalPx() {return verticalPx;}/*** @param verticalPx the verticalPx to set*/public void setVerticalPx(BigDecimal verticalPx) {this.verticalPx = verticalPx;}/*** @return the horizontalPx*/public BigDecimal getHorizontalPx() {return horizontalPx;}/*** @param horizontalPx the horizontalPx to set*/public void setHorizontalPx(BigDecimal horizontalPx) {this.horizontalPx = horizontalPx;}/*** @return the widthPx*/public BigDecimal getWidthPx() {return widthPx;}/*** @param widthPx the widthPx to set*/public void setWidthPx(BigDecimal widthPx) {this.widthPx = widthPx;}/*** @return the heightPx*/public BigDecimal getHeightPx() {return heightPx;}/*** @param heightPx the heightPx to set*/public void setHeightPx(BigDecimal heightPx) {this.heightPx = heightPx;}/*** @return the type*/public TYPE getType() {return type;}/*** @param type the type to set*/public void setType(TYPE type) {this.type = type;}}

WallWorker.java

package maze.view;/*** 迷宫砸墙工人类* * @author 见瑞彬**/
public class WallWorker {/** 砸墙工人水平坐标 */private int horizontal;/** 砸墙工人垂直坐标 */private int vertical;/** 砸墙工人所在的迷宫 */private Room[][] maze;/*** * @param startHorizontal 起点水平坐标* @param startVertical   起点垂直坐标* @param maze            迷宫*/public WallWorker(Room[][] maze) {// 取得迷宫this.maze = maze;// 设定 砸墙工人的起点房间this.setVertical(0);this.setHorizontal(0);maze[0][0].setDestroyed(true);}/*** 所有的房间是否都被砸过墙* * @return*/public boolean destroyAllRoom() {for (int i = 0; i < maze.length; i++) {for (int j = 0; j < maze.length; j++) {// 当判定该房间没有的墙没有被砸过,则继续砸墙if (!maze[i][j].isDestroyed()) {return false;}}}return true;}/*** 就传送到一个被砸过的房间里*/public void gotoAnyDestroyedRoom() {while (true) {// 随机位置int vertical = (int) (Math.random() * maze.length);int horizontal = (int) (Math.random() * maze.length);// 已访问判定if (maze[vertical][horizontal].isDestroyed()) {// 访问这个房间this.setVertical(vertical);this.setHorizontal(horizontal);break;}}}/*** 当前位置是否已经不在迷宫* * @param vertical* @param horizontal* @return*/private boolean isOutMaze(int vertical, int horizontal) {if (vertical >= 0 && vertical < maze.length && horizontal >= 0 && horizontal < maze.length) {// 不出界,返回falsereturn false;}// 出界返回truereturn true;}/*** 砸开房间上面的墙* * @return*/public boolean destroyTopWall() {// 上面房间的垂直、水平坐标int nextVertical = this.getVertical() - 1;int nextHorizontal = this.getHorizontal();// 出界if (isOutMaze(nextVertical, nextHorizontal)) {return false;}// 如果已经被砸过if (maze[nextVertical][nextHorizontal].isDestroyed()) {return false;}// 砸墙maze[getVertical()][getHorizontal()].getTopWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].getBottomWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].setDestroyed(true);// 更新砸墙工人的位置this.setVertical(nextVertical);this.setHorizontal(nextHorizontal);return true;}/*** 砸开房间下面的墙* * @return*/public boolean destroyBottomWall() {// 下面房间的垂直、水平坐标int nextVertical = getVertical() + 1;int nextHorizontal = getHorizontal();// 出界if (isOutMaze(nextVertical, nextHorizontal)) {return false;}// 如果已经被砸过if (maze[nextVertical][nextHorizontal].isDestroyed()) {return false;}// 砸墙maze[getVertical()][getHorizontal()].getBottomWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].getTopWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].setDestroyed(true);// 更新砸墙工人的位置this.setVertical(nextVertical);this.setHorizontal(nextHorizontal);return true;}/*** 砸开房间左面的墙* * @return*/public boolean destroyLeftWall() {// 左面房间的垂直、水平坐标int nextVertical = getVertical();int nextHorizontal = getHorizontal() - 1;// 出界if (isOutMaze(nextVertical, nextHorizontal)) {return false;}// 如果已经被砸过if (maze[nextVertical][nextHorizontal].isDestroyed()) {return false;}// 砸墙maze[getVertical()][getHorizontal()].getLeftWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].getRightWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].setDestroyed(true);// 更新砸墙工人的位置this.setVertical(nextVertical);this.setHorizontal(nextHorizontal);return true;}/*** 砸开房间右面的墙* * @return*/public boolean destroyRightWall() {// 右面房间的垂直、水平坐标int nextVertical = getVertical();int nextHorizontal = getHorizontal() + 1;// 出界if (isOutMaze(nextVertical, nextHorizontal)) {return false;}// 如果已经被砸过if (maze[nextVertical][nextHorizontal].isDestroyed()) {return false;}// 砸墙maze[getVertical()][getHorizontal()].getRightWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].getLeftWall().setType(Wall.TYPE.DESTROYED);maze[nextVertical][nextHorizontal].setDestroyed(true);// 更新砸墙工人的位置this.setVertical(nextVertical);this.setHorizontal(nextHorizontal);return true;}/*** @return the horizontal*/public int getHorizontal() {return horizontal;}/*** @param horizontal the horizontal to set*/public void setHorizontal(int horizontal) {this.horizontal = horizontal;}/*** @return the vertical*/public int getVertical() {return vertical;}/*** @param vertical the vertical to set*/public void setVertical(int vertical) {this.vertical = vertical;}/*** @return the maze*/public Room[][] getMaze() {return maze;}/*** @param maze the maze to set*/public void setMaze(Room[][] maze) {this.maze = maze;}}

Java 代码分享(第4篇),绘制迷宫2 绘制起点终点和路径相关推荐

  1. 好程序员Java教程分享之jvm篇

    好程序员java教程分享之jvm篇,在前面的文章中,介绍了JVM内存模型分为:堆区.虚拟机栈.方法区.本地方法区和程序计数器,其中堆区是JVM中最大的一块内存区域,在Java中的所有对象实例都保存在此 ...

  2. 【纯干货】微信支付接入攻略—JAVA代码分享

    [纯干货]微信支付接入攻略-JAVA代码分享 [声明]本文作者是Gekec网站开发总监Arne Chen.Arne在实际接入微信支付时遇到诸多问题并且逐一解决的过程中总结了不少实战经验.文中引用代码是 ...

  3. 模拟退火算法 java_转 | 模拟退火算法(SA)和迭代局部搜索(ILS)求解TSP的Java代码分享...

    以下文章来源于数据魔术师 ,作者周航 前言 大家好呀!我们你们好久不见的...咳咳,初次见面的小编! 之前重新整理了ILS的代码,有人留言问能不能提供java版. 正好最近在学启发式算法和java,为 ...

  4. 百度午夜蓝地图瓦片数据爬取--java代码(地图数据篇.15)

    听老人家说:多看美女会长寿 地图之家总目录(建议先查看该内容) 文章末尾处提供保证可运行完整代码包,运行如有问题,可"私信"博主. 效果如下所示: 爬取后的瓦片数据可通过nginx ...

  5. 腾讯地图影像瓦片数据爬取--java代码(地图数据篇.9)

    听老人家说:多看美女会长寿 地图之家总目录(建议先查看该内容) 文章末尾处提供保证可运行完整代码包,运行如有问题,可"私信"博主. 效果如下所示: 爬取后的瓦片数据可通过nginx ...

  6. 天地图瓦片数据爬取--java代码(地图数据篇.1)

    听老人家说:多看美女会长寿 地图之家总目录(建议先查看该内容) 文章末尾处提供保证可运行完整代码包,运行如有问题,可"私信"博主. 效果如下所示: 爬取后的瓦片数据可通过nginx ...

  7. 高德地图、google、openstreenmap地图瓦片数据爬取--java代码(地图数据篇.3)

    听老人家说:多看美女会长寿 地图之家总目录(建议先查看该内容) 文章末尾处提供保证可运行完整代码包,运行如有问题,可"私信"博主. 效果如下所示: 爬取后的瓦片数据可通过nginx ...

  8. 百度地图瓦片数据爬取--java代码(地图数据篇.2)

    听老人家说:多看美女会长寿 地图之家总目录(建议先查看该内容) 文章末尾处提供保证可运行完整代码包,运行如有问题,可"私信"博主. 效果如下所示: 爬取后的瓦片数据可通过nginx ...

  9. python迷宫起点终点所有路径_通向终点的路不止一条!python迷宫。

    马上注册,结交更多好友,享用更多功能^_^ 您需要 登录 才可以下载或查看,没有帐号?立即注册 x 本帖最后由 wei_Y 于 2014-11-24 19:53 编辑 2008121223547917 ...

最新文章

  1. 解决svn Authorization failed错误
  2. BZOJ2339: [HNOI2011]卡农(dp 容斥)
  3. .NET MongoDB Driver 2.2使用示例
  4. 机器学习中Python常用库总结(numpy,scipy,matplotlib,pandas)
  5. linux七大功能,值得Linux向其他系统借鉴的七大功能特性
  6. C语言经典算法 11-20
  7. 【微信小程序】生成二维码方式
  8. 使用Mutex进行线程处理
  9. VSTO学习笔记(二)Excel对象模型
  10. 距离的度量(Dissimilarity Measure、Distance Metric)
  11. 摆脱Wi-Fi信号干扰的对策
  12. 关于直线、折线分割平面,平面的分割空间问题
  13. linux下内存释放问题
  14. js设置北京时区_盘一盘 Python 系列特别篇十九之 时区和夏时令
  15. PMP认证考试情况整理
  16. 通过AT指令将air202 接入阿里云
  17. 利用文本挖掘技术来找出《天龙八部》中的“小鲜词”
  18. markdown文本居中
  19. 你还在用 format 格式化字符串?
  20. 查看linux当前屏保文件夹,linux下屏保设置

热门文章

  1. 秋招提前批来了,早就是优势!
  2. Android 解决打包时提示65536问题
  3. k8s调度之亲和/反亲和
  4. 卸载工具Android,教你轻松卸载/删除Android手机内置游戏/软件
  5. Python数据清洗:提取爬虫文本中的电话号码
  6. 系统分析师-资料总结-中
  7. 《算法竞赛中的初等数论》(六)正文 0x60 原根(ACM / OI / MO)(二十万字符数论书)
  8. 数据资产管理的5个步骤和6个要素
  9. ubuntu文献翻译软件:兰译
  10. 公众号模板消息 跳转小程序报错invalid weapp pagepath解决方法