连连看游戏设计

连连看是一种很受大家欢迎的小游戏。微软亚洲研究院的实习生们就曾经开发过一个类似的游戏--Microsoft Link-up。

  

图1-17为Microsoft Link-up的一个截图。如果用户可以把两个同样的图用线(连线拐的弯不能多于两个)连到一起,那么这两个头像就会消掉,当所有的头像全部消掉的时候,游戏成功结束。游戏头像有珍稀动物、京剧脸谱等。Microsoft Link-up还支持用户输入的图像库,微软的同事们曾经把新员工的漫画头像加到这个游戏中,让大家在游戏之余也互相熟悉起来。

假如让你来设计一个连连看游戏的算法,你会怎么做呢?要求说明:

1. 怎样用简单的计算机模型来描述这个问题?

2. 怎样判断两个图形能否相消?

3. 怎样求出相同图形之间的最短路径(转弯数最少,路径经过的格子数目最少)。

4. 怎样确定目前是处于死锁状态,如何设计算法来解除死锁?

分析与解法

连连看游戏的设计,最主要包含游戏局面的状态描述,以及游戏规则的描述。而游戏规则的描述就对应着状态的合法转移(在某一个状态,有哪些操作是满足规则的,经过这些满足规则的操作,会到达哪些状态)。所以,自动机模型适合用来描述游戏设计。

下面是一个参考的连连看游戏的伪代码:

代码清单1-22

  1. 生成游戏初始局面
  2. Grid preClick = NULL, curClick = NULL;
  3. while(游戏没有结束)
  4. {
  5. 监听用户动作
  6. if(用户点击格子(x, y),且格子(x, y)为非空格子)
  7. {
  8. preClick = curClick;
  9. curClick.Pos = (x, y);
  10. }
  11. if(preClick != NULL && curClick != NULL
  12. && preClick.Pic == curClick.Pic
  13. && FindPath(preClick, curClick) != NULL)
  14. {
  15. 显示两个格子之间的消去路径
  16. 消去格子preClick, curClick;
  17. preClick = curClick = NULL;
  18. }
  19. }

从上面的整体框架可以看到,完成连连看游戏需要解决下面几个问题:

   

1. 生成游戏初始局面。

2. 每次用户选择两个图形,如果图形满足一定条件(两个图形一样,且这两个图形之间存在少于3个弯的路径),则两个图形都能消掉。给定具有相同图形的任意两个格子,我们需要寻找这两个格子之间在转弯最少的情况下,经过格子数目最少的路径。如果这个最优路径的转弯数目少于3,则这两个格子可以消去。

3. 判断游戏是否结束。如果所有图形全部消去,游戏结束。

4. 判断死锁,当游戏玩家不可能再消去任意两个图像的时候,游戏进入"死锁"状态。如图1-18,该局面中已经不存在两个相同的图片相连的路径转弯数目小于3的情况。

在死锁的情况下,我们也可以暂时不终止游戏,而是随机打乱局面,打破"死锁"局面。

首先思考问题:怎样判断两个图形能否相消?在前面的分析中,我们已经知道,两个图形能够相消的充分必要条件是这两个图形相同,且它们之间存在转弯数目小于3的路径。因此,需要解决的主要问题是,怎样求出相同图形之间的最短路径。首先需要保证最短路径的转弯数目最少。在转弯数目最少的情况下,经过的格子数目也要尽可能地少。

在经典的最短路径问题中,需要求出经过格子数目最少的路径。而这里,为了保证转弯数目最少,需要把最短路径问题的目标函数修改为从一个点到另一个点的转弯次数。虽然目标函数修改了,但算法的框架仍然可以保持不变。广度优先搜索是解决经典最短路问题的一个思路。我们看看在新的目标函数(转弯数目最少)下,如何用广度优先搜索来解决图形A(x1, y1)和图形B(x2, y2)之间的最短路径问题。

首先把图形A(x1, y1)压入队列。

然后扩展图形A(x1, y1)可以直线到达的格子(即图形A(x1, y1)可以通过转弯数目为0的路径(直线)到达这些格子)。假设这些格子为集合S0,S0 = Find(x1, y1)。如果图形B(x2, y2)在集合S0中,则结束搜索,图形A和B可以用直线连接。

否则,对于所有S0集合中的空格子(没有图形),分别找到它们可以直线到达的格子。假设这个集合为S1。S1 = {Find(p)| p ∈S0}。S1包含了S0,我们令S1'= S1-S0,则S1'中的格子和图形A(x1, y1)可以通过转弯数目为1的路径连起来。如果图形B(x2, y2)在S1'中,则图形A和B可以用转弯数目为1的路径连接,结束搜索。

