C語言/C++編程學(xué)習(xí):C語言實(shí)現(xiàn)《黑夜迷宮逃亡》小游戲

C語言是面向過程的,而C++是面向?qū)ο蟮?/p>

C和C++的區(qū)別:

C是一個結(jié)構(gòu)化語言,它的重點(diǎn)在于算法和數(shù)據(jù)結(jié)構(gòu)。C程序的設(shè)計(jì)首要考慮的是如何通過一個過程,對輸入(或環(huán)境條件)進(jìn)行運(yùn)算處理得到輸出(或?qū)崿F(xiàn)過程(事務(wù))控制)。

C++,首要考慮的是如何構(gòu)造一個對象模型,讓這個模型能夠契合與之對應(yīng)的問題域,這樣就可以通過獲取對象的狀態(tài)信息得到輸出或?qū)崿F(xiàn)過程(事務(wù))控制。 所以C與C++的最大區(qū)別在于它們的用于解決問題的思想方法不一樣。之所以說C++比C更先進(jìn),是因?yàn)椤?設(shè)計(jì)這個概念已經(jīng)被融入到C++之中 ”。

C與C++的最大區(qū)別:在于它們的用于解決問題的思想方法不一樣。之所以說C++比C更先進(jìn),是因?yàn)椤?設(shè)計(jì)這個概念已經(jīng)被融入到C++之中 ”,而就語言本身而言,在C中更多的是算法的概念。那么是不是C就不重要了,錯!算法是程序設(shè)計(jì)的基礎(chǔ),好的設(shè)計(jì)如果沒有好的算法,一樣不行。而且,“C加上好的設(shè)計(jì)”也能寫出非常好的東西。

今天給大家?guī)淼氖且粋€迷宮游戲,可能大家就會覺得迷宮游戲有什么好玩的,寫出來也很簡單,不過呢,今天的迷宮游戲卻比一般的迷宮游戲要有趣多了。

從標(biāo)題上就透露出了一些信息,既然是《黑夜迷宮逃亡》,那么游戲的環(huán)境肯定是在黑夜中進(jìn)行來的了,是不是難度就大了許多,那我們先去看看游戲的情況吧。

首先游戲開始的時候,可以看到迷宮地圖的全貌,當(dāng)然了,也只會持續(xù)很短的時間,實(shí)際上考驗(yàn)的就是大家的記憶力,你要是能夠把游戲地圖全貌都能記下來,我只能說 :“ 你不適合玩這種游戲!”

小編推薦一個學(xué)C語言/C++的學(xué)習(xí)裙【 六九九,四七零,五九六 】,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享!

然后呢,當(dāng)夜幕降臨的時候,整個地圖就都會陷入一片黑漆漆的環(huán)境中,想要在這樣的環(huán)境中走出迷宮是很難的。不過啦,因?yàn)橹鹘枪猸h(huán)的需要,我們的主角獲得了 “ 隨身小手電 +1 ”,用來幫助主角走出迷宮。

隨身小手電的方向隨著鼠標(biāo)的移動而移動,然后根據(jù)黑夜降臨前我們所記住的整個迷宮的地圖大概位置項(xiàng)前行走,逃出黑夜中的迷宮。

最后,主角憑借著光環(huán)效果,走到了出口,我們的游戲就這樣結(jié)束了! “ o_O 此處應(yīng)有掌聲 ”

喜歡的可以自己對照源碼寫出來玩玩,可以的話,請大家多多轉(zhuǎn)發(fā)關(guān)注哦!

下期看下源碼:

#include

#include

#include

#include

// 定義常量

#define PI3.14// 圓周率

#define UNIT_GROUND0// 表示地面

#define UNIT_WALL1// 表示墻

#define LIGHT_API / 3// 燈光的角度范圍

#defineLIGHT_R120// 燈光的照射距離

#defineWIDTH480// 迷宮的寬度

#defineHEIGHT480// 迷宮的高度

