前段時間姑娘報名參加第二十一屆全國中小學(xué)生電腦制作活動程序設(shè)計的競賽。抽時間指導(dǎo)孩子做了一個Scratch實現(xiàn)的古典益智游戲華容道的小項目。把當時指導(dǎo)姑娘寫的設(shè)計思路的文檔分享一下,由于Scratch沒有腳本源代碼的形式,大量積木塊的截圖就不在此粘貼了。
1. 創(chuàng)作背景
華容道是古老的中國民間益智游戲,也是中國古代的一個地名,相傳當年曹操曾經(jīng)敗走此地,故游戲因此得名。華容道游戲有352種開局,真可謂變化多端、百玩不厭。它與魔方、獨立鉆石棋一起被國外智力專家并稱為“智力游戲界的三個不可思議”。它與七巧板、九連環(huán)等中國傳統(tǒng)益智玩具同被譽為“中國的難題”。家里很早買過一套木質(zhì)的華容道游戲拼板,它的“簡單”和“復(fù)雜”深深吸引了我。
在學(xué)習(xí)了Scratch的基礎(chǔ)之后,我深刻感受到Scratch作為一種圖形化的入門編程語言,其所具備的簡單、直觀而又不失強大的特點。我想如果能用Scratch從零開始編寫一個完整的小游戲,對自己來說一定是一種非常棒的挑戰(zhàn)和提升,能夠幫助自己更好地掌握所學(xué)知識,更快地培養(yǎng)編程的概念和思想。于是我選擇了以華容道這款益智游戲為課題,決心把木質(zhì)拼板“搬上”電腦屏幕。在學(xué)編程之余,也希望通過分享這款游戲給朋友們帶來一點開心快樂。
2. 功能分析
2.1. 游戲規(guī)則
華容道是一種滑塊類游戲,傳統(tǒng)上一般是由放在長方形盤中的不同大小的10塊滑塊拼成。

其中最大的一塊2*2的正方形滑塊代表曹操。五塊1*2的長方形滑塊分別代表關(guān)羽、趙云、馬超、黃忠和張飛,這五塊在不同的關(guān)卡布局中可以是豎放也可以是橫放。另有四塊1*1的正方形滑塊代表四個小兵。
華容道的關(guān)卡布局非常多,據(jù)說有352種之多,例如以下是比較常見的幾種布局:

游戲的目標是在只滑動滑塊而不從棋盤中拿起的情況下,盡力用最少的移動步數(shù)和時間將代表曹操的那一塊移到底部出口。
最早系統(tǒng)研究游戲華容道的是蘇州大學(xué)數(shù)學(xué)教授許莼舫先生。1952年,他在《數(shù)學(xué)漫談》中對這個游戲作了詳細的分析,總結(jié)出8條規(guī)則。8條規(guī)則又可以歸納為以下4個要點:
1、四個小兵必須兩兩在一起,不要分開;
2、曹操,關(guān)羽,大將移動時前面應(yīng)有兩個小兵開路;
3、曹操移動時后面還應(yīng)有兩個小兵追趕;
4、以上三種狀況,其中各塊都可局部(不妨礙其他地方)任意移動。
2.2. Scratch特性優(yōu)勢
在許多圖形化編程語言工具中,由MIT媒體實驗室終身幼兒園團隊研發(fā)的Scratch,算得上是中國家長們最廣為人知的一種編程語言。

使用Scratch,你可以編寫屬于你的互動媒體,像是故事、游戲、動畫,然后你可以將你的創(chuàng)意分享給全世界。Scratch幫助年輕人更具創(chuàng)造力、邏輯力、協(xié)作力,這些都是生活在 21 世紀不可或缺的基本能力。
相對于C++、VB、JAVA、Python等語言來說,Scratch最突出的特色,便是提供用戶一套由積木系統(tǒng)組成的編程指令,使用者不需要會敲代碼,不需要會使用鍵盤,不需要懂英語,就可以學(xué)習(xí)編程。所以它更適合用于初學(xué)者教學(xué),我覺得Scratch有三大優(yōu)點,這也正是我選擇使用Scratch實現(xiàn)《華容道》游戲的原因。
1、入門簡單
圖形化可視編程,界面生動有趣。無關(guān)原有編程基礎(chǔ),適合中小學(xué)學(xué)生初次學(xué)習(xí)編程語言時使用。
2、內(nèi)容豐富
內(nèi)容豐富,針對有興趣、喜愛繪畫的學(xué)生,提供角色繪制設(shè)計功能,為喜歡動畫的學(xué)生提供情景設(shè)計功能,為喜歡游戲的學(xué)生提供簡單游戲設(shè)計功能,甚至還能提供喜歡音樂的學(xué)生音頻處理的功能。
3、成果直觀
通過使用Scratch,讓學(xué)生在動畫、游戲設(shè)計過程中逐漸形成邏輯分析、獨立思考創(chuàng)新的思維方式,學(xué)會提出問題,解決問題。相比其他編程軟件,其更加直觀,學(xué)生通能比較容易地看到自己的勞動成果,更有成就感。
2.3. 角色屬性
要在電腦上實現(xiàn)華容道游戲,每個滑塊可以稱之為一個角色,每個角色都有其特定的屬性。
1、大小:
我將華容道棋盤整體看作一個4*5的長方形網(wǎng)格區(qū)域,此區(qū)域中每個小格大小為50*50像素,如下圖:

