|
在我实在无聊的情况下, 我看到了我的C语言书,遂我开始无聊之旅-2
<hr/>该程序属于也属于简单的循环结构,但是涉及多个循环进行判定和应用,对逻辑处理有一定的要求。
效果

Ps:使用 W 代表玩家控制的飞机,^ 代表发射的子弹,@ 代表 敌机。(以下都直接简写符号)
思路
想必大家都有玩过雷霆战机,那么脑子里应该有一个构思:
1、(制造飞机):需要使 W(飞机) 初始位置设定在界面正中央的下方位置
2、(控制飞机):需要使 W 动起来,总不能输出一次,动一下程序就关闭了吧
3、(发射子弹):需要让 W 可以点击某一固定按钮时发射 ^ (子弹)
4、(随机敌机):需要实现 @ 随机出现且子弹击中后必须消失。
过程
1、试着输出“飞机”(笔者使用W代表飞机),那么 printf(&#34;W&#34;) 就可以输出飞机,理论上可行,但是位置就会出现在第1行第1列,很明显哪有飞机游戏一开始飞机出现在最上面的呢,那么可以设定一个坐标轴(X,Y)。Ps:C语言中的坐标和生活中的坐标是相反的,想象一下二维数组 a[0][0]所在的位置,不难理解的。
因此在 飞机 前面输出 y 个空格,在 飞机 上面输出 x 个换行即可实现飞机出现在下侧中央
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
int i, j;
int x = 10,y = 8; //声明画布尺寸
for (i = 0; i < x; i++) //输出飞机上面的换行符号
printf(&#34;\n&#34;);
for (j = 0; j < y; j++) //输出飞机前面的空格符号
printf(&#34; &#34;);
printf(&#34;W\n&#34;); //输出飞机
system(&#34;pause&#34;);
} 实现了 飞机 位置放置的效果

2、现在飞机已经成功输出了,但是游戏需要持续运行,总不能随便按个键就停止运行了吧?如何让其持续输出飞机呢,死循环可以做到。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
int i, j;
int x = 10,y = 8; //声明画布尺寸
while (1) //死循环
{
for (i = 0; i < x; i++) //输出飞机上面的换行符号
printf(&#34;\n&#34;);
for (j = 0; j < y; j++) //输出飞机前面的空格符号
printf(&#34; &#34;);
printf(&#34;W\n&#34;); //输出飞机符号
}
}那么面临一个问题,死循环在每一次循环是不是整个界面全是飞机或者子弹,那么要引入一个新函数,清屏函数 system(&#34;cls&#34;); 加入死循环中。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
int i, j;
int x = 10,y = 8;
while (1)
{
system(&#34;cls&#34;); //清屏函数
for (i = 0; i < x; i++)
printf(&#34;\n&#34;);
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;W\n&#34;);
}
}此时飞机已经可以一直停留在DOS界面上,并且一闪一闪的,按任何按键也不会停止运行。那更进一步是不是需要“控制飞机”:
根据我们第一步设置飞机出现在下侧中央的想法,我们只需要让飞机的坐标随着玩家按下W、A、S、D进行增减X、Y轴即可
输入S,X加一 //飞机下移一格
输入W,X减一 //飞机上移一格
输入A,Y减一 //飞机左移一格
输入D,Y加一 //飞机右移一格原理可行,那么进行实践:之前使用scanf_s() 函数就可以解决输入的问题,但是此函数需要进行回车程序才做出响应,很是影响游戏体验。C语言有个头文件可以解决这个问题,conio.h中的getch()函数就不需要按回车键,这从另一方面暗示这个函数只能单字符输入。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h> //包含头文件
void main(void)
{
int i, j;
int x = 10,y = 8;
char c; //声明输入变量
while (1)
{
system(&#34;cls&#34;);
for (i = 0; i < x; i++)
printf(&#34;\n&#34;);
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;W\n&#34;);
c = _getch(); //采集用户输入的数据
if (c == &#39;w&#39;) //判断是否上移
x--;
if (c == &#39;s&#39;) //判断是否下移
x++;
if (c == &#39;a&#39;) //判断是否左移
y--;
if (c == &#39;d&#39;) //判断是否右移
y++;
}
}飞机可以实现运动了,那么让它可以发射子弹,这里使用“^”代表子弹,一般子弹都是出现在飞机正上方的,这里引入一个双重循环可以做到:
也就是在每行输入回车前,输入一定的空格,然后在输入“^”,最后回车
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
int i, j;
int x = 10, y = 8;
char c;
int number = 5, arm = 0;
while (1)
{
system(&#34;cls&#34;);
for (i = 0; i < x; i++) //这里引入双重循环,在每次回车前输入一定的空格
{
for (j = 0; j < y; j++) //输出飞机前面的空格符号
printf(&#34; &#34;);
printf(&#34;^\n&#34;);
}
for (j = 0; j < y; j++) //输出飞机前面的空格符号
printf(&#34; &#34;);
printf(&#34;W\n&#34;);
c = _getch();
if (c == &#39;w&#39;)
x--;
if (c == &#39;s&#39;)
x++;
if (c == &#39;a&#39;)
y--;
if (c == &#39;d&#39;)
y++;
}
}

此时已经有了子弹,那么需要实现控制子弹的发射。这个用控制飞机的思路是一样的也很简单,只需要监控某一按键进行判断就行。这里使用空格键控制输出子弹。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
int i, j;
int x = 10, y = 8;
char c;
int k = 0; //声明判断变量,当k=0时输出回车,当=1时输出子弹
while (1)
{
system(&#34;cls&#34;);
if (k == 0) //当k=0时输出回车
{
for (i = 0; i < x; i++)
printf(&#34;\n&#34;);
}
if (k == 1) //当k=1时输出子弹
{
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;^\n&#34;);
}
k = 0; //每次输入完子弹后,将k归零
if (number == j)
arm = 1;
}
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;W\n&#34;);
c = _getch();
if (c == &#39;w&#39;)
x--;
if (c == &#39;s&#39;)
x++;
if (c == &#39;a&#39;)
y--;
if (c == &#39;d&#39;)
y++;
if (c == &#39; &#39;) //当用户输入空格是,将k的值更改为1
k = 1;
}
}现在飞机和子弹都有了,就差敌机了,那该怎么实现呢?
首先敌机需要具备两个特点:①随机出现 ②子弹打中就要消失
先定义一个固定的敌机出现在第一行,这里需要声明一个新的变量,打中消失需要判断子弹的Y值和敌机的Y值是否相等,如果相等敌机消失。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
void main(void)
{
int i, j;
int x = 10, y = 8;
char c;
int k = 0;
int number = 5, arm = 0; //定义飞机前面的空格;判断敌机是否输出,为0输出,为1不输出敌机
while (1)
{
system(&#34;cls&#34;);
if (arm == 0) //现在判断是否输出敌机
{
for (i = 0; i < number; i++)
printf(&#34; &#34;);
printf(&#34;@\n&#34;);
}
if (k == 0)
{
for (i = 0; i < x; i++)
printf(&#34;\n&#34;);
}
if (k == 1)
{
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;^\n&#34;);
}
k = 0;
if (number == j) //判断子弹是否击中敌机
arm = 1;
}
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;W\n&#34;);
c = _getch();
if (c == &#39;w&#39;)
x--;
if (c == &#39;s&#39;)
x++;
if (c == &#39;a&#39;)
y--;
if (c == &#39;d&#39;)
y++;
if (c == &#39; &#39;)
k = 1;
}
}

具体功能已经实现,但是问题又来了,敌机位置是我们自己定义的,也就只有一个敌机。这样的游戏就没有任何意义。
那接下来就需要解决敌机随机出现,且击中一个敌机后,下一个敌机会立刻出现:
随机数的产生在C语言中可以使用rand()函数,但是这个函数只有第一次会随机,以后的每一次输出的随机数都和第一次是一致的。那么就需要对其进行初始化srand((unsigned)time(NULL)),这样每次都不一样了。初始化需要引入头文件<time.h>。
要想敌机随机出现,应该将随机数赋值给谁呢?很明显决定敌机出现位置的循环是:敌机前面的空格的多少,那就是number。同时还需要设置一个变量让敌机被击中后立刻刷新。
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h> //引入
void main(void)
{
int i, j;
int x = 10, y = 8;
char c;
int k = 0;
int number = 5, arm = 0;
int l = 0; //判断是否需要改变敌机的位置,为0不改,为1更改
srand((unsigned)time(NULL)); //初始化随机函数
while (1)
{
system(&#34;cls&#34;);
if (l == 1) //等于1的时候更改敌机的位置
{
number = rand() % 10; //产生一个0~10的随机整数
l = 0;
}
if (arm == 0)
{
for (i = 0; i < number; i++)
printf(&#34; &#34;);
printf(&#34;@\n&#34;);
}
if (k == 0)
{
for (i = 0; i < x; i++)
printf(&#34;\n&#34;);
}
if (k == 1)
{
for (i = 0; i < x; i++)
{
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;^\n&#34;);
}
k = 0;
if (number == j)
{
arm = 0; //由于始终显示敌机,因此设置为0
l = 1; //击中敌机的时候,更改敌机位置
}
}
for (j = 0; j < y; j++)
printf(&#34; &#34;);
printf(&#34;W\n&#34;);
c = _getch();
if (c == &#39;w&#39;)
x--;
if (c == &#39;s&#39;)
x++;
if (c == &#39;a&#39;)
y--;
if (c == &#39;d&#39;)
y++;
if (c == &#39; &#39;)
k = 1;
}
}实现了全部效果,飞机、子弹、敌机 功能有限,有想法完善的同学可以进行优化:
比如:
- 敌机也可以发射子弹?
- 敌机可以根据某一速度进行移动(移动靶子)?
- 子弹是一颗颗发的,不是“激光”?
- 敌机会有概率出现BOSS?击中两次才回消失
- 加入分数指示器?
- 血条?
这些需要整体优化,我这个代码不能实现。
完整代码:
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
void main(void)
{
int i, j;
int x = 10, y = 8; //声明画布尺寸
char c;
int k = 0; //声明判断变量,当k=0时输出回车,当=1时输出子弹
int number = 5, arm = 0; //定义飞机前面的空格;判断敌机是否输出,为0输出,为1不输出敌机
int l = 0; //判断是否需要改变敌机的位置,为0不改,为1更改
srand((unsigned)time(NULL)); //初始化随机函数
while (1) //死循环
{
system(&#34;cls&#34;); //清屏函数
if (l == 1) //等于1的时候更改敌机的位置
{
number = rand() % 10; //产生一个0~10的随机整数
l = 0;
}
if (arm == 0) //现在判断是否输出敌机
{
for (i = 0; i < number; i++)
printf(&#34; &#34;);
printf(&#34;@\n&#34;);
}
if (k == 0) //当k=0时输出回车
{
for (i = 0; i < x; i++) //输出飞机上面的换行符号
printf(&#34;\n&#34;);
}
if (k == 1) //当k=1时输出子弹
{
for (i = 0; i < x; i++) //这里引入双重循环,在每次回车前输入一定的空格
{
for (j = 0; j < y; j++) //输出飞机前面的空格符号
printf(&#34; &#34;);
printf(&#34;^\n&#34;);
}
k = 0; //每次输入完子弹后,将k归零
if (number == j)//判断子弹是否击中敌机
{
arm = 0; //由于始终显示敌机,因此设置为0
l = 1; //击中敌机的时候,更改敌机位置
}
}
for (j = 0; j < y; j++) //输出飞机前面的空格符号
printf(&#34; &#34;);
printf(&#34;W\n&#34;); //输出飞机符号
c = _getch(); //采集用户输入的数据
if (c == &#39;w&#39;) //判断是否上移
x--;
if (c == &#39;s&#39;) //判断是否下移
x++;
if (c == &#39;a&#39;) //判断是否左移
y--;
if (c == &#39;d&#39;) //判断是否右移
y++;
if (c == &#39; &#39;) //当用户输入空格是,将k的值更改为1
k = 1;
}
}<hr/>一闪而过解决办法: |
|