用C语言数组实现扫雷游戏(思路及代码分享)

扫雷游戏功能说明

  • 使⽤控制台实现经典的扫雷游戏
  • 游戏可以通过菜单实现继续玩或者退出游戏
  • 扫雷的棋盘是9*9的格⼦
  • 默认随机布置10个雷
  • 可以排查雷
    • 如果位置不是雷,就显⽰周围有⼏个雷
    • 如果位置是雷,就炸死,游戏结束
  • 把除10个雷之外的所有雷都找出来,排雷成功,游戏结束

对代码进行了优化
使用二维数组,指针和函数的知识实现地雷数和棋盘大小可变的扫雷游戏

代码运行截图

开始菜单
游戏中
扫雷失败

思路及代码实现

1.打印开始菜单

void menu() {
    printf("***********扫雷************\n");
    printf("********1. 开始游戏********\n");
    printf("********0. 退出游戏********\n");
    printf("***************************\n");
}

2.开始及退出游戏

int main() {
    int select;
    do{
        menu(); //打印开始菜单
        scanf("%d", &select); // 输入数字0或1判断继续游戏还是结束游戏
        switch (select){
        case 1://输入1时进入game函数,开始游戏
            system("CLS");//每次选择时清空屏幕,保持界面干净
            printf("加载中,请等待游戏开始\n");
            game();
            break;
        case 0://输入0时结束游戏
            system("CLS");
            printf("游戏退出");
            break;
        default://输入其他数据时重新选择
            printf("输入有误,重新输入");
            break;
        }
    }while(select);
    return 0;
}

3 初始化游戏数据

每次新的游戏开始时初始化游戏界面和雷的位置

  1. 创建4个全局变量,标记数据
int arr[9][9]; //标记每个位置周围的地雷数,探测过时显示此位置上的地雷数
int flag[9][9]; //标记已经探测过的位置,当已经探测过,显示周围地雷数,否则显示*
int mine[9][9]; // 统计地雷位置,有雷时为1,无雷时为0;
int num = 0; //统计探测次数,到达71次时退出,此时所有未探测的地方都有雷
  1. 使用随机数函数rand初始化10个地雷的位置
void Laymines() {
    int x, y;
    for (int i = 0; i < 9; i++){
    //使地雷标记全为0,防止上次游戏的数据残留影响导致雷的数量大于10个
        for (int j = 0; j < 9; j++) {
            mine[i][j] = 0;
        }
    }
    srand((unsigned)time(NULL));
    for (int i = 0; i < 11;) {//标记10个位置有雷
        x = rand() % 9;
        y = rand() % 9;
        if (mine[x][y]) continue;//当已经被标记过地雷时进行下次循环,地雷计数不变
        else {
            mine[x][y] = 1;//未被标记过未地雷时,标记为地雷
            i++;//地雷计数加1,当为11时退出。保证只有10颗雷
        }
    }
}
  1. 初始化flag数组,因为初始时玩家还未有探测行为,所有全部初始化为0
void Layflag() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            flag[i][j] = 0;
        }
    }
}
  1. 初始化arr数组,用来显示每个格子的周围有多少雷
void Layarr() {//标记周围8个格子共有多少个地雷
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
        	if (mine[i][i]) continue;//此格子有雷时不需要统计
        	else{//每个格子周围如果有格子(数组下标未溢出)则统计是否有雷
            	if (mine[i - 1][j - 1] && i >= 0 && j >= 0) arr[i][j]++;
            	if (mine[i - 1][j] && i >= 0) arr[i][j]++;
            	if (mine[i - 1][j + 1] && i >= 0 && j < 9) arr[i][j]++;
            	if (mine[i][j - 1] && j >= 0) arr[i][j]++;
            	if (mine[i][j + 1] && j < 9) arr[i][j]++;
            	if (mine[i + 1][j - 1] && i < 9 && j >= 0) arr[i][j]++;
            	if (mine[i + 1][j] && i < 9 ) arr[i][j]++;
            	if (mine[i + 1][j + 1] && i < 9 && j <9) arr[i][j]++;
            }
        }
    }
}

4.打印游戏界面

void interface() {
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if (0 == i) printf("%d ", j); //第一行为列位置标记
            else if (0 == j) printf("%d ", i); //第一列为行位置标记
            else if (flag[i-1][j-1]) printf("%d ", arr[i-1][j-1]); 
            //如果被探测过则显示周围有几颗雷
            else printf("* "); // 没探测过则显示*
        }
        printf("\n");
    }
    return 0;
}

5.进行探测行为

int detect() {
    int x, y;
    printf("请输入你要探测的位置>");
    scanf("%d %d", &x, &y);
    if (mine[x - 1][y - 1]) return 0;//如果有雷则返回0
    else {
        flag[x - 1][y - 1] = 1;//无雷则标记已经探测
        num++;//探测计数
    }
    return 1;//无雷返回1
}

6.游戏主体,循环进行探测操作,直到游戏失败或成功