這樣每個滑塊位于棋盤中時對應(yīng)的大小可以有兩種概念,一是像素寬*高,二是占網(wǎng)格列數(shù)*行數(shù)。
曹操:100*100像素;2列*2行
關(guān)羽、趙云、馬超、黃忠、張飛:50*100像素;1列*2行(豎放)或100*50像素;2列*1行(橫放)
小兵:50*50像素;1列*1行
2、位置:
每個角色也有兩個層面的位置概念。一個是角色中心相對于整個舞臺的x,y坐標位置。另一個是相對于棋盤網(wǎng)格來說的位于第幾個格子的位置,這個位置我以角色所占區(qū)域的最左上角所在格子的行和列來表示。例如下圖中棋盤位于整個舞臺的中心,每個網(wǎng)格是50*50像素時,曹操的位置是:x=0,y=75;1行2列。

3、橫豎:
關(guān)羽、趙云、馬超、黃忠、張飛這五個角色,有橫和豎兩種布局方式。
曹操和小兵因為都是正方形,所以只有一種布局方式。
2.4. 角色行為
每個角色都有以下行為:
1、移動:
每個角色都可以沿棋盤網(wǎng)格向上、下、左、右四個有空余空間的新位置移動,每次只能移動一個網(wǎng)格的距離。如果移動方向上沒有空余空間,則此移動無效。例如下圖中關(guān)羽可以向左或右移動一個網(wǎng)格,但不能向上、下方向移動。

2、顯示/隱藏:
在選定關(guān)卡之前,棋盤和角色都處于隱藏狀態(tài),當選關(guān)后,開始本關(guān)游戲時角色才顯示出來。
2.5. 功能需求
總的來說,華容道游戲需要實現(xiàn)的大體功能還是比較簡單。
1、要能方便的定義不同關(guān)卡的布局,實現(xiàn)多個關(guān)卡的游戲功能。
2、要按照傳統(tǒng)華容道游戲的游戲規(guī)則,實現(xiàn)鼠標拖動各角色移動的功能,角色不能移動到棋盤網(wǎng)格之外,角色僅能向有空余空間的網(wǎng)格處移動,每次移動一個網(wǎng)格距離,如遇無效移動的操作,角色能自動返回到原位置。
3、以曹操正確移動到棋盤下方出口位置為本關(guān)卡結(jié)束。
4、實現(xiàn)移動步數(shù)的統(tǒng)計和闖關(guān)積分功能。步數(shù)統(tǒng)計每關(guān)結(jié)束后歸零,積分在程序退出前需要對成功闖過的每個關(guān)卡進行累計積分。
5、為提升游戲體驗,給游戲添加背景音樂功能,且可以由玩家自主控制打開或關(guān)閉。
3. 編程思路和算法
3.1. 鼠標操作和移動
通過鼠標移動角色,按照以下流程算法進行程序設(shè)計:

需要注意的要點:
1、鼠標在角色上按下時將角色置于最前,以確保移動過程中不被其它角色遮擋。
2、要計算鼠標點中位置與角色中心位置之間的位移,確保在角色跟隨鼠標指針移動過程中保持位置的同步。
3.2. 移動方向計算
對鼠標釋放時鼠標指針所在位置與角色原位置之間的x和y坐標進行比較,x軸上位移大于y軸上的位移時則限定為左右移動,y軸上位移大于x軸上的位移時則限定為上下移動,再進一步比較上下或左右方向上坐標值的差,即可最終限定鼠標的拖動行為最終應(yīng)向哪一個方向進行移動。

3.3. 移動有效測試

