首页 > 作文

Java实现经典游戏复杂迷宫

更新时间:2023-04-04 21:23:00 阅读: 评论:0

目录
前言主要设计功能截图代码实现总结

前言

人类建造迷宫已有5000年的历史。在世界的不同文化发展时期,这些奇特的建筑物始终吸引人们沿着弯弯曲曲、困难重重的小路吃力地行走,寻找真相。迷宫类小游戏应运而生。在游戏中,迷宫被表现为冒险舞台里,藏有各式各样奇妙与谜题或宝藏的危险区域。型态有洞窟、人工建筑物、怪物巢穴、密林或山路等。迷宫内有恶徒或凶猛的生物(真实存在或想像物体都有)徘徊,其中可能会有陷阱、不明设施、遗迹等。

《复杂迷宫》游戏是用java语言实现,采用了swing技术进行了界面化处理,设计思路用了面向对象思想。

主要需求

方向键控制移动,角色走出迷宫,游戏胜利。增加游戏难度和增加随机地图。

主要设计

1、构建游戏地图面板

2、设定迷宫地图,包含可走的通道,不可走的墙体,还有出口位置

3、键盘的上下左右按键,来控制角色的移动

4、角色移动的算法,通道可走,遇到墙体不可走

5、走到终点,有成功通关的提示。

6、增加游戏的难度选择,难度1,难度2和难度3

7、每次生成的地图是随机的

8、地图大小可选择,迷宫的长在10-45之间,宽在10-90之间

9、增加撞墙的音乐效果

功能截图

游戏开始页面

生成难度1,10*10的迷宫地图

随机地图:生成难度1,10*10的迷宫地图

生成难度2,30*30的迷宫地图

生成难度3,90*45的迷宫地图

成功过关-效果

代码实现

窗口布局

