学习c语言的时候,想写例子,但是课后习题又太枯燥怎么办?
写小游戏可以锻炼我们的编程抽象能力和思维,而且比较有趣,最重要的是还能自己玩玩。
控制台文字游戏
c语言学了一点基础就可以写了,因为基本上只用到了输入输出和逻辑判断。
文字游戏可以做很长的剧情,我们用来学习就做个简单的,并且熟悉一下游戏中非常重要的一部分:随机。
srand、rand、time
srand
函数原型(<stdlib.h>
):void srand( unsigned int seed );
功能:设置伪随机数生成器的起始种子值
参数:
seed
— 伪随机数生成的种子
srand
函数原型(<stdlib.h>
):int rand( void );
功能:得到一个伪随机数
返回值:返回一个伪随机数范围为0~RAND_MAX(32767)
注:
- 第一次调用
rand()
之前没有调用srand()
,那么系统会为你自动调用srand()
,自动调用传参值为1。 - 使用相同种子(
srand
函数传参值相同),调用rand()
生成的是相同随机数序列。
看完上面的函数我们发现使用上有困难:srand
函数传参固定会导致生成的随机数是相同随机数序列。那就不传固定的数,无时无刻不在改变当然可以是时间戳。
time
函数原型(<time.h>
):time_t time( time_t *destTime );
功能:获取系统时间
功能:
destTime
:指向时间的存储位置的指针。可以为NULL
,在这种情况下,不存储返回值。
返回值:返回自1970年1月1日午夜以来经过的秒数,如果发生错误,则返回-1。
组合使用:
比如我们想要获取1~10的随机数,rand()
为[0, 32767],rand() % 10
为[0, 9],1 + rand() % 10
为[1, 10].
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; ++i)
{
printf("%d ", 1 + rand() % 10);
}
system("pause");
return 0;
}
当然也可以自己试着实现一下,效果也还行:
#include <stdio.h>
#include <time.h>
/* 种子 */
unsigned long int next = 1;
/**
* 设置随机数种子
*
* @param seed 随机数种子
*/
void srand(unsigned int seed)
{
next = seed;
}
/* 获取随机数 */
int rand(void)
{
next = next * 1103515245 + 12345;
return (unsigned int)(next / 65536) % 32768;
}
int main(void)
{
srand((unsigned int)time(NULL));
for (int i = 0; i < 10; i++)
{
printf("%d ", 1 + rand() % 10);
}
system("pause");
return 0;
}
猜拳游戏
我们有了伪随机函数就能模拟电脑猜拳了,可以生成0~2的随机数(可以当做索引
),0代表剪刀,1代表石头,2代表布。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 结果
const char* result[3][3] =
{
{"平手", "赢了", "输了"},
{"输了", "平手", "赢了"},
{"赢了", "输了", "平手"}
};
// 石头 剪刀 布
const char* menu[3] = { "剪刀", "石头", "布" };
int main(void)
{
int player = 0; // 玩家
int computer = 0; // 电脑
srand((unsigned)time(NULL));
while (1)
{
// 提示
printf("这是一个猜拳的小游戏,请输入下列选项:\n0:剪刀\n1:石头\n2:布\n");
// 获取输入
scanf("%d", &player);
scanf("%*[^\n]%*c");
if (player < 0 || player > 2)
{
printf("你的选择有错\n");
}
else
{
computer = rand() % 3;
printf("电脑出了%s\t你出了%s\n", menu[computer], menu[player]);
printf("%s\n", result[computer][player]);
}
system("pause");
system("cls");
}
return 0;
}
system
可以用来执行系统命令,pause
为按任意键继续,cls
为清屏。
控制台动作游戏
一开始可能对这种动起来的游戏没什么思路,我们可以类比一下动画播放,画面一直在改变我们就觉得它在动了。
运动的小球
我们先做一个没有交互的小例子体验一下。
我们把控制台想象成一个坐标系:
小球就有一个具体的坐标,我们只要不断改变小球的坐标并且重新绘制小球就能让它动起来。
绘制的思路(先来个无脑的):
- 先清屏
- 然后按照y坐标多少输出换行
- 按照x坐标输出空格
- 最后输出小球(就是一个特殊字符)
我们还需要一个新的函数Sleep
用来延时,因为计算机处理的很快,所以不延时就移动的太快了。(其实这个涉及到了一个概念–帧率
)
Sleep
函数原型(<windows.h>
):void Sleep(DWORD dwMilliseconds);
功能:将进程挂起一段时间
参数:
dwMilliseconds
— 停止时间,单位为毫秒
#include <stdio.h>
#include <windows.h>
void MyPrint(int x, int y)
{
system("cls");
for (int i = 0; i < y; ++i)
{
printf("\n");
}
for (int i = 0; i < x; ++i)
{
printf(" ");
}
printf("●");
}
int main(void)
{
int x = 4, // 小球的x坐标
y = 5, // 小球的y坐标
speedX = 2, // 小球x轴方向的速度
speedY = 1; // 小球y轴方向的速度
while (1)
{
// 小球移动
x += speedX;
if (40 == x || 0 == x)
{
speedX = -speedX;
}
y += speedY;
if (19 == y || 0 == y)
{
speedY = -speedY;
}
// 打印小球
MyPrint(x, y);
Sleep(100);
}
}
贪吃蛇
以前学习时候看的视频:C语言贪吃蛇(原来哔哩哔哩上有免费的,现在好像没了)
这视频看完还不会建议多看两遍,代码多写两遍。
视频学完之后就有个问题,虽然蛇闪烁减少了,但是时不时还在闪,贪吃蛇解决闪烁的方法。
音乐
游戏肯定是要背景音乐的,windows自带的:c/c++播放音乐(PlaySound、mciSendString、mciSendCommand)。
图形界面
easyx介绍
安装教程和基本介绍官网都有。
官网上的教学信息很多,推荐几个看一下:
精确延时的实现
通过直接操作显示缓冲区实现高速绘图和特殊效果(如逐渐变亮)
同时检测多个按键和平滑按键处理
学习保存应用程序的配置信息
正确处理鼠标和按键消息(解决反应迟钝或消息丢失的问题)
一步步拓展程序,实现文字在背景上的移动
为什么屏幕分辨率是 640x480?
详解透明贴图和三元光栅操作
对慢羊羊的半透明贴图函数进行改良
在程序中正确使用 Unicode 和 MBCS 字符集
游戏也推荐几个,这些都是比较简单的,不是说没推荐的就不好,
涂格子游戏(也叫点灯游戏)(by 豆腐果)
贪吃蛇游戏的双人对战版
推箱子游戏(by 自然向日葵)
别踩白块儿(双人版) VC 源代码
超级蘑菇2(模拟 FC 游戏:超级玛丽)(by 木子念念)
后续
如果你上面的内容搞完了,说明c语言肯定入门了,这边也不再说后续干嘛了,找个学习路线继续学吧。