C語言手把手教你實現貪吃蛇AI(上)

2022-10-04 00:21:27 字數 4050 閱讀 1482

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檔案,讀取最高紀錄 ...