简单的撸了一个扫雷小游戏

简介: 简单的撸了一个扫雷小游戏

一、相关知识点

程序员必备资源,值得收藏!点击下载



1、键盘监听


在扫雷游戏中,当用户输入是否开始游戏的 Y/N 时,程序能够自动监听,当用户输入完成后,不用回车,程序立即做出反应,这就用到了键盘监听。


所谓键盘监听,就是用户按下某个键时系统做出相应的处理,本章讲到的输入输出函数也是键盘监听函数的一种,例如 getchar()、getche()、getch() 等。下面的代码演示了 getche() 函数的使用:

#include <stdio.h>
#include <conio.h>
int main(){
    char ch;
    int i = 0;
    //循环监听,直到按Esc键退出
    while(ch = getch()){
        if(ch == 27){
            break;
        }else{
            printf("Number: %d\n", ++i);
        }
    }
    return 0;
}

这段代码虽然达到了监听键盘的目的,但是每次都必须按下一个键才能执行 getch() 后面的代码,也就是说,getch() 后面的代码被阻塞了。


阻塞式键盘监听用于用户输入时一般没有任何问题,用户输入完数据再执行后面的代码往往也符合逻辑。然而在很多小游戏中,阻塞式键盘监听会带来很大的麻烦,用户要不停按键游戏才能进行,这简直就是灾难,所以在小游戏中一般采用非阻塞式键盘监听:用户输入数据后程序可以捕获,用户不输入数据程序也可以继续执行。


在 Windows 系统中,conio.h头文件中的kbhit()函数就可以用来实现非阻塞式键盘监听。


conio.h 是 Windows 下特有的头文件,所以 kbhit() 也只适用于 Windows,不适用于 Linux 和 Mac OS。


用户每按下一个键,都会将对应的字符放到输入缓冲区中,kbhit() 函数会检测缓冲区中是否有数据,如果有的话就返回非 0 值,没有的话就返回 0 值。但是 kbhit() 不会读取数据,数据仍然留在缓冲区,所以一般情况下我们还要结合输入函数将缓冲区种的数据读出。请看下面的例子:


#include <stdio.h>
#include <windows.h>
#include <conio.h>
int main(){
    char ch;
    int i = 0;
    //循环监听,直到按Esc键退出
    while(1){
        if(kbhit()){  //检测缓冲区中是否有数据
            ch = getch();  //将缓冲区中的数据以字符的形式读出
            if(ch == 27){
                break;
            }
        }
        printf("Number: %d\n", ++i);
        Sleep(1000);  //暂停1秒
    }
    return 0;
}

每次循环,kbhit() 会检测用户是否按下某个键(也就是检测缓冲区中是否有数据),没有的话继续执行后面的语句,有的话就通过 getch() 读取,并判断是否是 Esc,是的话就退出循环,否则继续循环。


扫雷完整代码。点击下载


2、改变输出文本的颜色


在扫雷游戏中,当用户输入是否开始游戏的 Y/N 时,程序能够自动监听,当用户输入完成后,不用回车,程序立即做出反应,这就用到了键盘监听。


C语言不总是“黑底白字”,它也可以是彩色的,可以调用Windows.h头文件下的SetConsoleTextAttribute函数改变文字和背景颜色。


调用形式为:


SetConsoleTextAttribute( HANDLE hConsoleOutput, WORD wAttributes );

hConsoleOutput表示控制台缓冲区句柄,可以通过GetStdHandle(STD_OUTPUT_HANDLE)来获得;wAttributes表示文字颜色和背景颜色。


0~F 分别代表的颜色如下:


0 = 黑色 8 = 灰色 1 = 淡蓝 9 = 蓝色 2 = 淡绿 A = 绿色 3 = 湖蓝 B = 淡浅绿

C = 红色 4 = 淡红 5 = 紫色 D = 淡紫

6 = 黄色 E = 淡黄 7 = 白色 F = 亮白


例如,将背景设置为淡绿色,文字设置为红色:


#include <stdio.h>
#include <windows.h>
int main(){
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, 0x2C );
    puts("c语言与cpp编程");
    return 0;
}

如果只希望设置文字颜色,背景保持黑色,那么也可以只给出一位16进制数,例如:


SetConsoleTextAttribute(hConsole, 0xC );  //将文字颜色设置为红色

SetConsoleTextAttribute(hConsole, 0xF );  //将文字颜色设置为白色

再来看一个例子:


#include <stdio.h>
#include <windows.h>
int main(){
    HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(hConsole, 0xC );
    puts("红色文字");
    SetConsoleTextAttribute(hConsole, 0xF );
    puts("白色文字");
    SetConsoleTextAttribute(hConsole, 2 );
    puts("淡绿色文字");
    return 0;
}

3、获取随机数


扫雷游戏中,雷区会随机出现在整个区域的任意位置,没有任何规律,这就要求程序能够生成随机数值,由随机数设置雷区的位置。


在 C 语言中,我们一般使用<stdlib.h> 头文件中的 rand() 函数来生成随机数,它的用法为:


int rand (void);

void 表示不需要传递参数。C语言中还有一个 random() 函数可以获取随机数,但是 random() 不是标准函数,不能在 VC/VS 等编译器通过,所以比较少用。


