好久了,久到我都忘了我是怎么走过来的了...
设计的人工智能贪吃蛇是我初学寻路算法的时候胡乱捣鼓改的贪吃蛇代码,主要思路就是通过广度寻路算法,查找蛇头和食物之间是否有路,从而达到自动寻找食物的目的。
某次小学妹要做贪吃蛇的课题大作业,问我要贪吃蛇的代码我才想起还有个半成品的人工智能贪吃蛇。
向下滑动查看
当时奇思妙想的半成品,深度寻路算法学过数据结构都应该知道原理,就是实现的问题,如果没有需求我应该不会继续完善这个半成品了,吃力不讨好,要是谁能完善下就好了。
另外这是一个半成品,不是残次品,VS,VC6.0装Easyx能跑通的,可能就是这条蛇比较蠢,容易迷路...
此外,代码使用需谨慎,我加Sleep睡眠是有原因的,不要瞎改,出现任何无厘头状况一概与我无关...
代码如下: 或者发送关键字【人工智能贪吃蛇】获取
#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;
}