关于c语言扫雷游戏

本次用c语言完成扫雷游戏的最初版

在开始要先有计划,对自己写的代码要有一个基本逻辑,对要写的游戏也需要有一个具体的逻辑,要是埋头就写结束后就可能有很多问题。

所有的代码我放在最后一段了。下面是我在学习后的理解想看的可以看下。

本次将扫雷分两部分来写。分别为:1、游戏框架 2、游戏主体函数和实现

1、游戏框架

首先一个游戏进入要有菜单,进入游戏和退出游戏可供玩家选择

我们也可以用一do while循环来供玩家选择多轮游戏

进入游戏就是游戏主体函数

退出就是退出游戏

最后就是对玩家的选项进行判断

#include"game.h"

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));//用于随机数
    do
    {
        menu();//菜单
        printf("\n\n请选择:>\n");
        scanf("%d", &input);
        switch(input)
        {
        case 1:
            game();//游戏主体函数
            break;
        case 0:
            printf("游戏已退出!\n");
            break;
        default:
            printf("输入有误!请重新输入!\n");
            break;
        };
    }while(input);
    return 0;
}
void menu()//菜单函数实现
{
    printf("*************************************\n");
    printf("****                             ****\n");
    printf("****   1、play        0、exit    ****\n");
    printf("****                             ****\n");
    printf("*************************************\n");
}

2、游戏主体

void game()//主体实现
{
    //需要两个数组
    //一个用来存放地雷
    //另一个用来存放提示
    char mine[Wids][Lens] = {0};//地雷
    char show[Wids][Lens] = {0};//提示
    //初始化数组
    initboard(mine, Wids, Lens, '0');
    initboard(show, Wids, Lens, '*');

    //打印棋盘
    displayboard(mine, Wid, Len);
    displayboard(show, Wid, Len);

    //埋雷
    setmine(mine, Wid, Len);
    //displayboard(mine, Wid, Len);

    //查雷
    findmine(mine, show, Wid, Len);
}

首先要对扫雷这个游戏进行逻辑分析,我们要将扫雷分解成为两部分来进行

第一个部分:我们要埋雷,将地雷随机埋进棋盘中

第二个部分:我们要查雷,锁定坐标得到提示,提示即周围一格内所有的地雷总数

所以我们需要两个二维数组来存放

一个存放地雷,一个存提示

    char mine[9][9] = {0};//地雷
    char show[9][9] = {0};//提示

接着我们需要对齐进行初始化

在初始化的时候我们知道数组的规格

首先我们要知道如果我们想创建一个9*9的棋盘,那么在扫雷中我们需要一个11*11的数组才可以存下。我们知道,提示是得到周围一格内所有的地雷数,如果我们想要的到9*9最边边那一列的提示的话那么数组可能会溢出。例如,我们要得到最右下角的那一块的提示,那么它需要将周围一格内所有的地雷进行判断和计数,但我们给的只有一格9*9的棋盘,所以可能溢出。为此我们需要将棋盘行和列各加两个,保证数组不会溢出。两个数组都加是因为我们要保证其坐标一致,方便后续操作。

这时我们就可以在头文件中进行宏定义。

#define Len 9
#define Wid 9
#define Lens 11
#define Wids 11

在我们的到这些参数后就可以进行数组初始化和棋盘打印了

我们在初始化的时候需要考虑我们要送进去的内容,我们上面使用的是char型数组,所以我们这里也都使用字符来送入。

地雷 = ‘1’        无地雷 = ‘0’      未提示 = ✳      提示 = ‘0’ ~ ‘9’

    //需要两个数组
    //一个用来存放地雷
    //另一个用来存放提示
    char mine[Wids][Lens] = {0};//地雷
    char show[Wids][Lens] = {0};//提示
    //初始化数组
    initboard(mine, Wids, Lens, '0');
    initboard(show, Wids, Lens, '*');

下面是对其函数的实现

void initboard(char board[Wids][Lens], int wids, int lens, char set)//初始化数组实现
{
    int i, j;
    for(i = 0; i < wids; i++)
    {
        for(j = 0; j < lens; j++)
        {
            board[i][j] = set;
        }
    }
}

接着我们将打印棋盘的函数也写出

    //打印棋盘
    displayboard(mine, Wid, Len);
    displayboard(show, Wid, Len);

      对其实现