rand() 会随机生成一个位于 0 ~ RAND_MAX 之间的整数。


RAND_MAX 是 <stdlib.h> 头文件中的一个宏,它用来指明 rand() 所能返回的随机数的最大值。C语言标准并没有规定 RAND_MAX 的具体数值,只是规定它的值至少为 32767。在实际编程中,我们也不需要知道 RAND_MAX 的具体值,把它当做一个很大的数来对待即可。


下面是一个随机数生成的实例: 纯文本复制


#include <stdio.h>
#include <stdlib.h>
int main(){
    int a = rand();
    printf("%d\n",a);
    return 0;
}

生成一定范围内的随机数


在实际开发中,我们往往需要一定范围内的随机数,过大或者过小都不符合要求,那么,如何产生一定范围的随机数呢?我们可以利用取模的方法:


int a = rand() % 10;    //产生0~9的随机数,注意10会被整除

如果要规定上下限:


int a = rand() % 51 + 13;    //产生13~63的随机数

分析:取模即取余,rand()%51+13我们可以看成两部分:rand()%51是产生 0~50 的随机数,后面+13保证 a 最小只能是 13,最大就是 50+13=63。


最后给出产生 13~63 范围内随机数的完整代码:


#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(){
    int a;
    srand((unsigned)time(NULL));
    a = rand() % 51 + 13;
    printf("%d\n",a);
    return 0;
}

二、扫雷游戏初始化


扫雷游戏初始化过程中,我们使用到了 3 个二维数组:mine、show、mineDow:


mine 数组用于初始化扫雷游戏。具体做法是:首先默认整个二维数组中没有雷区,全部设为安全区域(用 0 表示),然后在二维数组中随机安插一定数量的雷区;


show 数组用于每次将结果输出给用户。当用户输入完成后,show 数组会根据用户的输入对存储的数据做适当的更新,然后输出给用户;


mineDow 数组中每个数据表示的,该位置相邻的周围雷区的数量,此数组的建立为的是实现“点击一个位置,开出一片安全区域”的效果 提示:在源代码的 game 函数中,在 mine_sweep() 函数之前的所有工作,都是初始化工作。


三、扫雷功能的实现


扫雷功能的实现,整体思路是:


判断用户输入坐标处是否是雷区;


更新 show 数组:如果是雷区,将 show 数组中该坐标位置上由字符 ‘*’ 改为表示雷区的字符 ‘o’;如果不是雷区,借助 mineDow数组中存储的信息,使用递归的方式,找到其他符合条件的非雷区区域(show_deal 函数的作用),将找到的所有区域一并更新到 show 数组中;


将新的 show 数组以一定的格式输出,反馈给用户;


提示:show_deal 函数找的是该区域既不是雷区,其周围也没有雷区的区域,将其全部更新到 show 数组中。一旦遇到周围有雷区的区域(这部分区域也会被更新到 show 数组中),则递归结束。


扫雷功能的具体实现,可见源代码中的 mine_sweep 函数。


四 扫雷界面的优化


扫雷界面,实际上是将 show 数组中存储的数据换了一种方式输出出来。


例如,show 数组中存储有字符 ‘*’,在输出时,统一换为“■”;表示雷区的字符 ‘o’,统一换为 ‘●’,等等。


注意:用于替换的字符,并不是普通的字符,它们并不在 ASCII 码范围内,是宽字符,占用两个字节。


采用此种方式,再配以合适的颜色(采用Windows API),可以将二维数组以如下的这种形式反馈给用户:


扫雷界面的详细优化代码,可见原代码中的 display_board() 函数的实现。


image.png



相关文章
|
3月前
|
存储 安全 算法
C 语言——实现扫雷小游戏
本文介绍了使用二维数组创建棋盘并实现扫雷游戏的方法。首先,通过初始化数组创建一个9x9的棋盘,并添加行列标识以便操作。接着,利用随机数在棋盘上布置雷。最后,通过判断玩家输入的坐标来实现扫雷功能,包括显示雷的数量和处理游戏胜利或失败的情况。文中提供了完整的代码实现。
56 1
C 语言——实现扫雷小游戏
|
6月前
小游戏:三子棋的代码实现
小游戏:三子棋的代码实现
38 3
|
6月前
|
开发者 Python
小游戏实战丨基于Tkinter的五子棋小游戏
小游戏实战丨基于Tkinter的五子棋小游戏
99 4
|
7月前
|
C语言 C++
C语言项目(1)----扫雷小游戏的实现
C语言项目(1)----扫雷小游戏的实现
59 0
|
小程序
小游戏扫雷实现教学(详解)
小游戏扫雷实现教学(详解)
232 0
小游戏扫雷实现教学(详解)
|
C语言
C/关于扫雷小游戏的创建
C/关于扫雷小游戏的创建
|
7月前
|
Python
python实现贪吃蛇小游戏(附源码)
python实现贪吃蛇小游戏(附源码)
121 0
|
存储
扫雷小游戏
扫雷小游戏
85 0
|
Linux 开发者 iOS开发
不来看看?通过Python实现贪吃蛇小游戏
不来看看?通过Python实现贪吃蛇小游戏
132 0
|
小程序
扫雷小游戏详解
扫雷小游戏详解
75 0

相关实验场景

更多