否则,我们继续对所有S1'集合中的空格子(没有图形),分别找出它们可以直线到达的格子,假设这个集合为S2,S2 = Find{ Find(p)| p ∈S1'}。S2包含了S0和S1,我们令S2'= S2 - S0 - S1 = S2 - S0 - S1'。集合S2'是图形A(x1, y1)可以通过转弯数目为2的路径到达的格子。如果图形B(x2, y2)在集合S2'中,则图形A和B可以用转弯数目为2的路径连接,否则图形A和B不能通过转弯小于3的路径连接。

在扩展的过程中,只要记下每个格子是从哪个格子连过来的(也就是转弯的位置),最后图形A和B之间的路径就可以绘制出来。

在上面的广度优先搜索过程中,有两步操作:S1' = S1 - S0和S2'= S2 - S0 -S1。它们可以通过记录从图形A(x1, y1)到该格子(x, y)的转弯数目来实现。开始,将所有格子(x, y)和格子A(x1, y1)之间路径的最少转弯数目MinCrossing(x, y)初始化为无穷大。然后,令MinCrossing(A)= MinCrossing(x1, y1)= 0,格子A到自身当然不需要任何转弯。第一步扩展之后,所有S0集合中的格子的MinCrossing值为0。在S0集合继续扩展得到的S1集合中,格子X和格子A之间至少有转弯为1的路径,如果格子X本身已经在S0中,那么,MinCrossing(X)= 0。这时,我们保留转弯数目少的路径,也就是MinCrossing(X)= MinValue(MinCrossing(X), 1)= 0。这个过程,就实现了上面伪代码中的S1'= S1 - S0。S2'= S2 - S0-S1的扩展过程也类似。