public class startview extends jframe {    public startview() {        this.ttitle("复杂迷宫");        this.tsize(240, 265);        this.tlocationrelativeto(null);        this.tdefaultclooperation(exit_on_clo);        this.tresizable(fal);        initialize();        this.tvisible(true);    }    private void initialize() {        jpanel contentpane = new jpanel();        this.tcontentpane(contentpane);        contentpane.tlayout(null);        jlabel widthlabel = new jlabel("迷宫长度:");        jlabel heightlabel = new jlabel("迷宫高度:");        jlabel levellabel = new jlabel("难度:");        jtextfield widthtext = new jtextfield();        jtextfield heighttext = new jtextfield();        jradiobutton level1 = new jradiobutton("1");        jradiobutton level2 = new jradiobutton("2");        jradiobutton level3 = new jradiobutton("3");        buttongroup levelgroup = new buttongroup();        levelgroup.add(level1);        levelgroup.add(level2);        levelgroup.add(level3);        jbutton run = new jbutton("生成迷宫");        // 设定标签位置        widthlabel.tbounds(20, 20, 100, 30);        heightlabel.tbounds(20, 70, 110, 30);        widthtext.tbounds(120, 20, 70, 30);        heighttext.tbounds(120, 70, 70, 30);        levellabel.tbounds(20, 120, 60, 30);        level1.tbounds(80, 120, 50, 30);        level2.tbounds(130, 120, 50, 30);        level3.tbounds(180, 120, 50, 30);        run.tbounds(55, 170, 120, 30);        // 限制输入框只接收数字        widthtext.tdocument(new numbertextfield());        heighttext.tdocument(new numbertextfield());        // 改变字体        font font = new font("楷体", font.plain, 17);        widthlabel.tfont(font);        heightlabel.tfont(font);        widthtext.tfont(font);        heighttext.tfont(font);        levellabel.tfont(font);        level1.tfont(font);        level2.tfont(font);        level3.tfont(font);        run.tfont(font);        // 取消按钮选中边框        level1.tfocuspainted(fal);        level2.tfocuspainted(fal);        level3.tfocuspainted(fal);        // 默认选择难度3        level3.tlected(true);        contentpane.add(widthlabel);        contentpane.add(heightlabel);        contentpane.add(widthtext);        contentpane.add(heighttext);        contentpane.add(levellabel);        contentpane.add(level1);        contentpane.add(level2);        contentpane.add(level3);        contentpane.add(run);        // 生成迷宫监听器        run.addactionlistener(e -> {            // 建议宽在10-90,长在10-45之间            if (widthtext.gettext().equals("")) {                joptionpane.showmessagedialog(null, "长度不能为空!", "提示", joptionpane.information_message);            } el if (heighttext.gettext().equals("")) {                joptionpane.showmessagedialog(null, "高度不能为空!", "提示", joptionpane.information_message);            } el {                int width = integer.parint(widthtext.gettext());                int height = integer.parint(heighttext.gettext());                if (width >= 10 && width <= 90 && height >= 10 && height <= 45) {                    int level = level1.islected() ? 1 : level2.islected() ? 2 : 3;                    mazemodel maze = new mazemodel(width, height, level);                    this.dispo();                    maze.draw();                } el {                    joptionpane.showmessagedialog(null, "迷宫的长必须在10-45之间,宽必须在10-何有90之间,请检查输入是否有误!", "错误输入", joptionpane.error_message);                }            }        });        // 添加回车键入监听器        keyadapter enteradapter = new keyadapter() {            @override            public void keypresd(keyevent e) {                if (e.getkeycode() == keyevent.vk_enter) {                    run.doclick();   // 回车即生成迷宫                }            }        };        widthtext.addkeylistener(enteradapter);        heighttext.addkeylistener(enteradapter);    }    public static void main(string[] args) {        new startview();    }}

迷宫的数学模型

public class mazemodel {private int width;private int height;private arraylist<mazepoint> mazepoints;/*** 迷宫的构造方法** @param width  迷宫的宽度* @param height 迷宫的* @param level  1 -> 递归分割算法生成迷宫,2 -> 递归回溯算法生成迷宫,3 -> 普里姆算法生成迷宫*/public mazemodel(int width, int height, int level) {super();this.width = width;this.height = height;switch (level) {ca 1 : this.mazepoints = recursivedivision();ca 2 : this.mazepoints = recursivebacktracker();ca 3 : this.mazepoints = prim();}}/*** 递归回溯生成迷宫** @return 生成的迷宫的单元格集合*/private arraylist<mazepoint> recursivebacktracker() {arraylist<mazepoint> maze = new arraylist<>();// 初始化所以单元格都被强包围for (int h = 0; h < height; h++) {for (int w = 0; w < width; w++) {mazepoint point = new mazepoint(w, h, true);maze.add(point);}}// 建立一个存放操作单元格的栈stack<mazepoint> stack = new stack<>();// 选择(0,0)点作为起始点,开始打通迷宫stack.push(maze.get(0));maze.get(0).visited = true;random random = new random();int x;   // 操作单元格的横坐标int y;   // 操作单元格的纵坐标int direction;   // 方向while (!stack.empty()) {// 选择栈顶元素作为当前操作数mazepoint operatingpoint = stack.peek();x = operatingpoint.getx();y = operatingpoint.gety();direction = random.nextint(4);mazepoint adjacency;switch (direction) {ca 0: // 左边if ((x - 1) >= 0) {   // 判断左边是否为边缘adjacency = maze.get(x - 1 + y * width);   // 判断左边单元格是否被访问过if (!adjacency.visited) {operatingpoint.tleft(0);   // 打通操作单元格的左墙,和左边单元格的右墙adjacency.tright(0);stack.push(adjacency);    // 将左墙入栈,作为下次循环的操作单元格adjacency.visited = true;    // 将左边的单元格设置为访问过了x--;   // 改变操作单元格的坐标,方便后面判断当前单元格四周是否都访问过}}break;ca 1: // 右边// 注释参照ca0if ((x + 1) < width) {adjacency = maze.get(x + 1 + y * width);if (!adjacency.visited) {operatingpoint.tright(0);adjacency.tleft(0);stack.push(adjacency);adjacency.visited = true;x++;}}break;ca 2: // 上边// 注释参照ca0if ((y - 1) >= 0) {adjacency = maze.get(x + (y - 1) * width);if (!adjacency.visited) {operatingpoint.tup(0);adjacency.tdown(0);stack.push(adjacency);adjacency.visited = true;y--;}}break;ca 3: // 下边// 注释参照ca0if ((y + 1) < height) {adjacency = maze.get(x + (y + 1) * width);if (!adjacency.visited) {operatingpoint.tdown(0);adjacency.tup(0);stack.push(adjacency);adjacency.visited = true;y++;}}break;}// 若操作单元格四周都被访问过,将该单元格出栈。if ((x - 1 < 0 || maze.get(x - 1 + y * width).visited)&& (x + 1 >= width || maze.get(x + 1 + y * width).visited)&& (y - 1 < 0 || maze.get(x + (y - 1) * width).visited)&& (y + 1 >= height || maze.get(x + (y + 1) * width).visited)) {stack.pop();}}maze.get(0).tleft(0);    // 左上角开墙作为入口maze.get(width * height -怎样写记叙文 1).tright(0);    // 右下角开墙作为出口return maze;}/*** 分割迷宫区域** @param maze  单元格集合* @param right 区域的宽* @param top   区域的高*/private void divide(arraylist<mazepoint> maze, int left, int right, int top, int down) {if (right - left > 0 && top - down > 0) {// 在区域中心”十“字筑墙for (int x = left, y = 正军级待遇(top - down) / 2 + down; x <= right; x++) {maze.get(x + y * this.width).tdown(1);maze.get(x + (y + 1) * this.width).tup(1);}for (int x = (right - left) / 2 + left, y = down; y <= top; y++) {maze.get(x + y * this.width).tright(1);maze.get(x + 1 + y * this.width).tleft(1);}// 在“十”字墙中选其中三个方向拆一面墙random random = new random();int direction = random.nextint(4);int x = (right - left) / 2 + left;int y = (top - down) / 2 + down;int tempx;int tempy;if (direction != 0) {    // 打通一面左边的墙if (x - left > left) {tempx = random.nextint(x - left + 1) + left;} el {tempx = left;}tempy = y;maze.get(tempx + tempy * this.width).tdown(0);maze.get(tempx + (tempy + 1) * this.width).tup(0);}if (direction != 1) {    // 打通一面右边的墙if (right - (x + 1) > x + 1) {tempx = random.nextint(right - (x + 1) + 1) + x + 1;} el {tempx = x + 1;}tempy = y;maze.get(tempx + tempy * this.width).tdown(0);maze.get简爱简介(tempx + (tempy + 1) * this.width).tup(0);}if (direction != 2) {    // 打通一面上面的墙tempx = x;if (y - 恐龙帝国down > down) {tempy = random.nextint(y - down + 1) + down;} el {tempy = down;}maze.get(tempx + tempy * this.width).tright(0);maze.get(tempx + 1 + tempy * this.width).tleft(0);}if (direction != 3) {    // 打通一面下面的墙tempx = x;if (top - (y + 1) > y + 1) {tempy = random.nextint(top - (y + 1) + 1) + y + 1;} el {tempy = y + 1;}maze.get(tempx + tempy * this.width).tright(0);maze.get(tempx + 1 + tempy * this.width).tleft(0);}maze.stream().limit(this.width).foreach(m -> m.tup(1));maze.stream().skip((this.height - 1) * this.width).foreach(m -> m.tdown(1));maze.stream().filter(m -> m.getx() == 0).foreach(m -> m.tleft(1));maze.stream().filter(m -> m.getx() == width - 1).foreach(m -> m.tright(1));divide(maze, left, (right - left) / 2 + left, (top - down) / 2 + down, down);divide(maze, left, (right - left) / 2 + left, top, (top - down) / 2 + down + 1);divide(maze, (right - left) / 2 + left + 1, right, (top - down) / 2 + down, down);divide(maze, (right - left) / 2 + left + 1, right, top, (top - down) / 2 + down + 1);}}/*** 递归分割生成迷宫** @return 生成的迷宫的单元格集合*/private arraylist<mazepoint> recursivedivision() {// 初始化迷宫的所有单元格arraylist<mazepoint> maze = new arraylist<>();for (int h = 0; h < height; h++) {for (int w = 0; w < width; w++) {mazepoint point = new mazepoint(w, h);maze.add(point);}}divide(maze, 0, width - 1, height - 1, 0);  // 递归分割迷宫maze.get(0).tleft(0);    // 左上角开墙作为入口maze.get(width * height - 1).tright(0);    // 右下角开墙作为出口return maze;}private arraylist<mazepoint> prim() {arraylist<mazepoint> mazepoints = new arraylist<>();primmaze primmaze = new primmaze(width * 2 + 1, height * 2 + 1);int[][] tempmaze = primmaze.getmaze();for (int i = 0; i < tempmaze.length; i++) {for (int j = 0; j < tempmaze[i].length; j++) {if (i % 2 != 0 && j % 2 != 0) {mazepoint mazepoint = new mazepoint(i / 2, j / 2);if (tempmaze[i - 1][j] == 10) {mazepoint.tleft(1);}if (tempmaze[i + 1][j] == 10) {mazepoint.tright(1);}if (tempmaze[i][j - 1] == 11) {mazepoint.tup(1);}if (tempmaze[i][j + 1] == 11) {mazepoint.tdown(1);}mazepoints.add(mazepoint);}}}mazepoints.get(0).tleft(0);    // 左上角开墙作为入口mazepoints.get(width * height - 1).tright(0);    // 右下角开墙作为出口return mazepoints;}public void draw() {new playview(mazepoints);}}

普里姆算法

class primmaze {private int[][] maze;public int[][] getmaze() {return maze;}primmaze(int row, int column) {int row1 = row / 2;int column1 = column / 2;maze = new int[row1 * 2 + 1][column1 * 2 + 1];for (int x = 0; x < row1 * 2 + 1; x++)            //初始化迷宫{for (int y = 0; y < column1 * 2 + 1; y++) {if (x == 0 || x == row1 * 2) {maze[x][y] = -1;}if (y == 0 || y == column1 * 2) {maze[x][y] = -1;}}}for (int x = 1; x < row1 * 2; x++) {for (int y = 1; y < column1 * 2; y++) {if (x % 2 == 1 || y % 2 == 1) {maze[x][y] = 0;}if (x % 2 == 0 || y % 2 == 0) {maze[x][y] = 1;}}}arraylist<int[]> list = new arraylist<>();            //记录已连通的"路"的坐标的集合int[] coordinate = new int[2];        //记录未访问的点坐标int x = 1, y = 1;        //设置起点位置coordinate[0] = coordinate[1] = 1;list.add(coordinate);        //将起点加入已经连通的路集合//x,y表示当前访问坐标while (list.size() < row1 * column1)            //当所有点都已访问完时结束{boolean flag1;        //标识坐标是否已经被访问int[] record = {-1, -1, -1, -1};        //用于记录四周未被访问的方位,0代表上,1代表下,2代表左,3代表右if (x - 2 > 0)            //判断当前位置上方是否有路{int[] a = new int[2];a[0] = x - 2;a[1] = y;flag1 = judge(a, list);        //判断上方是否已经被访问if (flag1) {record[0] = 0;}}if (x + 2 < row1 * 2)        //判断当前位置下方是否有路{int[] a = new int[2];a[0] = x + 2;a[1] = y;flag1 = judge(a, list);        //判断下方是否已经被访问if (flag1) {record[1] = 1;}}if (y - 2 > 0)        //判断当前位置左方是否有路{int[] a = new int[2];a[0] = x;a[1] = y - 2;flag1 = judge(a, list);        //判断左方是否已经被访问if (flag1) {record[2] = 2;}}if (y + 2 < column1 * 2)        //判断当前位置右方是否有路{int[] a = new int[2];a[0] = x;a[1] = y + 2;flag1 = judge(a, list);        //判断右方是否已经被访问if (flag1) {record[3] = 3;}}boolean flag2 = fal;            //flag2标识四周是否有未访问过的路for (int i = 0; i < 4; i++)        //判断当前位置的四个方位是否有未访问过的路{if (record[i] == i) {flag2 = true;        //如果有未访问过的路,跳出循环break;}}int r = new random().nextint(4);while (record[r] == r) {r = new random().nextint(4);}while (record[r] != r && flag2)            //当方位标识错误且当前位置四周有未访问过的点时继续随机获取一个新的方位标识,直到标识正确{r = new random().nextint(4);        //随机选取一个可以符合条件的墙并将其敲碎if (record[r] == r)        //当标识正确时,敲碎两点之间的墙{if (r == 0) {       //当上方有未访问过的点时,敲碎上方的墙maze[x - 1][y] = 0;}if (r == 1) {        //当下方有未访问过的点时,敲碎下方的墙maze[x + 1][y] = 0;}if (r == 2) {         //当左方有未访问过的点时,敲碎左方的墙maze[x][y - 1] = 0;}if (r == 3) {       //当右方有未访问过的点时,敲碎右方的墙maze[x][y + 1] = 0;}}}//将与当前坐标之间的墙被敲碎的路的坐标从未被访问的集合中移出if (r == 0 && flag2)        //如果敲碎的是上方的墙,则将上方的路加入到已连通的路集合{int[] b = new int[2];b[0] = x - 2;b[1] = y;if (judge(b, list)) {list.add(b);}}if (r == 1 && flag2)        //如果敲碎的是下方的墙,则将下方的路加入到已连通的路集合{int[] b = new int[2];b[0] = x + 2;b[1] = y;if (judge(b, list)) {list.add(b);}}if (r == 2 && flag2)        //如果敲碎的是左方的墙,则将左方的路加入到已连通的路集合{int[] b = new int[2];b[0] = x;b[1] = y - 2;if (judge(b, list)) {list.add(b);}}if (r == 3 && flag2)        //如果敲碎的是右方的墙,则将右方的路加入到已连通的路集合{int[] b = new int[2];b[0] = x;b[1] = y + 2;if (judge(b, list)) {list.add(b);}}int i = new random().nextint(list.size());            //随机选取一个被连通的路坐标x = list.get(i)[0];                //获取路坐标y = list.get(i)[1];}for (int r = 0; r < maze.length; r++)//将方格墙转为线条墙,10表示横,11表示竖{for (int c = 0; c < maze[r].length; c++) {if (r % 2 == 0 && c % 2 == 1) {if (maze[r][c] != 0) {maze[r][c] = 10;}}if (r % 2 == 1 && c % 2 == 0) {if (maze[r][c] != 0) {maze[r][c] = 11;}}}}}boolean judge(int[] coordinate, arraylist<int[]> list)            //判断路是否已经加入通路集合,已加入则返回fal{boolean flag = true;for (int[] ints : list) {if (coordinate[0] == ints[0] && coordinate[1] == ints[1])            //若已访问点集合中含有该位置的坐标,表示该位置已访问过,不用重复加入该位置的坐标{flag = fal;break;}}return flag;}}

总结

通过此次的《复杂迷宫》游戏实现,让我对swing的相关知识有了进一步的了解,对java这门语言也有了比以前更深刻的认识。

java的一些基本语法,比如数据类型、运算符、程序流程控制和数组等,理解更加透彻。java最核心的核心就是面向对象思想,对于这一个概念,终于悟到了一些。

以上就是java实现经典游戏复杂迷宫的详细内容,更多关于java迷宫游戏的资料请关注www.887551.com其它相关文章!

本文发布于:2023-04-04 21:22:58,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/zuowen/079d59f1068c29000cfa0f66262e75be.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

本文word下载地址:Java实现经典游戏复杂迷宫.doc

本文 PDF 下载地址:Java实现经典游戏复杂迷宫.pdf

标签:迷宫   单元格   递归   坐标
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图