小游戏课程设计.docx

上传人:b****4 文档编号:4922869 上传时间:2022-12-11 格式:DOCX 页数:18 大小:518.55KB
下载 相关 举报
小游戏课程设计.docx_第1页
第1页 / 共18页
小游戏课程设计.docx_第2页
第2页 / 共18页
小游戏课程设计.docx_第3页
第3页 / 共18页
小游戏课程设计.docx_第4页
第4页 / 共18页
小游戏课程设计.docx_第5页
第5页 / 共18页
点击查看更多>>
下载资源
资源描述

小游戏课程设计.docx

《小游戏课程设计.docx》由会员分享,可在线阅读,更多相关《小游戏课程设计.docx(18页珍藏版)》请在冰豆网上搜索。

小游戏课程设计.docx

小游戏课程设计

 

课程名称:

算法分析与设计

设计题目:

2048游戏

院系:

班级:

设计者:

学号:

指导教师:

设计时间:

2017.6.24-2017.6.25

 

任务书

姓名:

院(系):

专业:

学号:

任务起止日期:

 

课程设计题目:

2048游戏

 

课程设计要求:

在处理每一个题目的时候,要从分析题目的需求入手,按设计抽象数据类型、构思算法、通过类的设计实现抽象数据类型、编制上机程序代码并调试的步骤完成题目,最终写出完整的分析报告。

见到题目,案头工作准备不足,忙于上机敲程序不是优秀程序员的工作风格。

注意设计与实现过程的经验积累,编码应尽量利用前阶段的成熟数据结构包,加大代码的重用率。

 

工作计划及安排:

1.讲解课程设计要求,布置并分析题目,进行人员分组0.5天

2.查阅资料,进行算法分析,并进行需求分析;详细设计,编写代码0.5天

3.论文编写及排版,算法优化,并改进代码0.5天

4.论文答辩,提交课程设计报告0.5天

 

指导教师签字

年月日

课程设计(大作业)成绩

学号:

姓名:

指导教师:

课程设计题目:

2048游戏

总结:

通过这次课程设计我明白了算法是一系列解决问题的清晰指令,代表着用系统的方法描述解决问题的策略机制。

算法能够对一定规范的输入,在有限时间内获得所要求的输出。

如果一个算法有缺陷,或不适合某个问题,执行这个算法将不会解决这个问题。

不同的算法可能用不同的时间、空间或效率来完成同样的任务。

一个算法的优劣可以用空间复杂性和时间复杂度来衡量。

算法可以使用自然语言、伪代码、流程图等多种不同的方法来描述。

计算机系统中的操作系统、语言编译系统、数据库管理系统以及各种各样的计算机应用系统中的软件,都必须使用具体的算法来实现。

算法设计与分析是计算机科学与技术的一个核心问题。

此次课程设计我受益匪浅,将课上遗漏的知识又进一步补上。

实践过程中遇到了很多困难,比如在程序中导入图片,设置方块随机出现的方法,如何将最高分显示出来。

由于本次试验的很多知识都是现学现用,以致很多地方的代码显得累赘繁琐,也了解了一些看似简单的小游戏,都蕴含着丰富的算法知识,只有亲自设计,才能领会其中算法的奥秘。

 

指导教师评语:

 

成绩:

 

填表时间:

指导教师签名:

 

课程设计(大作业)报告

一、需求分析

目前对休闲小游戏的需求是:

提高游戏的操作可行性,降低游戏的操作难度,降低游戏的上手难度,降低游戏的竞争需求,对使用设备的要求趋于简单化和多样化,游戏界面更加人性化,功能更加贴合使用。

1.1界面需求

一款的好的游戏其界面必须友好,简洁已经成为当今UI设计的主流,简单易上手才能得到玩家的青睐。

1.2功能需求

1)能够显示游戏的当前得分,再次次打开游戏时重置分数,游戏的主界面上,相同的数字要显示相同的颜色。

