C 语言 ConsoleRogueLike 控制台肉鸽游戏 DEVC++ VS2022都可用

使用 C 语言和 windows 的键盘检测函数和延迟函数,开发的控制台 roguelike 游戏
点开 .exe 文件立即进入游戏
AWSD 移动
J 攻击
K 加成buff
没有结束条件,除非碰到敌人。
其他模块功能还没来得及开发

author : 民用级脑的研发记录
DEVC++ 项目工程代码副本:
链接:https://pan.baidu.com/s/1HVjKRDJrzxtRlddyfrBZow 
提取码:jhip
VS2022 项目工程代码副本
链接:https://pan.baidu.com/s/1vWCI2EIdNwpyqdoeNV2-DA 
提取码:aexz
CSDN 源代码 
https://mp.csdn.net/mp_blog/creation/editor?spm=1001.2101.3001.5352
代码请随意使用,在下抛砖引玉,给其他初学者的一点参考代码

BUG 说明:

在第一行时,敌人不会接触。
原理暂不明确,可能是坐标计算错了。
不打算修正了,直接当安全区可还行?

Have a good time

未完待续,后续若整好了 C 语言的 RPG 地图编辑器也一并开源

 

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <windows.h>
#define KEY_DOWN(vKey) ((GetAsyncKeyState(vKey) & 0x8000) ? 1:0)							// 判断是否按下按键,按下之后,最高位变成1,所以需要位运算去除其他位,只检测最高位 
#define KEY_DOWN_FOREGROUND(hWnd,vk) (KEY_DOWN(vk) && GetForegroundWindow() == hWnd) 		// 前景窗口判断
#pragma warning(disable : 4996)																// VS2022 报错某些不安全函数,这里禁用 VS 的某些警告 方便在其他函数移植进 Visualstdio2022 
struct enemys
{
	int x;
	int y;
	int is_live;
};
inline void showgame(int** gamemap, int high, int wide, char* player, char* ai)
{			// 更新游戏,由于printf只能一行接着一行打印,所以不能覆盖先前字符,只能增加缓冲区,在缓冲区里实现覆盖
	char p[10000] = { '\0' };
	char pen[2];
	int tile;
	for (int j = 0; j < wide; j++)
		strcat(p, "#");
	strcat(p, "\n");
	for (int i = 0; i < high; i++)
	{
		strcat(p, "#");
		for (int j = 0; j < wide; j++)
		{
			tile = gamemap[i][j];
			switch (tile)
			{
				case 0:
					strcpy(pen, " ");
					break;
				default:
					sprintf(pen, "%d", tile);
					break;
			}
			strcat(p, pen);
		}
		strcat(p, "#\n");
	}
	for (int j = 0; j < wide; j++)
	{
		strcat(p, "#");
	}
	strcat(p, "\n");
	printf("%s", p);													// 加载进缓存数组,减少 printf 使用,解决 printf 速度慢导致的屏闪
}

