欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

C語言手把手教你實(shí)現(xiàn)貪吃蛇AI(下)

 更新時(shí)間:2018年01月23日 16:22:57   作者:kuweicai  
這篇文章主要手把手教你實(shí)現(xiàn)C語言版貪吃蛇AI,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

本文實(shí)例為大家分享了C語言實(shí)現(xiàn)貪吃蛇AI的具體代碼,供大家參考,具體內(nèi)容如下

1. 目標(biāo)

        這一部分的目標(biāo)是把之前寫的貪吃蛇加入AI功能,即自動(dòng)的去尋找食物并吃掉。

2. 控制策略

        為了保證蛇不會(huì)走入“死地”,所以蛇每前進(jìn)一步都需要檢查,移動(dòng)到新的位置后,能否找到走到蛇尾的路徑,如果可以,才可以走到新的位置;否則在當(dāng)前的位置尋找走到蛇尾的路徑,并按照路徑向前走一步,開始循環(huán)之前的操作,如下圖所示。這個(gè)策略可以工作,但是并不高效,也可以嘗試其他的控制策略,比如易水寒的貪吃蛇AI


        運(yùn)行效果如下:

3. 源代碼

需要注意的是,由于mapnode的數(shù)據(jù)量比較大,這里需要把棧的大小設(shè)置大一點(diǎn),如下圖所示,否則會(huì)出現(xiàn)棧溢出的情況。

整個(gè)項(xiàng)目由以下三個(gè)文件組成:

a. snake AI.h

#ifndef SNAKE_H_ 
#define SNAKE_H_ 
#include<stdio.h> 
#include<Windows.h> //SetConsoleCursorPosition, sleep函數(shù)的頭函數(shù) 
#include<time.h> //time()的頭函數(shù) 
#include<malloc.h>  //malloc()的頭函數(shù) 
#define N 32 //地圖大小 
#define snake_mark '#'//表示蛇身 
#define food_mark '$'//表示食物 
#define sleeptime 50//間隔時(shí)間 
 
#define W 10//權(quán)重 
 
typedef struct STARNODE{ 
  int x;//節(jié)點(diǎn)的x,y坐標(biāo) 
  int y; 
  int G;//該節(jié)點(diǎn)的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;//該節(jié)點(diǎn)的父節(jié)點(diǎn) 
} 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; 
 
/*表示蛇身坐標(biāo)的結(jié)構(gòu)體*/ 
typedef struct SNAKE{ 
  int x; //行坐標(biāo) 
  int y; //列坐標(biāo) 
  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" 
 
/*控制光標(biāo)的坐標(biāo)*/ 
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; 
 
  //打印上下邊框(每個(gè)■占用一行兩列) 
  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); 
} 
 
