{

set_cursor_position(0, i);

printf("■");

set_cursor_position(N+2, i);

printf("■");

}

}

/*初始化蛇身*/

/*蛇身初始化坐标为(5,8),(4,8), (3,8) */

psnake initial_snake()

{

inti=5;//列

int j = N / 4;//行

psnake snake = NULL, tsnake = NULL, temp = NULL;

snake = (psnake)malloc(sizeof(snake_body));

(snake)->x = i;

(snake)->y = j;

(snake)->next = NULL;

tsnake = snake;

for (i = 4; i >2; i--)

{

temp = (psnake)malloc(sizeof(snake_body));

(temp)->x = i;

(temp)->y = j;

(temp)->next = NULL;

(tsnake)->next = (temp);

(tsnake) = (tsnake)->next;

}

return snake;

}

void create_food(psnake snake, psnake food)

{

static int i=1;

psnake head = snake;

srand((unsigned)time(NULL));

food->x = rand() % N + 2;

food->y = rand() % (N/2) + 1;

//检查食物是否和蛇身重回

while (head)

{

if (head->x == food->x && head->y == food->y)

{

free(food);

food = NULL;

create_food(snake,food);

}

else

{

head = head->next;

}

}

}

void printe_map(psnake snake, psnake food)

{

psnake temp=snake;

while (temp)

{

set_cursor_position(temp->x, temp->y);

printf("%c",snake_mark);

temp = temp->next;

}

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)

{

if (snake_head->x == food->x && snake_head->y == food->y)

return 1;

return 0;

}

//判断是否撞到墙,撞到墙返回 1,否则返回 0;

int is_boundary(psnake snake_head)

{

if (snake_head->y <= 0 || snake_head->y >= N / 2 + 1 || snake_head->x <= 1 || snake_head->x >= N + 1)

return 1;

return 0;

}

//判断是否撞到自己,撞到自己返回 1,否则返回 0;

int is_snakebody(psnake snake_head)

{

psnake temp=snake_head->next;

while (temp)

{

if (snake_head->x == temp->x && snake_head->y == temp->y)

return 1;

else

temp = temp->next;

}

return 0;

}

//将蛇身移动到合适的位置,并打印出来

psnake snake_move(psnake snake, psnake food)

