一、效果:
二、實現步驟:(我寫**是就是按著下面的步驟一步步實現的,順帶在紙上畫一畫思路)
三、功能:
1.按上下左右方向鍵運動
2.按+或-加速或減速
3.撞牆或咬到蛇身時遊戲失敗
4.記錄吃食物的數量,即得分
四、難點:如何實現蛇身的移動
在while迴圈裡設定個定時器(sleep函式),這樣每隔0.5秒程式執行一次,實現蛇身的移動。
一般思路:蛇身移動會遇到兩種情況:
1.蛇頭的下乙個節點是食物 :吃掉食物,不釋放尾節點記憶體,重新生成食物
2.蛇頭的下乙個節點不是食物:在蛇頭malloc記憶體生成乙個新節點,將蛇尾節點的記憶體free掉
我的思路:將食物節點在棧分配記憶體,重新生成食物只是修改食物節點的x/y值,而蛇身節點是動態分配記憶體的。
那麼實現思路是:
每次迴圈時,把蛇頭第乙個節點的x/y座標相應+1,並用頭插法在蛇頭第乙個節點後再分配記憶體插入乙個節點。
將蛇頭第乙個節點的x/y座標與食物節點比較
1.如果判斷下乙個節點是食物,不釋放尾節點記憶體,重新生成食物。
2.如果判斷下乙個節點不是食物,釋放蛇最後乙個節點。
插入新節點**:
五、**如下(編譯環境:vs2017):
#define _crt_secure_no_warnings
#include #include #include #include //蛇的狀態,u:上 ;d:下;l:左 r:右
#define u 1
#define d 2
#define l 3
#define r 4
#define empty 0
#define bit_self 1 //咬到蛇身
#define touch_wall 2 //碰到牆
#define true 1
#define false 0
typedef struct snake //蛇身的乙個節點
snake;
//head用於指向蛇的第乙個節點,標識整條蛇,但不屬於蛇的節點
snake head, *temp_ptr, food_node;
//direction 鍵入方向
//game_over_reason 記錄遊戲失敗原因
//speed 移動速度
int direction = r, game_over_reason = empty, speed = 100;
void locateandprint(int x, int y); //在游標位置輸出方塊
void locateandclear(int x, int y); //在游標位置清除方塊
void creatmap(); //建立地圖
void createfood(); //建立食物
void intsnake(int snake_len, int start_x, int start_y); //初始化蛇身
void endgame(); //結束遊戲
void getentereddirection(); //獲取鍵入的方向
void snakemove(); //蛇移動
void startgame(); //遊戲迴圈
/*在游標位置輸出方塊*/
void locateandprint(int x, int y)
/*在游標位置清除方塊*/
void locateandclear(int x, int y)
/*建立地圖*/
void creatmap()
for (i = 1; i < 26; i++)//列印左右邊框 }
/*建立食物*/
void createfood()
while (rand_x % 2 != 0);//x需要是2的偶數,黑框中x和y的方塊有侷限性
//判斷生成的食物是否跟蛇身重疊
temp_ptr = head.next;
while (temp_ptr != null)
temp_ptr = temp_ptr->next;
} //food的座標跟蛇身重疊,重新生成food_node
if (false == create_food_success_flag)
//建立成功,在黑框中列印
create_food_success_flag = true;
food_node.x = rand_x;
food_node.y = rand_y;
locateandprint(rand_x, rand_y);
break; }}
/*初始化蛇身*/
void intsnake(int snake_len, int start_x, int start_y)
}/*遊戲結束*/
void endgame()
//清屏並輸出遊戲失敗原因
system("cls");
if (bit_self == game_over_reason)
else if (touch_wall == game_over_reason)
getchar();
}/*獲取鍵入的方向*/
void getentereddirection()
else if (getasynckeystate(vk_oem_minus))
else if (getasynckeystate(vk_up) && direction != d)
else if (getasynckeystate(vk_down) && direction != u)
else if (getasynckeystate(vk_left) && direction != r)
else if (getasynckeystate(vk_right) && direction != l) }
/*蛇移動*/
void snakemove()
else if (direction == l)
else if (direction == u)
else if (direction == d)
//故可合併
snake * temp = (snake *)malloc(sizeof(snake));
temp->x = temp_x;
temp->y = temp_y;
temp->next = head.next->next;
head.next->next = temp;
//判斷是否撞牆
if (head.next->x >= 58 || head.next->x <= 0 || head.next->y <= 0 || head.next->y >= 26)
//判斷下乙個節點是否食物
if (
food_node.x == head.next->x &&
food_node.y == head.next->y
) else
temp_ptr = temp_ptr->next;
} //清除蛇尾的節點
locateandclear(temp_ptr->next->x, temp_ptr->next->y);
free(temp_ptr->next);//釋放蛇尾節點記憶體
temp_ptr->next = null; }}
/*遊戲迴圈*/
void startgame()}
int main()
六、總結:
寫**不是一步到位的。
我寫貪吃蛇經歷了幾個步驟:
1.第一次是每次蛇身移動就改變所有蛇身節點的座標,並清屏,重新輸出蛇身所有節點。這樣的問題就是介面一直閃爍。
2.第二次是每次蛇身移動分下一節點是否食物寫兩大段**。針對兩種情況。
3.發現第二次的兩種情況的**可以在第乙個頭結點後插入新節點進行合併,才有現在的版本。
4....可能以後會有其他改進
C語言貪吃蛇實現 鍊錶學習
以下 片段就是整個源 主要是github上大佬寫的,附上位址 我又在這基礎上優化了點,釋放漏釋放的記憶體,禁止蛇反向運動 include include include include include include define src width 70 define src height 20 ...
c語言寫了乙個貪吃蛇
很簡單的 可能存在一些bug 大牛不要嘲笑 include stdafx.h include include head.h include include int x 1,y 1,m 0 m為蛇的長度 n為食物個數 int nx 1,ny 1,n 0 int chengji 0 void 遊戲開始 ...
C語言遊戲之貪吃蛇 鍊錶實現
早自習時突然想到怎麼寫貪吃蛇,話不多說,如下 開發環境 vs2015 雖然開始還是出了很多指標問題。很煩c語言指標 除錯了很久也大概是可以暢快的玩了。c語言新手,有很多寫得不好的地方望大神提出 當然,我也不介意把我 拿去學習 這樣就說明我的 有學習價值 標頭檔案 snake.h by liu yuc...