李雨哲 孫煉
摘 要:貪吃蛇是一款深受人們喜愛的游戲。在貪吃蛇游戲設(shè)計過程中,涉及蛇與食物的顯示與更新、數(shù)據(jù)的收集與更新等問題。本文通過利用C語言對貪吃蛇游戲進(jìn)行設(shè)計和編寫,并對設(shè)計好的游戲進(jìn)行測試。結(jié)果表明,程序通過編譯后邏輯上沒有明顯漏洞,且運(yùn)行結(jié)果與預(yù)期無較大出入。
關(guān)鍵詞:C語言;貪吃蛇;函數(shù)
中圖分類號:TP317文獻(xiàn)標(biāo)識碼:A文章編號:1003-5168(2020)07-0031-03
Abstract: Snake is a popular game. In the design process of Snake game, it involves the display and update of snake and food, data collection and update. This paper used the C programming language to design and write Snake game, and tested the designed game. The results show that there are no obvious flaws in the program's compiling and logic, and the running results are not different from the expected ones.
Keywords: the C programming language;snake game;function
雖然現(xiàn)在市面上已經(jīng)有各種各樣的游戲,例如:王者榮耀、和平精英、狂野飆車等,并且這些游戲的可玩度較高,但貪吃蛇這款游戲的市場依然存在。貪吃蛇的游戲出現(xiàn)之后不斷發(fā)展,從最開始用匯編語言開發(fā)在游戲機(jī)上玩,到后來用Java開發(fā)在手機(jī)上玩;從最開始的一人游戲,到現(xiàn)在的多人游戲。貪吃蛇吸引人的地方在于,隨著游戲進(jìn)程加快,節(jié)奏也不斷加快,給人們帶來更強(qiáng)的刺激感。該游戲的優(yōu)勢是簡單易行。本文通過利用C語言對貪吃蛇游戲進(jìn)行設(shè)計和編寫,以更加深入地理解C語言的應(yīng)用。
1 編程語言簡介
1.1 C語言簡介
C語言是一門面向過程的、抽象化的通用程序設(shè)計語言,廣泛應(yīng)用于底層開發(fā)。C語言程序是由函數(shù)構(gòu)成的,每一個函數(shù)完成相對獨立的功能。一個C程序至少且包含一個main函數(shù),也可以包含一個main函數(shù)和若干其他函數(shù)[1]。C語言具有豐富的運(yùn)算符和數(shù)據(jù)類型,便于實現(xiàn)各類復(fù)雜的數(shù)據(jù)結(jié)構(gòu),并引入了指針概念,可使程序效率更高。面向?qū)ο蟮恼Z言具有封裝、繼承、多態(tài)三大特性,決定了面向?qū)ο笳Z言可修改性很強(qiáng)[2]。C語言則與面向?qū)ο蟮恼Z言不同,在進(jìn)行C語言程序設(shè)計時,如果開發(fā)者沒有一開始就確定好合適的數(shù)據(jù)類型、結(jié)構(gòu)體、變量等,那么在調(diào)試時,查到程序錯誤或者有漏洞,修改起來就會相當(dāng)困難。
1.2 設(shè)計環(huán)境
本程序利用C-Free 5.0來進(jìn)行編譯。C-Free是一個支持多編譯器的專業(yè)C/C++集成開發(fā)環(huán)境(IDE)。在C-Free中,用戶可以自由編輯、編譯、運(yùn)行和調(diào)試程序。C-Free包含了C/C++源解析器。該開發(fā)工具的優(yōu)勢是所占資源少,具有強(qiáng)大的特性[3-5]。
2 程序設(shè)計
2.1 程序簡介
貪吃蛇游戲是一款經(jīng)典游戲,適合所有年齡段。蛇在封閉的墻壁內(nèi),食物隨機(jī)出現(xiàn)在墻壁內(nèi)。玩家可以通過按鍵盤上的W、A、S、D上下左右移動來確定蛇的運(yùn)動,如果蛇的頭碰到食物,食物被吃掉,蛇的身體就會長出一段,同時得分,然后食物隨機(jī)在地圖內(nèi)出現(xiàn),重復(fù)以上環(huán)節(jié)。如果蛇在運(yùn)動中碰到墻壁或碰到自己的身體,則游戲結(jié)束。
2.2 設(shè)計思路
在設(shè)計時,需要用一個圖標(biāo)來代表蛇的一節(jié)身體,筆者用“@”,因為這個圖標(biāo)比較接近圓形,移動時不會顯得突兀。每當(dāng)蛇吃掉一個食物,身體就會增加一節(jié)。當(dāng)蛇移動時,必須從蛇頭開始,因此蛇不能向相反的方向移動,這意味著蛇尾不能變成蛇頭,并且蛇體會隨著蛇頭的變化而變化。如果玩家不按任何鍵,蛇自行在當(dāng)前方向上前移。當(dāng)玩家按下有效的方向鍵時,蛇頭會朝著方向按鍵所指的方向移動,一步移動一節(jié)身體,所以按下有效方向鍵后,先確定蛇頭的位置,而后蛇的身體隨蛇頭移動。而食物的投放,也需要一個小圖標(biāo)來表示,這里是用“$”。用兩個rand函數(shù)來產(chǎn)生兩個隨機(jī)數(shù),用于確定食物所在地圖的位置。
整個貪吃蛇游戲的過程包括以下5個環(huán)節(jié)。
環(huán)節(jié)1:初始化游戲界面,出現(xiàn)蛇、食物和地圖。
環(huán)節(jié)2:蛇開始不停地前進(jìn)。
環(huán)節(jié)3:判斷蛇是否撞到自己或墻壁。
環(huán)節(jié)4 A:蛇沒有撞到自己或墻壁,蛇繼續(xù)前進(jìn);B:蛇撞到自己或墻壁,游戲結(jié)束(從環(huán)節(jié)4開始游戲有兩種情況A和B)。
環(huán)節(jié)5:判斷蛇是否吃到食物,如果蛇吃到食物,蛇身增長一節(jié),原來的食物消失,隨機(jī)在地圖中出現(xiàn)食物;
程序重復(fù)以上環(huán)節(jié),直至遇見情況B。
2.3 設(shè)計流程圖
游戲的設(shè)計流程如圖1所示。
程序初始化界面,繪制地圖、蛇、投放食物,當(dāng)玩家有輸入時,程序會判斷是否是有效輸入,如果是無效輸入,蛇正常運(yùn)行;如果是有效輸入,蛇就會朝著按鍵方向正常移動。程序會不斷判斷蛇是否吃到食物,如果吃到食物,則更新得分并進(jìn)入下一個判定;如果沒吃到食物也繼續(xù)判斷。如果蛇碰壁或碰到自己,則蛇死亡,游戲結(jié)束;如果沒有,則繼續(xù)循環(huán),直到蛇碰到墻壁或自己。
3 算法分析
主函數(shù)main()首先調(diào)用函數(shù)initialize()來實現(xiàn)程序的初始化,然后調(diào)用函數(shù)drawMap()來畫游戲地圖,調(diào)用函數(shù)putFood()在地圖內(nèi)隨機(jī)投放食物,再通過while循環(huán)來調(diào)用drawSnake()、intoKey()、move()等函數(shù)分別實現(xiàn)畫蛇、接收玩家的按鍵輸入、蛇的移動等功能,調(diào)用函數(shù)point()來顯示和實時更新玩家所得分?jǐn)?shù),最后如果蛇撞到墻壁或自身,則通過調(diào)用函數(shù)gameOver()結(jié)束游戲。接下來對各函數(shù)進(jìn)行詳細(xì)分析。
3.1 主函數(shù)main()
主函數(shù)是程序的主要流程,用來調(diào)用各個函數(shù)。各函數(shù)最終都在主函數(shù)中被直接或間接的調(diào)用執(zhí)行。
3.2 初始化函數(shù)initialize()
用srand()函數(shù)設(shè)置隨機(jī)數(shù)種子為現(xiàn)在的時間,清除并隱藏光標(biāo),初始化蛇的坐標(biāo)并給蛇頭坐標(biāo)賦值,讓蛇的最初長度為4,因為蛇的長度只有在大于4時才會撞到自身,所以蛇的長度初始化為4。最后要初始化地圖,為繪制地圖做鋪墊。
3.3 繪制地圖函數(shù)drawMap()
地圖實際上是一個封閉的矩形墻壁,其是用一個嵌套的雙重for循環(huán)分別在屏幕的[X]軸和[Y]軸連續(xù)打印出圖標(biāo),代表地圖的墻壁,形成一個長為70個字符、寬為30個字符的密閉圍墻。
3.4 投放食物函數(shù)putFood()
在while循環(huán)中調(diào)用兩次rand函數(shù)生成兩個隨機(jī)數(shù),直到產(chǎn)生的隨機(jī)數(shù)滿足新食物生成點的條件,移動光標(biāo)到這個點并畫出食物。
3.5 移動光標(biāo)函數(shù)goToXy()
在本程序中,該函數(shù)是比較重要的一個部分,雖然代碼量很少,但是用處很大。在添加了windows.h頭文件后,就可以使用COORD這個結(jié)構(gòu),它能定位到屏幕上的坐標(biāo)。此后就能方便蛇的移動、投放食物等函數(shù)的編寫。
本函數(shù)代碼如下:
void goToXy(int i,int j) //移動光標(biāo)
{
COORD position={j,i};
SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),position);
}
3.6 蛇的移動函數(shù)move()
蛇的移動是程序中的主要部分,筆者用move函數(shù)用來描述蛇的移動。通過調(diào)用自定義的移動光標(biāo)函數(shù)來擦除尾巴,擦除尾巴可以直接調(diào)用goToXy()函數(shù),從尾巴開始,每一個點的位置等于它前面一個點的位置,用direction表示蛇移動的方向。如果吃掉了食物,蛇的長度增加1節(jié)。
move函數(shù)定義如下:
void move()
{
int i;
goToXy(Snake[Slength-1][0],Snake[Slength-1][1]);//擦除尾巴
printf(" ");
for(i=Slength-1;i>0;i--) //從尾巴開始,每一個點的位置等于它前面一個點的位置
{
Snake[i][0]=Snake[i-1][0];
Snake[i][1]=Snake[i-1][1];
}
switch(direction)
{
case UP:Snake[0][0]--;break;
case DOWN:Snake[0][0]++;break;
case LEFT:Snake[0][1]--;break;
case RIGHT:Snake[0][1]++;break;
}
if(pdEatFood)
{
Slength++;
pdEatFood=false;
}
}
3.7 游戲結(jié)束函數(shù)gameOver()
判斷游戲是否結(jié)束,如果結(jié)束返回true,否則返回false。需要注意的是,在ISO/IEC 9899:1999標(biāo)準(zhǔn)中有bool類型,在添加stdbool.h頭文件后就可以使用。
3.8 分?jǐn)?shù)函數(shù)point()
該函數(shù)是用于實時更新并顯示玩家得分。
3.9 檢查函數(shù)check()
判定該點是否能投放食物,如果該點能投放則返回1,不能返回0,返回值會被putFood函數(shù)調(diào)用。
4 程序測試
程序測試的目的是檢測程序有無編譯上的漏洞和邏輯上的漏洞。
在編寫程序期間,設(shè)置斷點進(jìn)行調(diào)試可以很好地幫助程序員進(jìn)行調(diào)試。筆者在測試運(yùn)行時發(fā)現(xiàn),蛇已經(jīng)在行走,但蛇之前行走的痕跡卻依然存在,在move函數(shù)處設(shè)置斷點,程序執(zhí)行到move函數(shù)會暫停,在設(shè)置斷點后運(yùn)行發(fā)現(xiàn)move函數(shù)有漏洞。找到漏洞后就需要程序員思考如何清除漏洞。這里添加goToXy(s[sLength-1][0],s[sLength-1][1]); printf(" ");兩個語句在move函數(shù)體的開頭,蛇的尾部添加空格,把蛇的尾巴擦除,以達(dá)到擦除痕跡的效果。
程序編寫完成,進(jìn)行最終測試。在鍵盤輸入時,需要把輸入法調(diào)成英文。給程序W、A、S、D以外的按鍵輸入,會發(fā)現(xiàn)蛇依舊按照程序中設(shè)定的線路走;而按照W、A、S、D鍵輸入時,蛇按照鍵入方向改變了原本的線路,說明程序輸入和蛇的移動沒有問題。對于程序界面,需要設(shè)計者自行觀察,看運(yùn)行界面與預(yù)期的界面有無較大誤差,若誤差較大,可以用設(shè)置斷點的方法來判斷在哪個函數(shù)出現(xiàn)了漏洞。如果發(fā)現(xiàn)蛇移動的速度過快或過慢,或者想要改變速度,可以在程序中修改之前已經(jīng)定義好的靜態(tài)變量WAIT_TIME。經(jīng)過最終測試,本程序通過編譯后邏輯上沒有明顯漏洞,且運(yùn)行結(jié)果與預(yù)期無較大出入。
5 結(jié)語
本文基于C語言,在C-Free5.0下完成了對貪吃蛇游戲的程序設(shè)計,闡述了設(shè)計工具、設(shè)計思路,并對設(shè)計的程序進(jìn)行測試。結(jié)果表明,程序通過編譯后邏輯上沒有明顯漏洞,且運(yùn)行結(jié)果與預(yù)期無較大出入。
參考文獻(xiàn):
[1]蘇小紅.C語言大學(xué)實用教程學(xué)習(xí)指導(dǎo)[M].4版.北京:電子工業(yè)出版社,2017.
[2]王一萍,梁偉,李長榮.C語言從入門到項目實戰(zhàn)[M].北京:中國水利水電出版社,2019.
[3]孫霄霄.C語言程序設(shè)計與應(yīng)用開發(fā)[M].3版.北京:清華大學(xué)出版社,2018.
[4]譚浩強(qiáng).C程序設(shè)計[M].5版.北京:清華大學(xué)出版社,2017.
[5]嚴(yán)蔚敏.數(shù)據(jù)結(jié)構(gòu)(C語言版)[M].北京:清華大學(xué)出版社,2018.