int main()
{
	int** bkmap;													// 游戏背景图
	int** gamemap;													// 记录当前游戏地图形式
	int high;														// 地图高,宽
	int wide;
	int limitx;
	int limity;
	high = 20;
	wide = 100;
	limitx = 100;
	limity = 20;
	bkmap = new int* [limity];										// 初始化游戏地图
	gamemap = new int* [high];
	for (int i = 0; i < limity; i++)
		bkmap[i] = new int[limitx];
	for (int i = 0; i < high; i++)
		gamemap[i] = new int[wide];
	for (int i = 0; i < limity; i++)
		for (int j = 0; j < limitx; j++)
			bkmap[i][j] = 0;
	for (int i = 0; i < high; i++)
		for (int j = 0; j < wide; j++)
			gamemap[i][j] = 0;
	int playerx;													//	玩家位置
	int playery;
	int gamex;														// 显示区域
	int gamey;
	int player;														// 玩家记号
	player = 1;
	playerx = 0;
	playery = 0;
	gamex = 0;
	gamey = 0;
	int field = 9;
	int enemy;														// 敌人记号
	int indix;														// 刷新敌人时更新数组
	int enemynum;													// 敌人个数
	int enemymax;													// 敌人上限
	enemy = 2;
	enemynum = 10;
	enemymax = 100;
	enemys ai[100];													// 敌人数组
	for (int i = 0; i < 100; i++)
	{
		ai[i].is_live = 0;
		ai[i].x = 0;
		ai[i].y = 0;
	}
	char playerview[100] = "6";
	char enemyview[100] = "2";
	printf("%s", playerview);
	int characterx;													// 敌人位置
	int charactery;
	charactery = 10;
	characterx = 10;
	printf("%s", enemyview);
	showgame(gamemap, high, wide, playerview, enemyview);
	int flag_x;
	int flag_y;
	int is_atk;
	int atk_area;
	int is_buff;
	flag_x = 0;
	flag_y = 0;
	is_atk = 0;
	atk_area = 1;
	is_buff = 0;
	HWND hwnd;
	hwnd = GetForegroundWindow();										// 获取前端窗口句柄,由于程序刚运行时是在前端,所以这就是本程序的窗口句柄
	srand(time(NULL));												// 设置随机数种子
	int gameover;
	gameover = 0;
	int cnt = 0;														// 敌人计算位置,每两帧移动一次
	while (1)
	{
		flag_x = 0;													// 默认不按键时速度为0
		flag_y = 0;
		if (KEY_DOWN_FOREGROUND(hwnd, 0x41))
		{
			flag_x -= 1;
		}
		if (KEY_DOWN_FOREGROUND(hwnd, 0x57))
		{
			flag_y -= 1;
		}
		if (KEY_DOWN_FOREGROUND(hwnd, 0x44))
		{
			flag_x += 1;
		}
		if (KEY_DOWN_FOREGROUND(hwnd, 0x53))
		{
			flag_y += 1;
		}

		if (is_atk == 0 && KEY_DOWN_FOREGROUND(hwnd, 0x4A))
		{
			is_atk = 1;
		}
		if (is_buff == 0 && KEY_DOWN_FOREGROUND(hwnd, 0x4B))
		{
			is_buff = 1;
		}
		if (KEY_DOWN_FOREGROUND(hwnd, VK_ESCAPE))
		{
			printf("游戏退出\n");
			break;
		}
		if (KEY_DOWN_FOREGROUND(hwnd, 0x30))									// 绘制地图
			bkmap[playery][playerx] = 0;
		if (KEY_DOWN_FOREGROUND(hwnd, 0x36))									// 绘制地图
			bkmap[playery][playerx] = 6;
		if (KEY_DOWN_FOREGROUND(hwnd, 0x37))									// 绘制地图
			bkmap[playery][playerx] = 7;
		if (KEY_DOWN_FOREGROUND(hwnd, 0x38))									// 绘制地图
			bkmap[playery][playerx] = 8;
		if (KEY_DOWN_FOREGROUND(hwnd, 0x39))									// 绘制地图
			bkmap[playery][playerx] = 9;

		if (flag_x > 1)														// 速度限制
			flag_x = 1;
		else if (flag_x < -1)
			flag_x = -1;
		if (flag_y > 1)
			flag_y = 1;
		else if (flag_y < -1)
			flag_y = -1;


		if (flag_x)															// 位移改变
			playerx += flag_x;
		if (flag_y)
			playery += flag_y;


		if (playerx >= limitx)													// 角色位置限制
			playerx = limitx - 1;
		else if (playerx < 0)
			playerx = 0;
		if (playery >= limity)
			playery = limity - 1;
		else if (playery < 0)
			playery = 0;

		for (int i = 0; i < high; i++)
			for (int j = 0; j < wide; j++)
				if (gamemap[i][j] != bkmap[i + gamey][j + gamex])									// 去除上次动作记录
					gamemap[i][j] = bkmap[i + gamey][j + gamex];
		if (is_atk % 12 != 0)  																	// 攻击
		{
			if (playerx < atk_area || playerx >= limitx - atk_area || playery < atk_area || playery >= limity - atk_area)
			{
				is_atk = 0;
			}
			else
			{
				is_atk++;
				if (characterx - playerx >= -atk_area && charactery - playery >= -atk_area && characterx - playerx <= atk_area && charactery - playery <= atk_area)										// 是否攻击到敌人
					field = 0;
				for (int n = 0; n < 100; n++)
				{
					if (ai[n].is_live)
					{
						if (ai[n].x - playerx >= -atk_area && ai[n].y - playery >= -atk_area && ai[n].x - playerx <= atk_area && ai[n].y - playery <= atk_area)	// 是否攻击到敌群
							ai[n].is_live = 0;
					}
				}
				for (int i = playery - atk_area; i <= playery + atk_area; i++)
					for (int j = playerx - atk_area; j <= playerx + atk_area; j++)						// 范围攻击记号
					{
						gamemap[i][j] = is_atk;
						if (bkmap[i][j] != 0)
							bkmap[i][j] = 0;
					}
			}
		}
		else is_atk = 0;
		for (int n = 0; n < 100; n++)															// 打印存活敌人
			if (ai[n].is_live)
				gamemap[ai[n].y][ai[n].x] = enemy;
		gamemap[charactery][characterx] = field;												// 敌人比攻击晚赋值,所以敌人可以覆盖攻击图标
		if (is_buff % 22 != 0)																	// buff 持续时间 12 帧
		{
			is_buff++;
			atk_area = 3;
			player = is_buff;
		}
		else
		{
			is_buff = 0;
			atk_area = 1;
			player = 1;
		}
		indix = 0;
		enemynum = 0;
		cnt++;
		while (indix < enemymax)																	// 加入新的敌人
		{
			if (ai[indix].is_live)
			{
				enemynum++;
				if (cnt % 2 == 0)
				{
					if (ai[indix].x < playerx)
						ai[indix].x++;
					else if (ai[indix].x > playerx)
						ai[indix].x--;
					if (ai[indix].y < playery)
						ai[indix].y++;
					else if (ai[indix].y > player)
						ai[indix].y--;
					cnt = cnt % 2;
				}
				if (playerx == ai[indix].x && playery == ai[indix].y)
				{
					gameover = 1;
					player = 1;
				}
			}
			else
			{
				ai[indix].x = rand() % 100;
				ai[indix].y = rand() % 20;
				ai[indix].is_live = 1;
				enemynum++;
			}
			indix++;
			if (enemynum >= 15)
				break;
		}
		printf("player x %d y %d\n", playerx, playery);
		gamemap[playery][playerx] = player;
		showgame(gamemap, high, wide, playerview, enemyview);
		while (gameover == 1)
		{
			printf("game over\n");
			printf("按 R 重新开始\n按 ESC 退出游戏\n");
			if (KEY_DOWN_FOREGROUND(hwnd, 0x52))
			{
				gameover = 0;
				playerx = 0;
				playery = 0;
				enemynum = 0;
				break;
			}
			else if (KEY_DOWN_FOREGROUND(hwnd, VK_ESCAPE))
			{
				break;
			}
			showgame(gamemap, high, wide, playerview, enemyview);
			Sleep(50);
			system("cls");
		}
		if (gameover == 1)
			break;
		Sleep(100);
		system("cls");																		// 清屏
	}
	system("cls");
	printf("Have a good time\n");
	system("pause");
	Sleep(50);
	return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【机构vip教程】Appium自动化(2):Python+Appium环境搭建

windows下搭建pythonappium环境 搭建过程步骤如下&#xff1a; 1、安装jdk并配置好环境变量&#xff08;jdk版本1.8以上&#xff09; 2、安装android-sdk并配置好环境变量&#xff1b;具体步骤见&#xff1a;https://www.cnblogs.com/YouJeffrey/p/15243705.html 3、安装安…

是面试官放水,还是公司实在是太缺人?,字节原来这么容易进...

字节是大企业&#xff0c;是不是很难进去啊&#xff1f;” “在华为做软件测试&#xff0c;能得到很好的发展吗&#xff1f; 一进去就有19.5K&#xff0c;其实也没有想的那么难” 直到现在&#xff0c;心情都还是无比激动&#xff01; 本人211非科班&#xff0c;之前在华为…

嵌入式学习-C++-Day6

思维导图 作业 以下是一个简单的比喻&#xff0c;将多态概念与生活中的实际情况相联系&#xff1a; 比喻&#xff1a;动物园的讲解员和动物表演 想象一下你去了一家动物园&#xff0c;看到了许多不同种类的动物&#xff0c;如狮子、大象、猴子等。现在&#xff0c;动物园里有一…

3年,5年,10年,网工人必看!

你们好&#xff0c;我是老杨。 2023年的职场上&#xff0c;无数人在思考“什么时候才能提前退休”这个问题。 对很多底层网工来说&#xff0c;二三十岁的年纪&#xff0c;距离60岁退休还有30年左右&#xff0c;是不是会觉得有点遥遥无期&#xff0c;毫无盼头&#xff1f; 现…

物奇平台ENC算法开关接口修改方法

物奇ENC算法开关接口修改 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)?可加我微信hezkz17, 本群提供音频技术答疑服务,+群赠送语音信号处理降噪算法,蓝牙耳机音频,DSP音频项目核心开发资料, 1 配置工具 2 代码接口

