当前位置: 首页 > news >正文

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语言飞机大战

一、前言 [设计难度 : ★☆☆☆☆ [参考书籍&#xff1a;《C语言课程设计与游戏开发实践教程》 [主要涉及知识&#xff1a;函数封装 循环判断语句 [程序运行效果图&#xff1a; [主要的游戏功能&#xff1a; 通过按键’w’,‘s’,‘a’,d’分别实现飞机的上下左右移动 按空格…...

js 原型 和 原型链

function Person(name,age){ this.name name this.age age } var p new Person(张三,11) //创建构造函数的时候&#xff0c;解析器会自动为构造函数创建prototype属性&#xff0c;prototype属性对应的对象就是原型对象 // prototype 翻译为 原…...

如何利用SD-WAN节省运维成本和简化运维工作?

在当今数字化时代&#xff0c;企业对于网络的要求越来越高&#xff0c;需要保障网络的安全性、可靠性和灵活性。同时&#xff0c;随着企业的上云和远程办公等需求的增加&#xff0c;传统的WAN网络已经无法满足企业的需求。因此&#xff0c;SD-WAN技术应运而生。 SD-WAN节省运维…...

在工作中使用CHAT提高效率

问CHAT&#xff1a;数智时代与中国情境下的营销管理创新方向&#xff1a;市场营销&#xff08;管理&#xff09;的使命 CHAT回复&#xff1a;市场营销&#xff08;管理&#xff09;的使命可以被概述为寻找、吸引和保留消费者。通过识别、满足甚至超越消费者期望&#xff0c;以实…...

Maven 项目的三种打包方式与 pom.xml 文件中项目描述

目录&#xff1a; 定义项目的信息 本项目描述相关标签<parent> 标签<relativePath/> 标签<scope> 标签 Maven 三种打包方式 JARWARPOM 原文链接 — —...

【普中】基于51单片机简易计算器数码管显示设计( proteus仿真+程序+实物演示+讲解视频)

【普中开发板】基于51单片机简易计算器数码管显示设计( proteus仿真程序实物演示讲解视频&#xff09; Proteus 仿真&#xff1a;Proteus 8.16(有低版本) 程序编译器&#xff1a;keil 4/keil 5 编程语言&#xff1a;C语言 设计编号&#xff1a;P04 1. 主要功能&#xff1a…...

【Android】DeepLink

官方文档&#xff1a;创建指向应用内容的深层链接 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共享登录状态

一、背景 随着项目越来越大&#xff0c;需要将多个服务拆分成微服务&#xff0c;使代码看起来不要过于臃肿&#xff0c;庞大。微服务之间通常采取feign交互&#xff0c;为了保证不同微服务之间增加授权校验&#xff0c;需要增加Spring Security登录验证&#xff0c;为了多个服务…...

30道C++ 基础高频题整理(附答案背诵版)

1. C和C有什么区别&#xff1f; C是C语言的超集&#xff08;我看网上很多文章说这是不对的&#xff09;&#xff0c;这意味着几乎所有的C程序都可以在C编译器中编译和运行。然而&#xff0c;C引入了许多新的概念和特性&#xff0c;使得两种语言在一些关键点上有显著的区别。 …...

【Spark面试】Spark面试题答案

目录 1、spark的有几种部署模式&#xff0c;每种模式特点&#xff1f;&#xff08;☆☆☆☆☆&#xff09; 2、Spark为什么比MapReduce块&#xff1f;&#xff08;☆☆☆☆☆&#xff09; 3、简单说一下hadoop和spark的shuffle相同和差异&#xff1f;&#xff08;☆☆☆☆☆…...

Axure的动态面板

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

【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调用。是后端项目中非常重要的组件。 用于设计业务流程、业务逻辑&#xff0c;以保障数据的完整性、有效性、安全性。 2. Service使用举例——“添加相册”…...

kafka学习笔记--节点的服役与退役

本文内容来自尚硅谷B站公开教学视频&#xff0c;仅做个人总结、学习、复习使用&#xff0c;任何对此文章的引用&#xff0c;应当说明源出处为尚硅谷&#xff0c;不得用于商业用途。 如有侵权、联系速删 视频教程链接&#xff1a;【尚硅谷】Kafka3.x教程&#xff08;从入门到调优…...

2023-12-16:用go语言,给定整数数组arr,求删除任一元素后, 新数组中长度为k的子数组累加和的最大值。 来自字节。

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

libxls - 编译

文章目录 libxls - 编译概述笔记静态库工程测试控制台exe工程测试备注备注END libxls - 编译 概述 想处理.xls格式的excel文件. 查了一下libxls库可以干这个事. 库地址 https://github.com/libxls/libxls.git 但是这个库的makefile写的有问题, 在mingw和WSL下都编译不了. 好在…...

自建私有git进行项目发布

自建私有git进行博客项目发布 之前尝试过通过建立私有git仓库&#xff0c;来发布自己的hexo静态博客&#xff0c;但是失败了&#xff0c;今天尝试了一下午&#xff0c;算是有了结果。下面记录我的过程。 我的需求&#xff1a; 我有一个服务器&#xff0c;希望在服务器端建一…...

华为HCIP认证H12-821题库上

1、2.OSPF核心知识 &#xff08;单选题&#xff09;下面关于0SPF的特殊区域&#xff0c;描述错误的是: A、Totally Stub Area允许ABR发布缺省的三类LSA,不接受五类LSA和细化三类LSA B、NSSA Area和Stub区域的不同在于该区域允许自治系统外部路由的引入&#xff0c;由ABR发布…...

Web安全漏洞分析—文件包含

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

C++入门【9-C++循环】

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

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

线程同步:确保多线程程序的安全与高效!

全文目录&#xff1a; 开篇语前序前言第一部分&#xff1a;线程同步的概念与问题1.1 线程同步的概念1.2 线程同步的问题1.3 线程同步的解决方案 第二部分&#xff1a;synchronized关键字的使用2.1 使用 synchronized修饰方法2.2 使用 synchronized修饰代码块 第三部分&#xff…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:

根据万维钢精英日课6的内容&#xff0c;使用AI&#xff08;2025&#xff09;可以参考以下方法&#xff1a; 四个洞见 模型已经比人聪明&#xff1a;以ChatGPT o3为代表的AI非常强大&#xff0c;能运用高级理论解释道理、引用最新学术论文&#xff0c;生成对顶尖科学家都有用的…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...