移動有效性檢測過程較為復(fù)雜,需要考慮以下重點:
1、角色大小不一,要確定所要移移動方向上1或多行/列是否有空余位置。
2、需要查詢布局列表中的數(shù)值(1代表已占用,0代表空閑)來獲得整個棋盤位置占用數(shù)據(jù)。
3、左右移動不能超過1至4列范圍,上下移時不能超過1至5行范圍。即不能超出棋盤網(wǎng)格的范圍。
3.4. 位置計算
在確定移動方向和移動有效性后,得到的是向某一方向移動一個網(wǎng)格(即移到特定行/列)的信息。而角色實際的移動需要以確定的x,y坐標來指定,因此需要根據(jù)目標行或目標列的值、行列單元格的邊長、角色高、角色寬等數(shù)值來計算目標坐標值。
X坐標=(((目標行-1)*4+目標列-1)mod 4*單元格邊長+寬*單元格邊長/2)-4*單元格邊長/2
Y坐標=(5*單元格邊長-floor(((目標行-1)*4+目標列-1)/4)*單元格邊長+高*單元格邊長/2)-5*單元格邊長/2
棋盤空間的占用,使用了四個列表來表示棋盤的4個列,每個列表含有5個元素,表示棋盤的5個行。每個列表元素值用0代表空閑,用1代表占用。
例如第一關(guān)“兵臨曹營”的初始狀態(tài)時,實際角色擺放和列表數(shù)據(jù)對應(yīng)關(guān)系如下:

| 列表1 | 列表2 | 列表3 | 列表4 |
|---|---|---|---|
| 1 | 1 | 1 | 1 |
| 0 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 1 |
| 1 | 1 | 1 | 0 |
3.5. 角色移動
在移動角色時除按照計算出來的位置坐標進行移動,還需要更新布局列表,將角色的移動反映為列表中0、1數(shù)值的占用標志。
另外對于曹操角色,要比其它角色多一個檢測是否到達出口闖關(guān)成功的環(huán)節(jié)。
曹操角色移動流程如下:

其它角色移動流程如下:

3.6. 關(guān)卡實現(xiàn)和角色擺放
關(guān)卡的布局是通過建立一個滑塊布局的列表來進行定義的。

按以上規(guī)則,游戲中的九個布局對應(yīng)列表值如下:

當玩家選擇好相應(yīng)關(guān)卡后,各角色即按該列表中定義的位置和擺放方式完成角色在棋盤上的顯示。
3.7. 背景變換
游戲中總共準備了兩個背景,一個是游戲開始時選擇關(guān)卡的背景,一個是進入具體關(guān)卡后棋盤后面的背景。
為展現(xiàn)文化氛圍,圖片的選擇上偏重于具有中國水墨畫風(fēng)格的圖片。
3.8. 聲音控制
為選關(guān)頁和游戲頁面也準備了不同的兩段背景音樂,通過在小喇叭按鈕角色中進行定義。當接收到“顯示菜單”和“關(guān)卡已選”兩個廣播消息時分別進行背景音樂的切換。通過一個“是否靜音”的變量來記錄當前的音樂播放狀態(tài)。
通過點擊該小喇叭按鈕可以打開和關(guān)閉音樂的音量。
3.9. 消息同步
各個角色之間,通過事件消息來傳遞運行進程中的事件,協(xié)調(diào)相關(guān)聯(lián)操作之間的運行時機。使得這些操作可以異步進行,提升程序的靈活性和運行效率。
4. 資源說明
4.1. 圖片素材
設(shè)計中使用到的背景圖片按“中國風(fēng)”關(guān)鍵詞從百度搜索得到,角色頭像的圖片按“華容道”關(guān)鍵詞從百度搜索中得到。程序中使用到的圖片如下:






