0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

C语言零基础项目:迷宫游戏!详细思路+源码分享

C语言编程学习基地 来源:C语言编程学习基地 作者:C语言编程学习基地 2022-12-21 10:08 次阅读

每天一个C语言小项目,提升你的编程能力!

迷宫游戏其实有很多种类型,比如说营救公主的一款,又比如说闯关的一款,其他的一些种类这里就不一一列举了。但是不管哪一款迷宫游戏,唯一不变的就是迷宫的实现这一核心功能,每一款迷宫游戏无非就是根据自己的游戏性质在迷宫之中添加一些必要的元素罢了。

我们今天的主要目标就是用C语言来实现迷宫的原本功能,纯天然无污染,没有添加任何防腐剂(因为没有其他的花里胡哨的功能)

f86d38d8-803c-11ed-8abf-dac502259ad0.png

上面就是咱们的效果图预览,以图形库easyX来搭配C语言语法实现的迷宫界面,然后也实现了例如一些按键操作,边界检测这样的功能,整体来说还是比较完善的。

本项目编译环境:Visual Studio 2019/2022,EasyX插件

代码展示:

#include
        
         #include
         
          #include
          
           ////////////////////////////////////////////////////// // 定义全局变量 // BY
           TE** g_aryMap = NULL; // 迷宫地图 SIZE g_szMap; // 迷宫地图的尺寸 IMAGE g_imgSight(360, 280); // 游戏的视野 RECT g_rtSight; // 游戏的视野的范围 IMAGE g_imgItem(180, 20); // 地图元素 IMAGE g_imgGPS; // 迷你地图,用于显示游戏者在地图中的位置 POINT g_ptGPS; // 迷你地图的显示位置 SIZE g_szGPS; // 迷你地图的尺寸 POINT g_ptPlayer; // 游戏者的位置 // 枚举地图元素,兼做元素位置的 x 坐标 enum MA
           PITEM { MAP_WALL = 0, MAP_PLAYER = 20, MAP_GROUND = 40, MAP_MARKRED = 60, MAP_MARKGREEN = 80, MAP_MARKYELLOW = 100, MAP_ENTRANCE = 120, MAP_EXIT = 140, MAP_OUTSIDE = 160 }; // 枚举用户的控制命令 enum CMD { CMD_QUIT = 1, CMD_UP = 2, CMD_DOWN = 4, CMD_LEFT = 8, CMD_RIGHT = 16, CMD_MARKRED = 32, CMD_MARKGREEN = 64, CMD_MARKYELLOW = 128, CMD_CLE
           ARMARK = 256 }; ////////////////////////////////////////////////////// // 函数声明 // void Welcome(); // 绘制游戏界面 void Ini
           tImage(); // 初始化游戏图片 void InitGame(); // 初始化游戏数据 void GetMazeSize(); // 提示用户输入迷宫大小 void MakeMaze(int width, int height); // 生成迷宫:初始化(注:宽高必须是奇数) void TravelMaze(int x, int y); // 生成迷宫:遍历 (x, y) 四周 MAPITEM GetMazeItem(int x, int y); // 获取指定坐标的迷宫元素 void Paint(); // 绘制视野范围内的迷宫 int GetCmd(); // 获取用户输入的命令 void DispatchCmd(int cmd); // 处理用户输入的命令 void OnUp(); // 向上移动 void OnLeft(); // 向左移动 void OnRight(); // 向右移动 void OnDown(); // 向下移动 void OnMark(MAPITEM value); // 在地图中做标记 bool CheckWin(); // 检查是否到出口 bool Quit(); // 询问用户是否退出游戏 ////////////////////////////////////////////////////// // 函数定义 // // 主程序 void main() { // 初始化 initgraph(640, 480); // 创建绘图窗口 srand((unsigned)time(NULL)); // 设置随机种子 // 显示主界面 Welcome(); // 初始化 InitImage(); InitGame(); // 游戏过程 int c; while( !(((c = GetCmd()) & CMD_QUIT) && Quit()) ) { DispatchCmd(c); Paint(); if (CheckWin()) break; // 延时 Sleep(100); } // 清理迷宫地图占用的内存 f
           or(int x = 0; x < g_szMap.cx + 2; x++) delete[] g_aryMap[x]; delete [] g_aryMap; // 关闭图形模式 closegraph(); } // 绘制游戏界面 void Welcome() { // 绘制渐变色外框 for(int i=0; i<128; i++) { setlinecolor(RGB(0, 0, (127 - i) << 1)); rectangle(149 - i, 109 - (i >> 1), 490 + i, 370 + (i >> 1)); } // 设置字体样式 settextcolor(WHITE); setbkmode(TRANSPARENT); // 绘制标题 settextstyle(36, 0, _T("宋体")); outtextxy(248, 40, _T("迷宫")); // 绘制操作说明 settextstyle(12, 0, _T("宋体")); outtextxy(50, 382, _T("控制说明:")); outtextxy(74, 400, _T("方向键或 A/S/D/W:移动")); outtextxy(74, 418, _T("空格、Y、G:在地图上做红、黄、绿色 M 标记")); outtextxy(74, 436, _T("C:清除地图上的标记")); outtextxy(74, 454, _T("ESC:退出程序")); } // 初始化游戏图片 void InitImage() { // 预绘制游戏图片到 IMAGE 缓存(可以修改为加载图片以获得更好效果) SetWorkingImage(&g_imgItem); cleardevice(); // 绘制 PLAYER setorigin(MAP_PLAYER, 0); se
           tfillcolor(YELLOW); setlinecolor(YELLOW); fillellipse(2, 2, 17, 17); setlinecolor(BL
           ACK); line(7, 7, 7, 8); line(12, 7, 12, 8); arc(5, 6, 14, 14, 3.34, 6.08); // 绘制墙壁 setorigin(MAP_WALL, 0); settextcolor(BROWN); setfillstyle((BYTE*)"x20x20x20xffx04x04x04xff"); setlinecolor(BROWN); solidrectangle(1, 1, 18, 18); rectangle(0, 0, 19, 19); // 绘制红色标记 setorigin(MAP_MARKRED, 0); setlinecolor(RED); moveto(5, 15); linerel(0, -10); linerel(5, 5); linerel(5, -5); linerel(0, 10); // 绘制绿色标记 setorigin(MAP_MARKGREEN, 0); setlinecolor(GREEN); moveto(5, 15); linerel(0, -10); linerel(5, 5); linerel(5, -5); linerel(0, 10); // 绘制黄色标记 setorigin(MAP_MARKYELLOW, 0); setlinecolor(YELLOW); moveto(5, 15); linerel(0, -10); linerel(5, 5); linerel(5, -5); linerel(0, 10); // 绘制入口 setorigin(MAP_ENTRANCE, 0); setlinecolor(GREEN); settextstyle(12, 0, _T("宋体")); outtextxy(4, 4, _T("入")); // 绘制出口 setorigin(MAP_EXIT, 0); outtextxy(4, 4, _T("出")); // 绘制迷宫外面的空地 setorigin(MAP_OUTSIDE, 0); settextcolor(GREEN); setfillstyle((BYTE*)"x50x55x22x20x05x55x22x02"); solidrectangle(0, 0, 19, 19); // 恢复坐标系 setorigin(0, 0); // 显示作者 SetWorkingImage(); settextcolor(BLUE); TCHAR author[] = _T("Powered by zhaoh1987@qq.com"); outtextxy(471, 4, author); settextcolor(LIGHTBLUE); outtextxy(470, 3, author); } // 初始化游戏数据 void InitGame() { // 提示用户输入迷宫大小 GetMazeSize(); // 初始化
           参数if (g_aryMap != NULL) { // 清理迷宫地图占用的内存 for(int x = 0; x < g_szMap.cx + 2; x++) delete[] g_aryMap[x]; delete [] g_aryMap; } MakeMaze(g_szMap.cx, g_szMap.cy); // 创建迷宫 g_ptPlayer.x = 2; // 设置游戏者的位置 g_ptPlayer.y = 2; g_rtSight.left = 0; // 设置视野范围 g_rtSight.top = 0; g_rtSight.right = 17; g_rtSight.bottom= 13; // 设置 GPS 显示区 setfillcolor(BLUE); solidrectangle(522, 368, 637, 471); if (g_szMap.cx > g_szMap.cy) { g_szGPS.cx = 100; g_szGPS.cy = (int)(100.0 * g_szMap.cy / g_szMap.cx + 0.5); } else { g_szGPS.cy = 100; g_szGPS.cx = (int)(100.0 * g_szMap.cx / g_szMap.cy + 0.5); } Resize(&g_imgGPS, g_szGPS.cx, g_szGPS.cy); g_ptGPS.x = 530 + 50 - g_szGPS.cx / 2; g_ptGPS.y = 370 + 50 - g_szGPS.cy / 2; // 画迷你地图外框 setlinecolor(RED); rectangle(g_ptGPS.x - 1, g_ptGPS.y - 1, g_ptGPS.x + g_szGPS.cx, g_ptGPS.y + g_szGPS.cy); // 画迷你地图入口和出口 setlinecolor(YELLOW); moveto(g_ptGPS.x - 8, g_ptGPS.y + g_szGPS.cy / g_szMap.cy); linerel(7, 0); linerel(-3, -3); moverel(3, 3); linerel(-3, 3); moveto(g_ptGPS.x + g_szGPS.cx, g_ptGPS.y + g_szGPS.cy - g_szGPS.cy / g_szMap.cy); linerel(7, 0); linerel(-3, -3); moverel(3, 3); linerel(-3, 3); // 绘制游戏区 Paint(); } // 提示用户输入迷宫大小 void GetMazeSize() { g_szMap.cx = g_szMap.cy = 0; // 获取用户输入的宽高 TCHAR s[4]; while(g_szMap.cx < 20 || g_szMap.cx > 200) { InputBox(s, 4, _T("请输入迷宫的宽度 范围:20~200"), _T("输入"), _T("25")); g_szMap.cx = _ttoi(s); } while(g_szMap.cy < 20 || g_szMap.cx > 200) { InputBox(s, 4, _T("请输入迷宫的高度 范围:20~200"), _T("输入"), _T("25")); g_szMap.cy = _ttoi(s); } // 确保宽高为奇数 if (g_szMap.cx % 2 != 1) g_szMap.cx++; if (g_szMap.cy % 2 != 1) g_szMap.cy++; } // 生成迷宫:初始化(注:宽高必须是奇数) void MakeMaze(int width, int height) { if (width % 2 != 1 || height % 2 != 1) return; int x, y; // 定义迷宫尺寸,并分配迷宫内存 g_aryMap = new BYTE*[width + 2]; for(x = 0; x < width + 2; x++) { g_aryMap[x] = new BYTE[height + 2]; memset(g_aryMap[x], MAP_WALL, height + 2); } // 定义边界 for (x = 0; x <= width + 1; x++) g_aryMap[x][0] = g_aryMap[x][height + 1] = MAP_GROUND; for (y = 1; y <= height; y++) g_aryMap[0][y] = g_aryMap[width + 1][y] = MAP_GROUND; // 定义入口和出口 g_aryMap[1][2] = MAP_ENTRANCE; g_aryMap[width][height - 1] = MAP_EXIT; // 从任意点开始遍历生成迷宫 TravelMaze(((rand() % (width - 1)) & 0xfffe) + 2, ((rand() % (height - 1)) & 0xfffe) + 2); // 将边界标记为迷宫外 for (x = 0; x <= width + 1; x++) g_aryMap[x][0] = g_aryMap[x][height + 1] = MAP_OUTSIDE; for (y = 1; y <= height; y++) g_aryMap[0][y] = g_aryMap[width + 1][y] = MAP_OUTSIDE; } // 生成迷宫:遍历 (x, y) 四周 void TravelMaze(int x, int y) { // 定义遍历方向 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; } // 尝试周围四个方向 g_aryMap[x][y] = MAP_GROUND; for(i = 0; i < 4; i++) if (g_aryMap[x + 2 * d[i][0]][y + 2 * d[i][1]] == MAP_WALL) { g_aryMap[x + d[i][0]][y + d[i][1]] = MAP_GROUND; TravelMaze(x + d[i][0] * 2, y + d[i][1] * 2); // 递归 } } // 获取指定坐标的迷宫元素 MAPITEM GetMazeItem(int x, int y) { return (MAPITEM)g_aryMap[x][y]; } // 绘制视野范围内的迷宫 void Paint() { int x1, y1; // 绘制视野内的迷宫 SetWorkingImage(&g_imgSight); for(int x = g_rtSight.left; x <= g_rtSight.right; x++) for(int y = g_rtSight.top; y <= g_rtSight.bottom; y++) { x1 = (x - g_rtSight.left) * 20; y1 = (y - g_rtSight.top) * 20; putimage(x1, y1, 20, 20, &g_imgItem, GetMazeItem(x, y), 0); } // 绘制游戏者 x1 = (g_ptPlayer.x - g_rtSight.left) * 20; y1 = (g_ptPlayer.y - g_rtSight.top) * 20; putimage(x1, y1, 20, 20, &g_imgItem, MAP_PLAYER, 0); // 绘制迷你地图 SetWorkingImage(&g_imgGPS); cleardevice(); int tx = (int)((g_ptPlayer.x - 1) * g_szGPS.cx / (double)(g_szMap.cx - 1) + 0.5); int ty = (int)((g_ptPlayer.y - 1) * g_szGPS.cy / (double)(g_szMap.cy - 1) + 0.5); setlinecolor(YELLOW); circle(tx, ty, 1); // 更新到绘图窗口 SetWorkingImage(); putimage(150, 110, 340, 260, &g_imgSight, 10, 10); putimage(g_ptGPS.x, g_ptGPS.y, &g_imgGPS); } // 获取用户输入的命令 int GetCmd() { int c = 0; if (GetAsyncKeyState(VK_LEFT) & 0x8000) c |= CMD_LEFT; if (GetAsyncKeyState(VK_RIGHT) & 0x8000) c |= CMD_RIGHT; if (GetAsyncKeyState(VK_UP) & 0x8000) c |= CMD_UP; if (GetAsyncKeyState(VK_DOWN) & 0x8000) c |= CMD_DOWN; if (GetAsyncKeyState('A') & 0x8000) c |= CMD_LEFT; if (GetAsyncKeyState('D') & 0x8000) c |= CMD_RIGHT; if (GetAsyncKeyState('W') & 0x8000) c |= CMD_UP; if (GetAsyncKeyState('S') & 0x8000) c |= CMD_DOWN; if (GetAsyncKeyState(' ') & 0x8000) c |= CMD_MARKRED; if (GetAsyncKeyState('G') & 0x8000) c |= CMD_MARKGREEN; if (GetAsyncKeyState('Y') & 0x8000) c |= CMD_MARKYELLOW; if (GetAsyncKeyState('C') & 0x8000) c |= CMD_CLEARMARK; if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) c |= CMD_QUIT; return c; } // 处理用户输入的命令 void DispatchCmd(int cmd) { if (cmd & CMD_UP) OnUp(); if (cmd & CMD_DOWN) OnDown(); if (cmd & CMD_LEFT) OnLeft(); if (cmd & CMD_RIGHT) OnRight(); if (cmd & CMD_MARKRED) OnMark(MAP_MARKRED); if (cmd & CMD_MARKGREEN) OnMark(MAP_MARKGREEN); if (cmd & CMD_MARKYELLOW) OnMark(MAP_MARKYELLOW); if (cmd & CMD_CLEARMARK) OnMark(MAP_GROUND); } // 向上移动 void OnUp() { if (g_ptPlayer.y > 1 && GetMazeItem(g_ptPlayer.x, g_ptPlayer.y - 1) != MAP_WALL) { g_ptPlayer.y--; if (g_ptPlayer.y - g_rtSight.top < 4 && g_rtSight.top > 0) { g_rtSight.top--; g_rtSight.bottom--; } } } // 向左移动 void OnLeft() { if (g_ptPlayer.x > 1 && GetMazeItem(g_ptPlayer.x - 1, g_ptPlayer.y) != MAP_WALL && GetMazeItem(g_ptPlayer.x - 1, g_ptPlayer.y) != MAP_ENTRANCE) { g_ptPlayer.x--; if (g_ptPlayer.x - g_rtSight.left < 5 && g_rtSight.left > 0) { g_rtSight.left--; g_rtSight.right--; } } } // 向右移动 void OnRight() { if (g_ptPlayer.x < g_szMap.cx && GetMazeItem(g_ptPlayer.x + 1, g_ptPlayer.y) != MAP_WALL) { g_ptPlayer.x++; if (g_rtSight.right - g_ptPlayer.x < 5 && g_rtSight.right <= g_szMap.cx) { g_rtSight.left++; g_rtSight.right++; } } } // 向下移动 void OnDown() { if (g_ptPlayer.y < g_szMap.cy && GetMazeItem(g_ptPlayer.x, g_ptPlayer.y + 1) != MAP_WALL) { g_ptPlayer.y++; if (g_rtSight.bottom - g_ptPlayer.y < 4 && g_rtSight.bottom <= g_szMap.cy) { g_rtSight.top++; g_rtSight.bottom++; } } } // 在地图中做标记 void OnMark(MAPITEM value) { g_aryMap[g_ptPlayer.x][g_ptPlayer.y] = value; } // 检查是否到出口 bool CheckWin() { if (g_ptPlayer.x == g_szMap.cx && g_ptPlayer.y == g_szMap.cy - 1) { HWND hwnd = GetHWnd(); if (MessageBox(hwnd, _T("恭喜你走出来了! 您想再来一局吗?"), _T("恭喜"), MB_YESNO | MB_ICONQUESTION) == IDYES) { InitGame(); return false; } else return true; } return false; } // 询问用户是否退出游戏 bool Quit() { HWND hwnd = GetHWnd(); return (MessageBox(hwnd, _T("您确定要退出游戏吗?"), _T("询问"), MB_OKCANCEL | MB_ICONQUESTION) == IDOK); }
          
         
        

大家赶紧去动手试试吧!

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表德赢Vwin官网 网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 游戏
    +关注

    关注

    2

    文章

    714

    浏览量

    26188
  • C语言
    +关注

    关注

    180

    文章

    7561

    浏览量

    133386
  • 编程
    +关注

    关注

    88

    文章

    3495

    浏览量

    93102
  • 源码
    +关注

    关注

    8

    文章

    623

    浏览量

    28889

原文标题:C语言零基础项目:迷宫游戏!详细思路+源码分享

文章出处:【微信号:cyuyanxuexi,微信公众号:C语言编程学习基地】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    C语言零基项目:涂格子(点灯)游戏详细思路+源码分享

    点灯 游戏是一个十分有趣的智力 游戏:有一行N行N列的灯,开始时全部是灭的,当你点击其中一盏灯时他的上下左右(若存在的话)状态全部改变,现在要求你在限定的时间内以最少地步数,将全部的灯点亮。
    发表于12-16 09:47 756次阅读

    C语言零基项目:贪吃蛇!详细思路+源码分享

    每天一个 C 语言项目,提升你的编程能力!
    发表于12-19 11:04 537次阅读

    零基础怎样学习C语言呢?

    零基础学 c 语言如何开始
    发表于05-15 10:23

    C语言游戏源码分享

    C 语言游戏 源码24点火柴人俄罗斯等等等35个 游戏 源码网盘分享链接:https://pan.ba
    发表于04-12 17:11

    C语言零基础入门教学资料汇总下载

    C 语言 零基础入门教学资料汇总下载
    发表于05-29 10:41 132次下载

    C语言零基项目:打字母游戏详细思路+源码分享

    今天就用 C 语言写了这么个打字母的小程序,就是以前学习机上那种字母往下掉,然后按相应键字母消失的 游戏
    发表于12-15 15:02 553次阅读

    C语言零基项目:俄罗斯方块游戏详细思路+源码分享

    由小方块组成的不同形状的板块陆续从屏幕上方落下来,玩家通过调整板块的位置和方向,使它们在屏幕底部拼出完整的一条或几条。这些完整的横条会随即消失,给新落下来的板块腾出空间,与此同时,玩家得到分数奖励。没有被消除掉的方块不断堆积起来,一旦堆到屏幕顶端,玩家便告输, 游戏结束。
    的头像 发表于12-19 14:52 1656次阅读

    C语言零基项目:生命游戏详细思路+源码分享

    生命 游戏不需要任何玩家,它是一个二维矩形世界,这个世界中的每个方格居住着一个活细胞或为空。
    的头像 发表于12-22 11:17 838次阅读

    C语言零基项目:推箱子游戏详细思路+源码分享

    推箱子是一个来自日本的古老 游戏,目的是在训练你的逻辑思考能力。在一个狭小的仓库中,要求把木箱放到指定的位置,稍不小心就会出现箱子无法移动或者通道被堵住的情况,所以需要巧妙的利用有限的空间和通道,合理安排移动的次序和位置,才能顺利的完成任务。
    的头像 发表于12-27 10:38 740次阅读

    C语言零基项目:黑白棋游戏详细思路+源码分享

    《黑白棋》也叫翻转棋或者奥赛罗,其 游戏过程是相互翻转对方的棋子,最后以棋盘上谁的棋子多来判断胜负。虽然规则简单,但是变化复杂,是典型的易学难精,奥妙无穷,不信您就试试看吧!
    的头像 发表于12-29 11:12 829次阅读

    C语言零基项目:自制军棋游戏详细思路+源码分享

    每天一个 C 语言项目,提升你的编程能力!
    的头像 发表于12-29 17:14 8233次阅读

    C语言零基项目:对对碰(消除类)游戏详细思路+源码分享

    游戏中消除的对象为各种各样的头像,包括树、小车、草莓和酒瓶等一些头像。玩家通关移动这些头像位置凑够一定数量的相同图标即可消除。
    的头像 发表于01-03 11:13 610次阅读

    C语言零基项目:吃豆人小游戏详细思路+源码分享

    《吃豆 游戏》是一款休闲小 游戏,和贪吃蛇,球球大作战吃食物都是有差不多的 游戏逻辑。
    的头像 发表于01-03 11:38 1240次阅读

    C语言项目:矿井逃生游戏(密室)!详细思路+源码分享

    密室逃脱相信大部分都玩过了吧?本 游戏就是一种用 C 语言写的类似的 游戏,因为用手电筒照明找路,所以有点像矿工的样子,还是叫它矿井逃生吧!(以下是 游戏
    的头像 发表于01-07 09:41 1197次阅读

    C语言零基项目:打飞机游戏!300行源码分享+详细思路

    游戏中,你操控你的防空车尽可能的多击落飞机,躲避飞机扔的炸弹。
    的头像 发表于01-11 09:31 842次阅读