(图书介绍:童晶:《C和C++游戏趣味编程》新书预告)

本章我们将编写推箱子游戏,玩家键盘控制游戏角色将所有黄色箱子推到白色方块处,效果如图所示。

首先学习字符串与字符数组的概念,并应用字符数组初始化关卡数据;然后利用键盘控制游戏角色移动,实现地图元素更新和游戏胜利的判断;接着利用三维字符数组,实现多关卡的游戏;最后学习基于文件的关卡数据读取,利用枚举类型改进游戏代码。

9 推箱子

讲解视频:

最终代码:

#include <graphics.h>
#include <conio.h>
#include <stdio.h>
#define B_SIZE 60 // 方块大小
#define B_NUM 8 // 方块个数,一共8*8个方块struct Player // 结构体,用于记录玩家位置
{int i;int j;
};
Player player; // 玩家全局变量enum Element // 定义枚举类型,小方块所有的可能的种类
{wall,target,box,empty,achieved,role
};// 用于存储地图数据,用枚举类型实现
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; // 目标位置个数、完成目标个数void startup()  // 初始化函数
{initgraph(B_NUM*B_SIZE,B_NUM*B_SIZE); // 新开一个画面setbkcolor(RGB(150,150,150)); // 灰色背景BeginBatchDraw(); // 开始批量绘图int i,j;targetNum = 0; // 目标个数,初始为0// 对二维数组遍历for (i=0;i<B_NUM;i++)for (j=0;j<B_NUM;j++){if (level[i][j]==role) // 找到地图中player位置{player.i = i; // 设定player位置player.j = j; // level[i][j]=empty; // 把地图元素变成空白empty}else if (level[i][j]==target || level[i][j]==achieved ) // 如果元素是target或achievedtargetNum++; // 目标个数+1}
}void show() // 绘制函数
{int i,j;cleardevice(); // 以背景颜色清空屏幕// 遍历关卡二维数组数据for (i=0;i<B_NUM;i++){for (j=0;j<B_NUM;j++){if (level[i][j]==empty) // empty 元素是空白区域{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 元素是可移动的箱子{setfillcolor(RGB(255,255,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]==target) // target 元素是目标{setfillcolor(RGB(250,250,250)); // 绘制一个白色的小方块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 元素是已完成目标{setlinecolor(RGB(150,150,150));setfillcolor(RGB(255,255,0)); // 绘制一个黄色的方块fillrectangle(j*B_SIZE,i*B_SIZE,(j+1)*B_SIZE,(i+1)*B_SIZE);setfillcolor(RGB(250,250,250)); // 绘制一个白色的小方块fillrectangle((j+0.3)*B_SIZE,(i+0.3)*B_SIZE,(j+0.7)*B_SIZE,(i+0.7)*B_SIZE);}      }}// 以下绘制玩家,绘制一个人脸图案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);//一个红色圆脸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);//两个黑色眼睛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) // 如完成目标个数==目标个数{setbkmode(TRANSPARENT); // 透明显示文字settextcolor(RGB(0,255,255)); // 设置字体颜色settextstyle(80, 0, _T("宋体")); // 设置字体大小、样式outtextxy(80,200,_T("游戏胜利")); // 显示游戏胜利文字}FlushBatchDraw(); // 开始批量绘制
}void update()  // 每帧更新运行
{if(kbhit() && (achievedNum<targetNum) )  // 如果按键,并且游戏没有胜利{char input = getch(); // 获取按键if (input=='a' || input=='s' || input=='d' || input=='w') // 如果是有效按键{int goal_i = player.i; // 移动的目标位置int goal_j = player.j;int goalNext_i = goal_i; // 目标位置再向前的一个位置int goalNext_j = goal_j;// 根据用户的不同按键输入,获得目标位置、再向前的一个位置if (input=='a') // 向左{goal_j = player.j -1 ; // 目标位置在玩家位置的左边goalNext_j = goal_j-1; // 目标的下一个位置,在其再左边}else if (input=='d') // 向右{goal_j = player.j +1 ; // 目标位置在玩家位置的右边 goalNext_j = goal_j+1; // 目标的下一个位置,在其再右边}else if (input=='s') // 向下{goal_i = player.i+1; // 目标位置在玩家位置的下边 goalNext_i = goal_i+1; // 目标的下一个位置,在其再下边 }else if (input=='w') // 向上{goal_i = player.i-1; // 目标位置在玩家位置的上边 goalNext_i = goal_i-1; // 目标的下一个位置,在其再上边 }// 根据不同地图元素的情况,判断如何移动角色和更新地图元素    if (level[goal_i][goal_j]==empty || level[goal_i][goal_j]==target ) {   // 如果目标位置是empty,或者targetplayer.i = goal_i; // 玩家移动到目标位置player.j = goal_j;            }else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==empty ) {    // 如果目标位置是box,再前面一个是emptyplayer.i = goal_i; // 玩家移动到目标位置player.j = goal_j;     level[goal_i][goal_j]=empty;  // 目标位置变成emptylevel[goalNext_i][goalNext_j]=box;     // 再前面变成box}else if (level[goal_i][goal_j]==box && level[goalNext_i][goalNext_j]==target) {    // 如果目标位置是box,再前面一个是targetplayer.i = goal_i; // 玩家移动到目标位置player.j = goal_j;  level[goal_i][goal_j] = empty;  // 目标位置变成empty level[goalNext_i][goalNext_j] = achieved;    // 再前面变成achieved}else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== empty) {   // 如果目标位置是achieved,再前面一个是emptyplayer.i = goal_i; // 玩家移动到目标位置player.j = goal_j;      level[goal_i][goal_j] = target;  // 目标位置变成target level[goalNext_i][goalNext_j] = box; // 再前面变成box   }else if (level[goal_i][goal_j]==achieved && level[goalNext_i][goalNext_j]== target) {  // 如果目标位置是achieved,再前面一个是targetplayer.i = goal_i; // 玩家移动到目标位置player.j = goal_j;level[goal_i][goal_j] = target;  // 目标位置变成target  level[goalNext_i][goalNext_j] = achieved; // 再前面变成achieved     }else // 其他情况都推不动return; // 不做任何处理,函数直接返回}achievedNum = 0; // 完成目标个数,初始为0int i,j;for (i=0;i<B_NUM;i++) // 对二维数组遍历for (j=0;j<B_NUM;j++) // if (level[i][j]==achieved) // 如果元素是achievedachievedNum++; // 完成目标个数+1}
}int main() // 主函数
{startup();  // 初始化 while (1)  // 游戏主循环{show();     // 绘制update();   // 更新}return 0;
}