4.2. 聲音素材
程序中用到的聲音素材按關(guān)鍵字背景音樂在百度搜索中獲得,具體曲目名稱不詳。
5. 開發(fā)環(huán)境
5.1. 系統(tǒng)環(huán)境
我開發(fā)此程序所用的計算機環(huán)境如下:
CPU:Intel Core i7-3820QM
內(nèi)存:16G
操作系統(tǒng):Ubuntu 18.04.4 LTS
瀏覽器:Google Chrome 81.0.4044.129
5.2. 開發(fā)工具
編程環(huán)境:Scratch 3.0 linux 離線編輯器
圖像處理:GIMP 2.10.18
流程圖軟件:Dia 0.97+git
6. 創(chuàng)作過程
6.1. 資源處理
將網(wǎng)上下載得到的圖片的音頻素材進行處理。
背景圖片按照480*360像素大小進行處理。
棋盤處理為233*350像素大小,其中滑塊活動區(qū)域大小為200*250像素。
角色頭像圖片按照以下尺寸進行處理:
曹操:100*100像素
關(guān)羽、趙云、馬超、黃忠、張飛:50*100像素(豎放),100*50像素(橫放)各制作一套
小兵:50*50像素
聲音小喇叭按鈕制作有聲音和無聲音各一個。
按照9個布局關(guān)卡分別制作一個選關(guān)按鈕。
制作返回按鈕一個。
聲音文件轉(zhuǎn)換為mp3文件
6.2. 界面制作
游戲分為選關(guān)和進行游戲兩個場景。選關(guān)頁面中顯示游戲的名稱,并列出9個關(guān)卡按鈕和一個結(jié)束游戲的按鈕供玩家選擇。
游戲進行頁面中居中顯示棋盤,棋盤上方顯示關(guān)卡名稱變量,角色按選定的布局在棋盤上排列,棋盤左側(cè)上方顯示已走步數(shù)和闖關(guān)得分兩個變量,棋盤右側(cè)上方顯示返回按鈕和控制聲音的小喇叭按鈕。
6.3. 角色制作
曹操和小兵角色圖片為正方形,只包含一個形象。其它五位大將均包含兩個形象,一個是橫擺,一個是豎擺。
6.4. 變量規(guī)劃
關(guān)卡名稱、已走步數(shù)、闖關(guān)積分、當前關(guān)卡、單位格大小、棋盤的起始行、起始列、左上角坐標等變量為全局變量,可由所有角色訪問。
布局和棋盤位置占用情況采用列表變量實現(xiàn),也為全局變量,所有角色可以訪問。
各個角色自身相關(guān)的各種屬性和運行狀態(tài)所需的變量均為局部變量,僅由此角色自已訪問。
6.5. 腳本編寫
腳本的編寫基本參照前期分析規(guī)劃的功能和設(shè)計好的思路和算法進行編寫。腳本編寫大致分為三類:
1、舞臺的腳本
僅在舞臺腳本中包含一個當綠旗點擊的事件積木。腳本程序主要完成全局變量和列表的初始化、選關(guān)的執(zhí)行。
2、按鈕角色的腳本
按鈕角色包括關(guān)卡按鈕、返回按鈕、聲音按鍵,這些角色的功能相對簡單,主要有顯示、隱藏、點擊等操作。
3、滑塊角色的腳本
角色的腳本相對復(fù)雜,不過除曹操有獨特的判斷是否到達出口的操作外,其它部分每個角色基本都大體相同。主要包括顯示、隱藏、鼠標拖動等行為。
由于腳本數(shù)量較大,為更清晰的完成大量積木的編排,特將重復(fù)使用、特定功能、專用計算/測試等操作的積木腳本整合成自定義積木來使用。例如填寫列表、顯示/隱藏變量、選關(guān)、移動測試、計算當前行列和移動方向等功能均組織成了自定義積木的形式。
6.6. 排錯優(yōu)化
在腳本首次編寫完畢,測試運行中發(fā)現(xiàn)角色移動錯位的情況。通過點擊左側(cè)代碼積木中變量的名稱一步一步跟蹤變量值的動態(tài)變化情況,發(fā)現(xiàn)問題的原因是角色滑塊位置計算以左上角為基準,所以向右、向下移動時和向左、向上移動時由該基準位置判斷不同形狀的角色是否移到棋盤外的行列數(shù)限制是不一樣的。找到原因后根據(jù)角色寬和高的尺寸以及移動的方向計算得到行和列的測試補償值。在移動有效性測試時結(jié)合使用這個補償值來判斷是否移動出界,從而解決了問題。
7. 成果結(jié)論
完成本次華容道游戲作品用了大約一周時間,程序基本達到了設(shè)計的預(yù)期,游戲運行功能正常,操作響應(yīng)順暢,方便加入多個關(guān)卡的能力是本游戲的亮點,可以再搜集不同布局的資料錄入到布局列表中即可加入關(guān)卡。本游戲整體試玩體驗良好,寓教于樂,有一定的實用價值。
編寫這個游戲的過程中也遇到了不少困難,我覺得最有收獲的有以下幾處:
1、深入理解變量的作用域,掌握全局變量和局部變量的概念。
2、弄清舞臺坐標系的概念,精確控制角色的顯示和相互關(guān)系。
3、有效利用列表處理大量信息,為游戲增加擴展多個開局關(guān)卡的能力。
4、靈活運用消息廣播,實現(xiàn)角色之間有效通信和運行時相互協(xié)調(diào)。