基于bfs搜索算法的迷宫最短路径游戏
废话不多说:因为在我的上一篇博客里已经提到了bfs算法.花了一天的时间写的一个小游戏,虽然界面不怎么样,但是算法确实很难写。因为不知道怎么上传文件(不然我就整个项目上传了)直接上代码吧!
启动页面:
package com.renyou.main;
public class Main {
public static void main(String[] args) {
new MainFrame().mainFrame();
}
}
主界面
package com.renyou.main;
import javax.swing.JFrame;
import org.junit.Test;
public class MainFrame extends JFrame {
public void mainFrame() {
this.setTitle("迷宫");
this.setSize(907, 630);
this.setLocationRelativeTo(null);
this.setResizable(false);
this.setDefaultCloseOperation(3);
GamePanel gp = new GamePanel();
this.add(gp);
this.setVisible(true);
}
}
游戏面板:
package com.renyou.main;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;
import java.util.ArrayList;
import javax.swing.JPanel;
public class GamePanel extends JPanel {
public int[][] map;
private Crafic crafic;
private ME me;
public static ArrayList<Crafic> craficList = new ArrayList<Crafic>();// 障碍物容器
{// 代码块
map = ReadMap.readMap();
for (int i = 0; i < map.length; i++) {
for (int j = 0; j < map[i].length; j++) {
int x = j * 30;
int y = i * 30;
crafic = new Crafic(x, y, 30, 30);
if (map[i][j] == 0) {
crafic.blackorwhite = Color.WHITE;
} else if (map[i][j] == 1) {// 墙壁
crafic.blackorwhite = Color.BLACK;
}
craficList.add(crafic);
}
}
}
public GamePanel() {
me = new ME(this);// 自己对象
initListener();
me.start();// 启动线程
}
private void initListener() {
MouseListener listener = new MouseAdapter() {
public void mousePressed(MouseEvent e) {
int x = e.getY() / me.height + ((e.getY() % me.height != 0) ? 1 : 0) - 1;
int y = e.getX() / me.width + ((e.getX() % me.width != 0) ? 1 : 0) - 1;
if (map[x][y] == 0) {
me.setEndY(y);
me.setEndX(x);
}
}
};
this.addMouseListener(listener);
}
public void paint(Graphics g) {
BufferedImage bi = (BufferedImage) this.createImage(this.getWidth(), this.getHeight());
Graphics graphics = bi.getGraphics();
for (int i = 0; i < craficList.size(); i++) {// 画障碍物
crafic = craficList.get(i);
graphics.setColor(crafic.blackorwhite);
graphics.fillRect(crafic.x, crafic.y, crafic.width, crafic.height);
}
graphics.setColor(Color.LIGHT_GRAY);
for (int i = 0; i <= 600; i += 30) {
graphics.drawLine(0, i, 900, i);
}
for (int i = 0; i <= 870; i += 30) {
graphics.drawLine(i + 30, 0, i + 30, 600);
}
graphics.setColor(Color.GREEN);
graphics.fillRect(me.x * me.width, me.y * me.height, me.width, me.height);
g.drawImage(bi, 0, 0, null);
}
}
核心类
package com.renyou.main;
import java.awt.Color;
import java.awt.Point;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class ME extends Thread {
public int x = 0, y = 0;// 自己地图数组位置
public int width = 30, height = 30;// 自己宽高
public int endX, endY;
private final int INF = 100000000;// 一个不可能的常量来初始化最短距离数组
private int n = 20, m = 30;// 地图的宽高,即是数组的二维长度
private char[][] maze;// 二维地图数组 (.表示可以走) ( #表示墙壁)( s表示起点 )(g表示终点)
private int[][] d;// 到各个位置最短距离的数组
private int[] dx = { 1, 0, -1, 0 };// x4个方向的移动向量
private int[] dy = { 0, 1, 0, -1 };// y4个方向的移动向量
private GamePanel gp = null;
public void run() {
while (true) {
List<Point> list = retList();
if (list.size() != 1&&list.size() != 0) {
System.out.println("最短路径为" + (list.size() - 1) + "步");
}
for (int i = list.size() - 1; i >= 0; i--) {
y = (int) list.get(i).getX();
x = (int) list.get(i).getY();
gp.repaint();
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public ME(GamePanel gp) {
this.gp = gp;
}
public List<Point> retList() {
List<Point> list = new ArrayList<Point>();// 保存最短路径的坐标
if (list != null)
list.clear();
maze = new char[n][m];
d = new int[n][m];
/************* char数组赋值 ********************/
for (int i = 0; i < gp.map.length; i++) {
for (int j = 0; j < gp.map[i].length; j++) {
if (gp.map[i][j] == 0) {// 路
maze[i][j] = '.';// 路
} else if (gp.map[i][j] == 1) {// 墙壁
maze[i][j] = '#';// 墙壁
}
}
}
/************* 起点终点赋值 ********************/
maze[y][x] = 'S';// 起点
maze[endX][endY] = 'G';// 终点
Queue<Point> queue = new LinkedList<Point>();
// 初始化距离INF
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
d[i][j] = INF;
}
}
// 添加起点到队列并使起点距离为0
Point point = new Point(y, x);// 起点
queue.offer(point);
d[y][x] = 0;
while (queue.size() > 0) {
point = queue.poll();// 拿到队尾元素并删除
// 如果是终点则结束
if (point.getX() == endX && point.getY() == endY)
break;
// 遍历四个向量
for (int i = 0; i < 4; i++) {
int nx = (int) (point.getX() + dx[i]);
int ny = (int) (point.getY() + dy[i]);
// 如果点在地图里并且不是墙壁并且从未走过则添加到队列里并且距离加1
if (0 <= nx && nx < n && 0 <= ny && ny < m && maze[nx][ny] != '#' && d[nx][ny] == INF) {
queue.offer(new Point(nx, ny));
d[nx][ny] = d[(int) point.getX()][(int) point.getY()] + 1;
}
}
}
if (d[endX][endY] == INF) {
System.out.println("从S到G的路不通");
}
/*************** 遍历d数组不断的找出每个点然后添加到容器 ********************/
else {
list.add(new Point(endX, endY));// 添加终点
int number = d[endX][endY];
boolean flag;
int f = -1;
while (number > 0) {
number--;
f++;
flag = true;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (d[i][j] == number && ((Math.abs(i - list.get(f).getX()) == 1 && j == list.get(f).getY())
|| (Math.abs(j - list.get(f).getY()) == 1 && i == list.get(f).getX()))) {
if (flag) {
list.add(new Point(i, j));
}
flag = false;
}
}
}
}
}
return list;
}
public int getEndX() {
return endX;
}
public void setEndX(int endX) {
this.endX = endX;
}
public int getEndY() {
return endY;
}
public void setEndY(int endY) {
this.endY = endY;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return width;
}
public void setWidth(int width) {
this.width = width;
}
public int getHeight() {
return height;
}
public void setHeight(int height) {
this.height = height;
}
}
障碍物类
package com.renyou.main;
import java.awt.Color;
public class Crafic {
// 障碍物的xy坐标
public int x, y;
// 宽高度
public int width, height;
public Color blackorwhite;
public Crafic(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
}
读取地图
package com.renyou.main;
import java.io.FileInputStream;
public class ReadMap {
/**
* 工具方法
*
* @return
*/
public static int[][] readMap() {
int[][] map = null;
try {
FileInputStream fis = new FileInputStream("images/image4");
// 先定义一个字节数组
byte[] bytes = new byte[fis.available()];
fis.read(bytes);
// 编程字符串
String str = new String(bytes).trim();
// 总行数
int row = 0;
int column = 0;
// 总行数
String[] strs = str.split("\r\n");
row = strs.length;
// 确定列数
if (strs != null && strs.length >= 1) {
String[] allColumn = strs[0].split(",");
column = allColumn.length;
}
map = new int[row][column];
// 存数据
for (int i = 0; i < strs.length; i++) {
String value = strs[i];
String[] vs = value.split(",");
for (int j = 0; j < vs.length; j++) {
String v = vs[j];
map[i][j] = Integer.parseInt(v);
}
}
} catch (Exception e) {
e.printStackTrace();
}
return map;
}
}
地图文件
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,1,1,1,1,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,0,0,1,0,0,0,1,0,1,1,1,1,1,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,1,1,0,0,0
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0
0,0,0,1,0,1,1,1,1,1,0,1,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,0
0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0
0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,1,1,1,0,1,0,1,1,1,0,0,0
0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,0,0,1,0,0,0,0
0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,1,1,1,1,0,1,0,1,1,1,1,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0
地图文件我提一下:
要在工程目录下建一个images文件夹再在这个文件夹下建一个image4的txt文件,把01串复制进去就行。(读取地图类会去解析这个文件,呈现在界面上)
最后给截图一张:
最终的效果就是点击地图的某个点,那个蓝绿色的方块就会以最短的路径跑到你点击的位置。