2)游戏途中胜利和失败要有相应的提示。

3)游戏的主要目的是通过上下左右移动来将相邻相同的数字相加,通过不断地累加最终加到2048。

1.3操作性需求

游戏的体验是衡量一款游戏的关键,本游戏通过键盘方向键来控制方块的移动,单手都可以操作,充分考虑便捷性。

1.4可行性分析

1)面向对象的程序设计方法

Java面向对象程序设计的基本思想是通过构造和组织对象来求解问题的。

对象是很好理解的,任何一种物体都可以被认为是对象,例如,汽车就是一种对象。

对象具有两个最基本的属性:

具有一定的物质基础和一定的功能,这两种基本属性在Java语言中表现为拥有一定的存储单元并具备一定的功能。

理解了Java的这种面向对象程序设计的基本思想之后,在以后的编程过程中,就应当个构造人们容易理解的更接近于真实物理世界物体的对象。

Java面向对象程序设计的过程非常简单。

这里介绍一种自顶向下的程序设计方法,首先构造一个类来处理需要解决的问题,然后根据已经拥有的类(例如以前求解其它问题时实现的类),分析和构造新的类,设法将问题分解下去,而最开始构造的类通过组织这些新构造的类、已有的类及由他们生成的实例来求解指定的问题。

这个过程可以继续递归下去,用在新构造的类上,直到最后解决了指定的问题,例如Java的应用程序和小应用程序都必须有一个类作为入口求解问题。

在计算机语言中,面向对象的类一般具有三个基本特性:

封装性、继承性和多态性,这三种特性进一步简化了Java求解模型,提高了程序的复用性,节省了程序的代码量,从而提高了软件的生产率。

2)java技术分析

图形用户界面不仅可以提供各种数据的基本图形的直观表示形式,而且可以建立友好的交互方式,从而使计算机软件可以设计得十分简单易用。

从Java语言诞生到现在,Java语言已经提供了两代图形用户界面。

第一代图形用户界面AWT提供了基本的图形用户界面,它强烈地依赖于具体的计算机操作系统,而且缺少基本的剪贴板和打印支持功能。

现在第二代图形用户界面Swing对AWT进行了扩展,Swing不仅在功能上比AWT强大,而且在很大程度上克服了AWT的上述缺点,它所设计的图形用户界面与具体的计算机操作相关性很小,而且可以定制指定的操作系统风格的图形用户界面。

GUI(图形用户界面)组件构成了图形用户界面的基础。

在Java程序设计中,要求按照一定的布局方式将组件安排在容器中,然后通过事件处理的方式实现人机交互,而容器本身也是组件,这样在容器中也可以含有容器,从而可以通过这种嵌套方式方便地组合各种组件。

事件处理模型是Java语言提供的一种人机交互模型,它使得用户能够通过鼠标、键盘或其他输入设备来控制程序的执行流程,从而达到人机交互的目的。

对鼠标、键盘或其他输入设备的各种操作一般也称为事件。

Java语言对这些事件的处理模型是采用面向对象的方法,即通过对象的形式把各种事件进行封装和处理。

这种事件处理模型的三个基本要素是事件源、事件对象以及事件监听器。

事件源是各种组件,是接受各种事件的对象。

在各种事件源上运用鼠标、键盘或其他输入设备进行各种操作,就会有事件发生。

每种操作一般都对应着事件,Java语言通过事件对象来包装这些事件。

对事件进行处理是通过事件监听器实现的。

二、游戏原理

2.1游戏规则

开始时棋盘内随机出现两个数字,出现的数字可能为2或4,玩家可以选择上下左右四个方向,若棋盘内的数字出现位移或合并,视为有效移动。

玩家选择的方向上若有相同的数字则合并,每次有效移动可以同时合并,但不可以连续合并,合并所得的所有新生成数字相加即为该步的有效得分。

