贪吃蛇智能版(初级)
来源:互联网 发布:淘宝的折扣价怎么设置 编辑:程序博客网 时间:2024/06/10 02:51
说明:
贪吃蛇智能版(初级),在上一篇文章《C语言+easyX界面库实现贪吃蛇》的基础上,增加了智能模式的实现。
初级版本,主要是利用了广度寻路算法,能够搜索出一条从蛇头到目标食物点的一条可行的最短的路径,并且在蛇运动的过程当中,实时的调整这一条可行路径。吃食物的策略是优先吃大食物,然后吃小食物,因为大食物分数多,如果不吃,过一会就会消失,下面参考具体代码:
PS:如果有设计和思路上面的问题,请参考贪吃蛇系统中,我的另外一篇文章
文章链接( 贪吃蛇系列开篇—-设计智能贪吃蛇小游戏):
http://blog.csdn.net/yi_ming_he/article/details/72050888
easysnake.h
#pragma once#include <stdio.h>#include <graphics.h>#include <windows.h>#include <mmsystem.h>#include <time.h>#include <conio.h>#include <queue>#include "resource.h"#pragma comment(lib, "winmm.lib")#define SNAKE_DRAW_SIZE 15#define WND_WIDTH 1000#define WND_HEIGHT 600#define REGION_WIDTH 600#define REGION_HEIGHT 600#define RIGHT_EDGE_WIDTH 10#define HEADLINE_POSX 265#define HEADLINE_POSY 120#define TEXT_TIME_POSX 670#define TEXT_TIME_POSY 100#define TEXT_LEVEL_POSX 670#define TEXT_LEVEL_POSY 100#define TEXT_SCORE_POSX 670#define TEXT_SCORE_POSY 200#define TEXT_LEN_POSX 670#define TEXT_LEN_POSY 300#define TEXT_HIGHSCORE_POSX 670#define TEXT_HIGHSCORE_POSY 400#define TEXT_HIGHLEVEL_POSX 670#define TEXT_HIGHLEVEL_POSY 500#define SNAKE_INIT_PT_X (REGION_WIDTH / SNAKE_DRAW_SIZE / 5)#define SNAKE_INIT_PT_Y (REGION_HEIGHT / SNAKE_DRAW_SIZE / 2)#define FIRST_ITEM_POSX 375#define FIRST_ITEM_POSY 250#define FIRST_ITEM_WIDTH 220#define FIRST_ITEM_HEIGHT 30#define SECOND_ITEM_POSX 375#define SECOND_ITEM_POSY 350#define SECOND_ITEM_WIDTH 220#define SECOND_ITEM_HEIGHT 30#define THIRD_ITEM_POSX 375#define THIRD_ITEM_POSY 450#define THIRD_ITEM_WIDTH 220#define THIRD_ITEM_HEIGHT 30#define BIGFOOD_SHOWTIME 6000#define BIGFOOD_STEPTIME 100#define FOOD_SCORE 1#define BIG_FOOD_SCORE 5#define INIT_SPEED 110#define MINUS_SPEED 10#define TOTAL_TIME 100#define SNAKE_MAX ((REGION_WIDTH / SNAKE_DRAW_SIZE) * (REGION_HEIGHT / SNAKE_DRAW_SIZE))#define BREAKTHROUGHAPPNAME L"BreakThrough"#define BREAKTHROUGHSCORE L"HighScore"#define BREAKTHROUGHLEVEL L"HighLevel"#define TIMELIMITEDAPPNAME L"TimeLimited"#define TIMELIMITEDSCORE L"HighScore"#define AIAPPNAME L"Intelligence"#define AISCORE L"HighScore"#define AILEVEL L"HighLevel"int arrScore[] = { 0, 8, 16, 24, 32, 40, 48, 60, 72, 85, 95, 118, 130, 155, 170, 190, 210, 230, 250, 270, 300, 350, 400,460, 500, 550, 600, 650, 700, 750, 810, 880, 950, 1000, 1100,1250, 1400, 1600, 1850, 2100, 2400, 2700, 3000, 3400, 3800, 4200, 4600, 5000,5500, 5900, 6300, 6800, 7500, 8000, 8500, 9000, 9500, 10000 };enum EmPattern{ emBreakThroughPattern = 1, emTimeLimitedPattern, emIntelligencePattern,};enum EmStage{ emChooseStage = 1, emPlayStage,};enum EmDir{ emDirUp = 72, emDirDown = 80, emDirLeft = 75, emDirRight = 77,};struct Point{ int x; int y;};struct Snake{ int nCount; Point pt[SNAKE_MAX]; EmDir dir;};struct Food{ Point fpt; char isEat;};struct BigFood{ Point fpt; char isEat;};bool mp[REGION_WIDTH / SNAKE_DRAW_SIZE + 1][REGION_HEIGHT / SNAKE_DRAW_SIZE + 1];//存放地图标记bool isVisit[REGION_WIDTH / SNAKE_DRAW_SIZE + 1][REGION_HEIGHT / SNAKE_DRAW_SIZE + 1];//存放访问标记Point parent[REGION_WIDTH / SNAKE_DRAW_SIZE + 1][REGION_HEIGHT / SNAKE_DRAW_SIZE + 1];//存放父节点指向std::queue<Point>tempQ;//存放搜索过程中的节点std::queue<Point>pathQ;//存放路径节点int search_dir[4][2] = { { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 } };EmStage stage = EmStage::emChooseStage;EmPattern pattern = EmPattern::emBreakThroughPattern;Snake snake;Food food;BigFood bigFood;bool bUserInput = false;int nBigFoodTimer = 0;int nCurLevel = 1;int nCurScore = 0;int nSnakeLen = 3;int nHighLevel = 0;int nHighScore = 0;int nCurSpeed = INIT_SPEED;int nRemainTime = TOTAL_TIME;int nTimePast = 0;void SetMouseNormal();void SetMouseHand();void SetLevelText();void SetHoverStyle();void SetNormalStyle();void TackleMouseMove(int x, int y);void TackleLeftButtonDown(int x, int y);void TackleMouseAction();void InitFirstScene();void InitSecondBackGround();void InitSecondScene();bool SearchSnakePath(Point startPt, Point endPt);void InitMap();void GameInit();void PlayGame();int IsFoodPosOk(int x, int y, Point endPt);void ProduceFood();void DrawFood();int ProduceBigFood();void DrawBigFood();int IsEatBigFood();void EatFood();void LevelUp();void DrawSnake();void AIChangeDir();void AIRealChangeDirection();bool AISearchBigFood();bool AISearchSmallFood();void SnakeMove();void ChangeDir();void BreakSnake();void WriteRecord();void BigFoodDisappear();void TimeEclipse();void DecideHeadDirection();void DrawSnakeHead(int nIndex);void DecideCornerDirection(int idx);void DrawCorner(int nIndex, int idx);void DecideBodyDirection(int idx);void DrawBody(int nIndex, int idx);void DecideTailDirection(int idx);void DrawTail(int nIndex, int idx);void BreakThroughPattern();void TimeLimitedPattern();
easysnake.cpp
#include "easysnake.h"BOOL KExpandEnvironmentString(IN LPCTSTR lpEnvironmentString, OUT LPTSTR lpExpandString, IN ULONG ulExpandStringLength){ BOOL bResult = FALSE; LPTSTR lpBuffer = NULL; ULONG ulRetLength = 0; if (!lpEnvironmentString || !lpExpandString || 1 > ulExpandStringLength) { goto _abort; } ulRetLength = ::ExpandEnvironmentStrings(lpEnvironmentString, NULL, 0); if (1 > ulRetLength || ulRetLength > ulExpandStringLength - 1) { goto _abort; } __try { lpBuffer = new TCHAR[ulRetLength]; if (!lpBuffer) { goto _abort; } ::RtlZeroMemory(lpBuffer, sizeof(TCHAR)* ulRetLength); ulRetLength = ::ExpandEnvironmentStrings(lpEnvironmentString, lpBuffer, ulRetLength); if (ulRetLength && ulRetLength <= ulExpandStringLength - 1) { _tcsncpy_s(lpExpandString, ulExpandStringLength - 1, lpBuffer, ulRetLength); bResult = TRUE; } } __except (EXCEPTION_EXECUTE_HANDLER) { bResult = FALSE; }_abort: if (lpBuffer) { delete[] lpBuffer; lpBuffer = NULL; } return bResult;}void SetMouseNormal(){ HCURSOR hcur = LoadCursor(NULL, IDC_ARROW); HWND hwnd = GetHWnd(); SetClassLong(hwnd, GCL_HCURSOR, (long)hcur);}void SetMouseHand(){ HCURSOR hcur = LoadCursor(NULL, MAKEINTRESOURCE(32649)); HWND hwnd = GetHWnd(); SetClassLong(hwnd, GCL_HCURSOR, (long)hcur);}void SetLevelText(){ switch (pattern) { case EmPattern::emBreakThroughPattern: outtextxy(FIRST_ITEM_POSX, FIRST_ITEM_POSY, L"闯关模式"); break; case EmPattern::emTimeLimitedPattern: outtextxy(SECOND_ITEM_POSX, SECOND_ITEM_POSY, L"限时模式"); break; case EmPattern::emIntelligencePattern: outtextxy(THIRD_ITEM_POSX, THIRD_ITEM_POSY, L"智能模式"); break; default: break; }}void SetHoverStyle(){ settextcolor(RGB(255, 0, 119)); SetLevelText(); SetMouseHand();}void SetNormalStyle(){ settextcolor(BROWN); SetLevelText(); SetMouseNormal();}void TackleMouseMove(int x, int y){ if (stage == EmStage::emPlayStage) return; if (x > FIRST_ITEM_POSX && x < FIRST_ITEM_POSX + FIRST_ITEM_WIDTH && y >FIRST_ITEM_POSY && y < FIRST_ITEM_POSY + FIRST_ITEM_HEIGHT) { pattern = EmPattern::emBreakThroughPattern; SetHoverStyle(); return; } else { pattern = EmPattern::emBreakThroughPattern; SetNormalStyle(); } if (x > SECOND_ITEM_POSX && x < SECOND_ITEM_POSX + SECOND_ITEM_WIDTH && y > SECOND_ITEM_POSY && y < SECOND_ITEM_POSY + SECOND_ITEM_HEIGHT) { pattern = EmPattern::emTimeLimitedPattern; SetHoverStyle(); return; } else { pattern = EmPattern::emTimeLimitedPattern; SetNormalStyle(); } if (x > THIRD_ITEM_POSX && x < THIRD_ITEM_POSX + THIRD_ITEM_WIDTH && y > THIRD_ITEM_POSY && y < THIRD_ITEM_POSY + THIRD_ITEM_HEIGHT) { pattern = EmPattern::emIntelligencePattern; SetHoverStyle(); } else { pattern = EmPattern::emIntelligencePattern; SetNormalStyle(); }}void TimeLimitedPattern(){ settextstyle(20, 20, L"楷体", 0, 0, 900, 0, 0, 0); setbkmode(TRANSPARENT); settextcolor(RGB(255, 0, 0)); WCHAR szCurRemainTime[32]; WCHAR szCurScore[32]; WCHAR szSnakeLen[32]; WCHAR szHighScore[32]; swprintf_s(szCurRemainTime, L"剩余时间: %d", nRemainTime); swprintf_s(szCurScore, L"当前得分: %d", nCurScore); swprintf_s(szSnakeLen, L"蛇身长度: %d", snake.nCount); swprintf_s(szHighScore, L"最高分数: %d", nHighScore); outtextxy(TEXT_TIME_POSX, TEXT_TIME_POSY, szCurRemainTime); outtextxy(TEXT_SCORE_POSX, TEXT_SCORE_POSY, szCurScore); outtextxy(TEXT_LEN_POSX, TEXT_LEN_POSY, szSnakeLen); outtextxy(TEXT_HIGHSCORE_POSX, TEXT_HIGHSCORE_POSY, szHighScore);}void BreakThroughPattern(){ settextstyle(20, 20, L"楷体", 0, 0, 900, 0, 0, 0); setbkmode(TRANSPARENT); settextcolor(RGB(255, 0, 0)); WCHAR szCurLevel[32]; WCHAR szCurScore[32]; WCHAR szSnakeLen[32]; WCHAR szHighLevel[32]; WCHAR szHighScore[32]; swprintf_s(szCurLevel, L"当前级别: %d", nCurLevel); swprintf_s(szCurScore, L"当前得分: %d", nCurScore); swprintf_s(szSnakeLen, L"蛇身长度: %d", snake.nCount); swprintf_s(szHighLevel, L"最高级别: %d", nHighLevel); swprintf_s(szHighScore, L"最高分数: %d", nHighScore); outtextxy(TEXT_LEVEL_POSX, TEXT_LEVEL_POSY, szCurLevel); outtextxy(TEXT_SCORE_POSX, TEXT_SCORE_POSY, szCurScore); outtextxy(TEXT_LEN_POSX, TEXT_LEN_POSY, szSnakeLen); outtextxy(TEXT_HIGHSCORE_POSX, TEXT_HIGHSCORE_POSY, szHighLevel); outtextxy(TEXT_HIGHLEVEL_POSX, TEXT_HIGHLEVEL_POSY, szHighScore);}void TackleLeftButtonDown(int x, int y){ if (x > FIRST_ITEM_POSX && x < FIRST_ITEM_POSX + FIRST_ITEM_WIDTH && y >FIRST_ITEM_POSY && y < FIRST_ITEM_POSY + FIRST_ITEM_HEIGHT) { pattern = EmPattern::emBreakThroughPattern; InitSecondScene(); } if (x > SECOND_ITEM_POSX && x < SECOND_ITEM_POSX + SECOND_ITEM_WIDTH && y > SECOND_ITEM_POSY && y < SECOND_ITEM_POSY + SECOND_ITEM_HEIGHT) { pattern = EmPattern::emTimeLimitedPattern; InitSecondScene(); } if (x > THIRD_ITEM_POSX && x < THIRD_ITEM_POSX + THIRD_ITEM_WIDTH && y > THIRD_ITEM_POSY && y < THIRD_ITEM_POSY + THIRD_ITEM_HEIGHT) { pattern = EmPattern::emIntelligencePattern; InitSecondScene(); }}void TackleMouseAction(){ MOUSEMSG msg; while (1) { msg = GetMouseMsg();//获取鼠标信息 switch (msg.uMsg) { case WM_LBUTTONDOWN://处理鼠标的左键点击消息 TackleLeftButtonDown(msg.x, msg.y); break; case WM_MOUSEMOVE://处理鼠标的左键点击消息 TackleMouseMove(msg.x, msg.y); break; default: break; } }}void InitFirstScene(){ cleardevice(); stage = EmStage::emChooseStage; IMAGE img; for (int i = 0; i < 22; i++) { loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG1), SNAKE_DRAW_SIZE * 3, SNAKE_DRAW_SIZE * 3); putimage(4 + SNAKE_DRAW_SIZE * 3 * i, 0, &img); } settextstyle(38, 38, L"楷体", 0, 0, 1000, 0, 0, 0); setbkmode(TRANSPARENT); settextcolor(RGB(255, 0, 0)); outtextxy(HEADLINE_POSX, HEADLINE_POSY, L"贪吃蛇大作战"); settextstyle(28, 28, L"楷体", 0, 0, 1000, 0, 0, 0); setbkmode(TRANSPARENT); pattern = EmPattern::emBreakThroughPattern; SetNormalStyle(); pattern = EmPattern::emTimeLimitedPattern; SetNormalStyle(); pattern = EmPattern::emIntelligencePattern; SetNormalStyle(); pattern = EmPattern::emBreakThroughPattern; TackleMouseAction();}void InitSecondBackGround(){ setlinecolor(RED); setlinestyle(PS_SOLID, RIGHT_EDGE_WIDTH); line(REGION_WIDTH + 4, 0, REGION_WIDTH + 4, REGION_HEIGHT); if (EmPattern::emBreakThroughPattern == pattern) BreakThroughPattern(); else if (EmPattern::emTimeLimitedPattern == pattern) TimeLimitedPattern(); else if (EmPattern::emIntelligencePattern == pattern) BreakThroughPattern();}void InitSecondScene(){ cleardevice(); stage = EmStage::emPlayStage; GameInit(); InitSecondBackGround(); PlayGame();}bool IsSearchPointOk(int x, int y, Point endPt){ if (x < 0 || x > REGION_WIDTH / SNAKE_DRAW_SIZE - 1 || y < 0 || y > REGION_HEIGHT / SNAKE_DRAW_SIZE - 1) return false; if (isVisit[x][y]) return false; if (mp[x][y] && (x != endPt.x || y != endPt.y)) return false; return true;}void PushPath(Point startPt, Point endPt){ if (endPt.x != startPt.x || endPt.y != startPt.y) { PushPath(startPt, parent[endPt.x][endPt.y]); pathQ.push(endPt); }}bool SearchSnakePath(Point startPt, Point endPt){ while (!pathQ.empty()) pathQ.pop(); while (!tempQ.empty()) tempQ.pop(); tempQ.push(startPt); isVisit[startPt.x][startPt.y] = true; Point nextPoint; while (!tempQ.empty()) { Point firstPoint = tempQ.front(); tempQ.pop(); if (firstPoint.x == endPt.x && firstPoint.y == endPt.y) return true; for (int i = 0; i < 4; i++) { nextPoint.x = firstPoint.x + search_dir[i][0]; nextPoint.y = firstPoint.y + search_dir[i][1]; if (IsSearchPointOk(nextPoint.x, nextPoint.y, endPt)) { isVisit[nextPoint.x][nextPoint.y] = true; tempQ.push(nextPoint); parent[nextPoint.x][nextPoint.y].x = firstPoint.x; parent[nextPoint.x][nextPoint.y].y = firstPoint.y; } } } return false;}void InitMap(){ memset(mp, false, sizeof(mp)); //把地图标记还原 memset(isVisit, false, sizeof(isVisit)); for (int i = 0; i < snake.nCount; i++) mp[snake.pt[i].x][snake.pt[i].y] = true; for (int i = 0; i < REGION_WIDTH / SNAKE_DRAW_SIZE; i++) { for (int j = 0; j < REGION_HEIGHT / SNAKE_DRAW_SIZE; j++) { parent[i][j].x = -1; parent[i][j].y = -1; } }}void GameInit(){ snake.dir = EmDir::emDirRight; snake.nCount = 3; for (int i = 0; i < snake.nCount; i++) { snake.pt[i].x = SNAKE_INIT_PT_X - i; snake.pt[i].y = SNAKE_INIT_PT_Y; } food.isEat = 1; bigFood.isEat = 1; nBigFoodTimer = 0; InitMap();//初始化地图标记 WCHAR szTempPath[MAX_PATH] = { 0 }; WCHAR szIniPath[MAX_PATH] = { 0 }; KExpandEnvironmentString(L"%TEMP%", szTempPath, MAX_PATH); swprintf_s(szIniPath, L"%s\\record.ini", szTempPath); nCurSpeed = INIT_SPEED; nCurLevel = 1; nCurScore = 0; nSnakeLen = 3; nRemainTime = TOTAL_TIME; nTimePast = 0; if (pattern == EmPattern::emTimeLimitedPattern) nHighScore = ::GetPrivateProfileInt(TIMELIMITEDAPPNAME, TIMELIMITEDSCORE, 0, szIniPath); else if (pattern == EmPattern::emBreakThroughPattern) { nHighScore = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHSCORE, 0, szIniPath); nHighLevel = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHLEVEL, 1, szIniPath); } else if (pattern == EmPattern::emIntelligencePattern) { nHighScore = ::GetPrivateProfileInt(AIAPPNAME, AISCORE, 0, szIniPath); nHighLevel = ::GetPrivateProfileInt(AIAPPNAME, AILEVEL, 1, szIniPath); }}void PlayGame(){ while (1) { while (!_kbhit()) { ProduceFood(); BigFoodDisappear(); TimeEclipse(); BeginBatchDraw(); cleardevice(); InitSecondBackGround(); DrawFood(); DrawBigFood(); EatFood(); ProduceFood(); SnakeMove(); DrawSnake(); Sleep(nCurSpeed); EndBatchDraw(); BreakSnake(); } ChangeDir(); }}void TimeEclipse(){ if (pattern != EmPattern::emTimeLimitedPattern) return; nTimePast += nCurSpeed; nRemainTime = TOTAL_TIME - nTimePast / 1000; nCurSpeed = INIT_SPEED - nTimePast / 1000; if (nRemainTime < 0) { WCHAR szScore[32] = { 0 }; swprintf_s(szScore, L"你的得分是: %d", nCurScore); ::MessageBox(0, szScore, L"时间到", 0); WriteRecord(); InitFirstScene(); }}void BigFoodDisappear(){ if (1 == bigFood.isEat) return; nBigFoodTimer += BIGFOOD_STEPTIME;//大食物定时消失 if (nBigFoodTimer >= BIGFOOD_SHOWTIME) { bigFood.isEat = 1; nBigFoodTimer = 0; }}void WriteRecord(){ WCHAR szTempPath[MAX_PATH] = { 0 }; WCHAR szIniPath[MAX_PATH] = { 0 }; WCHAR szHighScore[8] = { 0 }; WCHAR szHighLevel[8] = { 0 }; KExpandEnvironmentString(L"%TEMP%", szTempPath, MAX_PATH); swprintf_s(szIniPath, L"%s\\record.ini", szTempPath); if (pattern == EmPattern::emBreakThroughPattern) { nHighLevel = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHLEVEL, 1, szIniPath); nHighScore = ::GetPrivateProfileInt(BREAKTHROUGHAPPNAME, BREAKTHROUGHSCORE, 0, szIniPath); if (nCurScore > nHighScore) { swprintf_s(szHighScore, L"%d", nCurScore); WritePrivateProfileString(BREAKTHROUGHAPPNAME, BREAKTHROUGHSCORE, szHighScore, szIniPath); } if (nCurLevel > nHighLevel) { swprintf_s(szHighLevel, L"%d", nCurLevel); WritePrivateProfileString(BREAKTHROUGHAPPNAME, BREAKTHROUGHLEVEL, szHighLevel, szIniPath); } } else if (pattern == EmPattern::emTimeLimitedPattern) { nHighScore = ::GetPrivateProfileInt(TIMELIMITEDAPPNAME, TIMELIMITEDSCORE, 0, szIniPath); if (nCurScore > nHighScore) { swprintf_s(szHighScore, L"%d", nCurScore); WritePrivateProfileString(TIMELIMITEDAPPNAME, TIMELIMITEDSCORE, szHighScore, szIniPath); } } else if (pattern == EmPattern::emIntelligencePattern) { nHighLevel = ::GetPrivateProfileInt(AIAPPNAME, AILEVEL, 1, szIniPath); nHighScore = ::GetPrivateProfileInt(AIAPPNAME, AISCORE, 0, szIniPath); if (nCurScore > nHighScore) { swprintf_s(szHighScore, L"%d", nCurScore); WritePrivateProfileString(AIAPPNAME, AISCORE, szHighScore, szIniPath); } if (nCurLevel > nHighLevel) { swprintf_s(szHighLevel, L"%d", nCurLevel); WritePrivateProfileString(AIAPPNAME, AILEVEL, szHighLevel, szIniPath); } }}void BreakSnake(){ if (snake.pt[0].x < 0 || snake.pt[0].x > REGION_WIDTH / SNAKE_DRAW_SIZE - 1 || snake.pt[0].y < 0 || snake.pt[0].y > REGION_HEIGHT / SNAKE_DRAW_SIZE - 1) { ::MessageBox(0, L"你撞墙了", L"游戏失败", 0); WriteRecord(); InitFirstScene(); } for (int i = snake.nCount - 2; i > 0; i--) { if (snake.pt[i].x == snake.pt[0].x && snake.pt[i].y == snake.pt[0].y) { ::MessageBox(0, L"你咬到尾巴了", L"游戏失败", 0); WriteRecord(); InitFirstScene(); } }}void ChangeDir(){ int dir = _getch(); switch (dir) { case EmDir::emDirUp: bUserInput = true; if (snake.dir != EmDir::emDirDown) snake.dir = EmDir::emDirUp; break; case EmDir::emDirDown: bUserInput = true; if (snake.dir != EmDir::emDirUp) snake.dir = EmDir::emDirDown; break; case EmDir::emDirLeft: bUserInput = true; if (snake.dir != EmDir::emDirRight) snake.dir = EmDir::emDirLeft; break; case EmDir::emDirRight: bUserInput = true; if (snake.dir != EmDir::emDirLeft) snake.dir = EmDir::emDirRight; break; default: break; }}void AIRealChangeDirection(){ Point pt = pathQ.front(); pathQ.pop(); if (pt.x == snake.pt[0].x) { if (pt.y - snake.pt[0].y == -1) snake.dir = EmDir::emDirUp; else if (pt.y - snake.pt[0].y == 1) snake.dir = EmDir::emDirDown; } else if (pt.y == snake.pt[0].y) { if (pt.x - snake.pt[0].x == -1) snake.dir = EmDir::emDirLeft; else if (pt.x - snake.pt[0].x == 1) snake.dir = EmDir::emDirRight; }}bool AISearchBigFood(){ if (bigFood.isEat) return false; InitMap(); if (!SearchSnakePath(snake.pt[0], bigFood.fpt)) return false; PushPath(snake.pt[0], bigFood.fpt); AIRealChangeDirection(); return true;}bool AISearchSmallFood(){ InitMap(); if (!SearchSnakePath(snake.pt[0], food.fpt)) return false; PushPath(snake.pt[0], food.fpt); AIRealChangeDirection(); return true;}void AIChangeDir(){ if (pattern != EmPattern::emIntelligencePattern) return; if (bUserInput) return; if (AISearchBigFood()) return; if (AISearchSmallFood()) return;}void SnakeMove(){ for (int i = snake.nCount; i > 0; i--) { snake.pt[i].x = snake.pt[i - 1].x; snake.pt[i].y = snake.pt[i - 1].y; } AIChangeDir(); switch (snake.dir) { case EmDir::emDirUp: snake.pt[0].y--; break; case EmDir::emDirDown: snake.pt[0].y++; break; case EmDir::emDirLeft: snake.pt[0].x--; break; case EmDir::emDirRight: snake.pt[0].x++; break; default: break; } bUserInput = false;}void DecideHeadDirection(){ if (snake.pt[0].y == snake.pt[1].y && snake.pt[0].x > snake.pt[1].x)//头往右走 DrawSnakeHead(0); else if (snake.pt[0].y == snake.pt[1].y && snake.pt[0].x < snake.pt[1].x)//头往左走 DrawSnakeHead(1); else if (snake.pt[0].x == snake.pt[1].x && snake.pt[0].y < snake.pt[1].y)//头往上走 DrawSnakeHead(2); else if (snake.pt[0].x == snake.pt[1].x && snake.pt[0].y > snake.pt[1].y)//头往下走 DrawSnakeHead(3);}void DrawSnakeHead(int nIndex){ IMAGE img; loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG2 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE); putimage(snake.pt[0].x * SNAKE_DRAW_SIZE, snake.pt[0].y * SNAKE_DRAW_SIZE, &img);}void DecideCornerDirection(int idx){ if (snake.pt[idx].y > snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x > snake.pt[idx + 1].x) DrawCorner(0, idx);//右->上 else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x > snake.pt[idx - 1].x && snake.pt[idx].y > snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x) DrawCorner(0, idx);//下->左 else if (snake.pt[idx].y > snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x < snake.pt[idx + 1].x) DrawCorner(1, idx);//左->上 else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x < snake.pt[idx - 1].x && snake.pt[idx].y > snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x) DrawCorner(1, idx);//下->右 else if (snake.pt[idx].y < snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x > snake.pt[idx + 1].x) DrawCorner(2, idx);//右->下 else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x > snake.pt[idx - 1].x && snake.pt[idx].y < snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x) DrawCorner(2, idx);//上->左 else if (snake.pt[idx].y < snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x && snake.pt[idx].y == snake.pt[idx + 1].y && snake.pt[idx].x < snake.pt[idx + 1].x) DrawCorner(3, idx);//左->下 else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x < snake.pt[idx - 1].x && snake.pt[idx].y < snake.pt[idx + 1].y && snake.pt[idx].x == snake.pt[idx + 1].x) DrawCorner(3, idx);//上->右 else DecideBodyDirection(idx);//不是corner的情况在考虑body}void DrawCorner(int nIndex, int idx){ IMAGE img; loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG6 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE); putimage(snake.pt[idx].x * SNAKE_DRAW_SIZE, snake.pt[idx].y * SNAKE_DRAW_SIZE, &img);}void DecideBodyDirection(int idx){ if (snake.pt[idx].x == snake.pt[idx - 1].x || snake.pt[idx].x == snake.pt[idx + 1].x)//上下 DrawBody(0, idx); else if (snake.pt[idx].y == snake.pt[idx - 1].y || snake.pt[idx].y == snake.pt[idx + 1].y)//左右 DrawBody(1, idx);}void DrawBody(int nIndex, int idx){ IMAGE img; loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG10 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE); putimage(snake.pt[idx].x * SNAKE_DRAW_SIZE, snake.pt[idx].y * SNAKE_DRAW_SIZE, &img);}void DecideTailDirection(){ int idx = snake.nCount - 1; if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x < snake.pt[idx - 1].x)//往右 DrawTail(0, idx); else if (snake.pt[idx].y == snake.pt[idx - 1].y && snake.pt[idx].x > snake.pt[idx - 1].x)//往左 DrawTail(1, idx); else if (snake.pt[idx].y > snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x)//往上 DrawTail(2, idx); else if (snake.pt[idx].y < snake.pt[idx - 1].y && snake.pt[idx].x == snake.pt[idx - 1].x)//往下 DrawTail(3, idx);}void DrawTail(int nIndex, int idx){ IMAGE img; loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG12 + nIndex), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE); putimage(snake.pt[idx].x * SNAKE_DRAW_SIZE, snake.pt[idx].y * SNAKE_DRAW_SIZE, &img);}void DrawSnake(){ for (int i = 0; i < snake.nCount; i++) { if (0 == i) DecideHeadDirection(); else if (i == snake.nCount - 1) DecideTailDirection(); else DecideCornerDirection(i); }}int IsEatBigFood(){ if (1 == bigFood.isEat) return 0; for (int i = bigFood.fpt.x; i < bigFood.fpt.x + 3; i++) { for (int j = bigFood.fpt.y; j < bigFood.fpt.y + 3; j++) { if (snake.pt[0].x == i && snake.pt[0].y == j) return 1; } } return 0;}void LevelUp(){ if (pattern == EmPattern::emTimeLimitedPattern) return; //WCHAR szLevelUp[32]; if (nCurScore > arrScore[nCurLevel]) { //swprintf_s(szLevelUp, L"恭喜你,升到第%d级", nCurLevel + 1); //::MessageBox(0, szLevelUp, L"升级啦", 0); nCurLevel++; if (nCurSpeed > 0) nCurSpeed -= MINUS_SPEED; }}void EatFood(){ if (snake.pt[0].x == food.fpt.x && snake.pt[0].y == food.fpt.y) { nCurScore += FOOD_SCORE; snake.nCount++; food.isEat = 1; ProduceBigFood(); } if (IsEatBigFood()) { nCurScore += BIG_FOOD_SCORE; snake.nCount++; bigFood.isEat = 1; } LevelUp();}int IsFoodPosOk(int x, int y){ for (int i = 0; i < snake.nCount; i++) { if (snake.pt[i].x == x && snake.pt[i].y == y) return 0; } if (0 == bigFood.isEat) { for (int i = bigFood.fpt.x; i < bigFood.fpt.x + 3; i++) { for (int j = bigFood.fpt.y; j < bigFood.fpt.y + 3; j++) { if (x == i && y == j) return 0; } } } return 1;}int IsBigFoodPosOk(int x, int y){ for (int i = x; i < x + 3; i++) { for (int j = y; j < y + 3; j++) { if (i < 0 || i > REGION_WIDTH / SNAKE_DRAW_SIZE - 1 || j < 0 || j > REGION_HEIGHT / SNAKE_DRAW_SIZE - 1) return 0; for (int k = 0; k < snake.nCount; k++) { if (snake.pt[k].x == i && snake.pt[k].y == j) return 0; } } } return 1;}void ProduceFood(){ if (0 == food.isEat) return; while (1) { food.fpt.x = rand() % (REGION_WIDTH / SNAKE_DRAW_SIZE); food.fpt.y = rand() % (REGION_HEIGHT / SNAKE_DRAW_SIZE); if (IsFoodPosOk(food.fpt.x, food.fpt.y)) break; } food.isEat = 0;}void DrawFood(){ IMAGE img; loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG1), SNAKE_DRAW_SIZE, SNAKE_DRAW_SIZE); putimage(food.fpt.x * SNAKE_DRAW_SIZE, food.fpt.y * SNAKE_DRAW_SIZE, &img);}int ProduceBigFood(){ if (0 == bigFood.isEat)//大食物没被吃掉,不产生 return 0; if (rand() % 2 == 0) { while (1) { bigFood.fpt.x = rand() % (REGION_WIDTH / SNAKE_DRAW_SIZE); bigFood.fpt.y = rand() % (REGION_HEIGHT / SNAKE_DRAW_SIZE); if (IsBigFoodPosOk(bigFood.fpt.x, bigFood.fpt.y)) break; } bigFood.isEat = 0; return 1; } return 0;}void DrawBigFood(){ if (1 == bigFood.isEat) return; IMAGE img; loadimage(&img, L"jpg", MAKEINTRESOURCE(IDR_JPG1), SNAKE_DRAW_SIZE * 3, SNAKE_DRAW_SIZE * 3); putimage(bigFood.fpt.x * SNAKE_DRAW_SIZE, bigFood.fpt.y * SNAKE_DRAW_SIZE, &img);}int main(){ HWND hWnd = GetConsoleWindow(); SendMessage(hWnd, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_ICON1))); initgraph(WND_WIDTH, WND_HEIGHT); srand((unsigned int)time(NULL)); InitFirstScene(); getchar(); closegraph(); return 0;}
运行结果:
4 0
- 贪吃蛇智能版(初级)
- 贪吃蛇智能版(中级)
- 贪吃蛇智能版(高级)
- 贪吃蛇智能版(专家)
- 初级贪吃蛇-霍氏贪吃蛇1.2版
- 初级贪吃蛇
- “智能”贪吃蛇
- 智能贪吃蛇
- 智能寻路贪吃蛇系列之 初级BFS寻路算法
- 贪吃蛇之智能蛇
- 智能贪吃蛇设计算法
- 贪吃蛇系列终章----贪吃蛇专家智能bug修复版
- 智能寻路贪吃蛇系列之 简单贪吃蛇的MFC实现(上)
- 智能寻路贪吃蛇系列之 简单贪吃蛇的MFC实现(下)
- 贪吃蛇系列开篇----设计智能贪吃蛇小游戏
- 贪吃蛇的进阶——智能贪吃蛇
- 边改边做模型设计智能贪吃蛇
- 贪吃蛇(字符版)
- “音之国度”界面分析(二)
- YouCompleteMe+anaconda+vim8.0自动补全
- c语言关键字
- 对LSTMStateTuple的理解
- 极大似然估计
- 贪吃蛇智能版(初级)
- 小白题解 Codeforces 807A Is it rated?
- 队列(数组描述)
- GPIO学习笔记1
- access c++ mfc使用
- 面向对象的编程
- BZOJ 1002: [FJOI2007]轮状病毒
- (项目)AR电子书系统创新实训第一周(1)
- 线性表的基本操作实现