/*初始化蛇身*/ 
/*蛇身初始化坐標(biāo)為(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; 
} 
 
//根據(jù)指針?biāo)赶虻墓?jié)點(diǎn)的F值,按大頂堆進(jìn)行調(diào)整 
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是鄰域點(diǎn)坐標(biāo) 
//curtnode是當(dāng)前點(diǎn)坐標(biāo) 
//endnode是目標(biāo)點(diǎn)坐標(biāo) 
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)//如果已經(jīng)在opentable中 
    { 
      if (mapnode[x1][y1].G > pcurtnode->G + W)//但是不是最優(yōu)路徑 
      { 
        mapnode[x1][y1].G = pcurtnode->G + W;//把G值更新(變?。?
        mapnode[x1][y1].ParentNode = pcurtnode;//把該鄰點(diǎn)的雙親節(jié)點(diǎn)更新 
        //由于改變了opentable中一個(gè)點(diǎn)的F值,需要對(duì)opentable中的點(diǎn)的順序進(jìn)行調(diào)整,以滿足有序 
        for (i = 1; i <= opennode_count; i++) 
        { 
          if (opentable[i]->x == x1 && opentable[i]->y == y1) 
          { 
            break; 
          } 
        } 
        heapsort(opentable, i); 
      } 
    } 
    else//如果不在opentable中,把該點(diǎn)加入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); 
    } 
  } 
} 
 
//尋找當(dāng)前點(diǎn)的四鄰域點(diǎn),把符合條件的點(diǎn)加入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指向蛇頭所對(duì)應(yīng)的結(jié)點(diǎn) 
 
  opentable[++opennode_count] = startnode;//起始點(diǎn)加入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個(gè)節(jié)點(diǎn)加入closetable中 
    if (!opennode_count)//如果opentable已經(jīng)為空,即沒有找到路徑 
    { 
      //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記錄蛇頭下一步應(yīng)該移動(dòng)的位置 
  { 
 
    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; 
} 
 
//蛇尾向前移動(dòng)一格,并把原來的蛇尾注銷 
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;//將蛇尾注銷掉 
} 
 
//將蛇身移動(dòng)到指定的位置(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);//釋放蛇尾的內(nèi)存空間 
    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)//如果能找到到達(dá)食物的路徑 
    { 
 
      x = nextnode->x; 
      y = nextnode->y; 
 
      tsnake=create_tsnake(); 
 
      mapnode[x][y].is_snakebody = 1; 
 
      t = search_snaketail(tsnake);//走到下一個(gè)節(jié)點(diǎn)后,能否找到更新后的蛇尾 
 
      if (t==1)//如果按照路徑走到下一個(gè)位置,可以找到蛇尾,就把蛇頭移動(dòng)到下一個(gè)位置 
      { 
        nextnode->x = x; 
        nextnode->y = y; 
        Sleep(sleeptime); 
        snake_move(); 
      } 
      else//否則,從該點(diǎn)出發(fā)去找蛇尾 
      { 
        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;//蛇頭下一步該走的結(jié)點(diǎn) 
 
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; 
}

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 詳解C語言中的wait()函數(shù)和waitpid()函數(shù)

    詳解C語言中的wait()函數(shù)和waitpid()函數(shù)

    這篇文章主要介紹了C語言中的wait()函數(shù)和waitpid()函數(shù),注意其在中斷進(jìn)程方面用法的不同,需要的朋友可以參考下
    2015-08-08
  • Qt利用tablewidget模擬手指實(shí)現(xiàn)滑動(dòng)

    Qt利用tablewidget模擬手指實(shí)現(xiàn)滑動(dòng)

    這篇文章主要為大家詳細(xì)介紹了Qt如何利用tablewidget模擬手指實(shí)現(xiàn)滑動(dòng)效果,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Qt有一定的幫助,需要的可以參考一下
    2023-01-01
  • C語言實(shí)現(xiàn)快速排序

    C語言實(shí)現(xiàn)快速排序

    快速排序不一定是穩(wěn)定排序,這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)快速排序算法,具有一定的參考價(jià)值,感興趣的同學(xué)可以借鑒閱讀
    2023-03-03
  • C++實(shí)現(xiàn)哈夫曼樹編碼解碼

    C++實(shí)現(xiàn)哈夫曼樹編碼解碼

    這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)哈夫曼樹編碼解碼,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-04-04
  • C語言 詳細(xì)分析結(jié)構(gòu)體的內(nèi)存對(duì)齊

    C語言 詳細(xì)分析結(jié)構(gòu)體的內(nèi)存對(duì)齊

    C 數(shù)組允許定義可存儲(chǔ)相同類型數(shù)據(jù)項(xiàng)的變量,結(jié)構(gòu)是 C 編程中另一種用戶自定義的可用的數(shù)據(jù)類型,它允許你存儲(chǔ)不同類型的數(shù)據(jù)項(xiàng),本篇讓我們來了解C 的結(jié)構(gòu)體內(nèi)存對(duì)齊
    2022-03-03
  • 如何用C寫一個(gè)web服務(wù)器之GCC項(xiàng)目編譯

    如何用C寫一個(gè)web服務(wù)器之GCC項(xiàng)目編譯

    本文主要介紹了,如何用C寫一個(gè)web服務(wù)器,Linux下用GCC進(jìn)行項(xiàng)目編譯,對(duì)此感興趣的同學(xué),可以參考下。
    2021-05-05
  • C++ COM編程之什么是組件?

    C++ COM編程之什么是組件?

    這篇文章主要介紹了COM編程之什么是組件?COM組件是以Win32動(dòng)態(tài)鏈接庫(DLLs)或可執(zhí)行文件(EXEs)的形式發(fā)布的可執(zhí)行代碼,需要的朋友可以參考下
    2014-10-10
  • C++設(shè)計(jì)模式之模板方法模式(TemplateMethod)

    C++設(shè)計(jì)模式之模板方法模式(TemplateMethod)

    這篇文章主要為大家詳細(xì)介紹了C++設(shè)計(jì)模式之模板方法模式TemplateMethod,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-04-04
  • c語言實(shí)現(xiàn)的hashtable分享

    c語言實(shí)現(xiàn)的hashtable分享

    哈希表效率高,眾所周知。應(yīng)用廣泛,php中大部分存儲(chǔ)使用的都是hashtable,包括變量,數(shù)組…如何使用c語言實(shí)現(xiàn)hashtable呢,現(xiàn)提供自己的思路,如有不妥之處,敬請(qǐng)賜教
    2014-01-01
  • C語言從代碼中加載動(dòng)態(tài)鏈接庫過程解析

    C語言從代碼中加載動(dòng)態(tài)鏈接庫過程解析

    這篇文章主要介紹了C語言從代碼中加載動(dòng)態(tài)鏈接庫過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2019-12-12

最新評(píng)論