一、游戲說明
本游戲仿造 4399 的小游戲-圍住神經(jīng)貓。
游戲操作:通過鼠標(biāo)點擊操作,設(shè)置路障,圍住神經(jīng)貓,當(dāng)成功圍住神經(jīng)貓時,游戲勝利。當(dāng)神經(jīng)貓?zhí)与x地圖邊緣,游戲失敗。
二、游戲截圖
三、實現(xiàn)思路
1. 地圖還原:
首先是游戲的道路,這里我們采用繪制灰白色的圓來表示可走的路,用黃色的圓來表示已存在的障礙物。同時還需要注意奇偶行需要交錯排列。
2.貓的移動:
這里我們采用廣度優(yōu)先搜索求最短路徑。"貓"在一個位置,能夠移動的方向有6個,需要注意的是:
由于奇偶行交替排列,導(dǎo)致奇偶行貓的可行路徑是不一樣的,奇數(shù)行:上,下,左,右,左下,左上。
偶數(shù)行:上,下,左,右,右下,右上。剩下的就是常規(guī)的求最短路徑即可。
注:代碼中所用圖片,請見文末
四、完整代碼
簡單了解游戲后我們就來試試吧!(直接上源碼,大家可以看注釋)
///////////////////////////////////////////////////////// // 程序名稱:圍住神經(jīng)貓 //編譯環(huán)境VisualStudio2019(C++語言標(biāo)準(zhǔn)選擇C++17),EasyX #include#include #include #include #include #pragma comment( lib, "MSIMG32.LIB") #define pix 50 // 像素比例 #define hight (14 * pix) #define width (10 * pix) using namespace std; int stepS; // 記錄已經(jīng)走的步數(shù) int startBarrier; // 開始的障礙物數(shù)目 wchar_t Score_[30]; MOUSEMSG m; // 鼠標(biāo)操作 IMAGE pig, bkimg;; // 加載圖片 enum class picture { none, barrier }; struct XY { int x, y; int lastX, lastY; //記錄上一個點的坐標(biāo) }cat; struct node { int x, y; //坐標(biāo),圓心位置 picture pic; //當(dāng)前位置的圖片內(nèi)容 }; node canvas[10][10]; // 地圖 bool visit[10][10]; // 記錄是否訪問過地圖中的元素 int path[10][10][2]; // 記錄上一個位置 //注意:因為地圖是交錯排列的,奇數(shù)列與偶數(shù)列貓的移動不同 int dirOdd[6][2]{ 1,0,-1,0,0,1,0,-1,-1,-1,-1,1 }; //控制方向奇數(shù)列 int dirEven[6][2]{ 1,0,-1,0,0,1,0,-1,1,-1,1,1 }; //控制方向偶數(shù)列 int main(); //貼圖函數(shù) void transparentimage(IMAGE* dstimg, int x, int y, IMAGE* srcimg,int direction) { HDC dstDC = GetImageHDC(dstimg); HDC srcDC = GetImageHDC(srcimg); int w = 50; int h = 100; // 使用 Windows GDI 函數(shù)實現(xiàn)透明位圖 if (direction == 0) TransparentBlt(dstDC, x, y, w, h, srcDC, 0, 0, w, h, 0); else TransparentBlt(dstDC, x, y, w, h, srcDC, 10, 187, w, h, 0); } //游戲初始化 void initial() { srand(time(0)); stepS = 0; startBarrier = rand() % 6 + 8; //障礙物數(shù)量 loadimage(&pig, L"pig.png"); loadimage(&bkimg, L"bkground.jpg", width, hight, true); initgraph(width, hight); HWND wnd = GetHWnd(); SetWindowText(wnd, L"圍住神經(jīng)貓");//設(shè)置文章標(biāo)題 for (int i = 1; i <= 9; ++i) for (int j = 1; j <= 9; ++j) { if (i & 1) //如果是奇數(shù)行 canvas[i][j] = node{ j * pix - pix / 4, pix * 4 + i * pix ,picture::none }; else canvas[i][j] = node{ j * pix + pix / 4, pix * 4 + i * pix ,picture::none }; } cat.x = 5; cat.y = 5; //貓最開始的地方 while (startBarrier--) { int bx, by; //設(shè)置初始障礙 do { bx = rand() % 10; by = rand() % 10; } while (canvas[by][bx].pic == picture::barrier || (by == cat.y && bx == cat.x)); canvas[by][bx].pic = picture::barrier; } setbkmode(TRANSPARENT); BeginBatchDraw(); } //繪制游戲畫面, 白色:空 黃色:障礙物 void show() { putimage(0, 0, &bkimg); setbkcolor(WHITE); settextstyle(20, 0, L"微軟雅黑"); outtextxy(200, 170, L"重玩"); outtextxy(250, 180, L"步數(shù): "); swprintf(Score_, 29, L"%d", stepS); outtextxy(290, 180, Score_); for (int i = 1; i <= 9; ++i) { for (int j = 1; j <= 9; ++j) { if (canvas[i][j].pic == picture::barrier) setfillcolor(YELLOW); else setfillcolor(LIGHTGRAY); solidcircle(canvas[i][j].x, canvas[i][j].y, (pix - 4) / 2); } } if (cat.y & 1) //奇數(shù)列 transparentimage(NULL, cat.x * pix - pix / 4 - 25, pix * 3 + cat.y * pix - 21, &pig,0); else //偶數(shù)列 transparentimage(NULL, cat.x * pix - 25 + pix / 4, pix * 3 + cat.y * pix - 21, &pig,1); FlushBatchDraw(); } //尋找下一個點的位置 struct LastOrder { int x, y; }; vector vec; void findNextXY(int x, int y) { if (x == cat.x && y == cat.y) { vec.push_back({ x,y }); return; } else { findNextXY(path[y][x][0], path[y][x][1]); vec.push_back({ x,y }); } } //利用廣度優(yōu)先搜索求最短路徑,xy為數(shù)組的i,j下標(biāo),注意傳參 void bfs(XY xy) { //每次搜索時初始化數(shù)組 memset(visit, false, sizeof(visit)); memset(path, 0, sizeof(path)); bool tag = true; queue que; que.push(xy); visit[xy.y][xy.x] = true; while (!que.empty()) { XY temp = que.front(); que.pop(); //如果找到出口 if (temp.x == 1 || temp.x == 9 || temp.y == 1 || temp.y == 9) { findNextXY(temp.x, temp.y); cat.x = vec[1].x; cat.y = vec[1].y; vec.clear(); tag = false; break; } int dx, dy; //尋找可走的路 for (int i = 0; i < 6; ++i) { if (temp.y & 1) { dx = temp.x + dirOdd[i][0]; dy = temp.y + dirOdd[i][1]; } else { dx = temp.x + dirEven[i][0]; dy = temp.y + dirEven[i][1]; } if (dx >= 1 && dx <= 9 && dy >= 1 && dy <= 9 && !visit[dy][dx] && canvas[dy][dx].pic == picture::none) { visit[dy][dx] = true; path[dy][dx][0] = temp.x; path[dy][dx][1] = temp.y; que.push({ dx,dy,temp.x,temp.y }); } } } if (tag) //如果沒找到出口 { show(); HWND wnd = GetHWnd(); swprintf(Score_, 29, L"你共用了%d步,重玩一局嗎", stepS); FlushBatchDraw(); if (MessageBox(wnd, Score_, L"成功", MB_YESNO | MB_ICONQUESTION) == IDYES) main(); else exit(-1); } } //鼠標(biāo)操作 void dataChangeWithMouseHit() { while (true) { m = GetMouseMsg(); if (m.x >= 200 && m.x <= 230 && m.y >= 170 && m.y <= 200) settextcolor(BLACK); else settextcolor(WHITE); outtextxy(200, 170, L"重玩"); FlushBatchDraw(); if (m.uMsg == WM_LBUTTONDOWN) { if (m.x >= 200 && m.x <= 230 && m.y >= 170 && m.y <= 200) main(); for (int i = 1; i <= 9; ++i) for (int j = 1; j <= 9; ++j) //如果在當(dāng)前方格內(nèi),則改變信息 if (canvas[i][j].pic != picture::barrier && (m.x - canvas[i][j].x) * (m.x - canvas[i][j].x) + (m.y - canvas[i][j].y) * (m.y - canvas[i][j].y) <= (pix - 4) * (pix - 4) / 4) { canvas[i][j].pic = picture::barrier; stepS++; bfs({ cat.x,cat.y,0,0 }); return; } } } } //不需要鼠標(biāo)的操作,判斷貓是否跑掉 void dataChangeWithoutMouseHit() { if (cat.x == 1 || cat.y == 1 || cat.x == 9 || cat.y == 9) { show(); HWND wnd = GetHWnd(); if (MessageBox(wnd, L"游戲結(jié)束。 神經(jīng)貓跑掉了!,重玩一局嗎", L"詢問", MB_YESNO | MB_ICONQUESTION) == IDYES) main(); else exit(-1); } } int main() { initial(); while (true) { show(); dataChangeWithMouseHit(); dataChangeWithoutMouseHit(); Sleep(20); } return 0; }
大家趕緊去動手試試吧!
審核編輯:湯梓紅
-
游戲
+關(guān)注
關(guān)注
2文章
742瀏覽量
26317 -
C語言
+關(guān)注
關(guān)注
180文章
7604瀏覽量
136824 -
C++
+關(guān)注
關(guān)注
22文章
2108瀏覽量
73651 -
代碼
+關(guān)注
關(guān)注
30文章
4788瀏覽量
68612
原文標(biāo)題:【項目實戰(zhàn)】C/C++輕松實現(xiàn)4399小游戲:圍住神經(jīng)貓!
文章出處:【微信號:cyuyanxuexi,微信公眾號:C語言編程學(xué)習(xí)基地】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論