控制台推箱子小游戏的实现

  • 首先,这个推箱子,是在黑窗口实现的,界面不美观,有能力的写好了可以尝试图形化窗口easyx封装好
    在这里插入图片描述

先来看看完整代码

#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <Windows.h>
#include <stdbool.h>//枚举定义变量
enum Element
{SPACE,WALL,PLAYER,BOX,DEST
};//空地 :0  墙:1  玩家:2  箱子:3  目的地:4
char map[9][9] =
{0,0,1,1,1,0,0,0,0,0,0,1,4,1,0,0,0,0,0,0,1,0,1,1,1,1,0,1,1,1,3,0,3,4,1,0,1,4,0,3,2,1,1,1,0,1,1,1,1,3,1,0,0,0,0,0,0,1,4,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
};/**********声明函数**************/
void drawMap();			//绘制地图
void KeyEvent();		//响应按键
void Win();				//判断输赢
void hideCursor();		//隐藏控制台光标
/********************************///显示地图
void drawMap()
{for (int i = 0; i < 9; i++){for (int k = 0; k < 9; k++){switch (map[i][k]){case SPACE:printf("  ");break;case WALL:printf("■");break;case PLAYER:printf("♀");break;case BOX:printf("◆");break;case DEST:printf("●");break;case BOX + DEST:printf("★");break;default:break;}}putchar('\n');}printf("墙:■,玩家:♀,箱子:◆,目的地:●,箱子到达目的地:★\n");puts("W:上");puts("S:下");puts("A:左");puts("D:右");
}
//按键操作
void KeyEvent()
{int lines = 0;int cols = 0;for (int i = 0; i < 9; i++){for (int k = 0; k < 9; k++){if (map[i][k]==PLAYER || map[i][k] == PLAYER + DEST)//定位玩家位置{lines = i;cols = k;}}}switch (getch()){case 'w':case 'W':case 72://玩家上面是空地或目的地if (map[lines - 1][cols] == SPACE || map[lines - 1][cols] == DEST){map[lines][cols] -= PLAYER;map[lines - 1][cols] += PLAYER;}//玩家上面是箱子或者玩家上面是箱子在目的地上else if (map[lines - 1][cols] == BOX || map[lines - 1][cols] == DEST + BOX){//如果有移动的地方(箱子上面是空地或目的地)就进行移动if (map[lines - 2][cols] == SPACE || map[lines - 2][cols] == DEST){map[lines][cols] -= PLAYER;map[lines][cols] += PLAYER;map[lines][cols] -= BOX;map[lines - 2][cols] += BOX;}}break;case 's':case 'S':case 80://玩家下面是空地或目的地if (map[lines + 1][cols] == SPACE || map[lines + 1][cols] == DEST){map[lines][cols] -= PLAYER;map[lines + 1][cols] += PLAYER;}//玩家下面是箱子或者玩家下面是箱子在目的地上else if (map[lines + 1][cols] == BOX || map[lines + 1][cols] == DEST + BOX){//如果有移动的地方(箱子下面是空地或目的地)就进行移动if (map[lines + 2][cols] == SPACE || map[lines + 2][cols] == DEST){map[lines][cols] -= PLAYER;map[lines + 1][cols] += PLAYER;map[lines + 1][cols] -= BOX;map[lines + 2][cols] += BOX;}}break;case 'a':case 'A':case 75://玩家左面是空地或目的地if (map[lines][cols - 1] == SPACE || map[lines][cols - 1] == DEST){map[lines][cols] -= PLAYER;map[lines][cols - 1] += PLAYER;}//玩家左面是箱子或者玩家左面是箱子在目的地上else if (map[lines][cols - 1] == BOX || map[lines][cols - 1] == DEST + BOX){//如果有移动的地方(箱子左面是空地或目的地)就进行移动if (map[lines][cols - 2] == SPACE || map[lines][cols - 2] == DEST){map[lines][cols] -= PLAYER;map[lines][cols - 1] += PLAYER;map[lines][cols - 1] -= BOX;map[lines][cols - 2] += BOX;}}break;case 'd':case 'D':case 77://玩家右面是空地或目的地if (map[lines][cols + 1] == SPACE || map[lines][cols + 1] == DEST){map[lines][cols] -= PLAYER;map[lines][cols + 1] += PLAYER;}//玩家右面是箱子或者玩家右面是箱子在目的地上else if (map[lines][cols + 1] == BOX || map[lines][cols + 1] == DEST + BOX){//如果有移动的地方(箱子右面是空地或目的地)就进行移动if (map[lines][cols + 2] == SPACE || map[lines][cols + 2] == DEST){map[lines][cols] -= PLAYER;map[lines][cols + 1] += PLAYER;map[lines][cols + 1] -= BOX;map[lines][cols + 2] += BOX;}}break;default:break;}
}//隐藏光标,对控制台进行美化
void hideCursor()
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);	//找到控制台的窗口句柄CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(handle, &CursorInfo);			//获取控制台光标信息CursorInfo.bVisible = false;						//隐藏控制台光标SetConsoleCursorInfo(handle, &CursorInfo);			//设置控制台光标状态
}//判断输赢并且反馈给用户
void Win()
{int result = 0;for (int i = 0; i < 9; i++){for (int k = 0; k < 9; k++){if (map[i][k] == BOX){result++;}}}if (result == 0){Sleep(100);MessageBox(NULL, L"你赢了", L"Win", MB_OK);exit(0);}
}int main()
{system("mode con lines=25 cols=50");//调整控制台大小hideCursor();while (1){system("cls");drawMap();Win();KeyEvent();}
}

