用C++實(shí)現(xiàn)推箱子小游戲
前言
推箱子小游戲相信是很多人的同年記憶了,今天用c++語(yǔ)言來(lái)嘗試下,用的是vs編譯器。
代碼還有很多可以優(yōu)化的地方,為了更直觀了解函數(shù)的形參和實(shí)參,所以地圖沒(méi)有用全局變量聲明了,其實(shí)用全局變量聲明會(huì)簡(jiǎn)潔很多。
頭文件和main函數(shù)分享在最下面了。
提示:以下是本篇文章正文內(nèi)容,下面案例可供參考
一、初始化游戲數(shù)據(jù)
void GameInit(int(*&pMap)[10][10], int index)//兩張地圖數(shù)據(jù) { // static:返回靜態(tài)全局區(qū)變量 static int localmap[2][10][10] = { { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 5, 0, 1, 0, 0, 3, 0, 1, 1, 0, 0, 0, 1, 0, 0, 3, 0, 1, 1, 0, 0, 4, 1, 0, 0, 3, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 }, { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 4, 0, 0, 0, 1, 1, 0, 5, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 3, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 } }; // 數(shù)組指針指向?qū)?yīng)關(guān)卡的地址 pMap = localmap ;//數(shù)組名表示指針,此時(shí)指向第一個(gè)二維數(shù)組地圖 }
用3維數(shù)組來(lái)編寫(xiě)兩個(gè)地圖,第一關(guān)過(guò)了就進(jìn)入下一關(guān),用static關(guān)鍵字聲明數(shù)組,保證地圖數(shù)據(jù)可以返回出去。
二、渲染地圖
void RenderMap(int(*pMap)[10][10]) { system("CLS"); for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { int element = (*pMap)[i][j]; switch (element) { case 0: cout << " ";//空地 break; case 1:cout << "■";//墻 break; case 3: cout << "☆";//勝利點(diǎn) break; case 4: cout << "□";//箱子 break; case 5: cout << "♀";//人 posx = i;//記錄人的坐標(biāo) posy = j; break; case 7: cout << "★";//箱子進(jìn)入勝利點(diǎn) break; case 8: cout << "♀";//人進(jìn)入勝利點(diǎn) posx = i;//記錄人的坐標(biāo) posy = j; break; } } cout << endl; } }
渲染地圖其實(shí)很簡(jiǎn)單了,做個(gè)二維數(shù)組的遍歷,用switch語(yǔ)句進(jìn)行渲染,
這里其實(shí)還有一點(diǎn)可以渲染的更明了一點(diǎn),可以在全局聲明,拿人來(lái)舉例子。
const int people = 5;
這樣的好處呢其實(shí)用people來(lái)代替5這個(gè)數(shù)字,顯得更直觀,不然下面更新地圖數(shù)據(jù)還要翻上去看哪個(gè)數(shù)字代表什么就很麻煩。
三、 更新地圖數(shù)據(jù)
void UpdateMap(int(*&pMap)[10][10]) { char input = _getch();//獲取從鍵盤輸入的字母 int offsetx=0, offsety=0;//設(shè)置偏移量 switch (input) { case 's': case 'S'://輸入s,人物向下走,x加1,偏移量為1,y不變,一次類推 offsetx= 1; offsety = 0; break; case 'w': case 'W': offsetx = -1; offsety = 0; break; case 'd': case 'D': offsety = 1; offsetx = 0; break; case 'a': case 'A': offsety = -1; offsetx = 0; break; default: break; } move(pMap, offsetx, offsety);//調(diào)用了move函數(shù) }
這是move函數(shù),形參為地圖和偏移量,在move函數(shù)中調(diào)用了 nextElement函數(shù);
可以看到,在一開(kāi)始定義了兩個(gè)int型常量分別保存英雄下一個(gè)位置和下下個(gè)位置的值;
void move(int(*&pMap)[10][10], int offsetx, int offsety) { int nextelementOfpos = nextElement(pMap, posx+offsetx, posy+offsety);//下一個(gè)位置 int nextnextelementOfpos = nextElement(pMap, posx+offsetx * 2,posy+offsety * 2);//下下個(gè)位置 if (nextelementOfpos == 0 || nextelementOfpos == 3) { *((*((*(pMap )) + posx)) + posy) -= 5; *((*((*(pMap )) + posx + offsetx)) + posy + offsety) += 5; } else if (nextelementOfpos == 4 || nextelementOfpos == 7) { if (nextnextelementOfpos == 0 || nextnextelementOfpos == 3) { *(*((*(pMap )) + posx) + posy) -= 5; *(*((*(pMap)) + posx + offsetx) + posy + offsety) += 5; *(*((*(pMap )) + posx + offsetx) + posy + offsety) -= 4; *(*((*(pMap )) + posx + offsetx * 2) + posy + offsety * 2) += 4; } } }
記錄移動(dòng)后人物的下一個(gè)位置
int nextElement(int(*&pMap)[10][10], int x, int y) { int k = *(*((*(pMap)) + x) + y);//指針偏移運(yùn)算,運(yùn)行結(jié)果為偏移后的地址,用k保存并返回 return k; }
//判定游戲過(guò)關(guān) bool isWin(int(*&pMap)[10][10]) { for (int i = 0; i < 10; i++) { for (int j = 0; j < 10; j++) { if ((*pMap)[i][j] == 4) return false; } } return true; }
四、頭文件的定義和引用
以下是頭文件的聲明
// 初始化游戲數(shù)據(jù) void GameInit(int(*&pMap)[10][10], int index); // 渲染地圖 void RenderMap(int(*pMap)[10][10]); // 更新地圖數(shù)據(jù) void UpdateMap(int(*&pMap)[10][10]); void move(int(*&pMap)[10][10], int offsetx, int offsety); int nextElement(int(*&pMap)[10][10], int x, int y); int posx, posy;//人物坐標(biāo) int mapPage=1;//第一張地圖 bool isWin(int(*&pMap)[10][10]);//判斷是否過(guò)關(guān)
main函數(shù)
#include <iostream> #include <conio.h> using namespace std; #include "header.h" int main() { // 地圖數(shù)據(jù) int(*mMap)[10][10]; // 1.初始化游戲數(shù)據(jù)(地圖) GameInit(mMap, mapPage); while (true) { // 2.渲染地圖 RenderMap(mMap); if (isWin(mMap)) { if (mapPage == 2) { cout << "恭喜你,已經(jīng)通關(guān)了" << endl; break; } cout << "游戲勝利,按任意鍵進(jìn)入下一關(guān)" << endl; getch(); mapPage++; mMap++; continue; } // 3.更新地圖數(shù)據(jù) UpdateMap(mMap); } return 0; }
五、總結(jié)
1.對(duì)于推箱子來(lái)說(shuō)找到規(guī)律很重要,還要一點(diǎn)要注意的就是形參為數(shù)組形式出現(xiàn),實(shí)參傳入數(shù)組進(jìn)去,數(shù)組會(huì)退化為指針的形式;
2.在更新地圖時(shí)調(diào)用了move函數(shù),要分清楚著重于人物要移動(dòng)時(shí)的下一個(gè)位置和下下個(gè)位置是什么來(lái)分開(kāi)討論,所以這也就是為什么要用兩個(gè)int型變量來(lái)保存偏移后的位置;
3.函數(shù)聲明取名字的重要性,不然等代碼一長(zhǎng),很難區(qū)分函數(shù)的功能,還要區(qū)仔細(xì)看代碼,會(huì)浪費(fèi)很多時(shí)間,還要就是多敲注釋的重要性;
希望這些可以幫助到你哦。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C++實(shí)現(xiàn)簡(jiǎn)單版通訊錄管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)簡(jiǎn)單版通訊錄管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06C語(yǔ)言中#define與typedef的互換細(xì)節(jié)詳解
本篇文章是對(duì)C語(yǔ)言中#define與typedef的互換細(xì)節(jié)進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下2013-05-05利用rapidjson實(shí)現(xiàn)解析嵌套的json的方法示例
今天小編就為大家分享一篇關(guān)于利用rapidjson實(shí)現(xiàn)解析嵌套的json的方法示例,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-04-04C++統(tǒng)計(jì)軟件使用時(shí)間代碼示例
這篇文章主要介紹了C++統(tǒng)計(jì)軟件使用時(shí)間的小程序,大家可以參考使用2013-11-11