玩家选择的方向行或列前方有空格则出现位移,每有效移动一步,棋盘的空位(无数字处)随机出现一个数字(依然可能为2或4)棋盘被数字填满,无法进行有效移动,判负,游戏结束;若棋盘上出现2048,判胜,游戏结束。

 

2.2游戏的关键

这个游戏有点像我们小时候玩的九连环,当你想成功合成一个比较大的数字(譬如游戏目标2048),必须先合成次大的1024,如此循环反复,递归。

若想获得胜利,在于尽可能多地保留数字挪移的空位。

三、算法分析

这个游戏的本质是二维数组,就以4*4的二维数组来分析关键的逻辑以及实现。

二维数组如图1

图3

   图1

图2

我们所有的操作都是对这个二维数组的数据的操作。

分为上下左右四个方向。

我们先说向左的方向(如图2)。

向左操作的结果如图3;

当相左的方向是,所有的数据沿着水平方向向左跑,这是看到的结果。

水平相左:

  水平说明操作的是二维数组的一行,而垂直操作的则是二位数组的一列。

这样就可以将二维数组的操作变成遍历后对一维数组的操作。

  向左说明数据的优先考虑的位置是从左开始的。

这样就确定了一维数组的遍历开始的位置。

   图2中共四行,每一个行都能得到一个以为数组

    arr1:

[0,0,2,0];

    arr2:

[0,4,2,0];

    arr3:

[0,0,4,4];

    arr4:

[2,0,2,0];

这样一来向左的方向就变成。

从上到下获得每一行的数组,方向向左。

其他的三个方向在开始的时候记住是怎样获得以为数组的,等操作完才放回去这样就能实现。

四、总体设计

2048游戏的总体设计内容比较的简单,对于小游戏界面的精简美观尤为重要,在精简的同时功能的实现,算法的稳定性也比较的重要,根据需求分析定义的游戏功能,可以将本游戏分为几个模块:

1)界面设计包括:

主界面、计分、重置、提示

2)算法设计包括:

计分规则、合并规则、游戏失败和胜利的判定规则

3)操作设计包括:

键盘事件监听、图片输入输出

总体模块设计图如下:

系统流程图如下:

五、算法优化

前面我们所做的是,在任何时刻,我都尝试合并值为2或者4的方块,也就是我会尝试让值为2和4的方块越少越好。

如果我尝试那么做,其它的方块会自动的合并,看起来像是个好策略。

但是是否有比这个策略更好的想法呢?

5.1基础算法Minimax

2048本质上可以抽象成信息对称双人对弈模型(玩家向四个方向中的一个移动,然后计算机在某个空格中填入2或4)。

这里“信息对称”是指在任一时刻对弈双方对格局的信息完全一致,移动策略仅依赖对接下来格局的推理。

使用核心算法为带Alpha-beta剪枝的Minimax。

下面先介绍不带剪枝的Minimax。

首先本文将通过一个简单的例子说明Minimax算法的思路和决策方式。

问题

现在考虑这样一个游戏:

有三个盘子A、B和C,每个盘子分别放有三张纸币。

A放的是1、20、50;B放的是5、10、100;C放的是1、5、20。

单位均为“元”。

有甲、乙两人,两人均对三个盘子和上面放置的纸币有可以任意查看。

游戏分三步:

1.甲从三个盘子中选取一个。

2.乙从甲选取的盘子中拿出两张纸币交给甲。

3.甲从乙所给的两张纸币中选取一张,拿走。

其中甲的目标是最后拿到的纸币面值尽量大,乙的目标是让甲最后拿到的纸币面值尽量小。

下面用Minimax算法解决这个问题。

基本思路

一般解决博弈类问题的自然想法是将格局组织成一棵树,树的每一个节点表示一种格局,而父子关系表示由父格局经过一步可以到达子格局。

Minimax也不例外,它通过对以当前格局为根的格局树搜索来确定下一步的选择。

而一切格局树搜索算法的核心都是对每个格局价值的评价。