经过上面的分析,我们知道,每一个格子X(x, y),都有一个状态值MinCrossing(X)。它记录下了该格子和起始格子A之间的最优路径的转弯数目。广度优先搜索,就是每次优先扩展状态值最少的格子。如果要保证在转弯数目最少的情况下,还要保持路径长度尽可能地短,则需要对每一个格子X保存两个状态值MinCrossing(X)和MinDistance(X)。从格子X扩展到格子Y的过程,可以用下面的伪代码实现:

  1. if((MinCrossing(X) + 1 < MinCrossing(Y)) ||
  2. ((MinCrossing(X) + 1 == MinCrossing(Y) &&
  3. (MinDistance(X) + Dist(X,Y) < MinDistance(Y)))
  4. {
  5. MinCrossing(Y) = MinCrossing(X) + 1;
  6. MinDistance(Y) = MinDistance(X) + Dist(X, Y);
  7. }

也就是说,如果发现从格子X过来的路径改进了转弯数目或者路径的长度,则更新格子Y。

"死锁"问题本质上还是判断两个格子是否可以消去的问题。最直接的方法就是,对于游戏中尚未消去的格子,都两两计算一下它们是否可以消去。此外,从上面的广度优先搜索可以看出,我们每次都是扩展出起始格子A(x1, y1)能够到达的格子。也就是说,对于每一个格子,可以调用一次上面的扩展过程,得到所有可以到达的格子,如果这些格子中有任意一个格子的图形跟起始格子一致,则它们可以消去,目前游戏还不是"死锁"状态。

扩展问题:

1. 在连连看游戏设计中,是否可以通过维护任意两个格子之间的最短路径来实现快速搜索?在每一次消去两个格子之后,更新我们需要维护的数据(任意两个格子之间的最短路径)。这样的思路有哪些优缺点,如何实现呢?

2. 在围棋或象棋游戏中,经过若干步操作之后,可能出现一个曾经出现过的状态(例如,围棋中的打劫)。如何在围棋、象棋游戏设计中检测这个状态呢?

参考链接:

《编程之美》读书笔记(六):连连看游戏设计

连连看设计之核心算法

编程之美之连连看游戏设计(核心代码)

第1章 游戏之乐——连连看游戏设计相关推荐

  1. 【java毕业设计】基于java+swing+GUI的连连看游戏设计与实现(毕业论文+程序源码)——连连看游戏

    基于java+swing+GUI的连连看游戏设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于java+swing+GUI的连连看游戏设计与实现,文章末尾附有本毕业设计的论文和源码下载地址哦 ...

  2. 基于java的连连看游戏系统设计与实现(项目报告+答辩PPT+源代码+数据库+截图+部署视频)

    项目说明报告 基于Java的连连看游戏设计与实现 连连看是一种消除类益智游戏,核心要求是在规定的时间内,消除游戏界面中选中的两张相同的图案,直至完全消除所有图案.这款游戏操作简单(只需单击鼠标左键操作 ...

  3. [计算机毕设]基于java的连连看游戏系统设计与实现(项目报告+答辩PPT+源代码+数据库)

    项目说明报告 基于Java的连连看游戏设计与实现 连连看是一种消除类益智游戏,核心要求是在规定的时间内,消除游戏界面中选中的两张相同的图案,直至完全消除所有图案.这款游戏操作简单(只需单击鼠标左键操作 ...

  4. Java实现连连看源代码文档_JAVA实现连连看游戏

    文件名大小更新时间 JAVA实现连连看游戏\java连连看游戏设计介绍 幻灯片.pptx22697322018-06-09 JAVA实现连连看游戏\源代码\JAVA连连看游戏设计 源代码\.class ...

  5. 果蔬连连看java源代码_《基于Qt的连连看游戏的设计》-毕业论文.doc

    PAGE 精品 摘 要 在现今电子信息高速发展的时代,电子游戏已然成为大众最受欢迎的娱乐消遣方式,经典的连连看是个老少皆宜的小游戏,它实现由各式各样的成对图片组成,然后存储在一个二维的数组中,计算机随 ...

  6. 基于Java的连连看游戏设计与实现

    项目介绍 连连看是一种消除类益智游戏,核心要求是在规定的时间内,消除游戏界面中选中的两张相同的图案,直至完全消除所有图案.这款游戏操作简单(只需单击鼠标左键操作).面向人群广泛,在限时操作的游戏要求下 ...

  7. 基于JavaSwing的连连看游戏的设计与实现

    目录 摘 要 1 Abstract 2 目录 2 绪论 1 1.1. 课题背景 1 1.2. Java游戏开发的现状 1 1.2.1. Java日益趋向成熟 1 1.2.2. Java极大的方便了游戏 ...

  8. java设计连连看心得_基于Java的连连看游戏的设计与实现

    ComputerKnowledgeand Technology 电脑知识与技术 软件设计开发本栏目责任编辑:谢媛媛 第7卷第35期 (2011年12月) 9 基于Java的连连看游戏的设计与实现 陈珊 ...

  9. 游戏设计的艺术:一本透镜的书——第二十五章 好的游戏是通过游戏测试做出来的

    这是一本游戏设计方面的好书 转自天之虹的博客:http://blog.sina.com.cn/jackiechueng 感谢天之虹的无私奉献 Word版可到本人的资源中下载 第二十五章好的游戏是通过游 ...

最新文章

  1. Cocos2d-x Eclipse下程序运行产生错误Effect initCheck() returned -1
  2. 60行代码爬取知乎“神回复”,句句戳中泪点
  3. python里面的之前打过的记忆信息-python中的记忆:如何缓存函数的运行结果(1)
  4. Qt Creator使用Memcheck检测内存泄漏
  5. 树链剖分 完美的想法
  6. BZOJ 4259: 残缺的字符串 [FFT]
  7. LeetCode 1684. 统计一致字符串的数目(哈希)
  8. Java笔记-spring-rabbit框架中消息中header的添加
  9. Linux——find命令常见用法
  10. 如何将电子海图的航线导到gps上_电子海图(ECDIS)使用总结
  11. 各版SQL字符串拼接
  12. SGI版本空间配置器
  13. 学设计要学python吗_北京学习Python设计大概需要多长时间能学会
  14. sql server 2012 自定义聚合函数(MAX_O3_8HOUR_ND) 计算最大的臭氧8小时滑动平均值
  15. IE缓存文件提取器 V2.1 绿色版
  16. K3Cloud不重启IIS修改调试代码
  17. 构建Spring Web应用程序
  18. python列举字符串的五种常用方法_python中字符串、列表、元组、字典每个常用的5个方法...
  19. 2018年北京信息科技大学第十届程序设计竞赛暨ACM选拔赛 C 颜料的混合 (计算几何)
  20. 开学季学生党需要准备哪些数码好物,分享几款实用的数码好物

热门文章

  1. HTML表格练习---个人简历
  2. 软件测试-18个功能测试点总结
  3. Python: Command Line Scripts
  4. 欢迎莅临HPX华南理工大学——产品经理职业规划讲座
  5. TimeUnit类常用方法
  6. 为什么很多人认为测试就是“鼠标点点点”?
  7. keras tensorboard的使用
  8. 微卡认证系统使用手册
  9. 贝壳采集器: 电话邦 数据采集
  10. 已拿offer热乎乎的蚂蚁金服面经分享,建议收藏(Java岗、附答案)