这一章主要讲解了字符串与字符数组、文件读写、枚举类型等语法知识,实现了推箱子游戏。读者可以尝试在本章代码基础上继续改进:

1、实现多关卡的选择界面;

2、实现某一步移动的撤销功能(类似于下棋游戏中的悔棋功能);

3、实现按'h'键后进行提示,播放正确步骤动画的功能;

4、实现一个图形编辑器,并将设计的关卡信息保存为txt文件。

读者也可以参考本章的开发思路,尝试设计并分步骤实现走迷宫、华容道等小游戏。

第9章 推箱子(《C和C++游戏趣味编程》配套教学视频)相关推荐

  1. 第12章 坚持一百秒(《C和C++游戏趣味编程》教学视频)

    (图书介绍:童晶:<C和C++游戏趣味编程>新书预告) 本章我们将编写坚持一百秒游戏,玩家通过鼠标控制火箭躲避一架UFO和越来越多的反弹子弹,效果如图所示. 首先学习图片的导入和显示,并利 ...

  2. 《推箱子》python小游戏(第二期)

    欢迎加入我们卧虎藏龙的python讨论qq群:996113038 ┉┉┉┉┉┉ 『导语』 ┉┉┉┉┉┉ 上期给大家讲了 最基本的推箱子原理 也就是游戏元素怎么表示 我们说了用"棋盘" ...

  3. python趣味编程100_《Python游戏趣味编程》 第8章 勇闯地下一百层

    知乎视频​www.zhihu.com 图书简介可以看这里:童晶:<Python游戏趣味编程>新书上架了​zhuanlan.zhihu.com 本章我们将编写一个勇闯地下一百层的游戏,键盘控 ...

  4. 弟子规python编程游戏_《Python游戏趣味编程》 第11章 消灭星星

    知乎视频​www.zhihu.com 图书简介可以看这里: 童晶:<Python游戏趣味编程>新书上架了​zhuanlan.zhihu.com 消灭星星是一款非常容易上瘾的消除类游戏,只需 ...

  5. python循环绘制六角星_《Python游戏趣味编程》 第3章 美丽的圆圈画

    知乎视频​www.zhihu.com 图书简介可以看这里: 童晶:<Python游戏趣味编程>新书上架了​zhuanlan.zhihu.com 本章我们将利用Python绘制美丽的圆圈画, ...

  6. c++ 随机字符串_第3章 别碰白块(《C和C++游戏趣味编程》配套教学视频)

    (图书介绍:童晶:<C和C++游戏趣味编程>新书预告) 本章我们将实现一个小球跳跃躲避方块的游戏. 首先学习字符的知识,按空格键控制小球起跳:然后学习矩形的绘制,利用逻辑运算符实现小球和方 ...

  7. 《C和C++游戏趣味编程》 第8章 十步万度

    没想到前几天新书预告中(童晶:<C和C++游戏趣味编程>新书预告),有这么多朋友对实现十步万度游戏感兴趣,下面提前开源最终代码. 这个案例使用VS 2010 + EasyX开发,感兴趣的朋 ...

  8. 第1章 C/C++与开发环境介绍(《C和C++游戏趣味编程》配套教学视频)

    三年前,我写了一本<c语言课程设计与游戏开发实践教程>,评价还可以. 按这种教学方法教学,一些同学的游戏大作业视频: 前一段时间,我想能否走的更极端一些,尽量脱离小黑窗,从一开始的语法知识 ...

  9. 第3章 别碰白块(《C和C++游戏趣味编程》配套教学视频)

    (图书介绍:童晶:<C和C++游戏趣味编程>新书预告) 本章我们将实现一个小球跳跃躲避方块的游戏. 3 别碰白块 首先学习字符的知识,按空格键控制小球起跳:然后学习矩形的绘制,利用逻辑运算 ...