Minimax算法基于以下朴素思想确定格局价值:

1.Minimax是一种悲观算法,即假设对手每一步都会将我方引入从当前看理论上价值最小的格局方向,即对手具有完美决策能力。

因此我方的策略应该是选择那些对方所能达到的让我方最差情况中最好的,也就是让对方在完美决策下所对我造成的损失最小。

2.Minimax不找理论最优解,因为理论最优解往往依赖于对手是否足够愚蠢,Minimax中我方完全掌握主动,如果对方每一步决策都是完美的,则我方可以达到预计的最小损失格局,如果对方没有走出完美决策,则我方可能达到比预计的最悲观情况更好的结局。

总之我方就是要在最坏情况中选择最好的。

下面看具体示例。

解题

下图是上述示例问题的格局树:

注意,由于示例问题格局数非常少,我们可以给出完整的格局树。

这种情况下我可以找到Minimax算法的全局最优解。

而真实情况中,格局树非常庞大,即使是计算机也不可能给出完整的树,因此我们往往只搜索一定深度,这时只能找到局部最优解。

我们从甲的角度考虑。

其中正方形节点表示轮到我方(甲),而三角形表示轮到对方(乙)。

经过三轮对弈后(我方-对方-我方),将进入终局。

黄色叶结点表示所有可能的结局。

从甲方看,由于最终的收益可以通过纸币的面值评价,我们自然可以用结局中甲方拿到的纸币面值表示终格局的价值。

下面考虑倒数第二层节点,在这些节点上,轮到我方选择,所以我们应该引入可选择的最大价值格局,因此每个节点的价值为其子节点的最大值:

这些轮到我方的节点叫做max节点,max节点的值是其子节点最大值。

倒数第三层轮到对方选择,假设对方会尽力将局势引入让我方价值最小的格局,因此这些节点的价值取决于子节点的最小值。

这些轮到对方的节点叫做min节点。

最后,根节点是max节点,因此价值取决于叶子节点的最大值。

最终完整赋值的格局树如下:

总结一下Minimax算法的步骤:

1.首先确定最大搜索深度D,D可能达到终局,也可能是一个中间格局。

2.在最大深度为D的格局树叶子节点上,使用预定义的价值评价函数对叶子节点价值进行评价。

3.自底向上为非叶子节点赋值。

其中max节点取子节点最大值,min节点取子节点最小值。

4.每次轮到我方时(此时必处在格局树的某个max节点),选择价值等于此max节点价值的那个子节点路径。

在上面的例子中,根节点的价值为20,表示如果对方每一步都完美决策,则我方按照上述算法可最终拿到20元,这是我方在Minimax算法下最好的决策。

格局转换路径如下图红色路径所示:

对于真实问题中的Minimax,再次强调几点:

1.真实问题一般无法构造出完整的格局树,所以需要确定一个最大深度D,每次最多从当前格局向下计算D层。

2.因为上述原因,Minimax一般是寻找一个局部最优解而不是全局最优解,搜索深度越大越可能找到更好的解,但计算耗时会呈指数级膨胀。

3.也是因为无法一次构造出完整的格局树,所以真实问题中Minimax一般是边对弈边计算局部格局树,而不是只计算一次,但已计算的中间结果可以缓存。

5.2Alpha-beta剪枝

简单的Minimax算法有一个很大的问题就是计算复杂性。

由于所需搜索的节点数随最大深度呈指数膨胀,而算法的效果往往和深度相关,因此这极大限制了算法的效果。

Alpha-beta剪枝是对Minimax的补充和改进。

采用Alpha-beta剪枝后,我们可不必构造和搜索最大深度D内的所有节点,在构造过程中,如果发现当前格局再往下不能找到更好的解,我们就停止在这个格局及以下的搜索,也就是剪枝。

Alpha-beta基于这样一种朴素的思想:

