温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C语言如何实现贪吃蛇AI

发布时间:2021-06-18 14:04:01 来源:亿速云 阅读:140 作者:小新 栏目:编程语言

小编给大家分享一下C语言如何实现贪吃蛇AI,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!

1. 目标

        编写一个贪吃蛇AI,也就是自动绕过障碍,去寻找最优路径吃食物。

2. 问题分析

        为了达到这一目的,其实很容易,总共只需要两步,第一步抓一条蛇,第二步给蛇装一个脑子。具体来说就是,首先我们需要有一条普通的贪吃蛇,也就是我们常玩儿的,手动控制去吃食物的贪吃蛇;然后给这条蛇加入AI,也就是通过算法控制,告诉蛇怎么最方便的绕开障碍去吃食物。为了讲清楚这个问题,文章将分为三部分:上,写一个贪吃蛇程序;中,算法基础(需要运用到什么算法);下,运用算法基础中的算法编写一个贪吃蛇AI。

        在动手写贪吃蛇之前,我们需要想清楚以下几个问题,就非常容易了:
        a. 蛇身。由于蛇在吃食物的过程中会不断的长大,所以很适合用单链表表示,并且吃食物的过程就是用头插法插入元素的过程
        b. 食物。食物直接用随机生成函数,随机生成食物,但是需要检查,所生成的食物的位置不可以和蛇身重合
        c. 显示。我们需要实时的显示出蛇身的移动,但事实上,我们不用每次都打印整个蛇身,因为蛇身每走一步,仅仅是蛇头和蛇尾的位置移动一格,其他的地方都没有变化,所以只需要打印一个新的蛇头,并把蛇尾的位置抹掉,那么视觉效果就是蛇身先前移动了一格,这个过程中,我们需要用到SetConsoleCursorPosition(),将光标移到到指定的位置(比如蛇尾),完成相应的操作(比如打印空格抹掉蛇尾)
        d.控制。我们需要用键盘来控制蛇身的移动,这个程序中是利用上下左右方向键来实现的,这里需要用到GetAsyncKeyState(),来实时监测按键的状态

3. 运行效果

 C语言如何实现贪吃蛇AI

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<stdio.h> 
#include<Windows.h> //SetConsoleCursorPosition, sleep函数的头函数 
#include<time.h> //time()的头函数 
#include<malloc.h>  //malloc()的头函数 
#define N 32 //地图大小 
#define snake_mark '#'//表示蛇身 
#define food_mark '$' 
#define sleeptime 500 
 
/*表示蛇身坐标的结构体*/ 
typedef struct SNAKE{ 
  int x; //行坐标 
  int y; //列坐标 
  struct SNAKE* next; 
}snake_body, *psnake; 
extern psnake food; 
 
typedef enum Direction{ 
  U,D,L,R} 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) 
{ 
  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<N/2+2; i++)   
  { 
    set_cursor_position(2*i, 0); 
    printf("■"); 
    set_cursor_position(2*i, N/2+1); 
    printf("■"); 
  } 
  for (i = 0; i<N/2+2; i++)  //打印左右边框  
  { 
    set_cursor_position(0, i); 
    printf("■"); 
    set_cursor_position(N+2, i); 
    printf("■"); 
  } 
} 
 
/*初始化蛇身*/ 
/*蛇身初始化坐标为(5,8),(4,8), (3,8) */ 
psnake initial_snake() 
{ 
  int i=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; 
}

1. 目标

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

2. 控制策略

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

C语言如何实现贪吃蛇AI

        运行效果如下:

C语言如何实现贪吃蛇AI

3. 源代码

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

C语言如何实现贪吃蛇AI

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

a. snake AI.h

#ifndef SNAKE_H_ 
#define SNAKE_H_ 
#include<stdio.h> 
#include<Windows.h> //SetConsoleCursorPosition, sleep函数的头函数 
#include<time.h> //time()的头函数 
#include<malloc.h>  //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

b. 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<N / 2 + 2; i++) 
  { 
    set_cursor_position(22 * i, 0); 
    printf("■"); 
    set_cursor_position(22 * i, N / 2 + 1); 
    printf("■"); 
  } 
  for (i = 0; i<N / 2 + 2; 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() 
{ 
  int i = 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 = 22 * 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(); 
    } 
  } 
}

c. 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; 
}

以上是“C语言如何实现贪吃蛇AI”这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注亿速云行业资讯频道!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI