前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员是怎么玩贪吃蛇的?

程序员是怎么玩贪吃蛇的?

作者头像
DeROy
发布2021-06-01 15:46:45
5030
发布2021-06-01 15:46:45
举报
文章被收录于专栏:编程学习基地编程学习基地

前言

看别人玩贪吃蛇永远牛逼,自己玩永远菜鸡... http://mpvideo.qpic.cn/0bf224aayaaaoiah2vnkefqfbv6dbtlqadaa.f10002.mp4?dis_k=a12775a0d9e7c95e27a3c88acebf9ab7&dis_t=1622533515&spec_id=MzU5NjI2NzM5OA%3D%3D1622533515&vid=wxv_1882247247656976387&format_id=10002&support_redirect=1&mmversion=false

好久了,久到我都忘了我是怎么走过来的了...

正文

01 背景

设计的人工智能贪吃蛇是我初学寻路算法的时候胡乱捣鼓改的贪吃蛇代码,主要思路就是通过广度寻路算法,查找蛇头和食物之间是否有路,从而达到自动寻找食物的目的。

某次小学妹要做贪吃蛇的课题大作业,问我要贪吃蛇的代码我才想起还有个半成品的人工智能贪吃蛇。

向下滑动查看

当时奇思妙想的半成品,深度寻路算法学过数据结构都应该知道原理,就是实现的问题,如果没有需求我应该不会继续完善这个半成品了,吃力不讨好,要是谁能完善下就好了。

另外这是一个半成品,不是残次品,VS,VC6.0装Easyx能跑通的,可能就是这条蛇比较蠢,容易迷路...

此外,代码使用需谨慎,我加Sleep睡眠是有原因的,不要瞎改,出现任何无厘头状况一概与我无关...

代码如下: 或者发送关键字【人工智能贪吃蛇】获取

代码语言:javascript
复制
#include<iostream>
#include<easyx.h>
#include<time.h>
#include<vector>
#define MAP_ROW 48
#define MAP_COL 60

using namespace std;

enum sense  //场景
{
 SPACE, WALL, BODY, HEAD, FOOD
};

enum DIR    //方向
{
 UP, LEFT, DOWN, RIGHT
};

struct PathDate   //辅助数组
{
 bool isFind;
 int val;
 DIR dir;
};

struct MyPathNode    //做数据     构造 树
{
 COORD pos;                  //坐标
 MyPathNode* parent;           //父指针
 vector<MyPathNode*> child;    //子指针
};

vector<COORD> snack;  //蛇

sense map[MAP_ROW][MAP_COL];//地图

size_t score;

void init();      //初始化
void drawMap();   //画图
void addFood();   //添加食物
void search();    //寻找路
void clear(MyPathNode* &root);//清空树
void move(COORD point);   //移动到point处
bool isMove(PathDate arr[][MAP_COL],COORD pos);  //是否可以移动
int main()
{
 initgraph(640, 500);
 init();
 while (true)
 {
  drawMap();
  search();
 }
 getchar();
 closegraph();
 return 0;
}
void init()
{
 //设置随机种子
 srand((unsigned)time(NULL));
 //初始化地图数据
 memset(map, SPACE, sizeof(sense)*MAP_ROW*MAP_COL);
 for (int i = 0; i < MAP_ROW; i++)
 {
  map[i][0] = WALL;
  map[i][MAP_COL - 1] = WALL;
 }
 for (int i = 1; i < MAP_COL - 1; i++)
 {
  map[0][i] = WALL;
  map[MAP_ROW - 1][i] = WALL;
 }
 map[3][5] = map[3][4] = BODY;
 map[3][6] = HEAD;

 //添加 蛇 节点
 snack.push_back({ 3, 6 });
 snack.push_back({ 3, 5 });
 snack.push_back({ 3, 4 });
 //添加食物
 addFood();

 score = 0;
}
void drawMap()
{
 //开始批量绘图
 BeginBatchDraw();
 //设置背景颜色为白色
 setbkcolor(WHITE);
 //清屏
 cleardevice();

 WCHAR arr[10];
 wsprintf(arr, L"%d", score);
 settextcolor(BLACK);
 outtextxy(0, 0, L"Score:");
 outtextxy(50, 0, arr);

 //根据map[i][j]数值分类画图
 for (int x = 0; x < MAP_ROW; x++)
 {
  for (int y = 0; y < MAP_COL; y++)
  {
   switch (map[x][y])
   {
   case SPACE:
    break;
   case WALL:
    setlinecolor(BLACK);
    setfillcolor(RGB(238, 233, 233));
    fillrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
    break;
   case BODY:
    setlinecolor(RGB(0, 245, 255));//绿色 
    setfillcolor(WHITE);
    fillrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
    break;
   case HEAD:
    //画七彩蛇头
    switch (rand() % 7)
    {
    case 0:
     setfillcolor(RGB(255, 0, 0));//红色 255 0 0
     solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
     break;
    case 1:
     setfillcolor(RGB(255, 165, 0));//橙  255 165 0 
     solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
     break;
    case 2:
     setfillcolor(RGB(255, 255, 0));//黄  255 255 0
     solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
     break;
    case 3:
     setfillcolor(RGB(0, 255, 0));//绿色  0, 255, 0
     solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
     break;
    case 4:
     setfillcolor(RGB(0, 255, 255));//青  0 255 255
     solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
     break;
    case 5:
     setfillcolor(RGB(0, 0, 255));//蓝  0 0 255
     solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
     break;
    case 6:
     setfillcolor(RGB(160, 32, 240));//紫  160 32 240
     solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
     break;
    default:
     break;
    }
    break;
   case FOOD:
    setfillcolor(RGB(255, 0, 0));//红色
    solidrectangle(y * 10, x * 10 + 20, y * 10 + 10, x * 10 + 30);
    break;
   default:
    break;
   }
  }
 }
 EndBatchDraw();
}
void addFood()
{
 int row, col;
 do
 {
  row = rand() % (MAP_ROW - 1) + 1;     //1 ~ (MAP_ROW-1)
  col = rand() % (MAP_COL - 1) + 1;     //1 ~ (MAP_COL-1)
 } while (map[row][col] != SPACE);         //知道条件map[row][col]为空地
 map[row][col] = FOOD;                 
}
void search()
{
 //进行辅助数组初始化 及 起点终点设置
 COORD beginPoint, endPoint, tailPoint;
 PathDate pathMap[MAP_ROW][MAP_COL];
 for (int i = 0; i < MAP_ROW; i++)
 {
  for (int j = 0; j < MAP_COL; j++)
  {
   //由于广度搜索是从终点找起点 所以起点设置成终点
   if (map[i][j] == HEAD)
   {
    endPoint.X = i;     
    endPoint.Y = j;
   }
   if (map[i][j] == FOOD)
   {
    beginPoint.X = i;
    beginPoint.Y = j;
   }
   pathMap[i][j].val = map[i][j];
   pathMap[i][j].isFind = false;
   pathMap[i][j].dir = UP;
  }
 }
 //尾部坐标
 tailPoint = snack[snack.size() - 1];
 //表示起点已搜索
 pathMap[endPoint.X][endPoint.Y].isFind = true;
 //做数据  建立一个数据结构  设置根节点及其初始化
 MyPathNode*pRood = new MyPathNode;
 pRood->pos = beginPoint;
 pRood->parent = nullptr;

 vector<MyPathNode*> list;      //当前搜索层  
 vector<MyPathNode*> tempList;  //待搜索层

 list.push_back(pRood);         //根节点插入当前搜索层
 COORD tempPoint;               //搜索节点
 while (true)
 {
  for (int i = 0; i < (int)list.size(); i++)
  {
   for (int j = 0; j < 4; j++)
   {
    tempPoint = list[i]->pos;  //  搜索节点赋初值 根据该值确定搜索节点
    switch (j)
    {
    case UP:
     tempPoint.X--;
     break;
    case DOWN:
     tempPoint.X++;
     break;
    case LEFT:
     tempPoint.Y--;
     break;
    case RIGHT:
     tempPoint.Y++;
     break;
    default:
     break;
    }
    //如果待搜索节点是SPACE(空地)或者FOOD(食物)那么可以前进
    if (isMove(pathMap, tempPoint))
    {
     //初始化一个树节点
     MyPathNode*pNode = new MyPathNode;
     //初始化节点数据
     pNode->pos = tempPoint;
     //链接节点的辈分
     pNode->parent = list[i];
     list[i]->child.push_back(pNode);
     //已搜索该搜索节点
     pathMap[tempPoint.X][tempPoint.Y].isFind = true;
     //已搜索的节点放入待搜索层
     tempList.push_back(pNode);
     if (tempPoint.X == endPoint.X&&tempPoint.Y == endPoint.Y)
     {
      //表示找到终点
      MyPathNode *tempNode = pNode;
      while (tempNode)
      {
       tempNode = tempNode->parent;
       if (tempNode)
       {
        move(tempNode->pos);
       }  
      }
      addFood();
      goto LABLE;
     }
    }
   }
  }
  if (tempList.size() == 0)
  {
   MessageBox(GetHWnd(), L"寻路失败", L"提示", MB_OK | MB_ICONEXCLAMATION);
   exit(0);
   break;
  }
  list = tempList;
  tempList.clear();
 }
LABLE:
 return;
}
void clearTree(MyPathNode* &root)
{
 if (root)
 {
  for (size_t i = 0; i < root->child.size(); i++)
   clearTree(root->child[i]);
  delete root;
  root = nullptr;
 }
}
void move(COORD point)
{
 if (map[point.X][point.Y] == FOOD)
 {
  score++;
  snack.push_back(point);
  map[snack[0].X][snack[0].Y] = BODY;
  for (int i = snack.size() - 1; i > 0; i--)
  {
   snack[i].X = snack[i - 1].X;
   snack[i].Y = snack[i - 1].Y;
  }
  snack[0] = point;
  map[snack[0].X][snack[0].Y] = HEAD;
  drawMap();
  Sleep(100); //睡眠0.1s,不然吃的太快了
 }
 else if (map[point.X][point.Y] == SPACE)
 {
  map[snack[snack.size() - 1].X][snack[snack.size() - 1].Y] = SPACE;
  map[snack[0].X][snack[0].Y] = BODY;
  for (int i = snack.size() - 1; i > 0; i--)
  {
   snack[i].X = snack[i - 1].X;
   snack[i].Y = snack[i - 1].Y;
  }
  snack[0] = point;
  map[snack[0].X][snack[0].Y] = HEAD;
 } 
 drawMap();
 Sleep(10);
}
bool isMove(PathDate arr[][MAP_COL], COORD pos)
{
 if (pos.X >= 0 && pos.Y >= 0 && pos.X < MAP_ROW&&pos.Y < MAP_COL)
 {
  if (arr[pos.X][pos.Y].isFind == false && arr[pos.X][pos.Y].val == SPACE)
  {
   return true;
  }
  else if (arr[pos.X][pos.Y].val == FOOD || arr[pos.X][pos.Y].val == HEAD)
  {
   return true;
  } 
 }
 return false;
}
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-05-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 编程学习基地 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 正文
    • 01 背景
    相关产品与服务
    图像处理
    图像处理基于腾讯云深度学习等人工智能技术,提供综合性的图像优化处理服务,包括图像质量评估、图像清晰度增强、图像智能裁剪等。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档