时时刻刻记得当前已经知道的最好选择,如果从当前格局搜索下去,不可能找到比已知最优解更好的解,则停止这个格局分支的搜索(剪枝),回溯到父节点继续搜索。

Alpha-beta算法可以看成变种的Minimax,基本方法是从根节点开始采用深度优先的方式构造格局树,在构造每个节点时,都会读取此节点的alpha和beta两个值,其中alpha表示搜索到当前节点时已知的最好选择的下界,而beta表示从这个节点往下搜索最坏结局的上界。

由于我们假设对手会将局势引入最坏结局之一,因此当beta小于alpha时,表示从此处开始不论最终结局是哪一个,其上限价值也要低于已知的最优解,也就是说已经不可能此处向下找到更好的解,所以就会剪枝。

下面同样以上述示例介绍Alpha-beta剪枝算法的工作原理。

我们从根节点开始,详述使用Alpha-beta的每一个步骤:

1.根节点的alpha和beta分别被初始化为−∞,和+∞。

2.深度优先搜索第一个孩子,不是叶子节点,所以alpha和beta继承自父节点,分别为−∞,和+∞

3.搜索第三层的第一个孩子,同上。

4.搜索第四层,到达叶子节点,采用评价函数得到此节点的评价值为1。

5.此叶节点的父节点为max节点,因此更新其alpha值为1,表示此节点取值的下界为1。

6.再看另外一个子节点,值为20,大于当前alpha值,因此将alpha值更新为20。

7.此时第三层最左节点所有子树搜索完毕,作为max节点,更新其真实值为当前alpha值:

20。

8.由于其父节点(第二层最左节点)为min节点,因此更新其父节点beta值为20,表示这个节点取值最多为20。

9.搜索第二层最左节点的第二个孩子及其子树,按上述逻辑,得到值为50(注意第二层最左节点的beta值要传递给孩子)。

由于50大于20,不更新min节点的beta值。

10.搜索第二层最左节点的第三个孩子。

当看完第一个叶子节点后,发现第三个孩子的alpha=beta,此时表示这个节点下不会再有更好解,于是剪枝。

11.继续搜索B分支,当搜索完B分支的第一个孩子后,发现此时B分支的alpha为20,beta为10。

这表示B分支节点的最大取值不会超过10,而我们已经在A分支取到20,此时满足alpha大于等于beta的剪枝条件,因此将B剪枝。

并将B分支的节点值设为10,注意,这个10不一定是这个节点的真实值,而只是上线,B节点的真实值可能是5,可能是1,可能是任何小于10的值。

但是已经无所谓了,反正我们知道这个分支不会好过A分支,因此可以放弃了。

12.在C分支搜索时遇到了与B分支相同的情况。

因此将C分支剪枝。

此时搜索全部完毕,而我们也得到了这一步的策略:

应该走A分支。

可以看到相比普通Minimax要搜索18个叶子节点相比,这里只搜索了9个。

采用Alpha-beta剪枝,可以在相同时间内加大Minimax的搜索深度,因此可以获得更好的效果。

并且Alpha-beta的解和普通Minimax的解是一致的。

5.3对2048游戏的优化

上面说过Minimax和Alpha-beta都是针对信息对称的轮流对弈问题,这里是这样抽象游戏的:

1.我方:

游戏玩家。

每次可以选择上、下、左、右四个行棋策略中的一种(某些格局会少于四种,因为有些方向不可走)。

行棋后方块按照既定逻辑移动及合并,格局转换完成。

2.对方:

计算机。

在当前任意空格子里放置一个方块,方块的数值可以是2或4。

放置新方块后,格局转换完成。

3.胜利条件:

出现某个方块的数值为“2048”。

4,失败条件:

格子全满,且无法向四个方向中任何一个方向移动(均不能触发合并)。

如此2048游戏就被建模成一个信息对称的双人对弈问题。

作为算法的核心,如何评价当前格局的价值是重中之重。

在2048中,除了终局外,中间格局并无非常明显的价值评价指标,因此需要用一些启发式的指标来评价格局。