下面对代码进行解释:

定义游戏元素和地图

  • 下面是对于推箱子游戏的每个元素用数据的形式进行表示,因为一直用数字也不太方便观看,可读性不高
enum Element
{SPACE,WALL,PLAYER,BOX,DEST
};
  • 下面就是你自己定义的地图,当然,你也可以用我们上面用枚举定义好的变量来替换,因为数字比较好敲,我就不进行替换了。
//空地 :0  墙:1  玩家:2  箱子:3  目的地:4
char map[9][9] =
{0,0,1,1,1,0,0,0,0,0,0,1,4,1,0,0,0,0,0,0,1,0,1,1,1,1,0,1,1,1,3,0,3,4,1,0,1,4,0,3,2,1,1,1,0,1,1,1,1,3,1,0,0,0,0,0,0,1,4,1,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,
};
  • 再接下来就是加载游戏地图部分,逻辑不难我就不多赘述了
    但是有一点要注意的是win11下的控制台打印出来的特殊字符占的是一个汉字大小的1/2,所以要在每个特殊字符后面加上一个空格来使这些字符组成一个完整的正方形。(其实就是用易读的符号去替换掉数字而已)
  • win11运行效果展示:
    win11的运行效果图
    win10运行效果展示:
    win10的运行效果图
void drawMap()
{for (int i = 0; i < 9; i++){for (int k = 0; k < 9; k++){switch (map[i][k]){case SPACE:printf("  ");break;case WALL:printf("■");break;case PLAYER:printf("♀");break;case BOX:printf("◆");break;case DEST:printf("●");break;case BOX + DEST:printf("★");break;default:break;}}putchar('\n');}printf("墙:■,玩家:♀,箱子:◆,目的地:●,箱子到达目的地:★\n");puts("W:上");puts("S:下");puts("A:左");puts("D:右");
}

按键操作

锁定玩家位置

  • 接下来就是最最最重要的逻辑部分了
  • 下面进行解释:
          首先我们要清楚,对于推箱子这个游戏我们是对玩家进行的移动,所以就不难解释下面这一部分的定位玩家位置的代码,就是要先找到玩家在哪个地方,然后对玩家的上下左右进行判断