Ansible fetch 模块 该模块用于从远程某主机获取(复制)文件到本地

这里写目录标题 参数实例查看返回结果在这里插入图片描述 参数 dest&#xff1a;用来存放文件的目录 src&#xff1a;在远程拉取的文件&#xff0c;并且必须是一个file&#xff0c;不能是**目录* 实例 ansible slave -m fetch -a src/data/hello.txt dest/data/可以看到一个…

2024年【安全员-C证】报名考试及安全员-C证考试资料

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 安全员-C证报名考试参考答案及安全员-C证考试试题解析是安全生产模拟考试一点通题库老师及安全员-C证操作证已考过的学员汇总&#xff0c;相对有效帮助安全员-C证考试资料学员顺利通过考试。 1、【多选题】《工伤保险…

软件实例分享,台球厅收费系统电脑桌球店计时软件及灯控线路图教程

软件实例分享&#xff0c;台球厅收费系统电脑桌球店计时软件及灯控线路图教程 一、前言 以下软件程序教程以 佳易王桌球室计时计费软件V17.0为例说明 软件文件下载可以点击最下方官网卡片——软件下载——试用版软件下载 1、每个桌子对应的有 开台时间&#xff0c;所用的时…

java数据结构与算法刷题-----LeetCode594. 最长和谐子序列

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 解题思路 子序列要尽可能长&#xff0c;并且最大值和最小值之间的差&#…

