当前位置:文档之家› 用VB设计汉诺塔动画游戏

用VB设计汉诺塔动画游戏

本栏目责任编辑:谢媛媛软件设计开发

ComputerKnowledgeandTechnology电脑知识

与技术

第5卷第30期(2009年10月)

用VB设计汉诺塔动画游戏刘德强(无锡职业技术学院,江苏无锡214024)摘要:汉诺塔问题是程序设计教学中关于递归调用的经典案例。该文介绍了用VB设计汉诺塔动画游戏程序的基本过程,其中重点介绍了用VB的自定义数据类型和图形处理技术设计游戏步点状态记录和动画效果的方法。关键词:VB;汉诺塔;动画中图分类号:TP311文献标识码:A文章编号:1009-3044(2009)30-8460-03

TheDesigningofHanoiTowersAnimationGamebyVBLIUDe-qiang(WuxiInstituteofTechnology,Wuxi214024,China)Abstract:TheHanoiTowersisatypicalcaseofrecursivecallsinprogrammingteaching.Thispaperintroducesthebasicprocessofdesign-ingHanoiTowersanimationgamebyVB,focusesonrecordinggamestatebetweentwostepsanddesigninganimationbyself-defineddatatypeandgraphskillinVB.

KeyWords:VB;Hanoi;animation汉诺塔问题源自印度的一个古老传说,传至现代演变成了汉诺塔游戏:有A、B、C三个垂直杆和若干个大小各不相同的圆片。开始时圆片全部套在A杆上,且从下至上圆片大小依次递减。要求借助B杆,将圆片全部移到C杆上,每次只能移动一片,并且整个过程中三个杆上的圆片都必须保持大的在下小的在上。游戏的难度由开始时放置在A杆上圆片的个数进行控制。

1游戏步点状态记录设计

笔者设计的汉诺塔游戏程序主要包括演示和游戏两方面的功能。演示功能实现的是根据汉诺塔问题算法预先计算出的圆片移动顺序由计算机自行对圆片进行移动;而游戏功能是指计算机通过人机交互界面根据游戏者的实时操作顺序进行圆片的移动。图1是程序运行时界面。无论是演示还是游戏,计算机执行的基本动作元素是相同的,即圆片从一个杆上移动到另一个杆上,这一过程体现在程序设计中就是在新的位置对圆片图形进行重画,它与每个杆的步点状态密切相关。步点状态是指每完成一步操作以后,开始下一步操作之前,一个杆上的圆片数量及各圆片的位置和大小等多个特征综合构成的状态,是多个数据的集合。将开始时圆片数记为n,从初始状态圆片都在A杆上,到终止状态n个圆片移到C杆上,其间每次移动圆片,各杆的步点状态都会发生变化。游戏进程中“记”住各杆的当前步点状态,是实现不断移动圆片的关键。以要移动A杆上的一个圆片到B杆为例:要判断圆片根据规则是否可以移动及圆片移动后放置在B杆的什么位置(y坐标),就必须知道当前B杆上最上端圆片的大小和B杆上当前圆片数量,即B杆的当前步点状态。综合以上分析,游戏步点状态记录是程序设计中的要点。鉴于描述步点状态需要多个数据,且数据间相互关联并构成整体,笔者在设计中采用了自定义数据类型的方法,数据类型名称为circles,所含内容和定义格式如下:TypecirclescountsAsintegerr()AsintegerxAsintegery()AsintegerEndTypecircles类型中,数据成员counts用于记录杆上实际圆片数,r用于记录各圆片的半径,x记录各圆片圆心的x坐标,y记录各圆片

圆心的y坐标。因为每次游戏设置的初始圆片数是不确定的且游戏进程中各杆都可能出现多个圆片,所以数据成员r和y定义为动态数组。数据类型circles定义以后,先使用该类型定义三个实例a、b、c,分别代表A、B、C三个杆的步点状态。语句如下:DimaAscircles,bAscircles,cAscircles当初始圆片数量确定后(记为n),可使用下列语句对A杆的步点状态a进行初始化。

投稿日期:2009-08-22作者简介:刘德强(1965-),江苏靖江人,无锡职业技术学院讲师。

图1运行界面

ISSN1009-3044ComputerKnowledgeandTechnology电脑知识

与技术

Vol.5,No.30,October2009,pp.8460-8462

E-mail:xsjl@cccc.net.cnhttp://www.dnzs.net.cnTel:+86-551-56909635690964

8460软件设计开发本栏目责任编辑:谢媛媛ComputerKnowledgeandTechnology电脑知识

与技术

第5卷第30期(2009年10月)