#define SCREENWIDTH640// 屏幕寬度

#defineSCREENHEIGHT480// 屏幕高度

#defineUNIT20// 每個墻壁單位的大小

#define PLAYER_R5// 游戲者的半徑

// 定義常量

constSIZEg_utMap = { 23, 23 };// 迷宮地圖的尺寸(基于 UNIT 單位)

constPOINTg_utPlayer = { 1, 1 };// 游戲者的位置(基于 UNIT 單位)

constPOINTg_utExit = { 21, 22 };// 出口位置(基于 UNIT 單位)

constPOINTg_ptOffset = { 10, 10 };// 迷宮顯示在屏幕上的偏移量

// 定義全局變量

POINTg_ptPlayer;// 游戲者的位置

POINTg_ptMouse;// 鼠標(biāo)位置

IMAGEg_imgMap(WIDTH, HEIGHT);// 迷宮平面圖

DWORD*g_bufMap;// 迷宮平面圖的顯存指針

IMAGEg_imgRender(WIDTH, HEIGHT);// 渲染

DWORD*g_bufRender;// 渲染的顯存指針

DWORD*g_bufScreen;// 屏幕的顯存指針

// 枚舉用戶的控制命令

enum CMD { CMD_QUIT = 1, CMD_UP = 2, CMD_DOWN = 4, CMD_LEFT = 8, CMD_RIGHT = 16, CMD_RESTART = 32 };

// 函數(shù)聲明

voidWelcome();// 繪制游戲界面

voidReadyGo();// 準(zhǔn)備開始游戲

voidInitGame();// 初始化游戲數(shù)據(jù)

// 迷宮生成

voidMakeMaze(int width, int height);// 初始化(注:寬高必須是奇數(shù))

voidTravelMaze(int x, int y, BYTE** aryMap);// 遍歷 (x, y) 四周

voidDrawWall(int x, int y, bool left, bool top, bool right, bool bottom);

// 畫一面墻

// 繪制

voidPaint();// 繪制視野范圍內(nèi)的迷宮

voidLighting(int _x, int _y, double _a);// 在指定位置和角度“照明”

voidDrawPlayer();// 繪制游戲者

voidDrawExit();// 繪制出口

// 處理用戶控制

intGetCmd();// 獲取用戶輸入的命令

voidOnUp();// 向上移動

voidOnLeft();// 向左移動

voidOnRight();// 向右移動

voidOnDown();// 向下移動

boolCheckWin();// 檢查是否到出口

// 主程序

void main()

