C语言飞机大战
一、前言
[设计难度 : ★☆☆☆☆
[参考书籍:《C语言课程设计与游戏开发实践教程》
[主要涉及知识:函数封装 + 循环判断语句
[程序运行效果图:
[主要的游戏功能:
通过按键’w’,‘s’,‘a’,'d’分别实现飞机的上下左右移动
按空格键发射子弹
按ESC实现游戏暂停
按q键返回菜单界面
实现子弹和敌机位置的自动更新
敌机的生成速度和下落速度随分数的增加而变快
实时打印得分和生命值。生命值为0时游戏结束
以下为飞机游戏全部的代码,大家可以直接拷贝运行:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
#include <time.h>#define height 25 //设置游戏边界
#define width 50
#define enemy_max 5enum Option //枚举增加代码可读性
{EXIT,PLAY,GUIDE,
};enum Condition //表示游戏幕布上的情况
{backspace,enemy,bullet,
};int canvas[height][width]; //游戏幕布存储对应的信息
int score;
int x, y; //飞机头部坐标
int Std_Speed; //敌机标准下落速度
int Std_Time; //敌机生成的标准速度
int HP; //玩家生命值
int enemy_num;
int times;void gotoxy(int x, int y) //清屏函数
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos;pos.X = x;pos.Y = y;SetConsoleCursorPosition(handle, pos);
}void HideCursor() //光标隐藏函数
{CONSOLE_CURSOR_INFO cursor_info = { 1, 0 };SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info);
}void Initgame()
{for (int i = 0; i < height; i++){for (int j = 0; j < width; j++) //将幕布上先初始化为空格canvas[i][j] = backspace;}HP = 3;score = 0;x = width / 2; //初始化飞机位置y = height / 2;enemy_num = 0;Std_Speed = 60;Std_Time = 60;
}void show()
{gotoxy(0, 0);for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){if (i == y && j == x) //打印飞机printf("*");else if (i == y + 1 && j == x - 2){printf("*****");j += 4;}else if (i == y + 2 && j == x - 1){printf("* *");j += 2;}else if (canvas[i][j] == bullet) // 打印子弹printf("|");else if (canvas[i][j] == enemy)printf("@");elseprintf(" ");}printf("|\n"); //打印游戏边框}for (int j = 0; j < width; j++) //打印游戏边框printf("-");printf("\n[得分:>%d\n", score); //打印游戏分数和血量printf("[生命值:>%d\n", HP);
}int updateWithinput()
{if (_kbhit()){int input = _getch();switch (input){case 'w': if (y > 0) //防止飞机飞出游戏边界y--;break;case 's': if (y < height - 3)y++;break;case 'a': if (x > 2)x--;break;case 'd': if (x < width - 3)x++;break;case 27: system("pause"); break; //ESC的ascll码值为27case ' ': if (y > 0)canvas[y - 1][x] = bullet;break;case 'q': return 1; //退出游戏}}return 0;
}int enemy_update()
{static int enemy_speed = 0;static int enemy_time = 0;int flag = 0;if (enemy_speed < Std_Speed) //依靠循环来控制更新速度enemy_speed++;if (enemy_time < Std_Time)enemy_time++;if (enemy_num < enemy_max && enemy_time >= Std_Time){int i, j;do{i = rand() % (height / 5);j = rand() % (width - 4) + 2; //j的范围:[2, width - 3]} while (canvas[i][j] != backspace);canvas[i][j] = enemy;enemy_num++;enemy_time = 0;}if (enemy_speed >= Std_Speed){flag = 1;enemy_speed = 0;}for (int i = height - 1; i >= 0; i--){for (int j = width - 1; j >= 0; j--){if (canvas[i][j] == enemy) //遇到敌机的情况{if (i == height - 1) //敌机飞到边界{score--;HP--;if (HP == 0)return 1;enemy_num--;canvas[i][j] = backspace;}else if (i < height - 1 && canvas[i + 1][j] == bullet)//检测是否被子弹击中{score++;printf("\a");enemy_num--;if (score % 5 == 0 && Std_Speed >= 12) //分数到达一定程度后下落加快,生成加快{Std_Speed -= 3; //下落加快Std_Time -= 3; //生成速度加快}canvas[i][j] = backspace;}else if (flag) //flag为1更新敌机位置{canvas[i + 1][j] = enemy;canvas[i][j] = backspace;}}}}return 0;
}void bullet_update()
{for (int i = 0; i < height; i++) //控制子弹的移动{for (int j = 0; j < width; j++){if (canvas[i][j] == bullet){if (i > 0 && canvas[i - 1][j] == enemy){score++;printf("\a");enemy_num--;if (score % 5 == 0 && Std_Speed >= 6) //分数到达一定程度后下落加快,生成加快{Std_Speed -= 3; //下落加快Std_Time -= 3; //生成速度加快}canvas[i - 1][j] = bullet;}else if (i > 0)canvas[i - 1][j] = bullet;canvas[i][j] = backspace;}}}
}void gamebody()
{system("cls");Initgame();HideCursor();srand((unsigned int)time(NULL));while (1){show();bullet_update();if (updateWithinput() || enemy_update()){show();printf("[本次游戏结束:>");system("pause");break;}}
}void menu()
{printf("*****************\n");printf("** 飞机游戏 **\n");printf("**-------------**\n");printf("** 1.PLAY **\n");printf("** 2.GUIDE **\n");printf("** 0.EXIT **\n");printf("*****************\n");
}void guide()
{printf("******************\n");printf("** 游戏操作指南 **\n");printf("**--------------**\n");printf("** w->上移 **\n");printf("** s->下移 **\n");printf("** a->左移 **\n");printf("** d->右移 **\n");printf("** q->返回 **\n");printf("** ESC->暂停 **\n");printf("** 空格->射击 **\n");printf("******************\n\n\n");}int main()
{int input = 0;do{menu();printf("[请选择:>");scanf("%d", &input);switch (input){case PLAY: gamebody(); break;case GUIDE: guide(); break;case EXIT: printf("成功退出游戏!\n"); break;default: printf("输入错误,请重新选择\n");}} while (input);return 0;
}
如果觉得还挺有意思的,那就继续保持着轻松的心情看下去吧!
二、从设计初始菜单界面开始
一个基本的游戏初始选择框架:
int main()
{int input = 0;do{menu();printf("[请选择:>");scanf("%d", &input);switch (input){case xxx:case xxx:case xxx:default: }}while (input);return 0;
}
我们根据游戏所包含的功能设计好相应的menu选项以及其对应的case事件即可。作为我们飞机游戏的第一个简单版本,我们先不考虑其他的模式和功能,仅包含PLAY
(游戏)功能、GUIDE
(操作说明)、EXIT
(退出游戏)三种功能。根据这个思路,我们写下这样的menu函数
void menu()
{printf("*****************\n");printf("** 飞机游戏 **\n");printf("**-------------**\n");printf("** 1.PLAY **\n");printf("** 2.GUIDE **\n");printf("** 0.EXIT **\n");printf("*****************\n");
}
为了增加代码的可读性
,我们在头文件处创建枚举变量。
enum Option //枚举增加代码可读性
{EXIT, // printf("%d", EXIT);的结果为 0PLAY, // printf("%d", PLAY);的结果为 1GUIDE, // printf("%d", GUIDE);的结果为 2
};
每个枚举常量都是有值的,第一个枚举成员的值默认为0(不人为修改的话),之后的随前一个递增。这恰好与我们的menu中功能序号相对应,于是我们可以用枚举变量作为case的整形常量表达语句,最终写出的主函数是这样的:
int main()
{int input = 0;srand((unsigned int)time(NULL)); //初始化rand函数,只需要初始化一次即可,所以放在主函数内do{menu();printf("[请选择:>");scanf("%d", &input);switch (input){case PLAY: gamebody(); break;case GUIDE: guide(); break;case EXIT: printf("成功退出游戏!\n"); break;default: printf("输入错误,请重新选择\n");}}while (input);return 0;
}
相关文章:
C语言飞机大战
一、前言 [设计难度 : ★☆☆☆☆ [参考书籍:《C语言课程设计与游戏开发实践教程》 [主要涉及知识:函数封装 循环判断语句 [程序运行效果图: [主要的游戏功能: 通过按键’w’,‘s’,‘a’,d’分别实现飞机的上下左右移动 按空格…...
js 原型 和 原型链
function Person(name,age){ this.name name this.age age } var p new Person(张三,11) //创建构造函数的时候,解析器会自动为构造函数创建prototype属性,prototype属性对应的对象就是原型对象 // prototype 翻译为 原…...
如何利用SD-WAN节省运维成本和简化运维工作?
在当今数字化时代,企业对于网络的要求越来越高,需要保障网络的安全性、可靠性和灵活性。同时,随着企业的上云和远程办公等需求的增加,传统的WAN网络已经无法满足企业的需求。因此,SD-WAN技术应运而生。 SD-WAN节省运维…...

在工作中使用CHAT提高效率
问CHAT:数智时代与中国情境下的营销管理创新方向:市场营销(管理)的使命 CHAT回复:市场营销(管理)的使命可以被概述为寻找、吸引和保留消费者。通过识别、满足甚至超越消费者期望,以实…...
Maven 项目的三种打包方式与 pom.xml 文件中项目描述
目录: 定义项目的信息 本项目描述相关标签<parent> 标签<relativePath/> 标签<scope> 标签 Maven 三种打包方式 JARWARPOM 原文链接 — —...

【普中】基于51单片机简易计算器数码管显示设计( proteus仿真+程序+实物演示+讲解视频)
【普中开发板】基于51单片机简易计算器数码管显示设计( proteus仿真程序实物演示讲解视频) Proteus 仿真:Proteus 8.16(有低版本) 程序编译器:keil 4/keil 5 编程语言:C语言 设计编号:P04 1. 主要功能:…...
【Android】DeepLink
官方文档:创建指向应用内容的深层链接 Intro to Deep Linking on Android What is Deep linking? Deeplinks are a concept that help users navigate between the web and applications. They are basically URLs which navigate users directly to the specif…...
微服务Redis-Session共享登录状态
一、背景 随着项目越来越大,需要将多个服务拆分成微服务,使代码看起来不要过于臃肿,庞大。微服务之间通常采取feign交互,为了保证不同微服务之间增加授权校验,需要增加Spring Security登录验证,为了多个服务…...
30道C++ 基础高频题整理(附答案背诵版)
1. C和C有什么区别? C是C语言的超集(我看网上很多文章说这是不对的),这意味着几乎所有的C程序都可以在C编译器中编译和运行。然而,C引入了许多新的概念和特性,使得两种语言在一些关键点上有显著的区别。 …...

【Spark面试】Spark面试题答案
目录 1、spark的有几种部署模式,每种模式特点?(☆☆☆☆☆) 2、Spark为什么比MapReduce块?(☆☆☆☆☆) 3、简单说一下hadoop和spark的shuffle相同和差异?(☆☆☆☆☆…...

Axure的动态面板
目录 动态面板 什么是Auxre动态模板 动态模板的步骤 应用场景 实战案例 轮播图 多功能登录界面 主界面左侧菜单栏 动态面板 什么是Auxre动态模板 动态面板是Axure中的一个重要功能,它允许用户创建可交互的页面,并模拟用户与页面的交互。通过添加元素…...

【STM32】STM32学习笔记-对射式红外传感器计次 旋转编码器计次(12)
00. 目录 文章目录 00. 目录01. NVIC相关函数1.1 NVIC_PriorityGroupConfig函数1.2 NVIC_PriorityGroup类型1.3 NVIC_Init函数1.4 NVIC_InitTypeDef类型 02. 外部中断相关API2.1 GPIO_EXTILineConfig2.2 EXTI_Init2.3 EXTI_GetITStatus2.4 EXTI_ClearITPendingBit2.5 中断回调函…...

后端项目操作数据库-中枢组件Service调用Mapper实现增删改查-实例
接上篇 使用MyBatis配置Mapper实现增删改查 1.Service的基本作用 Service在代码中的的作用是调用Mapper、被Controller调用。是后端项目中非常重要的组件。 用于设计业务流程、业务逻辑,以保障数据的完整性、有效性、安全性。 2. Service使用举例——“添加相册”…...
kafka学习笔记--节点的服役与退役
本文内容来自尚硅谷B站公开教学视频,仅做个人总结、学习、复习使用,任何对此文章的引用,应当说明源出处为尚硅谷,不得用于商业用途。 如有侵权、联系速删 视频教程链接:【尚硅谷】Kafka3.x教程(从入门到调优…...

2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值。 来自字节。
2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值。 来自字节。 答案2023-12-16: 来自左程云。 灵捷3.5 大体步骤如下: 算法 maxSum1 分析࿱…...

libxls - 编译
文章目录 libxls - 编译概述笔记静态库工程测试控制台exe工程测试备注备注END libxls - 编译 概述 想处理.xls格式的excel文件. 查了一下libxls库可以干这个事. 库地址 https://github.com/libxls/libxls.git 但是这个库的makefile写的有问题, 在mingw和WSL下都编译不了. 好在…...
自建私有git进行项目发布
自建私有git进行博客项目发布 之前尝试过通过建立私有git仓库,来发布自己的hexo静态博客,但是失败了,今天尝试了一下午,算是有了结果。下面记录我的过程。 我的需求: 我有一个服务器,希望在服务器端建一…...
华为HCIP认证H12-821题库上
1、2.OSPF核心知识 (单选题)下面关于0SPF的特殊区域,描述错误的是: A、Totally Stub Area允许ABR发布缺省的三类LSA,不接受五类LSA和细化三类LSA B、NSSA Area和Stub区域的不同在于该区域允许自治系统外部路由的引入,由ABR发布…...

Web安全漏洞分析—文件包含
在当今数字化时代,随着Web应用程序的广泛应用,网络安全问题愈加凸显。其中,文件包含漏洞作为一种常见但危险的安全隐患,为恶意攻击者提供了可乘之机。在这篇博客中,我们将深入探讨文件包含漏洞的本质、攻击手法以及应对…...

C++入门【9-C++循环】
C 循环 有的时候,可能需要多次执行同一块代码。一般情况下,语句是顺序执行的:函数中的第一个语句先执行,接着是第二个语句,依此类推。 编程语言提供了允许更为复杂的执行路径的多种控制结构。 循环语句允许我们多次…...

linux之kylin系统nginx的安装
一、nginx的作用 1.可做高性能的web服务器 直接处理静态资源(HTML/CSS/图片等),响应速度远超传统服务器类似apache支持高并发连接 2.反向代理服务器 隐藏后端服务器IP地址,提高安全性 3.负载均衡服务器 支持多种策略分发流量…...

Prompt Tuning、P-Tuning、Prefix Tuning的区别
一、Prompt Tuning、P-Tuning、Prefix Tuning的区别 1. Prompt Tuning(提示调优) 核心思想:固定预训练模型参数,仅学习额外的连续提示向量(通常是嵌入层的一部分)。实现方式:在输入文本前添加可训练的连续向量(软提示),模型只更新这些提示参数。优势:参数量少(仅提…...
三维GIS开发cesium智慧地铁教程(5)Cesium相机控制
一、环境搭建 <script src"../cesium1.99/Build/Cesium/Cesium.js"></script> <link rel"stylesheet" href"../cesium1.99/Build/Cesium/Widgets/widgets.css"> 关键配置点: 路径验证:确保相对路径.…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

EtherNet/IP转DeviceNet协议网关详解
一,设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络,本网关连接到EtherNet/IP总线中做为从站使用,连接到DeviceNet总线中做为从站使用。 在自动…...
Spring AI与Spring Modulith核心技术解析
Spring AI核心架构解析 Spring AI(https://spring.io/projects/spring-ai)作为Spring生态中的AI集成框架,其核心设计理念是通过模块化架构降低AI应用的开发复杂度。与Python生态中的LangChain/LlamaIndex等工具类似,但特别为多语…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
重启Eureka集群中的节点,对已经注册的服务有什么影响
先看答案,如果正确地操作,重启Eureka集群中的节点,对已经注册的服务影响非常小,甚至可以做到无感知。 但如果操作不当,可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
python报错No module named ‘tensorflow.keras‘
是由于不同版本的tensorflow下的keras所在的路径不同,结合所安装的tensorflow的目录结构修改from语句即可。 原语句: from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后: from tensorflow.python.keras.lay…...