🍅文末获取源码联系🍅
👇🏻 精彩项目推荐订阅👇🏻 不然下次找不到哟
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,希望帮助更多的人
系统介绍
连连看是一种消除类益智游戏,核心要求是在规定的时间内,消除游戏界面中选中的两张相同的图案,直至完全消除所有图案。这款游戏操作简单(只需单击鼠标左键操作)、面向人群广泛,在限时操作的游戏要求下,吸引玩家自发地锻炼观察能力、判断能力和反应能力,故从推出至今颇受欢迎。消除类游戏如今也有很多类型,但连连看游戏因其操作简单依旧广受好评,该游戏不仅能调节精神状态,还能在游戏中锻炼我们的眼力视野和集中力,开发思维能力的同时培养面对困难时具备攻克困难的信心。
此次设计所使用的语言为Java语言,开发环境为JDK Version1.7.0,开发工具为Eclipse。主要应用Swing组件,Java小程序,事件及接口等。本系统主要是运用Swing组件和事件处理技术,进行界面的绘制,鼠标的操作,以及积分的显示和沙漏的计时的显示等功能。
概要设计
模块设计
连连看系统总体结构
此次设计连连看的主体构成为连连看图片以及一些功能键。从界面布局来看,面板的右面有重新开始、刷新按钮,难度选择选项卡(4种难度),得分、关卡状态显示栏,以及沙漏状的时间倒计时装置。面板左面是一块主要操作区域,用来显示待消除的图片排列情况。本连连看系统应该包括以下两大结构:游戏界面模块;处理模块。游戏界面模块下分两个模块:功能键模块和操作模块。如图4-1:
图 4-1 连连看游戏模块图
连连看系统各模块介绍
图4-1所示的游戏模块图中,连连看游戏系统主要分成两个部分。第一部分是显示部分即游戏界面模块,该模块根据布局又分为功能键模块和操作间模块。第二部分是处理部分即处理模块,在该模块中,需要完成需求分析中的用户需求和功能需求。
游戏界面模块
游戏界面模块根据布局细分为操作模块和功能键模块。
操作模块:在游戏过程中,需要使用鼠标与游戏系统交互的主要模块。模块主要有排列的JButton构成,每个JButton上显示图片。所有JButton随机出现,且成对出现。借按钮组件及其事件处理机制,模拟游戏中选中图片并消除。当点击按钮组件时,这个外界刺激会触发事件监听器,事件监听器会接收事件并作出处理,就有了对这一操作的响应。
功能键模块:在游戏过程中,需要使用鼠标与游戏系统交互的次要模块。模块主要有JButton组件、下拉列表、JLabel等组件,构成完成游戏功能的控制部分,在此布局内,除了使用这些组件外,还要绘制一个沙漏状的动画,用以实现倒计时功能。同样,在此模块中所有组件除沙漏,均需要用鼠标操作,每个组件都应该有对应的响应事件和事件监听器。
为更好的区分开显示和实现,游戏界面模块将以布局为主要内容,具体的处理和响应将划分到处理模块。
处理模块
针对游戏的主要功能划分出一个模块:处理模块。这个模块中将实现一些功能,包括操作功能、计时功能、提示功能等。现将设计一下几个模块:
图像处理模块:程序运行后,这个模块将把资源文件中提供的图片进行排列。这个模块在初始化游戏布局和重新开始游戏以及刷新游戏时会用到。
响应模块:响应模块分两大类,一类是对操作模块中JButton的响应(即消除功能),一类是对功能键模块中各个组件的响应(每个响应都实现其对应功能)。
更改提示模块:这个模块主要负责记分、记录关数。
倒计时模块:倒计时模块是对沙漏动画的绘制,并在倒计时五秒处显示提示JLable,在倒计时结束后弹出提示框。
消除模块:判断选中的两个图片是否满足被消除的条件,此模块中,将实现判断。
确定类
在图形用户界面GUI设计中,会使用到javax.swing中的JButton、JDialog、JFrame 、JLabel、JPanel等组件。将这些组件放在JFrame容器中,构成LianLianKan类继承于JFrame类。如图4--2所示。在LianLianKan类中声明内部类LianLianKanJPanel类,继承于JPanel类。如图4-3所示,在LianLianKanJPanel类中声明了若干JButton、Choice、ImageIcon类对象。
图 4-2 连连看类图
图 4-3 LianLianKanJPanel类图
在LianLianKanJPanel类中再声明一个内部类loudou类。loudou类同样继承于JPanel类,在该类中创建Thread类、JLabel、JDialog类对象,漏斗形状的绘制通过调用paintComponent(Graphics g)方法完成。loudou类图如图4-4所示。Thread类图如图4-5所示
图 4-4 loudou类图
图 4-5 Thread类图
游戏素材
本游戏显示将采用图片连连看的模式,界面要满足需求分析中提出的简洁明了、友好大方,保证数据存储安全可靠。游戏素材则包括两类图片,一类是背景图片,一类是游戏操作模块中显示用的游戏图片。
背景图片
图 4-6 游戏背景图
游戏图片
前文提到,根据游戏难度的不同将选择显示不同种类的图片,现将按照难度区分,依次展示简单模式、中等模式、困难模式和变态模式下游戏界面将出现的游戏图片素材。除简单模式,每一难度模式将新增几种图片并包含上一难度模式下的图片种类。
简单模式下将出现四种简单的游戏图片,是四种颜色不同的球体,详见图4--7。
图 4-7 简单模式下的游戏图片
中等模式下将包括八种图片,图4-8将展示新增图片
图 4-8 中等模式下新增的游戏图片
困难模式将包括十二种图片,图4-9将显示新增四种图片。
图 4-9 困难模式下新增的游戏图片
变态模式将包括十五种图片,图4-10将展示新增的三种图片。
图 4-10 变态模式下新增的游戏图片
详细设计与实现
详细设计是在概要设计的基础上进行细化的过程。详细设计的主要任务是设计每个模块的实现算法即实现游戏界面、组件的事件处理等。在详细设计阶段,除了要注意具体模块的功能分解,还要绘制活动图、状态图、顺序图等动态模型,丰富静态结构图。
界面设计
游戏主界面以窗口形式给出,用户操作的游戏功能部分由各个组件构成,通过弹出的提示框开始游戏活动,用户通过点击窗口上的各个组件完成操作。游戏界面设计如下图5-1所示。
图 5-1 游戏界面设计图
界面实现
在游戏运行开始时,将弹出一个提示框以提示用户即将开始游戏,提示框如图5-2。此处弹出提示框一方面是提示作用,一方面是为便利扩展游戏功能,可将游戏扩展成多用户模式,在提示框实现处更改为用户登录模块,并联接数据库。鉴于本次任务时间有限此处未能实现。
图 5-2 游戏开始对话框
代码如下:
if (remainTimes == 0) {
JOptionPane.showMessageDialog(null, "游戏开始?");
单击确定按钮进入游戏主界面,默认进入简单模式下的游戏主界面,如图5-3。
图 5-3 简单模式下的游戏界面图
如上图所示,游戏主界面展示了本次连连看小游戏的主体布局界面。在界面的左侧是游戏主要操作和显示被操作图片的区域,界面的右侧展示了功能模块中几个功能组件。界面的右侧由上至下展示了“重新开始”按钮、“刷新”按钮、难度模式选择列表(默认是简单模式)、两个标签文本、一个沙漏状的倒计时动画(包括一个隐形的标签文本,当时间还剩五秒的时候,会显示倒计时信息)。
不同难度的游戏模式下,主要游戏界面展示略有不同,四种难度模式下的游戏界面图如图5-3、5-4、5-5、5-6。
图 5—4 中等模式下的游戏界面图
图 5—5 困难模式下的游戏界面图
图 5-6 变态模式下的游戏界面图
如上图所示,对游戏主界面没有任何操作时,四种难度模式下的游戏主界面最大的区别就是操作模块部分的图片排列,可以看出,难度越大图片种类越多,看起来越复杂,实现了前文对于难度变化提到的要求。每一种困难模式下的图片均是成对出现的,满足前文对于图片排列的要求。
整体界面以黑色为主,简洁大方,整体布局合理工整。左侧图片素材清晰、可爱,图片素材之间留有空隙,视觉上更舒服更易于区分,右侧功能键排列整齐,文字描述清晰。
布局部分代码如下:
Random random = new Random();
int temp = 0;
for (int i = 0; i < 32 - Kinds; i++) {
temp = random.nextInt(Kinds) + 1;
numbers.add(temp);
numbers.add(temp);
}
for (int i = 0; i < 8; i++) {
for (int j = 0; j < 8; j++) {
BlockButton[i][j] = new JButton();
add(BlockButton[i][j]);
BlockButton[i][j].addActionListener(this);
BlockButton[i][j].setBounds(30 + j * 40, 30 + i * 40, 31,34);
}
}
倒计时沙漏的设计
在游戏的界面上,还有一个特殊的面板,漏斗面板,漏斗面板上绘制了一个沙漏状的倒计时装置,该装置通过线程控制,时间变量每更新一次,漏斗面上重新绘制一次,每次绘制的线条通过判断条件设置摆放位置,随着时间的递增,沙漏状的倒计时装置就动态的开始倒计时,直至最后五秒,显示提示信息,倒计时结束后,弹出游戏失败提示框。沙漏示意图如下图5-7。
图 5-7 沙漏设计图
此处沙漏使用Graphics类的paintComponet()方法,游戏开始自动调用,在线程中,当剩余时间参数改变时调用repaint(),重载paintComponet(),通过判断剩余时间,绘制线条,这样随着每一秒时间的流逝,上方的绿色线条会在视觉上像是流动到下方。当属于时间不足5秒时,JLabel显示提示信息。代码如下:
super.paintComponent(g);
g.setColor(Color.green);
for (int i = 0; i < 56; i++) {
g.drawLine(x1 + i / 2 + 2, y1 + i, x2 - i / 2 - 2, y1 + i);
}
if (remainTimes < 55) {
for (int i = 0; i < remainTimes; i++) {
g.drawLine(x1+i/2+2, y2-i-1,x2-i/2-2, y2-i-1);
}
g.drawLine((x1 + x2) / 2, (y1 + y2) / 2, (x1 + x2) / 2, y2 - 2);
g.drawLine((x1+x2)/2+1, (y1+y2)/2+1, (x1+x2)/2+1, y2-2);
g.setColor(getBackground());
for (int i = 0; i < remainTimes; i++) {
g.drawLine(x1 + i / 2 + 2, y1 + i, x2 - i / 2 - 2, y1 + i);
}
}
if (remainTimes >= 50 && remainTimes <= 55)
overJLabel.setText((55-remainTimes) + "second");
if (remainTimes == 56)
overJLabel.setText("OVER");
remainTimes++;
repaint();
倒计时结束时,意味着在规定时间内未完成游戏,判定游戏失败,此时应该有提示框,如图5-8。
图 5-8 游戏结束对话框
部分代码如下:
if (remainTimes == 56) {
JOptionPane.showMessageDialog(null, "时间到!游戏结束!");
}
游戏执行的实现
因为每一次选择难度模式后、每通过一关游戏后都将开始一局新游戏,故一次游戏活动图如图5-9所示。最终状态有两种,游戏失败和游戏结束。
图 5-9 一次游戏活动图
一次游戏活动的顺序图如图5--10所示,一次游戏过程中,“点击图片”、“点击‘重新开始’按钮”、“点击‘刷新’按钮”操作上可不分时间先后顺序。每一次游戏结束后可以开始新一局游戏直至用户退出游戏。
图 5-10 一次游戏顺序图
点击图片的实现及其代码
前文提到,每选中一个图片应该区别于其他未被选中的图片。具体实现方式:当点击第一图片时,图片会变成激活状态,颜色变暗(用到了JButton的SetEnable方法)。当点击第二张图片时如果符合游戏规则,则两张图片消除,否则第一张图片变回默认状态,第二张图片变为激活状态;按钮状态图如图5-11所示,系统截图如图5-12。
图 5-11 按钮状态图
图 5-12 系统截图
此功能实现代码:
BlockButton[j][i].setEnabled(false);
记分,记关数的实现
在游戏过程中,需要对游戏当前状态进行记录,一次得分记录的过程活动图如图5-13,记录实例系统截图如下图5-14。
图 5-13 记录活动图
图 5-14 系统截图
游戏过程中,每消除一对相同图片,得分10,8×8格式的二维图片集,一共64张图片,共计32对,所以没过一关得分是320分,图5--9显示的是,消除34对后的得分。在每一难度下的每一关通过后,记分不清0,继续记分。但切换到不同难度时,得分会清0。
刷新功能的实现
游戏中每一关只有一次使用刷新功能的机会,此功能键触发的响应事件,会调用chongzai()方法,按照当前状态未消除的图片个数重新在二维按钮排列的其他位置排放其他图片。点“刷新”按钮的流程图如图5-15所示,前后变化如下图5-16、5-17所示。
图 5-15 “刷新”流程图
图 5-16刷新前系统截图 图 5-17 刷新后系统截图
刷新功能一关游戏只能使用一次,不论是那一个难度下,一关内刷新功能只能使用一次,只有通过这一关,下一关中刷新功能才能使用。使用一次之后,按钮将不能点击,状态图如图5-18,系统截图如下图5-19所示。
图 5-18 刷新按钮状态图
图 5-19 点击一次之后系统截图
刷新功能代码如下:
if (e.getSource() == reLoad) {
chongzai();
reLoad.setEnabled(false);
chongzai()中部分代码如下:
for (int i = 0; i < jishushengyu / 2; i++) {
kind = random.nextInt(Kinds) + 1;
do {
randomx1 = random.nextInt(8);//0-8随机数
randomy1 = random.nextInt(8);
} while (map[randomy1][randomx1] > 0);
map[randomy1][randomx1] = kind;
do {
randomx = random.nextInt(8);
randomy = random.nextInt(8);
} while (map[randomy][randomx] > 0);
map[randomy][randomx] = kind;
}
重新开始游戏功能的实现
重新开始游戏功能实际也是开始新游戏功能,重新开始布局的过程。将图片成对的显示在场景中,并打乱调用的是newMap()方法。在该方法中,用了一个数组以数字标记的形式来记录加载的图片是哪种图片,在每次加载图片的时候是一张图片连续加载两次,以保证加载图片成对。然后用数组的随机方法将数组打乱。
游戏的连接算法
连连看游戏中对于用户来说最简单的呈现,就是单击两个连在一起的相同的图像时,这两个图像就会消去,但是在Java代码中是如何实现的呢?连连看游戏的联通算法一般包括回溯法和堆栈实现的迷宫算法。
根据游戏规则能知道,即使不是紧邻的两个相同的图像块消去时也不能超过两次转弯。在本次开发的连连看中两个图像块可以消去的情况大致可以分为以下几种情况。
连连看连接方式的类型
连连看游戏的连接方式就是指两个图片之间连接的方式,一共可以分为以下这几种方法:
两点直线法示例如图5-20。
图 5-20 两点直线法示例图
三点直角折线法示例如图5-21。
图 5-21 三点直线法示例图
四点方形折线法示例如图5-22。
图 5-22 四点方形折线法示例图
四点梯形折线法示例如图5-23。
图 5-23 四点梯形折线法示例图
下面对上面四种类型进行细致划分讲解:
两点直线法的连接类型包括:上下,左右
三点直角折线法包括:上左,上右,下左,下右,左上,右上,左下,右下
四点方形折线法包括:上左下,上右下,下左上,下右上,左上右,右上左,左下右,右下左
四点梯形折线法包括:上左上,下左下,上右上,下左下,左上左,右上右,左下左,右下右
连连看连接方式分析
满足上述要求是第一步,即两个图片满足上次相连方式。第二步是满足图片相同。换言之,检验两个方块能否消掉,要让两个方块同时满足两个条件才行,就是两者配对并且连线成功,此处可分三种情况。从下面的这三种情况,我们可以知道,需要三个检测,这三个检测分别检测一条直路径。这样就会有三条路径。若这三条路径上都是空按钮,那么就刚好是三种直线(两个转弯点)把两个按钮连接起来了。
第一种情况:相邻。这种情况最简单。
第二种情况:不相邻。若不相邻,第一步在选中的第一个按钮的同行找到一个空按钮,此时分为两种情况:
情况A:找到空按钮后,再看选中的第二个按钮的横向到这个空按钮所在的列交叉处是否有按钮,若交叉处没有按钮,再从与第一个按钮到与它同行的那个空按钮之间是否有按钮,此时也没有按钮的话,路径通,反之则否。
情况B:第一步在选中的第一个按钮的同行找不到一个空按钮,此时在选中的第一个按钮的同列找一个空按钮。找到空按钮后,查看选中的第二个按钮竖向到这个空按钮所在行的交叉处是否有按钮。没有按钮的话,再查看选中的第一个按钮到与它同列的那个空按钮之间是否有按钮。没按钮的话,再判断与选中的第一个按钮同列的这个空按钮横向到与选中的第二个按钮同列有否有按钮,没有的话,路径通。
若满足以上情况的分析,也即路径通,选中的两个图片可消除。若以上情况分析均不满足,说明这两个按钮不可以消去。
具体判断流程图如图5―24。
图 5-24 判断流程图
代码中定义的方法有:
判断在一列之内两图片之间是否全部是空白或直接相邻
判断在一行之内两图片之间是否全部是空白或直接相邻
是否可以一条直线相连
是否可以两条直线相连
是否可以三条直线相连
是否可以三条直线相连,似U形
是否可以三条直线相连,似之字形N
是否处于游戏区域的四条边的同一边上
代码展示
// 判断在一列之内两图片之间是否全部是空白或直接相邻
// 直接相连,因而不包含空白
if (Math.abs(posY1 - posY2) == 0) {
return true;
}
int a = posY1 < posY2 ? posY1 : posY2;
int b = posY1 < posY2 ? posY2 : posY1;
for (int j = a + 1; j < b; j++) {
if (map[posX1][j] != 0) {
return false;
}
}
// 是否可以一直线相连
if (posX1 != posX2 && posY1 != posY2) {
return false;
}
if (posX1 == posX2) {
if (containsAllOrNoneZeroInColumn(posX1, posY1, posX2, posY2)) {
return true;
}
}
if (posY1 == posY2) {
if (containsAllOrNoneZeroInRow(posX1, posY1, posX2, posY2)) {
return true;
}
}
// 是否可以三直线相连,似之字形N
if (isOnZigzagWith1Row2Cols(posX1, posY1, posX2, posY2)) {
return true;
}
if (isOnZigzagWith2Rows1Col(posX1, posY1, posX2, posY2)) {
return true;
}
// 是否处于游戏区域的4条边的同一边上
if ((posY1 == posY2 && posY2 == 0)
|| (posY1 == posY2 && posY2 == 8 - 1)
|| (posX1 == posX2 && posX2 == 0)
|| (posX1 == posX2 && posX2 == 8 - 1)) {
return true;
}
// 是否可以三直线相连,似之字形, 两行一列 Z
int moreX = posX1 < posX2 ? posX2 : posX1;
int lessX = posX1 < posX2 ? posX1 : posX2;
for (int i = lessX + 1; i < moreX; i++) {
if (containsAllOrNoneZeroInColumn(i, posY1, i, posY2)
&& containsAllOrNoneZeroInRow(i, posY1, posX1, posY1)
&& containsAllOrNoneZeroInRow(i, posY2, posX2, posY2)
&& map[i][posY1] == 0 && map[i][posY2] == 0) {
return true;
}
}
总结
对连连看游戏进行了详细设计和实现,通过活动图和状态图,详细描述了操作的执行过程和一个特定对象的所有可能状态以及由于各种事件发生而引起的状态转换,为实现功能提供逻辑思路。
源码获取
大家点赞、收藏、关注、评论啦 、查看👇🏻获取联系方式👇🏻
关注公众号《编程乐学》,后台回复:24012521 自动回复