1. 目標
編寫乙個貪吃蛇ai,也就是自動繞過障礙,去尋找最優路徑吃食物。
2. 問題分析
為了達到這一目的,其實很容易,總共只需要兩步,第一步抓一條蛇,第二步給蛇裝乙個腦子。具體來說就是,首先我們需要有一條普通的貪吃蛇,也就是我們常玩兒的,手動控制去吃食物的貪吃蛇;然後給這條蛇加入ai,也就是通過演算法控制,告訴蛇怎麼最方便的繞開障礙去吃食物。為了講清楚這個問題,文章將分為三部分:上,寫乙個貪吃蛇程式;中,演算法基礎(需要運用到什麼演算法);下,運用演算法基礎中的演算法編寫乙個貪吃蛇ai。
在動手寫貪吃蛇之前,我們需要想清楚以下幾個問題,就非常容易了:
a. 蛇身。由於蛇在吃食物的過程中會不斷的長大,所以很適合用單鏈表表示,並且吃食物的過程就是用頭插法插入元素的過程
b. 食物。食物直接用隨機生成函式,隨機生成食物,但是需要檢查,所生成的食物的位置不可以和蛇身重合
c. 顯示。我們需要實時的顯示出蛇身的移動,但事實上,我們不用每次都列印整個蛇身,因為蛇身每走一步,僅僅是蛇頭和蛇尾的位置移動一格,其他的地方都沒有變化,所以只需要列印一www.cppcns.com個新的蛇頭,並把蛇尾的位置抹掉,那麼視覺效果就是蛇身先前移動了一格,這個過程中,我們需要用到setconsolecursorposition(),將游標移到到指定的位置(比如蛇尾),完成相應的操作(比如列印空格抹掉蛇尾)
d.控制。我們需要用鍵盤來控制蛇身的移動,這個程式中是利用上下左右方向鍵來實現的,這裡需要用到getasynckeystate(),來實時監測按鍵的狀態
3. 執行效果
4. 源**
總共由三個檔案組成gluttonous.h,source.c & main.cpp。由於這個貪吃蛇是用於後面加ai,所以並沒有加入一些錯誤檢測,比如是否撞到邊界,是否撞到蛇身等。
需要注意的是,這個程式中用到了比較特殊的字元('■')來表示遊戲空間的邊界,在vs2013中可以正常編譯,但是在codeblock中會亂碼。
另外還有一點容易混淆的是,我們通常都是用(x,y)座標表示第x行,第y列,但是在setconsolecursorposition(x,y)中,表示把游標移動到第y行,第x列
4.1 gluttonous.h
#ifndef snake_h_
#define snake_h_
#include
#include //setconsolecursorposition, sleep函式的頭函式
#include //time()的頭函式
#include //malloc()的頭函式
#define n 32 //地圖大小
#define snake_mark '#'//表示蛇身
#define food_mark '$'
#define sleeptime 500
/*表示蛇身座標的結構體*/
typedef struct snakesnake_body, *psnake;
extern psnake food;
typedef enum direction direction;//蛇頭的朝向
extern direction snake_direction;
void set_cursor_position(int x, int y);
void initial_map();
psnake initial_snake();
void create_food(psnake snake,psnake food);
void printe_map(psnake snake, psnake food);
int is_food(psnake snake_head, psnake food);
int is_boundary(psnake snake_head, psnake food);
int is_snakebody(psnake snake_head, psnake food);
psnake snake_move(psnake sanke, psnake food);
void control_snake();
#endif
4.2 source.cpp
#include"gluttonous.h"
void set_cursor_position(int x, int y)
;//x表示列,y表示行。
setconsolecursorposition(getstdhandle(std_output_handle), coord); }
/*初始化後的地圖為 n列 n/2行*/
/*遊戲的空間為2至n+1列,1至n/2行*/
void initial_map()
for (i = 0; ix = i;
(snake)->y = j;
(snake)->next = null;
tsnake = snake;
for (i = 4; i >2; i--)
return snake; }
void create_food(psnake snake, psnake food)
else
} }
void printe_map(psnake snake, psnake food)
if (food)
set_cursor_position(food->x,food->y );
printf("%c",food_mark);
set_cursor_position(0, n/2+2); }
//判斷是否吃到食物,吃到食物返回 1,否則返回 0;
int is_food(psnake snake_head, psnake food)
//判斷是否撞到牆,撞到牆返回 1,否則返回 0;
int is_boundary(psnake snake_head)
//判斷是否撞到自己,撞到自己返回 1,否則返回 0;
int is_snakebody(psnake snake_head)
return 0; }
//將蛇身移動到合適的位置,並列印出來
psnake snake_move(psnake snake, psnake food)
else if (snake_direction == d)
else if (snake_direction == l)
else if (snake_direction == r)
if (is_food(snake_head, food))//如果是食物
else if (is_boundary(snake_head) == 0 && is_snakebody(snake_head) == 0)//不是食物,不是邊界,也不是蛇身
set_cursor_position(temp->next->x, temp->next->y);
printf(" ");//把蛇尾用空格消掉
free(temp->next);//釋放蛇尾的記憶體空間
temp->next = null;//將temp的next置成null
printe_map(snake_head, food);
} else
return snake_head; }
void control_snake()
else if (getasynckeystate(vk_down) && snake_direction != u)
else if (getasynckeystate(vk_left) && snake_direction != r)
else if (getasynckeystate(vk_right) && snake_direction != l)
}4.3 main.cpp
#include"gluttonous.h"
direction snake_direction;
psnake food;
int main(void)
return 0;
}本文標題: c語言手把手教你實現貪吃蛇ai(上)
本文位址:
C語言貪吃蛇
include include include include include include define screen width 40 遊戲螢幕寬度 define screen length 15 遊戲螢幕長度 define start x 16 螢幕起始x座標 define start y ...
C語言 貪吃蛇
include include include define framewidght 22 define frameheight 22 short generaterandnumber short a,short b void posconsolecursor short x,short y voi...
C語言貪吃蛇
親測devc 編譯器完美執行 define crt secure no warnings include include include include void readini file fphead,int score,char argv 建立或開啟乙個和執行檔案對應的ini檔案,讀取最高紀錄 ...