int lines = 0;int cols = 0;for (int i = 0; i < 9; i++){for (int k = 0; k < 9; k++){if (map[i][k]==PLAYER || map[i][k] == PLAYER + DEST)//定位玩家位置{lines = i;cols = k;}}}

游戏移动逻辑判断

  • 然后就到了该游戏的逻辑部分:
          首先,什么情况下玩家可以移动呢,那不就是玩家周围是空地和目的地吗,所以我们就进行判断(这里以向上为例,其它类比)
    如果玩家上面是空地和目的地的话,我们就让玩家站的地方(map[lines][cols])进行-=玩家的操作(通俗来说就是玩家走了),然后我们对玩家的上一格进行+=玩家的操作(玩家来了),其实到了这里我们就能体会到用枚举来替换数据的好处了(更直观!!!)
          那有的小伙伴就要问了,为什么不用=,而要用+=和-=呢,你可以自己实现一遍,用的如果是=的话就会出现下面的情况,玩家怎么分身了,那是因为不减的话,玩家所在的位置就没有进行清空操作
    是=的情况
  • 接下来我们解释如果玩家周围有阻挡物(箱子 或者是 箱子在目的地上这个整体)该怎么办,首先肯定要判断这个箱子的周围有没有可以移动的位置,有的话才可以移动,然后玩家所在的地方要进行-=操作(玩家走了),玩家的上一格进行+=玩家的操作和-=箱子的操作(玩家来了,箱子走了),玩家的上上格进行+=箱子的操作(箱子来了)代码如下:
          其它三种情况也是同理(就不一一赘述了)
else if (map[lines - 1][cols] == BOX || map[lines - 1][cols] == DEST + BOX){//如果有移动的地方(箱子上面是空地或目的地)就进行移动if (map[lines - 2][cols] == SPACE || map[lines - 2][cols] == DEST){map[lines][cols] -= PLAYER;map[lines - 1][cols] += PLAYER;map[lines - 1][cols] -= BOX;map[lines - 2][cols] += BOX;}}
//按键操作
void KeyEvent()
{switch (getch()){case 'w':case 'W':case 72://玩家上面是空地或目的地if (map[lines - 1][cols] == SPACE || map[lines - 1][cols] == DEST){map[lines][cols] -= PLAYER;map[lines - 1][cols] += PLAYER;}//玩家上面是箱子或者玩家上面是箱子在目的地上else if (map[lines - 1][cols] == BOX || map[lines - 1][cols] == DEST + BOX){//如果有移动的地方(箱子上面是空地或目的地)就进行移动if (map[lines - 2][cols] == SPACE || map[lines - 2][cols] == DEST){map[lines][cols] -= PLAYER;map[lines][cols] += PLAYER;map[lines][cols] -= BOX;map[lines - 2][cols] += BOX;}}break;case 's':case 'S':case 80://玩家下面是空地或目的地if (map[lines + 1][cols] == SPACE || map[lines + 1][cols] == DEST){map[lines][cols] -= PLAYER;map[lines + 1][cols] += PLAYER;}//玩家下面是箱子或者玩家下面是箱子在目的地上else if (map[lines + 1][cols] == BOX || map[lines + 1][cols] == DEST + BOX){//如果有移动的地方(箱子下面是空地或目的地)就进行移动if (map[lines + 2][cols] == SPACE || map[lines + 2][cols] == DEST){map[lines][cols] -= PLAYER;map[lines + 1][cols] += PLAYER;map[lines + 1][cols] -= BOX;map[lines + 2][cols] += BOX;}}break;case 'a':case 'A':case 75://玩家左面是空地或目的地if (map[lines][cols - 1] == SPACE || map[lines][cols - 1] == DEST){map[lines][cols] -= PLAYER;map[lines][cols - 1] += PLAYER;}//玩家左面是箱子或者玩家左面是箱子在目的地上else if (map[lines][cols - 1] == BOX || map[lines][cols - 1] == DEST + BOX){//如果有移动的地方(箱子左面是空地或目的地)就进行移动if (map[lines][cols - 2] == SPACE || map[lines][cols - 2] == DEST){map[lines][cols] -= PLAYER;map[lines][cols - 1] += PLAYER;map[lines][cols - 1] -= BOX;map[lines][cols - 2] += BOX;}}break;case 'd':case 'D':case 77://玩家右面是空地或目的地if (map[lines][cols + 1] == SPACE || map[lines][cols + 1] == DEST){map[lines][cols] -= PLAYER;map[lines][cols + 1] += PLAYER;}//玩家右面是箱子或者玩家右面是箱子在目的地上else if (map[lines][cols + 1] == BOX || map[lines][cols + 1] == DEST + BOX){//如果有移动的地方(箱子右面是空地或目的地)就进行移动if (map[lines][cols + 2] == SPACE || map[lines][cols + 2] == DEST){map[lines][cols] -= PLAYER;map[lines][cols + 1] += PLAYER;map[lines][cols + 1] -= BOX;map[lines][cols + 2] += BOX;}}break;default:break;}
}

判断输赢

  • 什么情况下算赢呢?
          当你这个游戏通关时,场上就没有箱子了,那么我们就可以用场上是否有箱子来判断输赢(有箱子,没赢;没箱子,赢)
          我们可以用弹窗显示的方法进行输赢的反馈,也就是Messagebox()函数
//判断输赢并且反馈给用户
void Win()
{int result = 0;for (int i = 0; i < 9; i++){for (int k = 0; k < 9; k++){if (map[i][k] == BOX){result++;}}}if (result == 0){Sleep(100);MessageBox(NULL, L"你赢了", L"Win", MB_OK);exit(0);}
}

调用所写的功能函数

  • 窗口太大,游戏界面太小看起来不太美观
          我们可以用调用cmd命令(system()函数)来实现控制台的大小设置
  • system("mode con lines=25 cols=50");//调整控制台大小
  • 然后死循环不断调用函数来实现游戏
int main()
{system("mode con lines=25 cols=50");//调整控制台大小while (1){system("cls");drawMap();Win();KeyEvent();}
}

界面美化

      其实到了这里,所需的功能都已经完成了,但是当我们在进行运行的时候会有一个光标一直存在,不太美观
那么我们就可以对光标进行伪装
这段代码来自于https://blog.csdn.net/nocomment_84/article/details/53992730

void hideCursor()
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);	//找到控制台的窗口句柄CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(handle, &CursorInfo);			//获取控制台光标信息CursorInfo.bVisible = false;						//隐藏控制台光标SetConsoleCursorInfo(handle, &CursorInfo);			//设置控制台光标状态
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/48263.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于C#制作一个飞机大战小游戏

此文主要基于C#制作一个飞机大战游戏,重温经典的同时亦可学习。 实现流程1、创建项目2、界面绘制3、我方飞机4、敌方飞机5、子弹及碰撞检测实现流程 1、创建项目 打开Visual Studio,右侧选择创建新项目。搜索框输入winform,选择windows窗体应用,填写对应的保存路径点击下一…

CCL2023-Eval | 汉语高考机器阅读理解对抗鲁棒评测正式开启,诚邀您积极参与

简介 机器阅读理解领域近年来取得了显著的发展成果&#xff0c;然而&#xff0c;在面向开放、动态、真实环境下的推理与决策时&#xff0c;模型鲁棒性仍有待提高。为此&#xff0c;山西大学自然语言处理团队基于“CCL2022-高考语文阅读理解可解释评测”数据集 GCRC 构建了对抗鲁…

Java对接钉钉机器人推送消息

自定义钉钉机器人推送使用 钉钉官方文档 使用场景 可用于替换短信发送节约成本&#xff0c;也可以将报警等消息推送到指定的钉钉群中 调用频率限制 由于消息发送太频繁会严重影响群成员的使用体验&#xff0c;因此钉钉开放平台对自定义机器人发送消息的频率作出以下限制&…

DingTalk「开发者说」 钉钉连接平台:打通企业数据孤岛的开发实践

钉钉连接平台简介 钉钉连接平台是什么&#xff1f; 简单来说&#xff0c;钉钉连接平台是打破企业系统数据孤岛的开发平台。钉钉连接平台通过统一的标准协议&#xff0c;接入各类应用和系统&#xff0c;并提供强安全、高可用、轻量化的连接能力&#xff0c;同时输出覆盖各类业…

JAVA对接钉钉

正文 公司要求对接钉钉&#xff0c;之前没对接过&#xff0c;相当于从0开始&#xff0c;记录一下对接的过程 1、访问钉钉官网 申请成为开发者 因为公司没对接过&#xff0c;所以我自己注册了一个公司&#xff08;公司名随便填&#xff0c;其他的按要求填就好&#xff09; …

java对接钉钉 发送/更新 互动卡片消息

java对接钉钉 发送/更新 互动卡片消息 一、准备工作二、发送互动卡片消息三、更新互动消息卡片 先看下效果图 点击相应的积分按钮&#xff0c;就会给对应的申请人发送对应的积分&#xff08;对接到我们自己的系统发送&#xff09;&#xff0c;审核完之后&#xff0c;按钮变成已…

PHP-钉钉扫码登录对接第三方网站

这个小功能对于企业内部的一些自用后台网站还是很常用的&#xff0c;对接也相对简单&#xff0c;记录下对接流程。 开发文档&#xff1a;扫码登录第三方网站 - 钉钉开放平台 1.先登录钉钉开发者后台&#xff0c;创建扫码登录应用授权 开发者后台统一登录 - 钉钉统一身份认证 …

TED1984-2019全部中英对照演讲稿集 学习英文演讲写作的好帮手

TED1984-2019全部中英对照演讲稿集 学习英文演讲写作的好帮手 一、TED简介&#xff1a; TED&#xff08;指Technology, Entertainment, Design在英语中的缩写&#xff0c;即技术、娱乐、设计&#xff09;是美国的一家私有非营利机构&#xff0c;该机构以它组织的TED大会著称&…

那些会讲ppt的技术人有多爽?演讲的6个步骤

一场好的技术分享&#xff0c;可以用“有趣有料”四个字来形容&#xff0c;那么如何才能做到有趣又有料呢&#xff1f;结合我的经历&#xff0c;做了一些总结。 2015年&#xff0c;我出版《技术管理之巅》以后&#xff0c;先后收到QCon、CSDN、IT168等业界知名技术大会的邀请担…

关于计算机的英语演讲ppt模板,英语演讲ppt模板

目录 一、英语演讲ppt素材 ①.要简单点的 内容不限 但最好是寓言或者能给人点启示的东西 有意思就行 背景。 ②.要简单点的 内容不限 但最好是寓言或者能给人点启示的东西 有意思就行 背景。 ③.时间3-5分钟&#xff0c;主题无所谓&#xff0c;liuxiaoxuan89tom.com ④.Mans li…

自定义Msgbox密码登录

背景&#xff1a;虽然Excel是自带密码功能的&#xff0c;但是设置了密码以后&#xff0c;打开excel&#xff0c;是看不到excel的内容的。 如果想让使用者打开excel&#xff0c;能大概看到excel的内容 &#xff0c;但是会有弹窗&#xff0c;导致没法选择和更改数据&#xff0c;就…

Linux 系统密码策略设置

目录 Linux主要密码安全需求 1. 禁止使用旧密码 2.设置密码最短长度 3.设置密码复杂度 4.设置密码过期期限 Linux密码策略理论知识&#xff1a; 1、使用配置文件/etc/pam.conf 2、使用配置目录/etc/pam.d/ 讲怎么使用&#xff0c;后面有理论教程&#xff0c;先知其然再…

远程计算机guest密码更改了,怎么给guest设置密码

我们一般是在控制面板 - 用户帐户下启用来宾帐户&#xff0c;但我们可以在guest(供来宾访问计算机或访问域的内置帐户)下新建用户名和设置密码&#xff0c;方法简单&#xff0c;操作容易。下面是学习啦小编给大家整理的一些有关给guest设置密码的方法&#xff0c;希望对大家有帮…

计算机知识科普讲解大赛,谁是科普达人?2020年成都市科普讲解大赛拉开帷幕...

生活中无处不在的电磁波是怎样产生的呢&#xff1f; 被称为“汉代计算机”的一钩多综式提花织机与成都有什么关系&#xff1f; …… 近日&#xff0c;成都博物馆&#xff0c;40余家单位的70余名选手&#xff0c;通过4分钟参赛视频&#xff0c;亮相2020年成都市科普讲解大赛预赛…

chatgpt赋能python:Python预测分析:什么是预测分析?

Python预测分析&#xff1a;什么是预测分析&#xff1f; 随着数字化时代的到来&#xff0c;数据越来越多&#xff0c;数据分析的需求也随之增加。预测分析就是一种基于数据分析的技术&#xff0c;可以通过数据分析并应用统计模型&#xff0c;来预测未来发生的事件或趋势&#…

度盘搜失效?这款网盘搜索神器万万别错过!

奶糖猫来啦&#xff01;资源搜索一直以来都是需求非常大的一方面&#xff0c;总会有伙伴问我有没有这方面比较好用的软件。 之前很火的度盘搜失效了&#xff0c;后面也出现了一系列的资源搜索工具&#xff0c;但总存在一个致命的问题&#xff0c;资源普遍太老了&#xff0c;不能…

好用的网盘搜索引擎

最近&#xff0c;我们见到了许多安利网盘搜索引擎的推文&#xff0c;安利了很多网址和论坛。但经过答主亲测&#xff0c;许多被提到的网站&#xff0c;不是打不开链接&#xff0c;就是进去发现是广告&#xff0c;早已经被封停了&#xff0c;所以我们亲自测试了一些这方面的内容…

百度云盘搜索助手 V1.2(可查询提取码,带5个搜索引擎)

介绍&#xff1a; 云盘搜索助手功能强大&#xff0c;操作简单&#xff0c;使用后可以帮助用户更轻松快捷的搜索云盘资源。软件内置5个搜索引擎供您查资源&#xff0c;另外内置查询提取码功能。 网盘下载地址&#xff1a; http://www.bytepan.com/bNjeq9AKuVC 图片&#xff1a…

百度网盘_SEARCH

需求分析 我有一些资源网站&#xff0c;但是每次我需要资源的时候需要打开他们的网页&#xff0c;搜索再筛选我需要的网盘资源&#xff0c;这样的操作非常麻烦使用python模拟这些搜索操作&#xff0c;然后爬取我需要的百度网盘信息用python的Gui编程开发一个简单的界面 实现 …

使用ChatGPT进行个性化学习

推荐&#xff1a;将 NSDT场景编辑器 加入你的3D工具链 3D工具集&#xff1a; NSDT简石数字孪生 在这篇文章中&#xff0c;您将发现 ChatGPT 作为机器学习和数据科学爱好者的个人导师的好处。特别是&#xff0c;您将学习 如何让ChatGPT引导你学习抽象代数如何让 ChatGPT 帮助您…