本欄目責任編輯
:
謝媛媛
軟件設計開發
Computer
Knowledge
and
Technology
電腦知識
與技術
第
5
卷第
30
期
(2009
年
10
月
)
用
VB
設計漢諾塔動畫游戲
劉德強
(
無錫職業技術學院
,
江蘇
無錫
214024
)
摘要
:
漢諾塔問題是程序設計教學中關于遞歸調用的經典案例
。
該文介紹了用
VB
設計漢諾塔動畫游戲程序的基本過程
,
其中重點
介紹了用
VB
的自定義數據類型和圖形處理技術設計游戲步點狀態記錄和動畫效果的方法
。
關鍵詞
:
VB
;
漢諾塔
;
動畫
中圖分類號
:
TP311
文獻標識碼
:
A
文章編號
:
1009-3044(2009)30-8460-03
The
Designing
of
Hanoi
Towers
Animation
Game
by
VB
LIU
De-qiang
(Wuxi
Institute
of
Technology,Wuxi
214024,China)
Abstract:
The
Hanoi
Towers
is
a
typical
case
of
recursive
calls
in
programming
teaching.This
paper
introduces
the
basic
process
of
design
-
ing
Hanoi
Towers
animation
game
by
VB,focuses
on
recording
game
state
between
two
steps
and
designing
animation
by
self-defined
data
type
and
graph
skill
in
VB.
Key
Words:
VB;Hanoi;animation
漢諾塔問題源自印度的一個古老傳說
,
傳至現代演變成了漢諾塔游戲
:
有
A
、
B
、
C
三個垂直桿和若干個大小各不相同的圓片
。
開
始時圓片全部套在
A
桿上
,
且從下至上圓片大小依次遞減
。
要求借助
B
桿
,
將圓片全部移到
C
桿上
,
每次只能移動一片
,
并且整個過
程中三個桿上的圓片都必須保持大的在下小的在上
。
游戲的難度由開始時放置在
A
桿上圓片的個數進行控制
。
1
游戲步點狀態記錄設計
筆者設計的漢諾塔游戲程序主要包括演示和游戲兩方面的功能
。
演示功能實現的是根據漢諾塔問題算法預先計算出的圓片移
動順序由計算機自行對圓片進行移動
;
而游戲功能是指計算機通過人機交互界面根據游戲者的實時操作順序進行圓片的移動
。
圖
1
是程序運行時界面
。
無論是演示還是游戲
,
計算機執行的基本動作元素是相同的
,
即圓片從一個桿上移動到另一個桿上
,
這一過程
體現在程序設計中就是在新的位置對圓片圖形進行重畫
,
它與每個桿的步點狀態密切相關
。
步點狀態是指每完成一步操作以后
,
開始下一步操作之前
,
一個桿上
的圓片數量及各圓片的位置和大小等多個特征綜合構成的狀態
,
是多個
數據的集合
。
將開始時圓片數記為
n
,
從初始狀態圓片都在
A
桿上
,
到終
止狀態
n
個圓片移到
C
桿上
,
其間每次移動圓片
,
各桿的步點狀態都會
發生變化
。
游戲進程中
“
記
”
住各桿的當前步點狀態
,
是實現不斷移動圓片
的關鍵
。
以要移動
A
桿上的一個圓片到
B
桿為例
:
要判斷圓片根據規則
是否可以移動及圓片移動后放置在
B
桿的什么位置
(
y
坐標
),
就必須知
道當前
B
桿上最上端圓片的大小和
B
桿上當前圓片數量
,
即
B
桿的當前
步點狀態
。
綜合以上分析
,
游戲步點狀態記錄是程序設計中的要點
。
鑒于描述步點狀態需要多個數據
,
且數據間相互關聯并構成整體
,
筆
者在設計中采用了自定義數據類型的方法
,
數據類型名稱為
circles
,
所含
內容和定義格式如下
:
Type
circles
counts
As
integer
r()
As
integer
x
As
integer
y()
As
integer
End
Type
circles
類型中
,
數據成員
counts
用于記錄桿上實際圓片數
,
r
用于記錄各圓片的半徑
,
x
記錄各圓片圓心的
x
坐標
,
y
記錄各圓片
圓心的
y
坐標
。
因為每次游戲設置的初始圓片數是不確定的且游戲進程中各桿都可能出現多個圓片
,
所以數據成員
r
和
y
定義為動
態數組
。
數據類型
circles
定義以后
,
先使用該類型定義三個實例
a
、
b
、
c
,
分別代表
A
、
B
、
C
三個桿的步點狀態
。
語句如下
:
Dim
a
As
circles
,
b
As
circles
,
c
As
circles
當初始圓片數量確定后
(
記為
n)
,
可使用下列語句對
A
桿的步點狀態
a
進行初始化
。
投稿日期
:
2009-08-22
作者簡介
:
劉德強
(
1965-
),
江蘇靖江人
,
無錫職業技術學院講師
。
圖
1
運行界面
ISSN
1009-3044
Computer
Knowledge
and
Technology
電腦知識
與技術
Vol.5,No.30,
October
2009,
pp.8460-8462
E-mail:
xsjl@cccc.net.cn
http://www.dnzs.net.cn
Tel:+86-551-5690963
5690964
8460
軟件設計開發
本欄目責任編輯
:
謝媛媛
Computer
Knowledge
and
Technology
電腦知識
與技術
第
5
卷第
30
期
(2009
年
10
月
)
ReDim
a.y(n)
:
ReDim
a.r(n)
:
a.counts=n
a.x
=
-330:
a.y(1)
=
-260
For
i
=
1
To
n
a.r(i)
=
160
-
8
*
i
a.y(i)
=
-270
+
i
*
45
Picture1.Circle
(a.x,
a.y(i)),
a.r(i),
vbBlack,
,
,
0.14
Next
i
語句中
,
通過對實例
a
的各成員進行賦值
,
確定了
A
桿上圓片的數量
、
各圓片的大小和位置
,
并在相應位置畫出了代表各圓片
的橢圓圖形
。
程序設計中
B
桿和
C
桿的步點狀態可參照相同方法進行初始化
。
游戲進程中
,
當圓片從一個桿上移動到另一個桿上
,
兩桿的步點狀態會發生變化
,
新的步點狀態可通過下列語句進行記錄
,
以
圓片從
A
桿移到
B
桿為例
:
a.counts
=a.counts
-
1
b.counts
=
b.counts
+
1
b.r(b.
counts)
=
a.r(a.
counts
+
1)
Picture1.Circle
(b.x,
b.y(b
counts)),
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
桿上向上取出圓片為例
,
為表現圓片向上連續移動的動
畫效果
,
程序代碼為
:
For
k
=
20
To
220
-
a.y(a.counts)
Step
20
Picture1.Circle
(a.x,
a.y(a.counts)
+
k),
a.r(a.counts),
vbBlack,
,
,
0.14
delay
(delay_m)
Picture1.Circle
(a.x,
a.y(a.counts)
+
k),
a.r(a.counts),
&H8000000F,
,
,
0.14
Next
k
程
序
執
行
過
程
中
,
每
次
循
環
計
算
機
將
在
同
一
位
置
先
后
畫
同
樣
大
小
但
顏
色
不
同
的
橢
圓
兩
次
,
先
黑
色
(
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
過程來實現的
。
根據上述分析
,
漢諾塔問題的遞歸算法可
設計為
:
Private
Sub
moves(n
as
integer,pole_a
as
string,pole_b
as
string,pole_c
as
string)
If
n
=
1
Then
move_str1=move_str1
&
pole_a
&
pole_c
Else
Call
moves(n
-
1,
pole_a,
pole_c,
pole_b)
Call
moves(1,
pole_a,
pole_b,
pole_c)
Call
moves(n
-
1,
pole_b,
pole_a,
pole_c)
8461
本欄目責任編輯
:
謝媛媛
軟件設計開發
Computer
Knowledge
and
Technology
電腦知識
與技術
第
5
卷第
30
期
(2009
年
10
月
)
End
If
End
Sub
將三個桿分別標識為字符
“
A
”、“
B
”、“
C
”,
通過組合框控件設置初始圓片數后
,
移動圓片的順序可通過下列語句進行計算
。
n=val(combo1.text)
call
moves(n
,“
A
”,“
B
”,“
C
”
)
計算出的移動順序以字符串形式保存在變量
move_str1
中
。
字符串由標識三個桿的字符
“
A
”、“
B
”、“
C
”
組成
;
字符串中從首字符
起每兩個字符組成的子串代表一個操作步驟
,
如
“
AB
”
代表將圓片從
A
桿移到
B
桿
;
字符串中子串的排列順序就是圓片的移動順
序
,
如
“
ABAC
”
代表先移動
A
桿上一個圓片到
B
桿
,
再移動
A
桿上一個圓片到
C
桿
。
計算出圓片移動順序以后
,
演示功能接下來的設計就是要依次從字符串中取出代表操作步驟的各字符子串
,
并根據子串內容
和順序實現圓片的不斷有序移動
。
取字符子串可使用
VB
庫函數
Mid()
實現
,
而圓片移動方法的設計上文步點狀態記錄和動畫效果
設計部分已有詳細介紹
,
在此不再贅述
。
4
游戲功能設計
和演示不同
,
游戲時圓片的移動順序是隨機的
,
由游戲者的實時操作決定
,
因此設計時首要的是根據用戶操作事件確定代表圓
片移動的字符串
。
考慮到游戲者不同的操作習慣
,
筆者在設計過程中同時采用了命令按鈕的
Click
事件和圖片框的
MouseDown
事
件
,
前者通過單擊命令按鈕控制圓片移動
,
后者則通過在圖片框中按下鼠標左鍵進行控制
。
對于
Click
事件
,
針對移動圓片的六種不
同情況
,
筆者設計了六個命令按鈕
(
參見圖
1
,
位于界面底部
),
六個字符串可通過單擊不同按鈕產生
,
而對于
MouseDown
事件
,
僅用
單個對象的一種事件要實現六種不同的操作
,
需要對事件進行再判斷
,
筆者采用的方法是
:
通過兩次按下鼠標控制一次圓片移動
。
游戲中對鼠標按下次數進行統計
,
并對次數的奇偶性進行判斷
,
如果當前按下鼠標統計出是奇數次
,
則將其視為是一個移動步驟中
的首次按下
,
其作用是選擇要移動的圓片
,
按下時與鼠標位置距離近者
,
其桿上頂端的圓片即為要移動的圓片
;
如果當前按下鼠標
統計出是偶數次
,
則將其視為是一個移動步驟中的第二次按下
,
其作用是選擇圓片移動的目標位置
,
按下時與鼠標位置距離近者
,
其為圓片移動的目標桿
。
以圓片從
A
桿移到
B
桿為例
,
相關判斷語句如下
:
Static
mouse_n
as
integer
mouse_n
=
mouse_n
+
1
If
mouse_n
mod
2
=1
Then
If
X
<
0
And
X
-
(-330)
<
0
-
X
Then
move_str2
=
"A"
ElseIf
X
<
0
And
X
-
(-330)
>
0
-
X
Then
move_str2
=
"B"
End
If
else
If
X
<
0
And
X
-
(-330)
<
0
-
X
Then
move_str2=
move_str2
&
"A"
ElseIf
X
<
0
And
X
-
(-330)
>
0
-
X
Then
move_str2=
move_str2
&
"B"
End
If
End
If
程序運行時
,
當用戶先后在
A
桿和
B
桿的附近按下鼠標
,
計算機將生成字符串
“
AB
”,
并將其保存在字符變量
move_str2
中
。
針
對圓片移動的其余五種情況
,
相對應的字符串的產生可采用相同方法進行設計
。
根據用戶操作事件確定了代表圓片移動的字符串以后
,
游戲功能設計接下來要實現的與演示功能相同
,
是圓片的移動
,
其設計
方法在此不再重復
。
5
結束語
目前市場和網絡上有使用不同工具設計的多個漢諾塔游戲版本
,
所采用的方法各不相同
、
各有特色
。
筆者設計該游戲
,
旨在和
大家探討
VB
編程技術的一種實際應用
,
同時將其作為課程教學課件
,
以期提高課堂教學效果
。
參考文獻
:
[1]
聶黎生
.VB
動畫設計原理及其實現
[J].
電腦學習
,2006(10).
[2]
王偉杰
,
王曉燕
.
使用
Eclipse
開發
J2ME
漢諾塔動畫
[J].
電腦編程技巧與維護
,2008(14).
[3]
王吉岱
,
李慶
,
孫愛芹
,
盧坤媛
.
可視化編程軟件動畫仿真的實現方法研究
[J].
現代制造技術與裝備
,2009(2).
[4]
龍輝
.
基于
VB
的動畫設計
[J].
科技信息
,2009(5).
[5]
李艷
.VB
中動畫效果的實現
[J].
福建電腦
,2008(8).
[6]
周志德
.C++
程序設計
[M].
北京
:
電子工業出版社
,2002.
8462