那些分数高的“好”格局是容易引向胜利的格局,而分低的“坏”格局是容易引向失败的格局。

既然这个游戏是一个离散状态空间,信息完备的回合制游戏,类似于象棋和国际跳棋,那么我们就使用了针对这些游戏的证明过的行之有效的方法。

一套叫做minimaxsearch的算法,结合了alpha-betapruning(阿尔法-贝塔修剪)。

既然已经有很多信息解释了这套算法,那么我们就仅谈谈我们在staticevaluationfunction(静态评估函数)中使用到的两个重要概念。

单调性

这个概念保证方块的值沿着上下左右方向的,要么增加,要么减少。

这个概念单独地解释了一个大家提到的直觉,值较大的方块应该聚集到某一个角落。

这将有助于阻止值小的方块被孤立起来,也将让面板保持良好的组织结构,使得值小的方块渐进层叠式的并逐步合并为值大的方块。

下图是一个有完美单调性格子的截屏。

我们通过运行eval函数被设置为忽略其它概念的算法获得,仅仅考虑单调性。

平滑性

上面的概念倾向于构造值递减的结构,但如要合并,相邻的方格值必须相同。

因此,平滑性衡量相邻方格值的差,并尝试减少差。

下图是个有完美单平滑性的截屏。

空闲方块

最后,有一个针对空闲格子过少的惩罚。

毕竟面板过于拥挤的时候,选择受限且很快会被用完。

扫描游戏格子,同时优化以上标准,这会产生相当好的表现。

与明确硬编码的移动策略相比,这种使用通用性的方法有一个优点,这种算法可以找到有趣且难以预料的解决方案。

如果你观察它运行,它经常会做出一些惊奇但有效的移动,比如突然转向一个相反的墙或者角落。

修改

这是该方法强大能力的一个展示。

我拿掉了方格值大小的限制(到2048之后还可以继续运行,下图是8次尝试中最好一次的截屏,那是一个4096外加一个2048),那意味着在同一个面板上它完成了3次困难的2048方块。

六、运行结果

开始界面

在随机位置,随机生成两个2。

游戏失败

判定分条件:

所有方格被填满,且相邻没有相同的,不能再次合并,游戏结束。

游戏胜利

判定条件:

方格中合并出2048,游戏获胜,游戏结束。

七、总结

通过这次课程设计我明白了算法是一系列解决问题的清晰指令,代表着用系统的方法描述解决问题的策略机制。

算法能够对一定规范的输入,在有限时间内获得所要求的输出。

如果一个算法有缺陷,或不适合某个问题,执行这个算法将不会解决这个问题。

不同的算法可能用不同的时间、空间或效率来完成同样的任务。

一个算法的优劣可以用空间复杂性和时间复杂度来衡量。

算法可以使用自然语言、伪代码、流程图等多种不同的方法来描述。

计算机系统中的操作系统、语言编译系统、数据库管理系统以及各种各样的计算机应用系统中的软件,都必须使用具体的算法来实现。

算法设计与分析是计算机科学与技术的一个核心问题。

此次课程设计我受益匪浅,将课上遗漏的知识又进一步补上。

实践过程中遇到了很多困难,比如在程序中导入图片,设置方块随机出现的方法,如何将最高分显示出来。

由于本次试验的很多知识都是现学现用,以致很多地方的代码显得累赘繁琐,也了解了一些看似简单的小游戏,都蕴含着丰富的算法知识,只有亲自设计,才能领会其中算法的奥秘。

八、参考文献

[1]MetskerSJ.Java设计模式[M].第2版.电子工业出版社,2012年9月

[2]古德里奇、塔玛西亚.算法分析与设计由人民邮电出版社,2006年10月

[3]XX百科Alpha-Beta剪枝算法、minimax算法

[4]王晓东.算法分析与设计[M].第三版.清华大学出版社,2012年2月

九、源代码

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1