目录

一.项目要求

二.项目平台

三.项目实现过程

1.实现移动键盘控制

2.游戏画面及内容设置

3.游戏框架模型

4.页面按钮监听设置

5.主方法

四、项目实现效果

1.运行界面

2.自动寻路

3.完整代码


一.项目要求

(1)、迷宫随机生成

(2)、玩家走迷宫,留下足迹;

(3)、系统用广度遍历算法寻路,输出最佳路径

二.项目平台

IDEA.Java Swing

三.项目实现过程

1.实现移动键盘控制

  synchronized private void move(int c) {int tx = ballX, ty = ballY;switch (c) {case KeyEvent.VK_LEFT://对按钮控制的四个方向分别进行讨论ty--;break;case KeyEvent.VK_RIGHT:ty++;break;case KeyEvent.VK_UP:tx--;break;case KeyEvent.VK_DOWN:tx++;break;case KeyEvent.VK_ESCAPE:System.exit(0);break;case KeyEvent.VK_SPACE:if (drawPath == true) {drawPath = false;} else {drawPath = true;}break;default:}if (!isOutOfBorder(tx, ty) && (maze[tx][ty].getFather() == maze[ballX][ballY] || maze[ballX][ballY].getFather() == maze[tx][ty])) {ballX = tx;ballY = ty;}}private void setKeyListener() {this.addKeyListener(new KeyAdapter() {public void keyPressed(KeyEvent e) {int c = e.getKeyCode();move(c);repaint();checkIsWin();}});}

2.游戏画面及内容设置

private void createMaze() {Random random = new Random();int rx = Math.abs(random.nextInt()) % NUM;int ry = Math.abs(random.nextInt()) % NUM;maze = new Lattice[NUM][NUM];for (int i = 0; i < NUM ; i++)for (int j = 0; j < NUM ; j++)maze[i][j] = new Lattice(i, j);Stack<Lattice> s = new Stack<Lattice>();Lattice p = maze[rx][ry];Lattice neis[] = null;s.push(p);while (!s.isEmpty()) {p = s.pop();p.setFlag(Lattice.INTREE);neis = getNeis(p);int ran = Math.abs(random.nextInt()) % 4;//随机生成每个方格的路径数for (int a = 0; a <= 3; a++) {ran++;ran %= 4;if (neis[ran] == null || neis[ran].getFlag() == Lattice.INTREE)continue;s.push(neis[ran]);neis[ran].setFather(p);}}
//         changeFather(maze[0][0],null);}private void changeFather(Lattice p, Lattice f) {if (p.getFather() == null) {p.setFather(f);return;} else {changeFather(p.getFather(), p);}}private void clearFence(int i, int j, int fi, int fj, Graphics g) {int sx = padding + ((j > fj ? j : fj) * width),sy = padding + ((i > fi ? i : fi) * width),dx = (i == fi ? sx : sx + width),dy = (i == fi ? sy + width : sy);if (sx != dx) {sx++;dx--;} else {sy++;dy--;}g.drawLine(sx, sy, dx, dy);}private void drawPath(Graphics g) {Color PATH_COLOR = Color.RED, BOTH_PATH_COLOR = this.getBackground();if (drawPath == true)g.setColor(PATH_COLOR);elseg.setColor(this.getBackground());Lattice p = maze[NUM - 1][NUM - 1];g.fillOval(getCenterX(p) - width / 3, getCenterY(p) - width / 3,width / 2, width / 2);while (p.getFather() != null) {p.setFlag(2);g.drawLine(getCenterX(p), getCenterY(p), getCenterX(p.getFather()),getCenterY(p.getFather()));p = p.getFather();}p = maze[ballX][ballY];while (p.getFather() != null) {if (p.getFlag() == 2) {p.setFlag(3);g.setColor(BOTH_PATH_COLOR);}g.drawLine(getCenterX(p), getCenterY(p), getCenterX(p.getFather()),getCenterY(p.getFather()));p = p.getFather();}}protected void paintComponent(Graphics g) {super.paintComponent(g);for (int i = 0; i <= NUM; i++) {g.drawLine(padding + i * width, padding, padding + i * width,padding + NUM * width);}for (int j = 0; j <= NUM; j++) {g.drawLine(padding, padding + j * width, padding + NUM * width,padding + j * width);}g.setColor(this.getBackground());for (int i = NUM - 1; i >= 0; i--) {for (int j = NUM - 1; j >= 0; j--) {Lattice f = maze[i][j].getFather();if (f != null) {int fx = f.getX(), fy = f.getY();clearFence(i, j, fx, fy, g);}}}g.drawLine(padding, padding + 1, padding, padding + width - 1);int last = padding + NUM * width;g.drawLine(last, last - 1, last, last - width + 1);g.setColor(Color.RED);g.drawImage(pImg, getCenterX(ballY) - width / 2 - 3, getCenterY(ballX) - width / 2,width + 6, width, this);//     g.fillOval(getCenterX(ballY) - width / 3, getCenterY(ballX) - width / 3,//        width / 2, width / 2);if (drawPath == true)drawPath(g);}

3.游戏框架模型

public class Lattice {//框架static final int INTREE = 1;static final int NOTINTREE = 0;private int x = -1;private int y = -1;private int flag = NOTINTREE;private Lattice father = null;public Lattice(int xx, int yy) {x = xx;y = yy;}public int getX() {return x;}public int getY() {return y;}public int getFlag() {return flag;}public Lattice getFather() {return father;}public void setFather(Lattice f) {father = f;}public void setFlag(int f) {flag = f;}public String toString() {return new String("(" + x + "," + y + ")\n");}
}

4.页面按钮监听设置

public class Border extends JFrame implements ActionListener {//边界方法public static final int width = 640, padding = 20, LX = 350, LY = 80;//默认大小和位置public static int n = 30;Maze p;JMenuBar menuBar;//菜单栏对象JMenu menu, menu2, menu3;//菜单对象JMenuItem menuitem, menuitem2_2, menuitem3;public Border() {setTitle("迷宫");//标题setBounds(LX, LY, width + 4, width + 50);//默认大小和位置menuBar = new JMenuBar();//创建菜单栏对象setJMenuBar(menuBar);//添加菜单栏对象menu = new JMenu("开始");//创建菜单对象menuBar.add(menu);//将菜单对象添加到菜单栏对象中menuitem = new JMenuItem("新游戏");menu.add(menuitem);menuitem.addActionListener(this);//添加监听事件menu2 = new JMenu("设置");menuBar.add(menu2);//menuitem2_1 = new JMenuItem("声音设置");//暂时还没实现//menu2.add(menuitem2_1);//menuitem2_1.addActionListener(this);//添加监听事件menuitem2_2 = new JMenuItem("难度设置");menu2.add(menuitem2_2);menuitem2_2.addActionListener(this);//添加监听事件menu3 = new JMenu("结束");//创建菜单对象menuBar.add(menu3);//将菜单对象添加到菜单栏对象中menuitem3 = new JMenuItem("退出");menu3.add(menuitem3);menuitem3.addActionListener(this);//添加监听事件p = new Maze(getN(), (width - padding - padding) / getN(), padding);p.setpImg(Toolkit.getDefaultToolkit().getImage("haozi.png"));//得到要移动的对象this.getContentPane().add(p);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setResizable(false);this.setVisible(true);}

5.主方法

public class Start {public static void main(String[] args) {Border.startGame();//绘制游戏边界}
}

四、项目实现效果

1.运行界面

2.自动寻路

3.完整代码

package main.maze;import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;
import java.util.Stack;
import javax.swing.JOptionPane;
import javax.swing.JPanel;public class Migong extends JPanel {private static final long serialVersionUID = -8300339045454852626L;//用来表明类的不同版本的兼容性,消除系统的警告,后面的数是随机生成的private int NUM, width, padding;// width 每个格子的宽度和高度private Kuangjia[][] maze;private int ballX, ballY;private boolean drawPath = false;private Image pImg;public void setpImg(Image pImg) {this.pImg = pImg;}Migong(int m, int wi, int p) {NUM = m;width = wi;padding = p;createMaze();setKeyListener();this.setFocusable(true);}public void init() {for (int i = 0; i <= NUM - 1; i++)for (int j = 0; j <= NUM - 1; j++) {maze[i][j].setFather(null);maze[i][j].setFlag(Kuangjia.NOTINTREE);}ballX = 0;ballY = 0;drawPath = false;createMaze();this.setFocusable(true);repaint();}private int getCenterX(int x) {return padding + x * width + width / 2;}private int getCenterY(int y) {return padding + y * width + width / 2;}private int getCenterX(Kuangjia p) {return padding + p.getY() * width + width / 2;}private int getCenterY(Kuangjia p) {return padding + p.getX() * width + width / 2;}private void checkIsWin() {//判断人物是否到达终点,如果达到终点就弹出界面if (ballX == NUM - 1 && ballY == NUM - 1) {JOptionPane.showMessageDialog(null, "你走出了迷宫 !", "恭喜!",JOptionPane.PLAIN_MESSAGE);init();//关掉界面后重新绘制页面}}synchronized private void move(int c) {int tx = ballX, ty = ballY;switch (c) {case KeyEvent.VK_LEFT://对按钮控制的四个方向分别进行讨论ty--;break;case KeyEvent.VK_RIGHT:ty++;break;case KeyEvent.VK_UP:tx--;break;case KeyEvent.VK_DOWN:tx++;break;case KeyEvent.VK_ESCAPE:System.exit(0);break;case KeyEvent.VK_SPACE:if (drawPath == true) {drawPath = false;} else {drawPath = true;}break;default:}if (!isOutOfBorder(tx, ty) && (maze[tx][ty].getFather() == maze[ballX][ballY] || maze[ballX][ballY].getFather() == maze[tx][ty])) {ballX = tx;ballY = ty;}}private void setKeyListener() {//对按键进行监听this.addKeyListener(new KeyAdapter() {public void keyPressed(KeyEvent e) {int c = e.getKeyCode();move(c);repaint();checkIsWin();}});}private boolean isOutOfBorder(Kuangjia p) {return isOutOfBorder(p.getX(), p.getY());}private boolean isOutOfBorder(int x, int y) {return (x > NUM - 1 || y > NUM - 1 || x < 0 || y < 0) ? true : false;}private Kuangjia[] getNeis(Kuangjia p) {final int[] adds = {-1, 0, 1, 0, -1};// 顺序为上右下左if (isOutOfBorder(p)) {return null;}Kuangjia[] ps = new Kuangjia[4];// 顺序为上右下左int xt;int yt;for (int i = 0; i <= 3; i++) {xt = p.getX() + adds[i];yt = p.getY() + adds[i + 1];if (isOutOfBorder(xt, yt))continue;ps[i] = maze[xt][yt];}return ps;}private void createMaze() {Random random = new Random();int rx = Math.abs(random.nextInt()) % NUM;int ry = Math.abs(random.nextInt()) % NUM;maze = new Kuangjia[NUM][NUM];for (int i = 0; i < NUM ; i++)for (int j = 0; j < NUM ; j++)maze[i][j] = new Kuangjia(i, j);Stack<Kuangjia> s = new Stack<Kuangjia>();Kuangjia p = maze[rx][ry];Kuangjia neis[] = null;s.push(p);while (!s.isEmpty()) {p = s.pop();p.setFlag(Kuangjia.INTREE);neis = getNeis(p);int ran = Math.abs(random.nextInt()) % 4;//随机生成每个方格的路径数for (int a = 0; a <= 3; a++) {ran++;ran %= 4;if (neis[ran] == null || neis[ran].getFlag() == Kuangjia.INTREE)continue;s.push(neis[ran]);neis[ran].setFather(p);}}
//         changeFather(maze[0][0],null);}private void changeFather(Kuangjia p, Kuangjia f) {if (p.getFather() == null) {p.setFather(f);return;} else {changeFather(p.getFather(), p);}}private void clearFence(int i, int j, int fi, int fj, Graphics g) {int sx = padding + ((j > fj ? j : fj) * width),sy = padding + ((i > fi ? i : fi) * width),dx = (i == fi ? sx : sx + width),dy = (i == fi ? sy + width : sy);if (sx != dx) {sx++;dx--;} else {sy++;dy--;}g.drawLine(sx, sy, dx, dy);}private void drawPath(Graphics g) {Color PATH_COLOR = Color.RED, BOTH_PATH_COLOR = this.getBackground();if (drawPath == true)g.setColor(PATH_COLOR);elseg.setColor(this.getBackground());Kuangjia p = maze[NUM - 1][NUM - 1];g.fillOval(getCenterX(p) - width / 3, getCenterY(p) - width / 3,width / 2, width / 2);while (p.getFather() != null) {p.setFlag(2);g.drawLine(getCenterX(p), getCenterY(p), getCenterX(p.getFather()),getCenterY(p.getFather()));p = p.getFather();}p = maze[ballX][ballY];while (p.getFather() != null) {if (p.getFlag() == 2) {p.setFlag(3);g.setColor(BOTH_PATH_COLOR);}g.drawLine(getCenterX(p), getCenterY(p), getCenterX(p.getFather()),getCenterY(p.getFather()));p = p.getFather();}}protected void paintComponent(Graphics g) {super.paintComponent(g);for (int i = 0; i <= NUM; i++) {g.drawLine(padding + i * width, padding, padding + i * width,padding + NUM * width);}for (int j = 0; j <= NUM; j++) {g.drawLine(padding, padding + j * width, padding + NUM * width,padding + j * width);}g.setColor(this.getBackground());for (int i = NUM - 1; i >= 0; i--) {for (int j = NUM - 1; j >= 0; j--) {Kuangjia f = maze[i][j].getFather();if (f != null) {int fx = f.getX(), fy = f.getY();clearFence(i, j, fx, fy, g);}}}g.drawLine(padding, padding + 1, padding, padding + width - 1);int last = padding + NUM * width;g.drawLine(last, last - 1, last, last - width + 1);g.setColor(Color.RED);g.drawImage(pImg, getCenterX(ballY) - width / 2 - 3, getCenterY(ballX) - width / 2,width + 6, width, this);//     g.fillOval(getCenterX(ballY) - width / 3, getCenterY(ballX) - width / 3,//        width / 2, width / 2);if (drawPath == true)drawPath(g);}
}
public class Kuangjia {//框架static final int INTREE = 1;static final int NOTINTREE = 0;private int x = -1;private int y = -1;private int flag = NOTINTREE;private Kuangjia father = null;public Kuangjia(int xx, int yy) {x = xx;y = yy;}public int getX() {return x;}public int getY() {return y;}public int getFlag() {return flag;}public Kuangjia getFather() {return father;}public void setFather(Kuangjia f) {father = f;}public void setFlag(int f) {flag = f;}public String toString() {return new String("(" + x + "," + y + ")\n");}
}
public class Bianjie extends JFrame implements ActionListener {//边界方法public static final int width = 640, padding = 20, LX = 350, LY = 80;//默认大小和位置public static int n = 30;Migong p;JMenuBar menuBar;//菜单栏对象JMenu menu, menu2, menu3;//菜单对象JMenuItem menuitem, menuitem2_2, menuitem3;public Bianjie() {setTitle("迷宫");//标题setBounds(LX, LY, width + 4, width + 50);//默认大小和位置menuBar = new JMenuBar();//创建菜单栏对象setJMenuBar(menuBar);//添加菜单栏对象menu = new JMenu("开始");//创建菜单对象menuBar.add(menu);//将菜单对象添加到菜单栏对象中menuitem = new JMenuItem("新游戏");menu.add(menuitem);menuitem.addActionListener(this);//添加监听事件menu2 = new JMenu("设置");menuBar.add(menu2);//menuitem2_1 = new JMenuItem("声音设置");//暂时还没实现//menu2.add(menuitem2_1);//menuitem2_1.addActionListener(this);//添加监听事件menuitem2_2 = new JMenuItem("难度设置");menu2.add(menuitem2_2);menuitem2_2.addActionListener(this);//添加监听事件menu3 = new JMenu("结束");//创建菜单对象menuBar.add(menu3);//将菜单对象添加到菜单栏对象中menuitem3 = new JMenuItem("退出");menu3.add(menuitem3);menuitem3.addActionListener(this);//添加监听事件p = new Migong(getN(), (width - padding - padding) / getN(), padding);p.setpImg(Toolkit.getDefaultToolkit().getImage("haozi.png"));//得到要移动的对象this.getContentPane().add(p);this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);this.setResizable(false);this.setVisible(true);}@Overridepublic void actionPerformed(ActionEvent e) {if (e.getSource() == menuitem) {p.init();}
//        if (e.getSource()==menuitem2_1){//声音设置
//            System.out.println("2");
//            alert a=new alert(g);
//        }if (e.getSource() == menuitem2_2) {//难度设置Nandu b = new Nandu(this);//这边涉及到窗口的传值,就是把一个对象传进去}if (e.getSource() == menuitem3) {System.exit(0);}}public static void startGame() {new Bianjie();}public int getN() {return n;}public void setN(int n) {this.n = n;}
}
public class Nandu extends JDialog {//对难度选择窗体的定义和设置public Nandu(Bianjie b) {setTitle("难度选择!");//定义按钮标题setLayout(null);//清空布局管理器,空布局,常用于窗体大小固定的容器里setBounds(Bianjie.LX + 180, Bianjie.LY + 180, 300, 300);//组件左上角在容器的坐标和组件的长度和宽度Container container = getContentPane();//初始化一个container的容器container.setBackground(Color.LIGHT_GRAY.brighter());//给容器定义背景的颜色JButton jb1 = new JButton("简单");//在难度选择的窗体中定义三个按钮,设置游戏难度jb1.setBounds(90, 50, 100, 30);JButton jb2 = new JButton("一般");jb2.setBounds(90, 100, 100, 30);JButton jb3 = new JButton("困难");jb3.setBounds(90, 150, 100, 30);jb1.addActionListener(new ActionListener() {//设立确定按钮的点击事件@Overridepublic void actionPerformed(ActionEvent arg0) {b.setN(30);b.setVisible(false);b.startGame();setVisible(false);}});jb2.addActionListener(new ActionListener() {//设立确定按钮的点击事件@Overridepublic void actionPerformed(ActionEvent arg0) {b.setN(40);b.setVisible(false);b.startGame();setVisible(false);}});jb3.addActionListener(new ActionListener() {//设立确定按钮的点击事件@Overridepublic void actionPerformed(ActionEvent arg0) {b.setN(50);b.setVisible(false);b.startGame();setVisible(false);}});container.add(jb1);//将三个按钮添加到容器中container.add(jb2);container.add(jb3);setVisible(true);//初始化true}
}
public class Start {public static void main(String[] args) {Bianjie.startGame();//绘制游戏边界}
}

实验三 迷宫游戏开发相关推荐

  1. 实验项目三:基于A*搜索算法迷宫游戏开发

    基于A*搜索算法迷宫游戏开发 由于这一个不太完美,重新写了一个基于python的程序. 一.前言 二.基本流程 三.界面设计 四.迷宫随机生成 五.移动迷宫与尾迹生成 六.A*迷宫自动寻路 七.附加 ...

  2. 实验三 JSP应用开发进阶

    全部:https://download.csdn.net/download/weixin_42859280/11218260 实验三 JSP应用开发进阶:PDF版本[已经完成所有代码] 想看文档上面有 ...

  3. 20155225 实验三《敏捷开发与XP实践》实验报告

    20155225 实验三<敏捷开发与XP实践>实验报告 一.使用工具(Code->Reformate Code)把代码重新格式化 IDEA里的Code菜单有很多实用的功能可以帮助我们 ...

  4. 20145209 实验三 《敏捷开发与XP实践》 实验报告

    20145209 实验三 <敏捷开发与XP实践> 实验报告 实验内容 XP基础. XP核心实践. 相关工具. 实验步骤 敏捷开发与XP 1.敏捷开发 敏捷开发(Agile Developm ...

  5. 20155310 《Java程序设计》实验三(敏捷开发与XP实践)实验报告

    20155310 <Java程序设计>实验三(敏捷开发与XP实践)实验报告 实验内容 1.XP基础 2.XP核心实践 3.相关工具 实验步骤 (一)敏捷开发与XP 1.敏捷开发 敏捷开发( ...

  6. 2018-2019-2 20175320实验三《敏捷开发与XP实践》实验报告

    2018-2019-2 20175320实验三<敏捷开发与XP实践>实验报告 一.实验步骤及内容 软件工程是把系统的.有序的.可量化的方法应用到软件的开发.运营和维护上的过程.软件工程包括 ...

  7. 2018-2019-2 20175317 实验三《敏捷开发与XP实践》实验报告

    2018-2019-2 20175317 实验三<敏捷开发与XP实践>实验报告 一.实验步骤及内容 敏捷开发与XP实践-1 http://www.cnblogs.com/rocedu/p/ ...

  8. 2018-2019-2 20175227张雪莹《Java程序设计》实验三 《敏捷开发与XP实践》

    2018-2019-2 20175227张雪莹<Java程序设计> 实验三 <敏捷开发与XP实践> 实验报告封面 课程:Java程序设计 班级:1752班 姓名:张雪莹 学号: ...

  9. 2018-2019-2 20175311 实验三《敏捷开发与XP实践》实验报告

    2018-2019-2 20175311 实验三<敏捷开发与XP实践>实验报告 实验题目 敏捷开发与XP实践 http://www.cnblogs.com/rocedu/p/4795776 ...

最新文章

  1. 吴裕雄--天生自然 JAVASCRIPT开发学习:DOM EventListener
  2. 在坚持了15年后,我毅然决定离开 Linux,投入 Mac 的怀抱
  3. 柴油机计算机故障,柴油机故障论文,关于6105小型高速柴油机常见故障处理相关参考文献资料-免费论文范文...
  4. avalon 框架
  5. C++ 处理输入输出错误
  6. Linux(debian7)操作基础(十)之字符界面使用指南
  7. 怎样对付win7黑屏
  8. Maven学习总结(34)——Maven settings.xml配置解读
  9. Android调用.net的webservice服务器接收参数为空的情况
  10. 【机器人算法】机器人运动学参数辨识/DH参数校准/DH参数辨识
  11. 原型设计工具——墨刀
  12. 基于CBOW网络手动实现面向中文语料的word2vec
  13. 认识即时通讯开发通信协议之MQTT
  14. python核心编程 第3版_Python核心编程(第3版)PDF高清晰完整中文版
  15. FIDO2.0 认证注册流程
  16. 当代超吸金的行业“Python工程师”,如何快速从Pytho入门到初级Python工程师?
  17. 如何通过python爬股票接口获取证券交易日?
  18. 国科大 计算机学院 雁栖湖校区(研一上)
  19. 在try-catch机制优化IO流关闭时,OutputStreamWriter 数据流被截断 新语法
  20. @Value(“#{}“)与@Value(“${}“)的区别

热门文章

  1. UVa 10074 - Take the Land
  2. IDEA 常用快捷键(详细)
  3. 20160131-basic-linux-command
  4. 即有集团:品牌化运作成为集团发展“新基因”
  5. JavaScript看这一篇就够了,简单全面一发入魂
  6. python画魔法阵_半年了,这画我已经找不出什么出错的地方了,诚心请大佬们指点,我如何能更进一步?...
  7. NSA泄密事件之SMB系列远程命令执行漏洞及Doublepulsar后门全球数据分析
  8. 路由器输入宽带账号密码上网
  9. gorm实现insert ignore into语句调用
  10. 使用php运行python文件