void game() {
    int x = 1;
    Lay(); //初始化游戏数据
    while(x){
    	system("CLS");//清空屏幕
        print();//测试时使用,打印arr,flag,mine数组的内容
        interface(); //打印游戏界面
        x = detect(); 
        //detect函数返回值为0则表示此次探测无雷,为1则表示探测到雷,游戏结束
        if (71 == num) break;
        //num统计玩家探测的次数,当次数为71时,则剩下所有格子都是雷,游戏胜利
    }
    if (x) printf("*********扫雷完成**********\n");
    else printf("*********扫雷失败*********\n");
}

7.测试

在游戏初始化数据后打印arr,flag,mine数组的内容,然后正常游戏,判断自己的程序是否有bug

void print() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
    printf("***************************\n");
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            printf("%d ",flag[i][j]);
        }
        printf("\n");
    }
    printf("***************************\n");
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            printf("%d ",mine[i][j]);
        }
        printf("\n");
    }
    printf("***************************\n");
}

全部代码

#define _CRT_SECURE_NO_WARNINGS 
#include<stdio.h>
#include<stdlib.h>

static int arr[9][9]; //标记每个位置周围的地雷数,探测时显示
static int flag[9][9]; //标记已经探测过的位置,当已经探测过,显示周围地雷数,否则显示*
static int mine[9][9]; // 统计地雷位置,有雷时为1,无雷时为0;
static int num = 0; //统计探测次数,到达71次时退出,此时所有未探测的地方都有雷

//测试用,打印三个数组
void print() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            printf("%d ",arr[i][j]);
        }
        printf("\n");
    }
    printf("***************************\n");
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            printf("%d ",flag[i][j]);
        }
        printf("\n");
    }
    printf("***************************\n");
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            printf("%d ",mine[i][j]);
        }
        printf("\n");
    }
    printf("***************************\n");
}

//打印菜单
void menu() {
    printf("***********扫雷************\n");
    printf("********1. 开始游戏********\n");
    printf("********0. 退出游戏********\n");
    printf("***************************\n");
}

//初始化arr数组
void Layarr() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            if (mine[i - 1][j - 1] && i >= 0 && j >= 0) arr[i][j]++;
            if (mine[i - 1][j] && i >= 0) arr[i][j]++;
            if (mine[i - 1][j + 1] && i >= 0 && j < 9) arr[i][j]++;
            if (mine[i][j - 1] && j >= 0) arr[i][j]++;
            if (mine[i][j + 1] && j < 9) arr[i][j]++;
            if (mine[i + 1][j - 1] && i < 9 && j >= 0) arr[i][j]++;
            if (mine[i + 1][j] && i < 9 ) arr[i][j]++;
            if (mine[i + 1][j + 1] && i < 9 && j <9) arr[i][j]++;
        }
    }
}

//初始化flag数组
void Layflag() {
    for (int i = 0; i < 9; i++) {
        for (int j = 0; j < 9; j++) {
            flag[i][j] = 0;
        }
    }
}

//初始化10个地雷的位置
void Laymines() {
    int x, y;
    for (int i = 0; i < 9; i++){//使地雷标记全为0
        for (int j = 0; j < 9; j++) {
            mine[i][j] = 0;
        }
    }
    for (int i = 0; i < 11;) {
        srand((unsigned)time(NULL));
        x = rand() % 9;
        y = rand() % 9;
        if (mine[x][y]) continue;//当已经被标记过地雷时退出
        else {
            mine[x][y] = 1;//未被标记过未地雷时,标记为地雷
            i++;//地雷数加1,当为11时退出.
        }
    }
}

//初始化游戏数据
void Lay() {
    num = 0;
    int a;
    Laymines();//初始化10个地雷的位置
    Layarr();//初始化arr数组
    Layflag();//初始化flag数组
}

//进行探测
int detect() {
    int x, y;
    printf("请输入你要探测的位置>");
    scanf("%d %d", &x, &y);
    if (mine[x - 1][y - 1]) return 0;//如果有雷则退出
    else {
        flag[x - 1][y - 1] = 1;//无雷则标记已经探测
        num++;//探测计数
    }
    return 1;
}

//即时打印游戏界面
void interface() {
    for (int i = 0; i < 10; i++) {
        for (int j = 0; j < 10; j++) {
            if (0 == i) printf("%d ", j); //第一行为列位置标记
            else if (0 == j) printf("%d ", i); //第一列为行位置标记
            else if (flag[i-1][j-1]) printf("%d ", arr[i-1][j-1]); //如果被探测过则显示周围有几颗雷
            else printf("* "); // 没探测过则显示*
        }
        printf("\n");
    }
    return 0;
}

void game() {
    int x;
    Lay(); //初始化游戏数据
    system("CLS");
    do{
        print();
        interface(); //打印界面
        x = detect(); //进行扫雷行为
        system("CLS");//清空屏幕
        if (71 == num) break;
    } while (x);
    if (x) printf("*********扫雷完成**********\n");
    else printf("*********扫雷失败*********\n");
}

int main() {
    int select;
    while(1){
        menu(); //打印菜单
        scanf("%d", &select); // 输入选择判断继续游戏还是结束游戏
        if (select == 0) break;
        else if (select == 1) game();
        else printf("输入有误,重新输入");
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值