{

// 初始化

initgraph(SCREENWIDTH, SCREENHEIGHT);// 創(chuàng)建繪圖窗口

srand((unsigned)time(NULL));// 設(shè)置隨機(jī)種子

// 顯示主界面

Welcome();

// 游戲過程

int c;

do

{

ReadyGo();

while (true)

{

// 獲得用戶輸入

c = GetCmd();

// 處理用戶輸入

if (c & CMD_UP)OnUp();

if (c & CMD_DOWN)OnDown();

if (c & CMD_LEFT)OnLeft();

if (c & CMD_RIGHT)OnRight();

if (c & CMD_RESTART)

{

if (MessageBox(GetHWnd(), _T("您要重來一局嗎?"), _T("詢問"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK)

break;

}

if (c & CMD_QUIT)

{

if (MessageBox(GetHWnd(), _T("您確定要退出游戲嗎?"), _T("詢問"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK)

break;

}

// 繪制場景

Paint();

// 判斷是否走出迷宮

if (CheckWin())

{

// 是否再來一局

HWND hwnd = GetHWnd();

if (MessageBox(hwnd, _T("恭喜你走出來了! 您想再來一局嗎?"), _T("恭喜"), MB_YESNO | MB_ICONQUESTION) != IDYES)

c = CMD_QUIT;

break;

}

// 延時

Sleep(16);

}

} while (!(c & CMD_QUIT));

// 關(guān)閉圖形模式

closegraph();

}

// 準(zhǔn)備開始游戲

void ReadyGo()

{

// 初始化

InitGame();

// 黑夜降臨前兆

int time[7] = { 1000, 50, 500, 50, 50, 50, 50 };

int i, x, y;

for (i = 0; i < 7; i++)

{

if (i % 2 == 0)

{

putimage(0, 0, &g_imgMap);

DrawPlayer();

DrawExit();

}

else

clearrectangle(0, 0, WIDTH - 1, HEIGHT - 1);

Sleep(time[i]);

}

// 黑夜緩慢降臨

for (i = 255; i >= 0; i -= 5)

{

for (y = (HEIGHT - 1) * SCREENWIDTH; y >= 0; y -= SCREENWIDTH)

for (x = 0; x < WIDTH; x++)

if (g_bufScreen[y + x] != 0)

g_bufScreen[y + x] = g_bufScreen[y + x] - 0x050505;

FlushBatchDraw();

DrawPlayer();

DrawExit();

Sleep(50);

}

// 繪制游戲區(qū)

Paint();

}

// 繪制游戲界面

void Welcome()

{

setfillcolor(DARKGRAY);

solidrectangle(WIDTH, 0, SCREENWIDTH - 1, SCREENHEIGHT - 1);

// 設(shè)置字體樣式

settextcolor(WHITE);

setbkmode(TRANSPARENT);

// 繪制標(biāo)題

settextstyle(24, 0, _T("宋體"));

outtextxy(490, 40, _T("黑夜迷宮逃亡"));

// 繪制操作說明

RECT r = { 488, 100, 632, 470 };

settextstyle(12, 0, _T("宋體"));

drawtext(_T("[游戲說明]:   黑夜降臨啦,盡快離開黑夜中的迷宮哦。迅速借助你的小手電,在漆黑的迷宮里

找到出口逃出去吧。 [控制說明] 方向鍵: 移動 A/S/D/W:移動 鼠標(biāo):  控制照射

方向 F2:   重來一局 ESC:  退出游戲"), &r, DT_WORDBREAK);

}

// 初始化游戲數(shù)據(jù)

void InitGame()

{

// 獲得窗口顯存指針

g_bufRender = GetImageBuffer(&g_imgRender);

g_bufMap = GetImageBuffer(&g_imgMap);

g_bufScreen = GetImageBuffer(NULL);

// 設(shè)置 Render 環(huán)境

SetWorkingImage(&g_imgRender);

setbkmode(TRANSPARENT);

SetWorkingImage(NULL);

// 創(chuàng)建迷宮

MakeMaze(g_utMap.cx, g_utMap.cy);

// 設(shè)置游戲者位置

g_ptPlayer.x = g_utPlayer.x * UNIT + UNIT / 2 + g_ptOffset.x;

g_ptPlayer.y = g_utPlayer.y * UNIT + UNIT / 2 + g_ptOffset.y;

}

// 生成迷宮:初始化(注:寬高必須是奇數(shù))

void MakeMaze(int width, int height)

{

if (width % 2 != 1 || height % 2 != 1)

return;

int x, y;

// 定義迷宮二維數(shù)組,并初始化全部為墻壁

// 寬高比實(shí)際多 2,是因?yàn)閮啥烁饔幸粋€“哨兵”,用于方便處理數(shù)據(jù)

BYTE** aryMap = new BYTE*[width + 2];

for (x = 0; x < width + 2; x++)

{

aryMap[x] = new BYTE[height + 2];

memset(aryMap[x], UNIT_WALL, height + 2);

}

// 定義邊界(哨兵功能)

for (x = 0; x <= width + 1; x++)

aryMap[x][0] = aryMap[x][height + 1] = UNIT_GROUND;

for (y = 1; y <= height; y++)

aryMap[0][y] = aryMap[width + 1][y] = UNIT_GROUND;

// 從任意點(diǎn)開始遍歷生成迷宮

TravelMaze(((rand() % (width - 1)) & 0xfffe) + 2, ((rand() % (height - 1)) & 0xfffe) + 2, aryMap);

// 設(shè)置出口

aryMap[g_utExit.x + 1][g_utExit.y + 1] = UNIT_GROUND;

// 將迷宮繪制在 IMAGE 對象上

SetWorkingImage(&g_imgMap);

cleardevice();

for (y = 1; y <= height; y++)

for (x = 1; x <= width; x++)

if (aryMap[x][y] == UNIT_WALL)

DrawWall(x, y, aryMap[x - 1][y] == UNIT_WALL,

aryMap[x][y - 1] == UNIT_WALL,

aryMap[x + 1][y] == UNIT_WALL,

aryMap[x][y + 1] == UNIT_WALL);

SetWorkingImage(NULL);

}

小編推薦一個學(xué)C語言/C++的學(xué)習(xí)裙【 六九九,四七零,五九六 】,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享!

// 生成迷宮:遍歷 (x, y) 四周

void TravelMaze(int x, int y, BYTE** aryMap)

{

// 定義遍歷方向

int d[4][2] = { 0, 1, 1, 0, 0, -1, -1, 0 };

// 將遍歷方向亂序

int n, t, i;

for (i = 0; i < 4; i++)

{

n = rand() % 4;

t = d[i][0], d[i][0] = d[n][0], d[n][0] = t;

t = d[i][1], d[i][1] = d[n][1], d[n][1] = t;

}

// 嘗試周圍四個方向

aryMap[x][y] = UNIT_GROUND;

for (i = 0; i < 4; i++)

if (aryMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == UNIT_WALL)

{

aryMap[x + d[i][0]][y + d[i][1]] = UNIT_GROUND;

TravelMaze(x + d[i][0] * 2, y + d[i][1] * 2, aryMap);// 遞歸

}

}

// 生成迷宮:畫一面墻

// 參數(shù):left/top/right/bottom 表示墻壁是否與旁邊連接

void DrawWall(int x, int y, bool left, bool top, bool right, bool bottom)

{

// 墻壁厚 4 pixel

int cx, cy;

cx = x * UNIT - UNIT / 2 - 2 + 10;

cy = y * UNIT - UNIT / 2 - 2 + 10;

if (left)solidrectangle(x * UNIT - UNIT + 10, cy, cx + 4, cy + 4);

if (top)solidrectangle(cx, y * UNIT - UNIT + 10, cx + 4, cy + 4);

if (right)solidrectangle(cx, cy, x * UNIT + 9, cy + 4);

if (bottom)solidrectangle(cx, cy, cx + 4, y * UNIT + 9);

}

// 繪制視野范圍內(nèi)的迷宮

void Paint()

{

// 設(shè)置繪圖目標(biāo)為 Render 對象

SetWorkingImage(&g_imgRender);

// 清空 Render 對象

cleardevice();

// 計(jì)算視野角度

double dx, dy, a;

dx = g_ptMouse.x - g_ptPlayer.x;

dy = g_ptMouse.y - g_ptPlayer.y;

if (dx == 0 && dy == 0)

a = 0;

else if (dx != 0 && dy != 0)

a = atan(dy / dx);

else if (dx == 0)

a = (dy > 0) ? PI / 2 : PI * 3 / 2;

else

a = 0;

if (dx < 0)a += PI;

if (a < 0) a += PI * 2;

// 繪制燈光

Lighting(g_ptPlayer.x, g_ptPlayer.y, a);

// 畫游戲者

DrawPlayer();

// 畫出口

DrawExit();

// 設(shè)置繪圖目標(biāo)為窗口

SetWorkingImage(NULL);

// 顯示到窗口上

putimage(0, 0, &g_imgRender);

}

// 在指定位置和角度“照明”

void Lighting(int _x, int _y, double _a)

{

int i;// 定義循環(huán)變量

int x, y;// 定義臨時坐標(biāo)

double a;// 定義臨時角度

// 計(jì)算燈光照亮的角度區(qū)域

double a1 = _a - LIGHT_A / 2;

double a2 = _a + LIGHT_A / 2;

for (a = a1; a < a2; a += PI / 360)// 扇形循環(huán)

{

for (int r = 0; r < LIGHT_R; r++)// 半徑循環(huán)

{

// 計(jì)算照射到的位置

x = (int)(_x + cos(a) * r);

y = (int)(_y + sin(a) * r);

// 光線超出屏幕范圍,終止

// (為了簡化全憑模糊運(yùn)算,不處理最上和最下一行)

if (x < 0 || x >= WIDTH || y <= 0 || y >= HEIGHT - 1)

break;

// 光線碰到墻壁,終止

if (g_bufMap[y * WIDTH + x])

break;

// 光線疊加

g_bufRender[y * WIDTH + x] += 0x202000;// 0x202000 是很淡的黃色

}

}

// 計(jì)算光照扇形區(qū)域的最小包圍矩形

// 方法:獲得 7 個點(diǎn)的最值:圓心、圓弧兩端、圓與 xy 軸的 4 個交點(diǎn)

// 第一步:初始化 7 個點(diǎn)

POINT pt[7];

pt[0].x = _x;pt[0].y = _y;

pt[1].x = int(_x + LIGHT_R * cos(a1) + 0.5);pt[1].y = int(_y + LIGHT_R * sin(a1) + 0.5);

pt[2].x = int(_x + LIGHT_R * cos(a2) + 0.5);pt[2].y = int(_y + LIGHT_R * sin(a2) + 0.5);

for (a = ceil(a1 * 4 / (2 * PI)) * (PI / 2), i = 3; a < a2; a += PI / 2, i++)

{

pt[i].x = int(_x + LIGHT_R * cos(a) + 0.5);

pt[i].y = int(_y + LIGHT_R * sin(a) + 0.5);

}

// 第二步:獲取 7 個點(diǎn)的最大最小值,得到最小包圍矩形

i--;

RECT r = { pt[i].x, pt[i].y, pt[i].x, pt[i].y };

for (--i; i >= 0; i--)

{

if (pt[i].x < r.left)r.left = pt[i].x;

if (pt[i].x > r.right)r.right = pt[i].x;

if (pt[i].y < r.top)r.top = pt[i].y;

if (pt[i].y > r.bottom)r.bottom = pt[i].y;

}

// 調(diào)整矩形范圍

if (r.left < 0)r.left = 0;

if (r.top < 1)r.top = 1;

if (r.right >= WIDTH)r.right = WIDTH - 1;

if (r.bottom >= HEIGHT - 1)r.bottom = HEIGHT - 2;

// 修正曝光過度的點(diǎn)

for (y = r.top; y <= r.bottom; y++)

for (x = r.left; x <= r.right; x++)

{

i = y * WIDTH + x;

if (g_bufRender[i] > 0xffff00)

g_bufRender[i] = 0xffff00;

}

// 將光線模糊處理(避開墻壁)

for (y = r.top; y <= r.bottom; y++)

for (x = r.left; x <= r.right; x++)

{

i = y * WIDTH + x;

if (!g_bufMap[i])

g_bufRender[i] = RGB(

(GetRValue(g_bufRender[i - WIDTH]) + GetRValue(g_bufRender[i - 1]) + GetRValue(g_bufRender[i])

+ GetRValue(g_bufRender[i + 1]) + GetRValue(g_bufRender[i + WIDTH])) / 5,

(GetGValue(g_bufRender[i - WIDTH]) + GetGValue(g_bufRender[i - 1]) + GetGValue(g_bufRender[i])

+ GetGValue(g_bufRender[i + 1]) + GetGValue(g_bufRender[i + WIDTH])) / 5,

(GetBValue(g_bufRender[i - WIDTH]) + GetBValue(g_bufRender[i - 1]) + GetBValue(g_bufRender[i])

+ GetBValue(g_bufRender[i + 1]) + GetBValue(g_bufRender[i + WIDTH])) / 5);

}

}

// 繪制游戲者

void DrawPlayer()

{

// 畫安全帽

setlinecolor(DARKGRAY);

circle(g_ptPlayer.x, g_ptPlayer.y, 5);

}

// 繪制出口

void DrawExit()

{

settextstyle(12, 0, _T("宋體"));

outtextxy(g_utExit.x * UNIT + g_ptOffset.x, g_utExit.y * UNIT + g_ptOffset.y + 8, _T("出口"));

}

// 獲取用戶輸入的命令

int GetCmd()

{

int c = 0;

if ((GetAsyncKeyState(VK_LEFT) & 0x8000) ||

(GetAsyncKeyState('A') & 0x8000))c |= CMD_LEFT;

if ((GetAsyncKeyState(VK_RIGHT) & 0x8000) ||

(GetAsyncKeyState('D') & 0x8000))c |= CMD_RIGHT;

if ((GetAsyncKeyState(VK_UP) & 0x8000) ||

(GetAsyncKeyState('W') & 0x8000))c |= CMD_UP;

if ((GetAsyncKeyState(VK_DOWN) & 0x8000) ||

(GetAsyncKeyState('S') & 0x8000))c |= CMD_DOWN;

if (GetAsyncKeyState(VK_F2) & 0x8000)c |= CMD_RESTART;

if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)c |= CMD_QUIT;

MOUSEMSG m;

while (MouseHit())

{

m = GetMouseMsg();

g_ptMouse.x = m.x;

g_ptMouse.y = m.y;

}

return c;

}

// 向上移動

void OnUp()

{

int i = (g_ptPlayer.y - 6) * WIDTH + (g_ptPlayer.x - 5) + 1;

int j;

for (j = 0; j < 5; j++, i += 2)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.y--;

}

// 向左移動

void OnLeft()

{

int i = (g_ptPlayer.y - 5) * WIDTH + (g_ptPlayer.x - 5);

int j;

for (j = 0; j < 5; j++, i += WIDTH)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.x--;

}

// 向右移動

void OnRight()

{

int i = (g_ptPlayer.y - 5) * WIDTH + (g_ptPlayer.x + 5) + 1;

int j;

for (j = 0; j < 5; j++, i += WIDTH)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.x++;

}

// 向下移動

void OnDown()

{

int i = (g_ptPlayer.y + 5) * WIDTH + (g_ptPlayer.x - 5) + 1;

int j;

for (j = 0; j < 5; j++, i += 2)

if (g_bufMap[i])

break;

if (j == 5)

g_ptPlayer.y++;

}

小編推薦一個學(xué)C語言/C++的學(xué)習(xí)裙【 六九九,四七零,五九六 】,無論你是大牛還是小白,是想轉(zhuǎn)行還是想入行都可以來了解一起進(jìn)步一起學(xué)習(xí)!裙內(nèi)有開發(fā)工具,很多干貨和技術(shù)資料分享!

// 檢查是否到出口

bool CheckWin()

{

return (g_ptPlayer.y >= g_utExit.y * UNIT + UNIT / 2 + g_ptOffset.y);

}

這些是C/C++能做的

服務(wù)器開發(fā)工程師、人工智能、云計(jì)算工程師、信息安全(黑客反黑客)、大數(shù)據(jù) 、數(shù)據(jù)平臺、嵌入式工程師、流媒體服務(wù)器、數(shù)據(jù)控解、圖像處理、音頻視頻開發(fā)工程師、游戲服務(wù)器、分布式系統(tǒng)、游戲輔助等

可以的話,請大家多多轉(zhuǎn)發(fā)關(guān)注!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容