最新文章

  1. springboot(二):web综合开发
  2. pycharm 更改字体和界面样式
  3. IntelliJ IDEA 2018.1正式发布!什么?还能这么玩?
  4. UVa272 - TEX Quotes(输入输出)
  5. 数据结构32:树存储结构
  6. 23. Leetcode 86. 分隔链表 (链表-基础操作类-分隔链表)
  7. Mysql索引的类型和优缺点
  8. 第十三届东北师范大学程序设计竞赛热身赛 C(exgcd+欧拉函数)
  9. Fedora的systemctl命令详解 Fedora配置IP地址/DNS/Networking
  10. java中的算数运算符号用法与原理分析
  11. IOS 文件管理 2
  12. c语言 消除最后一个空格,新人提问:如何将输出时每行最后一个空格删除
  13. 大连理工大学计算机视觉实验室,首个镜子分割网络问世,大连理工、鹏城实验室、香港城大出品 | ICCV 2019...
  14. ztree 自定义参数_jQuery Ztree基本用法
  15. 数据治理系列1:数据治理框架【解读分析】
  16. 【C语言】求方程式 ax^2+bx+c=0 的根, 分别考虑: 1、有两个不等的实根 2、有两个相等的实根
  17. NIPS2022各学校统计,去China是200+哦~
  18. jsp怎么做柱状图_js实现柱状图
  19. Exp3 免杀原理与实践 ——20164316张子遥
  20. 虚拟服务器和vdi,如何搭建高效虚拟桌面架构(VDI)

热门文章

  1. 第 20 次 CSP认证 202009-5 密信与计数
  2. 【已解决】显示屏没有问题,主机电源键按不开机怎么办?
  3. PostgreSQL and SQLAlchemy [ubuntu]
  4. 东大OJ-一元三次方程解的个数
  5. 面试题 01.01. 判定字符是否唯一 (计数排序思想)
  6. Collections集合工具类的方法
  7. mongodb数据库调用
  8. 第二次作业+105032014037
  9. Spring中的ApplicationContextAware使用
  10. 解析activity之间数据传递方法的详解