Python教程(27)——如何使用Python中的上下文管理器

当我们在编写代码时&#xff0c;经常会遇到需要管理资源的情况&#xff0c;比如打开和关闭文件&#xff0c;如果遇到了一些异常情况&#xff0c;我们需要关闭资源&#xff0c;不然会导致资源泄露&#xff0c;虽然我们可以通过手动的方式来关闭&#xff0c;但如果有多个异常情况…

基于Springboot的新能源充电系统(有报告)。Javaee项目,springboot项目。

演示视频&#xff1a; 基于Springboot的新能源充电系统&#xff08;有报告&#xff09;。Javaee项目&#xff0c;springboot项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&a…

MyBatisPlus 整合 SpringBoot 遇见的问题

【异常】&#xff1a;Cause: java.sql.SQLSyntaxErrorException: Unknown column ‘udf1’ in ‘field list’… SQL: SELECT id,oper_id,btch_id,udf1, FROM scan_cyber Cause: java.sql.SQLSyntaxErrorException: Unknown column ‘udf1’ in ‘field list’; ,"messag…

OpenHarmony—UIAbility组件与UI的数据同步

基于HarmonyOS的应用模型&#xff0c;可以通过以下两种方式来实现UIAbility组件与UI之间的数据同步。 使用EventHub进行数据通信&#xff1a;基于发布订阅模式来实现&#xff0c;事件需要先订阅后发布&#xff0c;订阅者收到消息后进行处理。使用globalThis进行数据同步&#…

PostgreSQL Error Codes (PostgreSQL错误代码)

Whats PostgreSQL Error Codes PostgreSQL服务器发出的所有消息都分配了五个字符的错误代码&#xff0c; 这些代码遵循 SQL 的"SQLSTATE"代码的约定。 需要知道发生了什么错误条件的应用程序通常应该检测错误代码&#xff0c;而不是查看文本错误消息。 这些错误代码…

Flink介绍

Flink 介绍 文章目录 Flink 介绍1. 简介1.1 背景1.2 用途 2. 核心概念2.1 流&#xff08;Stream&#xff09;2.2 转换&#xff08;Transformation&#xff09;2.3 窗口&#xff08;Window&#xff09;2.4 状态&#xff08;State&#xff09; 3. 编程模型3.1 编程模型介绍3.2 程…

Selenium Grid分布式测试环境搭建

Selenium Grid简介 Selenium Grid实际上是基于Selenium RC的&#xff0c;而所谓的分布式结构就是由一个hub节点和若干个node代理节点组成。Hub用来管理各个代理节点的注册信息和状态信息&#xff0c;并且接受远程客户端代码的请求调用&#xff0c;然后把请求的命令转发给代理节…

ansible自动化运维工具及常见模块的使用

目录 一、ansible概述 二、ansible的特性 三、ansible 环境安装部署 管理端安装 ansible&#xff1a; 配置主机清单&#xff1a; 配置密钥对验证&#xff1a; 四、ansible 常见模块的使用 1&#xff0e;command 模块 2&#xff0e;shell 模块 3&#xff0e;cron 模块…

JS进阶——垃圾回收机制以及算法

版权声明 本文章来源于B站上的某马课程&#xff0c;由本人整理&#xff0c;仅供学习交流使用。如涉及侵权问题&#xff0c;请立即与本人联系&#xff0c;本人将积极配合删除相关内容。感谢理解和支持&#xff0c;本人致力于维护原创作品的权益&#xff0c;共同营造一个尊重知识…

Typora+PicGO+腾讯云COS做图床

文章目录 Typora&#xff0b;PicGO&#xff0b;腾讯云COS做图床一、为什么使用图床二、Typora、PicGO和腾讯云COS介绍三、下载Typora和PicGOTyporaPicGO 四、配置Typora、PicGO和腾讯云COS腾讯云COS配置PicGO配置Typora配置 Typora&#xff0b;PicGO&#xff0b;腾讯云COS做图床…

神经网络代码实现

目录 神经网络整体框架 核心计算步骤 参数初始化 矩阵拉伸与还原 前向传播 损失函数定义 反向传播 全部迭代更新完成 数字识别实战 神经网络整体框架 核心计算步骤 参数初始化 # 定义初始化函数 normalize_data是否需要标准化def __init__(self,data,labels,layers,…