void displayboard(char board[Wids][Lens], int wid, int len)//打印棋盘实现
{
    int i, j;
    printf("------棋盘-------\n");
    for(i = 0; i <= len; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for(i = 1; i <= wid; i++)
    {
        printf("%d ", i);
        for(j = 1; j <= len; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
    printf("------棋盘-------\n");
}

最后就是我们重要的两部分 埋地雷和查地雷了

首先埋地雷

我们的目标是将10个地雷随机的埋入9*9的格子中

    //埋雷
    setmine(mine, Wid, Len);

下面是实现

void setmine(char board[Wids][Lens], int wid, int len)//埋雷实现
{
    //需要随机值

    int count = setmine_count;
    while(count)
    {
        int x = rand() % wid + 1;
        int y = rand() % len + 1;
        if(board[x][y] == '0')
        {
            board[x][y] = '1';
            count--;
        }
    }
}

接着是查地雷

    //查雷
    findmine(mine, show, Wid, Len);

在实现函数时,我们要知道首先需要:

玩家输入坐标,接着对坐标进行判断,是否在1-9这个范围内。

若符合,则对坐标进行是否有地雷的判断

有地雷,游戏结束

无地雷,进行周围一格内所有的地雷进行检测并计数,并对棋盘进行提示

下面是对函数的实现

static findmine_count(char board[Wids][Lens], int x, int y)//查雷实现
{
    return board[x - 1][y - 1] +
            board[x - 1][y] +
            board[x - 1][y + 1] +
            board[x][y - 1] +
            board[x][y + 1] +
            board[x + 1][y - 1] +
            board[x + 1][y] +
            board[x + 1][y - 1] - 8 * '0';
}
void findmine(char mine[Wids][Lens], char show[Wids][Lens], int wid, int len)
{
    //需要玩家输入坐标,对坐标进行判断
    //对有雷和无雷进行实现
    int x = 0;
    int y = 0;
    int count = 0;
    while(count != wid * len - setmine_count)
    {
        printf("\n\n请输入要查的坐标:>\n");
        scanf("%d %d", &x, &y);
        if(x >= 1 && x <= wid && y >= 1 && y <= len)
        {
            //有雷 被炸死
            //没有雷 计算周围一格内的雷数并显示
            if(mine[x][y] == '1')
            {
                printf("\n\n\n*****************\n");
                printf("*** 菜      菜***\n");
                printf("***           ***\n");
                printf("***     菜    ***\n");
                printf("***           ***\n");
                printf("***菜       菜***\n");
                printf("*****************\n\n\n\n");
                break;
            }
            else
            {
                int set = findmine_count(mine, x, y);//计算周围一周的雷数
                show[x][y] = set + '0';//一个数字  +  '0'字符零 = 当前数字的字符形式
                displayboard(show, wid, len);
                count++;
            }
        }
        else
        {
            printf("\n\n输入的坐标有误!请重新输入!\n\n");
        }
    }
    if(count == wid * len - setmine_count)
    {
        printf("\n\n打得好啊!\n\n");
        displayboard(show, wid, len);
        printf("\n\n\n");
    }
}

使用static可以对当前函数进行修饰,使其只能在本文件内使用,不会导致其他文件内出现重名等现象。

至此,完成扫雷游戏,其中还可以有很多优化,碍于本人技术有限,琢磨半天递归也没给点一下如果周围没有0则全部点亮提示给整出来。还有上面的那个查雷其实可以用循环实现看起来厉害一点,这里可以直接把board[x][y]排除的,我这里直接在后面多 - '0' 也可以吧。

static findmine_count(char board[Wids][Lens], int x, int y)//查雷实现
{
    int i,j;
    int sum = 0;
    for(i = -1; i < 2; i++)
    {
        for(j = -1; j < 2; j++)
        {
            sum = sum + board[x + i][y + j];
        }
    }
    return sum - 9 * '0';
}

下面是所有的代码

主函数:main.c

/**              扫雷                **/

#include"game.h"

int main()
{
    int input = 0;
    srand((unsigned int)time(NULL));
    do
    {
        menu();//菜单
        printf("\n\n请选择:>\n");
        scanf("%d", &input);
        switch(input)
        {
        case 1:
            game();//游戏主体函数
            break;
        case 0:
            printf("游戏已退出!\n");
            break;
        default:
            printf("输入有误!请重新输入!\n");
            break;
        };
    }while(input);
    return 0;
}

game.h

#ifndef GAME_H_INCLUDED
#define GAME_H_INCLUDED

#include<stdio.h>
#include<stdlib.h>
#include<time.h>


#define Len 9
#define Wid 9
#define Lens 11
#define Wids 11
#define setmine_count 10 //地雷数

void menu();//菜单函数声明
void game();//主体函数声明
void initboard(char board[Wids][Lens], int wids, int lens, char set);//初始化数组声明
void displayboard(char board[Wids][Lens], int wid, int len);//打印棋盘声明
void setmine(char board[Wids][Lens], int wid, int len);//埋雷声明
void findmine(char mine[Wids][Lens], char show[Wids][Lens], int wid, int len);//查雷声明



#endif // GAME_H_INCLUDED

game.c

#include"game.h"


void menu()//菜单函数实现
{
    printf("*************************************\n");
    printf("****                             ****\n");
    printf("****   1、play        0、exit    ****\n");
    printf("****                             ****\n");
    printf("*************************************\n");
}

void game()//主体实现
{
    //需要两个数组
    //一个用来存放地雷
    //另一个用来存放提示
    char mine[Wids][Lens] = {0};//地雷
    char show[Wids][Lens] = {0};//提示
    //初始化数组
    initboard(mine, Wids, Lens, '0');
    initboard(show, Wids, Lens, '*');

    //打印棋盘
    displayboard(mine, Wid, Len);
    displayboard(show, Wid, Len);

    //埋雷
    setmine(mine, Wid, Len);
    //displayboard(mine, Wid, Len);

    //查雷
    findmine(mine, show, Wid, Len);
}

void initboard(char board[Wids][Lens], int wids, int lens, char set)//初始化数组实现
{
    int i, j;
    for(i = 0; i < wids; i++)
    {
        for(j = 0; j < lens; j++)
        {
            board[i][j] = set;
        }
    }
}


void displayboard(char board[Wids][Lens], int wid, int len)//打印棋盘实现
{
    int i, j;
    printf("------棋盘-------\n");
    for(i = 0; i <= len; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for(i = 1; i <= wid; i++)
    {
        printf("%d ", i);
        for(j = 1; j <= len; j++)
        {
            printf("%c ", board[i][j]);
        }
        printf("\n");
    }
    printf("------棋盘-------\n");
}

void setmine(char board[Wids][Lens], int wid, int len)//埋雷实现
{
    //需要随机值

    int count = setmine_count;
    while(count)
    {
        int x = rand() % wid + 1;
        int y = rand() % len + 1;
        if(board[x][y] == '0')
        {
            board[x][y] = '1';
            count--;
        }
    }
}

static findmine_count(char board[Wids][Lens], int x, int y)//查雷实现
{
    int i,j;
    int sum = 0;
    for(i = -1; i < 2; i++)
    {
        for(j = -1; j < 2; j++)
        {
            sum = sum + board[x + i][y + j];
        }
    }
    return sum - 9 * '0';

//    return board[x - 1][y - 1] +
//            board[x - 1][y] +
//            board[x - 1][y + 1] +
//            board[x][y - 1] +
//            board[x][y + 1] +
//            board[x + 1][y - 1] +
//            board[x + 1][y] +
//            board[x + 1][y - 1] - 8 * '0';
}


void findmine(char mine[Wids][Lens], char show[Wids][Lens], int wid, int len)
{
    //需要玩家输入坐标,对坐标进行判断
    //对有雷和无雷进行实现
    int x = 0;
    int y = 0;
    int count = 0;
    while(count != wid * len - setmine_count)
    {
        printf("\n\n请输入要查的坐标:>\n");
        scanf("%d %d", &x, &y);
        if(x >= 1 && x <= wid && y >= 1 && y <= len)
        {
            //有雷 被炸死
            //没有雷 计算周围一格内的雷数并显示
            if(mine[x][y] == '1')
            {
                printf("\n\n\n*****************\n");
                printf("*** 菜      菜***\n");
                printf("***           ***\n");
                printf("***     菜    ***\n");
                printf("***           ***\n");
                printf("***菜       菜***\n");
                printf("*****************\n\n\n\n");
                break;
            }
            else
            {
                int set = findmine_count(mine, x, y);//计算周围一周的雷数
                show[x][y] = set + '0';//一个数字  +  '0'字符零 = 当前数字的字符形式
                displayboard(show, wid, len);
                count++;
            }
        }
        else
        {
            printf("\n\n输入的坐标有误!请重新输入!\n\n");
        }
    }
    if(count == wid * len - setmine_count)
    {
        printf("\n\n打得好啊!\n\n");
        displayboard(show, wid, len);
        printf("\n\n\n");
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值