但是想想看,整個遊戲過程中並不需要重複列印整個介面,比如圍牆,比如未被吃掉的食物。要實現蛇的移動,我們只要列印出新的蛇頭,清除原來的蛇尾就好了。食物只有在被吃掉時才需要重新列印,邊界更是只用列印一次。好了,既然我們看到了可提公升的地方,就開始動手優化吧。
ps:以下內容都是基於《c語言實現貪吃蛇(一)—-陣列實現》,大家可能得去看看。
為了避免全屏重新整理,我們應直接定位到需要列印的地方進行列印操作,而不是像之前一樣通過迴圈列印。
因此我們將需要乙個可以自由移動游標的函式,這樣我們才能做到在需要的地方列印。
tc上有乙個叫gotoxy()的很方便的函式,該函式,顧名思義,就是將游標移動到(x,y)位置。然而現在估計很少有人還在使用tc。那麼我們就著手自己編寫乙個gotoxy()函式。
void gotoxy(unsigned
char x,unsigned
char y)
如果是沒有接觸過windows程式設計的同學看到這段**可能會有些懵逼,不過沒關係。整段**的邏輯其實十分簡單。
coord是windows api定義的結構,其宣告如下:
typedef
struct _coord coord, *pcoord;
正如其名字coordinate(座標)一樣,這是乙個儲存二維座標的結構體。
handle(控制代碼)在windows程式設計中是乙個十分重要的概念。在window程式設計中,對於乙個object(物件)我們只能通過handle來訪問它。覺得不好理解的同學把控制代碼當作指標來看待就好了。
getstdhandle函式獲取乙個指向特定標準裝置的控制代碼,包括標準輸入,標準輸出和標準錯誤。std_output_handle正是代表標準輸出(也就是顯示屏)的巨集。
setconsolecursorposition函式用於設定控制台游標的位置。
如果還不懂的同學還是 baidu 一下吧,畢竟我也是差不多的。。。。。
現在我們先來看看程式的最主要部分:主函式
int main(void)
}//清除螢幕
system("cls");
printf("game over!\n");
return
0;}
我們來看看程式修改後的一些變數和函式宣告(基本上跟之前的差不多的)
#include
#include
#include
#include
#include
//72,80,75,77是方向鍵對應的鍵值
#define up 72
#define down 80
#define left 75
#define right 77
#define snake 1
#define food 2
#define bar 3
//初始化地圖
char
map[17][17] = ;
//初始化蛇頭座標
unsigned
char snake[50] = ;
//初始化食物座標
unsigned
char food = 68;
//蛇長
char len = 1;
//儲存座標數字與x、y的轉換函式
void tran(unsigned
char num,unsigned
char * x,unsigned
char * y);
//初始化遊戲
void init_game(void);
//獲取方向函式(注意當蛇身長度超過一節時不能回頭)
int get_dir(int old_dir);
//移動蛇身函式(遊戲大部分內容在其中)
void move_snake(int dir);
//其中有個生產食物的函式,generate_food(),它利用隨機數生成函式生成食物座標
unsigned
char generate_food(void);
//判斷蛇死活的函式(判斷了蛇是否撞到邊界或者自食)
int isalive(void);
//將游標移動到命令列的 (x,y)位置
void gotoxy(unsigned
char x,unsigned
char y);
int main(void)
}//清除螢幕
system("cls");
printf("game over!\n");
return
0;}
與前一篇部落格對比,這裡的一下變化:
修改了 main() 主函式
用 init_game() 替換 print_game()
修改了 move_snake() 函式
增加了 gotoxy() 游標座標定位函式
main() 函式和 gotoxy() 函式我們已經介紹過了,現在我們看看 init_game() 函式:
//初始化遊戲
void init_game(void);
//初始化遊戲 (列印初始狀態)
void init_game(void)
//列印蛇頭
else
if (i == x&&j == y)
//列印食物
else
if (i == fy&&j == fx)
//空白地方
else
}putchar('\n');
}}
從 init_game() 函式中和在 main() 呼叫可以看出,該函式的作用僅僅是初始化作用(將一成不變的圍牆畫好,列印食物和蛇頭的初始位置)。後面就沒它什麼事了。
再來看看 move_snake() 函式:
//移動蛇身函式(遊戲大部分內容在其中)
void move_snake(int dir);
void move_snake(int dir)
//按位抑或(妙!)
snake[0] = ((x ^ 0) << 4) ^ y; //將x,y換回乙個數
//蛇吃到了食物
if (snake[0] == food)
for (i = 0; i//蛇移動的關鍵,通過將蛇頭原來的座標賦給第二節,原來的第二節賦給第三節,依次下去,完成蛇座標的更新
if (i == 0) //如果只有頭,跳過,因為前面已更新蛇頭座標
continue;
current = snake[i]; //將當前操作的蛇節座標儲存到current裡
snake[i] = last; //完成當前操作蛇節座標的更新
last = current; //last記錄的是上一次操作蛇節的座標,這次操作已經結束,故把current賦給last
}gotoxy(x, y); //將游標移動到指定位置
putchar('*'); //列印新的蛇頭
if (grow) else
}//避免游標一直跟著蛇尾(或食物)
gotoxy(0,17);
sleep(500);
}
從該函式中可以看出,我們利用 gotoxy() 函式,實現了區域性重新整理的功能,從而避免了遊戲的閃爍現象。
本部落格參考自《c語言實現貪吃蛇之區域性重新整理篇 》,在後續的部落格中,我將跟隨著原作者的腳步繼續折騰這個遊戲,感興趣的同學可以看看後續的文章。
C語言實現貪吃蛇
貪吃蛇是我們耳熟能詳的遊戲,遊戲思路很簡單,我們操縱一條蛇在螢幕上游走尋找食物,當吃到食物時蛇就會變長,當蛇頭碰到牆壁或者自己的身體時,此時蛇就會死亡,而遊戲也就結束了。那麼我們設計遊戲的時候,需要注意三點 1 及時重新整理蛇的位置 2 蛇吃到食物時,蛇的身體會變長,同時及時重新整理新的食物 3 蛇...
貪吃蛇 C語言實現
首先 必備知識棧 由於是用c實現,c的基礎就不廢話了 1.鍊錶相關知識的熟練使用 2.動態記憶體的簡單使用與釋放方法 3.隨機數的生成與儲存 4.監聽鍵盤函式的使用 5.window.h中基本的控制台函式 6.時間函式的簡單應用 其次 下面是實現的具體 有詳細的注釋解釋 pragma comment...
C語言實現貪吃蛇
include include include include include define up w define down s define left a define right d define quit q 函式宣告 void welcome 開始介面 void chose 選擇難度 vo...