經(jīng)典的推箱子是一個(gè)很古老的游戲了,相信大家都不陌生。其目的是在訓(xùn)練我們的邏輯思考能力。在一個(gè)狹小的倉(cāng)庫(kù)中,要求把木箱放到指定的位置,稍不小心就會(huì)出現(xiàn)箱子無(wú)法移動(dòng)或者通道被堵住的情況,所以需要巧妙的利用有限的空間和通道,合理安排移動(dòng)的次序和位置,才能順利的完成任務(wù)。
我們將編寫(xiě)推箱子游戲,玩家鍵盤(pán)控制游戲角色將所有黃色箱子推到白色方塊處,效果如圖所示:
操作方法:方向鍵↑↓←→控制移動(dòng)推箱子,將箱子推到對(duì)應(yīng)位置。
首先學(xué)習(xí)字符串與字符數(shù)組的概念,并應(yīng)用字符數(shù)組初始化關(guān)卡數(shù)據(jù);然后利用鍵盤(pán)控制游戲角色移動(dòng),實(shí)現(xiàn)地圖元素更新和游戲勝利的判斷;接著利用三維字符數(shù)組,實(shí)現(xiàn)多關(guān)卡的游戲;最后學(xué)習(xí)基于文件的關(guān)卡數(shù)據(jù)讀取,利用枚舉類型改進(jìn)游戲代碼。
源碼:
#include
#include
#include
#define B_SIZE 60 // 方塊大小
#define B_NUM 8 // 方塊個(gè)數(shù),一共8*8個(gè)方塊
struct Player // 結(jié)構(gòu)體,用于記錄玩家位置
{
int i;
int j;
};
Player player; // 玩家全局變量
enum Element // 定義枚舉類型,小方塊所有的可能的種類
{
wall,target,box,empty,achieved,role
};
// 用于存儲(chǔ)地圖數(shù)據(jù),用枚舉類型實(shí)現(xiàn)
Element level[B_NUM][B_NUM] =
{{wall,wall,wall,wall,wall,wall,wall,wall},
{wall,wall,wall,target,box,empty,empty,wall},
{wall,empty,empty,empty,empty,empty,empty,wall},
{wall,empty,empty,empty,empty,empty,empty,wall},
{wall,empty,empty,empty,empty,empty,empty,wall},
{wall,role,empty,box,target,wall,wall,wall},
{wall,empty,empty,empty,empty,wall,wall,wall},
{wall,wall,wall,wall,wall,wall,wall,wall}};
int targetNum,achievedNum; // 目標(biāo)位置個(gè)數(shù)、完成目標(biāo)個(gè)數(shù)
void startup() // 初始化函數(shù)
{
initgraph(B_NUM*B_SIZE,B_NUM*B_SIZE); // 新開(kāi)一個(gè)畫(huà)面
setbkcolor(RGB(150,150,150)); // 灰色背景
BeginBatchDraw(); // 開(kāi)始批量繪圖
int i,j;
targetNum = 0; // 目標(biāo)個(gè)數(shù),初始為0
// 對(duì)二維數(shù)組遍歷
for (i=0;i
for (j=0;j
{
if (level[i][j]==role) // 找到地圖中player位置
{
player.i = i; // 設(shè)定player位置
player.j = j; //
level[i][j]=empty; // 把地圖元素變成空白empty
}
else if (level[i][j]==target || level[i][j]==achieved ) // 如果元素是target或achieved
targetNum++; // 目標(biāo)個(gè)數(shù)+1
}
}
void show() // 繪制函數(shù)
{
int i,j;
cleardevice(); // 以背景顏色清空屏幕
// 遍歷關(guān)卡二維數(shù)組數(shù)據(jù)
for (i=0;i
{
for (j=0;j
{
if (level[i][j]==empty) // empty 元素是空白區(qū)域
{
setfillcolor(RGB(150,150,150)); // 繪制灰色地面
setlinecolor(RGB(150,150,150));
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
}
else if (level[i][j]==wall) // wall 元素是墻
{
setfillcolor(RGB(155,0,0));
setlinecolor(RGB(150,150,150)); // 繪制淡紅色、灰色線的方框
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
}
else if (level[i][j]==box) // box 元素是可移動(dòng)的箱子
{
setfillcolor(RGB(255,255,0)); // 繪制一個(gè)黃色的方塊
setlinecolor(RGB(150,150,150));
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
}
else if (level[i][j]==target) // target 元素是目標(biāo)
{
setfillcolor(RGB(250,250,250)); // 繪制一個(gè)白色的小方塊
fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
(j+0.7)*B_SIZE,(i+0.7)*B_SIZE);
}
else if (level[i][j]==achieved) // achieved 元素是已完成目標(biāo)
{
setlinecolor(RGB(150,150,150));
setfillcolor(RGB(255,255,0)); // 繪制一個(gè)黃色的方塊
fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);
setfillcolor(RGB(250,250,250)); // 繪制一個(gè)白色的小方塊
fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,
(j+0.7)*B_SIZE,(i+0.7)*B_SIZE);
}
}
}
// 以下繪制玩家,繪制一個(gè)人臉圖案
i = player.i;
j = player.j;
setfillcolor(RGB(255,0,0));
fillcircle((j+0.5)*B_SIZE,(i+0.5)*B_SIZE,0.4*B_SIZE);//一個(gè)紅色圓臉
setfillcolor(RGB(80,80,80));
setlinecolor(RGB(80,80,80));
fillcircle((j+0.3)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE);//兩個(gè)黑色眼睛
fillcircle((j+0.7)*B_SIZE,(i+0.45)*B_SIZE,0.08*B_SIZE);
setlinestyle(PS_SOLID,3);
line((j+0.35)*B_SIZE,(i+0.7)*B_SIZE,(j+0.65)*B_SIZE,(i+0.7)*B_SIZE);//深灰色嘴巴
setlinestyle(PS_SOLID,1);
if (achievedNum==targetNum) // 如完成目標(biāo)個(gè)數(shù)==目標(biāo)個(gè)數(shù)
{
setbkmode(TRANSPARENT); // 透明顯示文字
settextcolor(RGB(0,255,255)); // 設(shè)置字體顏色
settextstyle(80, 0, _T("宋體")); // 設(shè)置字體大小、樣式
outtextxy(80,200,_T("游戲勝利")); // 顯示游戲勝利文字
}
FlushBatchDraw(); // 開(kāi)始批量繪制
}
void update() // 每幀更新運(yùn)行
{
if(kbhit() && (achievedNum// 如果按鍵,并且游戲沒(méi)有勝利
{
char input = getch(); // 獲取按鍵
if (input=='a' || input=='s' || input=='d' || input=='w') // 如果是有效按鍵
{
int goal_i = player.i; // 移動(dòng)的目標(biāo)位置
int goal_j = player.j;
int goalNext_i = goal_i; // 目標(biāo)位置再向前的一個(gè)位置
int goalNext_j = goal_j;
// 根據(jù)用戶的不同按鍵輸入,獲得目標(biāo)位置、再向前的一個(gè)位置
if (input=='a') // 向左
{
goal_j = player.j -1 ; // 目標(biāo)位置在玩家位置的左邊
goalNext_j = goal_j-1; // 目標(biāo)的下一個(gè)位置,在其再左邊
}
else if (input=='d') // 向右
{
goal_j = player.j +1 ; // 目標(biāo)位置在玩家位置的右邊
goalNext_j = goal_j+1; // 目標(biāo)的下一個(gè)位置,在其再右邊
}
else if (input=='s') // 向下
{
goal_i = player.i+1; // 目標(biāo)位置在玩家位置的下邊
goalNext_i = goal_i+1; // 目標(biāo)的下一個(gè)位置,在其再下邊
}
else if (input=='w') // 向上
{
goal_i = player.i-1; // 目標(biāo)位置在玩家位置的上邊
goalNext_i = goal_i-1; // 目標(biāo)的下一個(gè)位置,在其再上邊
}
// 根據(jù)不同地圖元素的情況,判斷如何移動(dòng)角色和更新地圖元素
if (level[goal_i][goal_j]==empty || level[goal_i][goal_j]==target )
{ // 如果目標(biāo)位置是empty,或者target
player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
player.j = goal_j;
}
else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==empty )
{ // 如果目標(biāo)位置是box,再前面一個(gè)是empty
player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
player.j = goal_j;
level[goal_i][goal_j]=empty; // 目標(biāo)位置變成empty
level[goalNext_i][goalNext_j]=box; // 再前面變成box
}
else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==target)
{ // 如果目標(biāo)位置是box,再前面一個(gè)是target
player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
player.j = goal_j;
level[goal_i][goal_j] = empty; // 目標(biāo)位置變成empty
level[goalNext_i][goalNext_j] = achieved; // 再前面變成achieved
}
else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== empty)
{ // 如果目標(biāo)位置是achieved,再前面一個(gè)是empty
player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
player.j = goal_j;
level[goal_i][goal_j] = target; // 目標(biāo)位置變成target
level[goalNext_i][goalNext_j] = box; // 再前面變成box
}
else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== target)
{ // 如果目標(biāo)位置是achieved,再前面一個(gè)是target
player.i = goal_i; // 玩家移動(dòng)到目標(biāo)位置
player.j = goal_j;
level[goal_i][goal_j] = target; // 目標(biāo)位置變成target
level[goalNext_i][goalNext_j] = achieved; // 再前面變成achieved
}
else // 其他情況都推不動(dòng)
return; // 不做任何處理,函數(shù)直接返回
}
achievedNum = 0; // 完成目標(biāo)個(gè)數(shù),初始為0
int i,j;
for (i=0;i// 對(duì)二維數(shù)組遍歷
for (j=0;j//
if (level[i][j]==achieved) // 如果元素是achieved
achievedNum++; // 完成目標(biāo)個(gè)數(shù)+1
}
}
int main() // 主函數(shù)
{
startup(); // 初始化
while (1) // 游戲主循環(huán)
{
show(); // 繪制
update(); // 更新
}
return 0;
}
主要講解了字符串與字符數(shù)組、文件讀寫(xiě)、枚舉類型等語(yǔ)法知識(shí),實(shí)現(xiàn)了推箱子游戲。讀者可以嘗試在本章代碼基礎(chǔ)上繼續(xù)改進(jìn):
1、實(shí)現(xiàn)多關(guān)卡的選擇界面;
2、實(shí)現(xiàn)某一步移動(dòng)的撤銷功能(類似于下棋游戲中的悔棋功能);
3、實(shí)現(xiàn)按'h'鍵后進(jìn)行提示,播放正確步驟動(dòng)畫(huà)的功能;
4、實(shí)現(xiàn)一個(gè)圖形編輯器,并將設(shè)計(jì)的關(guān)卡信息保存為txt文件。
審核編輯 :李倩
-
C語(yǔ)言
+關(guān)注
關(guān)注
180文章
7581瀏覽量
135549 -
編輯器
+關(guān)注
關(guān)注
1文章
798瀏覽量
31011
原文標(biāo)題:C語(yǔ)言實(shí)現(xiàn)推箱子游戲?。ǔ?jiǎn)單詳細(xì))代碼思路+源碼分享
文章出處:【微信號(hào):cyuyanxuexi,微信公眾號(hào):C語(yǔ)言編程學(xué)習(xí)基地】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論