{

psnake snake_head = (psnake)malloc(sizeof(snake_body));

if (snake_direction == U)

{

snake_head->y = snake->y-1;

snake_head->x = snake->x;

snake_head->next = snake;

}

else if (snake_direction == D)

{

snake_head->y = snake->y + 1;

snake_head->x = snake->x;

snake_head->next = snake;

}

else if (snake_direction == L)

{

snake_head->y = snake->y;

snake_head->x = snake->x - 1;

snake_head->next = snake;

}

else if (snake_direction == R)

{

snake_head->y = snake->y;

snake_head->x = snake->x + 1;

snake_head->next = snake;

}

if (is_food(snake_head, food))//如果是食物

{

create_food(snake_head, food);

printe_map(snake_head, food);

}

else if (is_boundary(snake_head) == 0 && is_snakebody(snake_head) == 0)//不是食物,不是边界,也不是蛇身

{

psnake temp = snake_head;

while (temp->next->next)//寻找蛇尾

{

temp = temp->next;

}

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

{

free(snake_head);

snake_head = NULL;

}

return snake_head;

}

void control_snake()

{

if (GetAsyncKeyState(VK_UP) && snake_direction != D)

{

snake_direction = U;

}

else if (GetAsyncKeyState(VK_DOWN) && snake_direction != U)

{

snake_direction = D;

}

else if (GetAsyncKeyState(VK_LEFT) && snake_direction != R)

{

snake_direction = L;

}

else if (GetAsyncKeyState(VK_RIGHT) && snake_direction != L)

{

snake_direction = R;

}

}

4.3 main.cpp

#include"gluttonous.h"

direction snake_direction;

psnake food;

int main(void)

{

psnake snake;

initial_map();

snake=initial_snake();

food = (psnake)malloc(sizeof(snake_body));

food->next = NULL;

create_food(snake, food);

printe_map(snake, food);

snake_direction = R;

while (1)

{

Sleep(sleeptime);

control_snake();

snake=snake_move(snake, food);

}

return 0;

}

C语言-手把手教你写贪吃蛇AI(中)

1. 目标

这一部分主要是讲解编写贪吃蛇AI所需要用到的算法基础。

2. 问题分析

贪吃蛇AI说白了就是寻找一条从蛇头到食物的一条最短路径,同时这条路径需要避开障碍物,这里仅有的障碍就是蛇身。而A star 算法就是专门针对这一个问题的。在A star 算法中需要用到排序算法,这里采用堆排序(当然其他排序也可以),如果对堆排序不熟悉的朋友,请移步到这里——堆排序,先看看堆排序的内容。

3. A*算法

A star(也称A*)搜寻算法俗称A星算法。这是一种在图形平面上,有多个节点的路径,求出最低通过成本的算法。常用于游戏中对象的移动计算上。A* 算法是一种启发式搜寻算法,有别于DFS, BFS搜索。可以这样理解“启发式”的涵义,比如从起点A到达目的地B的路线,并不是直接告诉你,从A出发,向东行驶200米,右转进入XX路,直行500米到达B;而是从A出发,直行,直到遇到第一家肯德基,右转直到看到B大厦。而A*算法中用来启发的线索就是移动成本,也就是权重。

3.1 移动成本

如下图所示,从A点出发,可以有四个方向可走(由于贪吃蛇仅仅可以走上下左右四个方向,所以这里不考虑走斜线的情况),假设每个方向移动一格的成本为10,A*算法中采用的F值来评价移动成本,F=G+H。假设节点C是待考察的一个点,G代表的是从起点A到C的移动成本,如下图的情况G=10。那么H代表的就是从C点到目标B点的移动代价的预估值,如下图的情况H=50,那么F=60。为什么说是预估,因为现在对于从C点到B点的情况还不清楚,因为中间可能存在障碍物,那么实际的移动代价就会大于预估的情况。而对于待考察点D,其F=80,显然在C 和D点中(当然这里待考察的点不止C和D点),A*算法会选择C点。

3.2 算法流程图

4. 源代码

代码中假定起始点A(5,10),食物B(5,15),如下图。其中‘X’代表障碍物,‘O’代表的就是寻找到的从A到B的路径。

#include#include#define N 32

#define W 10

typedef struct STARNODE{

int x;//节点的x,y坐标

int y;

int G;//该节点的G, H值

int H;

int is_snakebody;//是否为蛇身,是为1,否则为0;

int in_open_table;//是否在open_table中,是为1,否则为0;

int in_close_table;//是否在close_table中,是为1,否则为0;

struct STARNODE* ParentNode;//该节点的父节点

} starnode, *pstarnode;

starnode mapnode[N/2+2][N+4];

pstarnode opentable[N*N/2];

pstarnode closetable[N*N/2];

int opennode_count=0;

int closenode_count=0;

starnode food;

//根据指针所指向的节点的F值,按大顶堆进行调整

void heapadjust(pstarnode a[], int m, int n)

{

int i;

pstarnode temp=a[m];

for(i=2*m;i<=n;i*=2)

{

if(i+1<=n && (a[i+1]->G+a[i+1]->H)>(a[i]->G+a[i]->H) )

{

i++;

}

if((temp->G+temp->H)>(a[i]->G+a[i]->H))

{

break;

}

a[m]=a[i];

m=i;

}

a[m]=temp;

}

void swap(pstarnode a[],int m, int n)

{

pstarnode temp;

temp=a[m];

a[m]=a[n];

a[n]=temp;

}

void crtheap(pstarnode a[], int n)

{

int i;

for(i=n/2;i>0;i--)

{

heapadjust(a, i, n);

}

}

void heapsort(pstarnode a[], int n)

{

int i;

crtheap(a,n);

for(i=n;i>1;i--)

{

swap(a,1,i);

heapadjust(a, 1,i-1);

}

}

//x1, y1是邻域点坐标

//curtnode是当前点坐标

void insert_opentable(int x1, int y1, pstarnode pcurtnode)

{

int i;

if(!mapnode[x1][y1].is_snakebody && !mapnode[x1][y1].in_close_table)//如果不是蛇身也不在closetable中

{

if(mapnode[x1][y1].in_open_table && mapnode[x1][y1].G>pcurtnode->G+W)//如果已经在opentable中,但是不是最优路径

{

mapnode[x1][y1].G=pcurtnode->G+W;//把G值更新

mapnode[x1][y1].ParentNode=pcurtnode;//把该邻点的双亲节点更新

//由于改变了opentable中一个点的F值,需要对opentable中的点的顺序进行调整,以满足有序

for(i=1;i<=opennode_count;i++)

{

if(opentable[i]->x==x1 && opentable[i]->y==y1)

{

break;

}

heapsort(opentable, i);

}

}

else//把该点加入opentable中

{

opentable[++opennode_count]=&mapnode[x1][y1];

mapnode[x1][y1].G=pcurtnode->G+W;

mapnode[x1][y1].H=(abs(food.x-x1)+abs(food.y-y1))*W;

mapnode[x1][y1].in_open_table=1;

mapnode[x1][y1].ParentNode=pcurtnode;

heapsort(opentable, opennode_count);

}

}

}

//寻找当前点的四邻域点,把符合条件的点加入opentable中

void find_neighbor(pstarnode pcurtnode)

{

int x=pcurtnode->x;

int y=pcurtnode->y;

if(x+1<=N/2)

{

insert_opentable(x+1, y, pcurtnode);

}

if(x-1>=1)

{

insert_opentable(x-1, y, pcurtnode);

}

if(y+1<=N+1)

{

insert_opentable(x,y+1, pcurtnode);

}

if(y-1>=2)

{

insert_opentable(x,y-1, pcurtnode);

}

}

int search_road(pstarnode startnode, pstarnode endnode)

{

int is_search_road=0;

opennode_count=0;

closenode_count=0;

pstarnode pcurtnode;

opentable[++opennode_count]=startnode;//起始点加入opentable中

startnode->in_open_table=1;

startnode->ParentNode=NULL;

startnode->G=0;

startnode->H=(abs(endnode->x-startnode->x)+abs(endnode->y-startnode->y))*W;

if(startnode->x==endnode->x && startnode->y==endnode->y)//如果起点和终点重合

{

is_search_road=1;

return is_search_road;

}

while(1)

{

//取出opentable中第1个节点加入closetable中

pcurtnode=opentable[1];

opentable[1]=opentable[opennode_count--];

closetable[++closenode_count]=pcurtnode;

pcurtnode->in_open_table=0;

pcurtnode->in_close_table=1;

if(pcurtnode->x==endnode->x && pcurtnode->y==endnode->y)

{

is_search_road=1;

break;

}

find_neighbor(pcurtnode);

if(!opennode_count)//如果opentable已经为空,即没有找到路径

{

break;

}

}

return is_search_road;

}

int main(void)

{

int i, j;

pstarnode startnode;

for(i=0;i

for(j=0;j

{

mapnode[i][j].G=0;

mapnode[i][j].H=0;

mapnode[i][j].in_close_table=0;

mapnode[i][j].in_open_table=0;

mapnode[i][j].is_snakebody=0;

mapnode[i][j].ParentNode=NULL;

mapnode[i][j].x=i;

mapnode[i][j].y=j;

}

startnode=&mapnode[5][10];

food.x=5;

food.y=15;

mapnode[5][13].is_snakebody=1;

mapnode[6][13].is_snakebody=1;

mapnode[4][13].is_snakebody=1;

mapnode[4][12].is_snakebody=1;

mapnode[6][12].is_snakebody=1;

int flag;

flag=search_road(startnode, &food);

pstarnode temp=&mapnode[5][15];

do{

printf("%d %d\n",temp->x, temp->y);

temp=temp->ParentNode;

}while(temp);

return 0;

C语言-手把手教你写贪吃蛇AI(下)

1. 目标

这一部分的目标是把之前写的贪吃蛇加入AI功能,即自动的去寻找食物并吃掉。

2. 控制策略

为了保证蛇不会走入“死地”,所以蛇每前进一步都需要检查,移动到新的位置后,能否找到走到蛇尾的路径,如果可以,才可以走到新的位置;否则在当前的位置寻找走到蛇尾的路径,并按照路径向前走一步,开始循环之前的操作,如下图所示。这个策略可以工作,但是并不高效,也可以尝试其他的控制策略,比如易水寒的贪吃蛇AI

运行效果如下:

3. 源代码

需要注意的是,由于mapnode的数据量比较大,这里需要把栈的大小设置大一点,如下图所示,否则会出现栈溢出的情况。

整个项目由以下三个文件组成:

a. snake AI.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 50//间隔时间

#define W 10//权重

typedef struct STARNODE{

int x;//节点的x,y坐标

int y;

int G;//该节点的G, H值

int H;

int is_snakebody;//是否为蛇身,是为1,否则为0;

int in_open_table;//是否在open_table中,是为1,否则为0;

int in_close_table;//是否在close_table中,是为1,否则为0;

struct STARNODE* ParentNode;//该节点的父节点

} starnode, *pstarnode;

extern starnode (*mapnode)[N + 4];

extern pstarnode opentable[N*N / 2];

extern pstarnode closetable[N*N / 2];

extern int opennode_count;

extern int closenode_count;

/*表示蛇身坐标的结构体*/

typedef struct SNAKE{

int x; //行坐标

int y; //列坐标

struct SNAKE* next;

}snake_body, *psnake;

extern psnake snake;

extern psnake food;

extern psnake snaketail;

extern psnake nextnode;

void set_cursor_position(int x, int y);

void initial_map();

void initial_mapnode();

void update_mapnode();

void printe_map();

void initial_snake();

void create_food();

int is_food();

void heapadjust(pstarnode a[], int m, int n);

void swap(pstarnode a[], int m, int n);

void crtheap(pstarnode a[], int n);

void heapsort(pstarnode a[], int n);

void insert_opentable(int x1, int y1, pstarnode pcurtnode, psnake endnode);

void find_neighbor(pstarnode pcurtnode, psnake endnode);

int search_short_road(psnake snakehead, psnake endnode);

int search_snaketail(psnake snakehead);

void update_snaketail(psnake snakehead);

void snake_move();

psnake create_tsnake();

void snake_control();

#endif

2. source.cpp

#include"Snake AI.h"

/*控制光标的坐标*/

void set_cursor_position(int x, int y)

{

COORD coord = { x, y };//x表示列,y表示行。

SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);

}

/*初始化后的地图为 N列 N/2行*/

/*游戏的空间为2至N+1列,1至N/2行*/

void initial_map()

{

int i = 0;

//打印上下边框(每个■占用一行两列)

for (i = 0; i

{

set_cursor_position(2 * i, 0);

printf("■");

set_cursor_position(2 * i, N / 2 + 1);

printf("■");

}

for (i = 0; i

{

set_cursor_position(0, i);

printf("■");

set_cursor_position(N + 2, i);

printf("■");

}

}

//初始化mapnode

void initial_mapnode()

{

int i = 0, j = 0;

for (i = 0; i < N / 2 + 2; i++)

for (j = 0; j < N + 4; j++)

{

mapnode[i][j].G = 0;

mapnode[i][j].H = 0;

mapnode[i][j].in_close_table = 0;

mapnode[i][j].in_open_table = 0;

mapnode[i][j].is_snakebody = 0;

mapnode[i][j].ParentNode = NULL;

mapnode[i][j].x = i;

mapnode[i][j].y = j;

}

}

//初始化mapnode

void update_mapnode()

{

psnake temp = snake;

int x, y;

initial_mapnode();//初始化mapnode

while (temp)

{

x = temp->x;

y = temp->y;

mapnode[x][y].is_snakebody = 1;

temp = temp->next;

}

}

void printe_map()

{

psnake temp = snake;

while (temp)

{

set_cursor_position(temp->y, temp->x);

printf("%c", snake_mark);

temp = temp->next;

}

if (food)

set_cursor_position(food->y, food->x);

printf("%c", food_mark);

set_cursor_position(0, N / 2 + 2);

}

/*初始化蛇身*/

/*蛇身初始化坐标为(8,5),(8,4), (8,3) */

void initial_snake()

{

inti = 5;//列

int j = N / 4;//行

psnake tsnake = NULL, temp = NULL;

snake = (psnake)malloc(sizeof(snake_body));

(snake)->x = j;

(snake)->y = i;

(snake)->next = NULL;

tsnake = snake;

for (i = 4; i >2; i--)

{

temp = (psnake)malloc(sizeof(snake_body));

(temp)->x = j;

(temp)->y = i;

(temp)->next = NULL;

(tsnake)->next = (temp);

(tsnake) = (tsnake)->next;

}

snaketail = tsnake;

}

//生成食物

void create_food()

{

srand((unsigned)time(NULL));

food->y = rand() % N + 2;//列

food->x = rand() % (N / 2) + 1;//行

//检查食物是否和蛇身重回

update_mapnode();

if (mapnode[food->x][food->y].is_snakebody)

{

create_food();

}

}

//判断是否吃到食物,吃到食物返回 1,否则返回 0;

int is_food()

{

if (snake->x == food->x && snake->y == food->y)

return 1;

return 0;

}

//根据指针所指向的节点的F值,按大顶堆进行调整

void heapadjust(pstarnode a[], int m, int n)

{

int i;

pstarnode temp = a[m];

for (i = 2 * m; i <= n; i *= 2)

{

if (i + 1 <= n && (a[i + 1]->G + a[i + 1]->H)>(a[i]->G + a[i]->H))

{

i++;

}

if ((temp->G + temp->H)>(a[i]->G + a[i]->H))

{

break;

}

a[m] = a[i];

m = i;

}

a[m] = temp;

}

void swap(pstarnode a[], int m, int n)

{

pstarnode temp;

temp = a[m];

a[m] = a[n];

a[n] = temp;

}

void crtheap(pstarnode a[], int n)

{

int i;

for (i = n / 2; i>0; i--)

{

heapadjust(a, i, n);

}

}

void heapsort(pstarnode a[], int n)

{

int i;

crtheap(a, n);

for (i = n; i>1; i--)

{

swap(a, 1, i);

heapadjust(a, 1, i - 1);

}

}

//x1, y1是邻域点坐标

//curtnode是当前点坐标

//endnode是目标点坐标

void insert_opentable(int x1, int y1, pstarnode pcurtnode, psnake endnode)

{

int i = 1;

if (!mapnode[x1][y1].is_snakebody && !mapnode[x1][y1].in_close_table)//如果不是蛇身也不在closetable中

{

if (mapnode[x1][y1].in_open_table)//如果已经在opentable中

{

if (mapnode[x1][y1].G > pcurtnode->G + W)//但是不是最优路径

{

mapnode[x1][y1].G = pcurtnode->G + W;//把G值更新(变小)

mapnode[x1][y1].ParentNode = pcurtnode;//把该邻点的双亲节点更新

//由于改变了opentable中一个点的F值,需要对opentable中的点的顺序进行调整,以满足有序

for (i = 1; i <= opennode_count; i++)

{

if (opentable[i]->x == x1 && opentable[i]->y == y1)

{

break;

}

}

heapsort(opentable, i);

}

}

else//如果不在opentable中,把该点加入opentable中

{

opentable[++opennode_count] = &mapnode[x1][y1];

mapnode[x1][y1].G = pcurtnode->G + W;

mapnode[x1][y1].H = (abs(endnode->x - x1) + abs(endnode->y - y1))*W;

mapnode[x1][y1].in_open_table = 1;

mapnode[x1][y1].ParentNode = pcurtnode;

heapsort(opentable, opennode_count);

}

}

}

//寻找当前点的四邻域点,把符合条件的点加入opentable中

void find_neighbor(pstarnode pcurtnode, psnake endnode)

{

int x;

int y;

x = pcurtnode->x;

y = pcurtnode->y;

if (x + 1 <= N / 2)

{

insert_opentable(x + 1, y, pcurtnode, endnode);

}

if (x - 1 >= 1)

{

insert_opentable(x - 1, y, pcurtnode, endnode);

}

if (y + 1 <= N + 1)

{

insert_opentable(x, y + 1, pcurtnode, endnode);

}

if (y - 1 >= 2)

{

insert_opentable(x, y - 1, pcurtnode, endnode);

}

}

int search_short_road(psnake snakehead, psnake endnode)

{

int is_search_short_road = 0;

opennode_count = 0;

closenode_count = 0;

pstarnode pcurtnode;

pstarnode temp;

pstarnode startnode = &mapnode[snakehead->x][snakehead->y];//startnode指向蛇头所对应的结点

opentable[++opennode_count] = startnode;//起始点加入opentable中

startnode->in_open_table = 1;

startnode->ParentNode = NULL;

startnode->G = 0;

startnode->H = (abs(endnode->x - startnode->x) + abs(endnode->y - startnode->y))*W;

while (1)

{

//取出opentable中第1个节点加入closetable中

if (!opennode_count)//如果opentable已经为空,即没有找到路径

{

//printf("No way");

return is_search_short_road;

}

pcurtnode = opentable[1];

opentable[1] = opentable[opennode_count--];

closetable[++closenode_count] = pcurtnode;

pcurtnode->in_open_table = 0;

pcurtnode->in_close_table = 1;

if (pcurtnode->x == endnode->x && pcurtnode->y == endnode->y)

{

is_search_short_road = 1;

break;

}

find_neighbor(pcurtnode, endnode);

}

if (is_search_short_road)//如果找到,则用nextnode记录蛇头下一步应该移动的位置

{

temp = closetable[closenode_count];

while (temp->ParentNode->ParentNode)

{

temp = temp->ParentNode;

}

nextnode->x = temp->x;

nextnode->y = temp->y;

nextnode->next = NULL;

}

return is_search_short_road;

}

int search_snaketail(psnake snakehead)

{

int t = 0;

update_mapnode();

mapnode[snaketail->x][snaketail->y].is_snakebody = 0;

t = search_short_road(snakehead, snaketail);

mapnode[snaketail->x][snaketail->y].is_snakebody = 1;

return t;

}

//蛇尾向前移动一格,并把原来的蛇尾注销

void update_snaketail(psnake snakehead)

{

psnake temp;

temp = snakehead;

while (temp->next->next)

{

temp = temp->next;

}

snaketail = temp;

temp = temp->next;

mapnode[temp->x][temp->y].is_snakebody = 0;//将蛇尾注销掉

}

//将蛇身移动到指定的位置(nextnode),并打印出来

void snake_move()

{

psnake snake_head = (psnake)malloc(sizeof(snake_body));

snake_head->x = nextnode->x;

snake_head->y = nextnode->y;

snake_head->next = snake;

snake = snake_head;

if (is_food())//如果是食物

{

create_food();

printe_map();

}

else//不是食物

{

psnake temp = snake_head;

while (temp->next->next)//寻找蛇尾

{

temp = temp->next;

}

snaketail = temp;//更新snaketail的位置

set_cursor_position(temp->next->y, temp->next->x);

printf(" ");//把蛇尾用空格消掉

free(temp->next);//释放蛇尾的内存空间

temp->next = NULL;//将temp的next置成NULL

printe_map();

}

snake=snake_head;

}

psnake create_tsnake()

{

psnake tsnake = (psnake)malloc(sizeof(snake_body));

tsnake->x = nextnode->x;

tsnake->y = nextnode->y;

tsnake->next = NULL;

psnake temp1 = snake;

psnake temp2 = tsnake;

while (temp1!=snaketail)

{

temp2->next = (psnake)malloc(sizeof(snake_body));

temp2->next->x = temp1->x;

temp2->next->y = temp1->y;

temp2->next->next = NULL;

temp1 = temp1->next;

temp2 = temp2->next;

}

return tsnake;

}

void snake_control()

{

int r, t, x, y;

psnake tsnake = NULL;;

while (1)

{

r = 0;

t = 0;

x = 0;

y = 0;

update_mapnode();

r = search_short_road(snake, food);

if (r == 1)//如果能找到到达食物的路径

{

x = nextnode->x;

y = nextnode->y;

tsnake=create_tsnake();

mapnode[x][y].is_snakebody = 1;

t = search_snaketail(tsnake);//走到下一个节点后,能否找到更新后的蛇尾

if (t==1)//如果按照路径走到下一个位置,可以找到蛇尾,就把蛇头移动到下一个位置

{

nextnode->x = x;

nextnode->y = y;

Sleep(sleeptime);

snake_move();

}

else//否则,从该点出发去找蛇尾

{

mapnode[x][y].is_snakebody = 0;

search_snaketail(snake);

Sleep(sleeptime);

snake_move();

}

free(tsnake);

}

else//如果找不到食物

{

search_snaketail(snake);

Sleep(sleeptime);

snake_move();

}

}

}

3. main.cpp

#include"Snake AI.h"

psnake snake = NULL;

psnake food = NULL;

psnake snaketail = NULL;

psnake nextnode = NULL;//蛇头下一步该走的结点

starnode (*mapnode)[N+4]=(starnode(*)[N+4])malloc(sizeof(starnode)*(N/2+2)*(N+4));

pstarnode opentable[N*N / 2];

pstarnode closetable[N*N / 2];

int opennode_count = 0;

int closenode_count = 0;

int main(void)

{

initial_map();

initial_snake();

food = (psnake)malloc(sizeof(snake_body));

nextnode = (psnake)malloc(sizeof(snake_body));

food->next = NULL;

create_food();

food->x = 1;

food->y = 3;

printe_map();

snake_control();

free(food);

free(snake);

free(mapnode);

return 0;

}

————————————————

版权声明:本文为CSDN博主「kuweicai」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/kuweicai/article/details/69487351

linux贪吃蛇c语言代码,C语言贪吃蛇讲解及源码相关推荐

  1. C语言实现扫雷游戏(超详细讲解+全部源码)

    电子信息 工科男 一点一点努力! 文章目录 前言 一.游戏介绍 二.游戏设计思路 二.具体步骤 1.创建test.c和game.c源文件以及 game.h头文件 2.创建菜单 3.创建雷盘 4.初始化 ...

  2. 免费开源的高精度OCR文本提取,支持 100 多种语言、自动文本定位和脚本检测,几行代码即可实现离线使用(附源码)

    免费开源的高精度OCR文本提取,支持 100 多种语言.自动文本定位和脚本检测,几行代码即可实现离线使用(附源码). 要从图像.照片中提取文本吗?是否刚刚拍了讲义的照片并想将其转换为文本?那么您将需要 ...

  3. C语言课设-----工资管理系统(附全部源码)

    C语言课设-----工资管理系统(附全部源码) 本系统分三个部分: 1.出售金鱼 2.数字菱形 3.工资管理系统 (ps:另外添加了登录界面 id:qwq password:123 可自己在代码里再更 ...

  4. mysql db模块下载_易语言MySql数据库操作类V1.0模块源码

    易语言MySql数据库操作类V1.0模块源码 易语言MySql数据库操作类V1.0模块源码 系统结构:MySql数据库连接类_测试子程序,置连接选项,连接,关闭,是否已连接,取连接句柄,置连接句柄,执 ...

  5. c语言 临时文件作用,c语言函数mktemp()产生唯一临时文件名实例源码介绍

    c语言函数mktemp()产生唯一临时文件名实例源码介绍.有关的函数:tmpfile引入的头文件:#include 定义函数mktemp():char * mktemp(char * template ...

  6. 编译哈工大语言技术平台云LTP(C++)源码及LTP4J(Java)源码

    JDK:java version "1.8.0_31" Java(TM) SE Runtime Environment (build 1.8.0_31-b13) Java HotS ...

  7. 价值4500的国际版多语言点赞抖音分享点赞任务平台源码(十二种语言)

    介绍: 平台会员分享给我的,他自己搭建成功了,测试可用!我就不测试了,需要的拿! 九种语言 :西班牙语,泰语.日语,印度尼西亚语言.越南语言.英文.繁体中文,简体中文,印度语 前台支持更换5种颜色风格 ...

  8. c语言打印空心数字图形,(完整word版)C语言编写打印实心和空心菱形【源码】

    <(完整word版)C语言编写打印实心和空心菱形[源码]>由会员分享,可在线阅读,更多相关<(完整word版)C语言编写打印实心和空心菱形[源码](13页珍藏版)>请在人人文库 ...

  9. 易语言免登录获取QQ/昵称/头像/在线状态源码

    易语言免登陆获取q资料卡的源码. 例子: 取得登录q  获取状态:在线 昵称 x7st 获取本人描述等 没有调用第三方接口,纯QQpost稳定,需要的可以下载查看 下载地址:https://6yunp ...

  10. Linux系统中软件的“四”种安装原理详解:源码包安装、RPM二进制安装、YUM在线安装、脚本安装包...

    一.Linux软件包分类 1.1 源码包 优点: 开源,如果有足够的能力,可以修改源代码: 可以自由选择所需的功能: 软件是编译安装,所以更加适合自己的系统,更加稳定.效率更高: 卸载方便: 缺点: ...

最新文章

  1. 忍不住要发感慨,我的这个罗技鼠真好用...
  2. 腾讯Elasticsearch海量规模背后的内核优化剖析
  3. SilverLight开发系列第2步:使用vs2008和Blend 2.5打造Hellow World程序
  4. 5939. 半径为 k 的子数组平均值
  5. 开源中国android代码是什么,开源中国 OsChina Android 客户端源码分析(1)启动界面 app_start...
  6. c语言程序设计 cap 翁恺,GPS数据处理 翁恺老师C语言程序设计CAP第10章编程题
  7. jQuery-星级评价
  8. 离散数学 计算机应用,计算机应用融入离散数学的思考
  9. 参加Oracle OCP和MySQL OCP考试的学员怎样在VUE预约考试
  10. Python爬取图片之家
  11. vbox win10 分辨率_win10如何更改分辨率?
  12. Windows 模块安装程序必须更新,才能安装此程序包。 请更新计算机上的 Windows 模块安装程序,然后重试安装。问题解决
  13. mysql ibd文件删除_误删除MySQL数据库表的ibd文件怎么办
  14. F280049C 输出三相互补对称SPWM波
  15. splice,splite,slice的区别
  16. 安装hadoop 问题记录
  17. 编程语言专题《开发篇,实参数组名与形参数组名》
  18. 基于Neo4j的网络安全知识图谱构建分析
  19. NOIP2018·赛道修建
  20. windterm复制长命令,换行只显示最后一行需修改配置

热门文章

  1. 工业互联网的基础技术有哪些
  2. 微信多开工具,微信防撤回、QQ防撤回、Tim防撤回工具,微信消息防撤回、QQ消息防撤回、Tim消息防撤回,无视撤回功能,不错过每一条消息
  3. C++对类中字符串成员进行初始化的两种方法以及友元函数的使用
  4. 1.3 人工智能产业发展
  5. 计算机网络谢希仁第七版知识点总结
  6. 工控之台达HMI和三菱FX PLC连接
  7. QT 制作 gif 录屏 小工具
  8. 嵌入式系统使用时,Ubuntu缺少一些服务的解决办法
  9. 课堂jQuery笔记
  10. 计算机毕业设计Python+uniapp+安卓电影院售票管理APP论文(WEB+APP+LW)