ReDima.y(n):ReDima.r(n):a.counts=na.x=-330:a.y(1)=-260Fori=1Tona.r(i)=160-8*ia.y(i)=-270+i*45Picture1.Circle(a.x,a.y(i)),a.r(i),vbBlack,,,0.14Nexti语句中,通过对实例a的各成员进行赋值,确定了A杆上圆片的数量、各圆片的大小和位置,并在相应位置画出了代表各圆片的椭圆图形。程序设计中B杆和C杆的步点状态可参照相同方法进行初始化。游戏进程中,当圆片从一个杆上移动到另一个杆上,两杆的步点状态会发生变化,新的步点状态可通过下列语句进行记录,以圆片从A杆移到B杆为例:a.counts=a.counts-1b.counts=b.counts+1b.r(b.counts)=a.r(a.counts+1)Picture1.Circle(b.x,b.y(bcounts)),b.r(b.counts),vbBlack,,,0.14

语句中,成员counts记录两个杆上圆片数量的变化,成员r记录新画椭圆的半径。圆片在三个杆间的移动共分六种情况:分别是A→B、A→C、B→C、B→A、C→A和C→B,其余五种情况新的步点状态记录可采用相同方法。

综上所述,尽管各杆的步点状态需要多个数据进行描述,且在游戏进程中不断变化,采用自定义数据类型的方法可方便地对各杆的当前步点状态进行记录。

2游戏动画效果设计

根据前述,汉诺塔游戏的基本动作元素是圆片从一个杆上移到另一个杆上,如果将移动过程设计成动画,将提高游戏的趣味性和观赏性。和电影原理相似,动画是利用人眼的视觉暂留效应使静止图像或图形产生连续运动和变化效果的一种技术[1],如当相关连的序

列画面以30帧/秒左右的速度播放时,人眼所观察到的变化就是连续的。实现动画效果有两个基本要素:一是序列画面相互关连或相同;二是播放速度合适。在VB程序设计中,实现动画效果可通过在图片或图像控件中以一定的速度装载和卸载关连图像或图形文件序列实现;也可通过以一定的速度对装载了关连图像或图形文件的控件序列的Visible属性进行设置来实现[1];还可以利用VB的画圆(circle)、画线

(Line)等方法在关连位置以一定的速度,以背景色和另一种不同颜色不断交替绘制图形的方法来实现。汉诺塔游戏要表现的动画效果是圆片从一个杆移到另一个杆上的连续移动过程,即同一图形相对屏幕的位移,是一种简单的位移动画[1],笔者在设计过程中,采

用的是使用circle方法在关连位置交替绘制椭圆的方法(参见图1)。以从A杆上向上取出圆片为例,为表现圆片向上连续移动的动画效果,程序代码为:Fork=20To220-a.y(a.counts)Step20Picture1.Circle(a.x,a.y(a.counts)+k),a.r(a.counts),vbBlack,,,0.14delay(delay_m)Picture1.Circle(a.x,a.y(a.counts)+k),a.r(a.counts),&H8000000F,,,0.14Nextk程序执行过程中,每次循环计算机将在同一位置先后画同样大小但颜色不同的椭圆两次,先黑色(vbBlack),再背景色(&H8000000F),两次之间有一定的时间间隔,产生的视觉效果是黑色圆片在该位置先出现后消失,又随循环次数增加,所画椭圆位置会随变量k变化而不断上移,产生的综合视觉效果是黑色圆片连续向上移动。设计过程中,为使圆片的移动看上去更加平滑,所达到的动画效果更加逼真,可对循环语句的步长和延时过程delay中的参数delay_m进行调整。汉诺塔游戏中圆片的移动方向可概括为向上、平移和向下共三种,其余两种可采用相同原理进行动画效果设计。

3演示功能设计

演示功能主要是给游戏者提供操作步骤参考,设计演示功能先要设计汉诺塔问题算法、并依据其计算出移动圆片的顺序。对汉诺塔问题进行分析,将A杆上n个圆片全部移到C杆上,可以分解成以下三个相对容易的新问题:1)先将n-1个圆片,借助C杆,由A杆移到B杆上;

2)再将A杆上留下的1个圆片移到C杆上;

3)接着将B杆上n-1个圆片,借助A杆,移到C杆上。

三个新问题中1个圆片的移动是单步骤就能直接完成的已知操作,而n-1个圆片的移动又可以采用相同方法进一步分解成n-2个圆片和1个圆片的移动。依此类推,经过层层分解,每次分解出的新问题中要移动的圆片数不断减少,最终都将分解成1个圆片

的移动。上述分解过程是典型的递归过程。用递归方法解决问题,在VB程序设计中是通过设计和调用递归Sub过程来实现的。根据上述分析,汉诺塔问题的递归算法可设计为:PrivateSubmoves(nasinteger,pole_aasstring,pole_basstring,pole_casstring)Ifn=1Thenmove_str1=move_str1&pole_a&pole_cElseCallmoves(n-1,pole_a,pole_c,pole_b)Callmoves(1,pole_a,pole_b,pole_c)Callmoves(n-1,pole_b,pole_a,pole_c)

8461

相关主题