溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

掃雷的分析與實(shí)現(xiàn)——C語(yǔ)言

發(fā)布時(shí)間:2020-07-19 19:12:15 來(lái)源:網(wǎng)絡(luò) 閱讀:217 作者:Xin_37 欄目:編程語(yǔ)言

掃雷作為一款經(jīng)典游戲,為大家所熟知。今天我使用C語(yǔ)言來(lái)編寫(xiě)一個(gè)簡(jiǎn)單的掃雷程序。

主要功能有

1.第一次下子不被炸死;
2.下子后顯示周?chē)祭讛?shù);

分析游戲及功能

首先可以將掃雷的游戲界面看做一個(gè)二維數(shù)組;然后有限的雷隨機(jī)排布在這個(gè)二維數(shù)組中,玩家通過(guò)輸入坐標(biāo)來(lái)確定該坐標(biāo)對(duì)應(yīng)的二維數(shù)組坐標(biāo)是否是雷,若不是則顯示周?chē)祭讛?shù),這時(shí)考慮坐標(biāo)如果在數(shù)組的中間則少顯示周?chē)?個(gè)坐標(biāo)布雷情況,而在數(shù)組邊緣則小于8。因此我在創(chuàng)建數(shù)組時(shí)創(chuàng)建一個(gè)比所需數(shù)大2行2列。將所需數(shù)組視為中間數(shù)組即可;如圖:

掃雷的分析與實(shí)現(xiàn)——C語(yǔ)言

代碼創(chuàng)建

創(chuàng)建test.c,game.c和game.h三個(gè)文件

1.創(chuàng)建主函數(shù),打印菜單用do,whlie語(yǔ)句實(shí)現(xiàn)基選擇功能;

代碼如下:

int main()
{
    srand((unsigned int)time(NULL));//產(chǎn)生隨機(jī)數(shù)生成器
    int input = 0;
    do
    {
        muen();
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戲\n");
            break;
        default:
            printf("輸入錯(cuò)誤,重新輸入\n");
            break;
        }
    } while (input);
    system("pause");
    return 0;
}

2.在game.c中先完成菜單,數(shù)組的創(chuàng)建,以及玩家的界面,和布雷的界面

代碼如下;

void muen()
{
    printf("*******************************\n");
    printf("*****1.play       0.exit*******\n");
    printf("*******************************\n");
}

void init_mine()//初始化兩個(gè)棋盤(pán)
{
    int i = 0;
    int j = 0;
    for (int i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            show_mine[i][j] = '*';
            real_mine[i][j] = '0';
        }
    }
}

void print_player()//打印玩家棋盤(pán)
{
    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <row - 2; i++)
    {
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        {
            printf("%c ", show_mine[i][j]);//玩家棋盤(pán)數(shù)組
        }
        printf("\n");
    }
    printf("10 ");//開(kāi)始打印最后一行
    for (i = 1; i < row - 1; i++)
    {
        printf("%c ", show_mine[10][i]);
    }
    printf("\n");
}

void print_mine()//打印設(shè)計(jì)者棋盤(pán)
{
    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <row - 2; i++)
    {
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        {
            printf("%c ", real_mine[i][j]);
        }
        printf("\n");
    }
    printf("10 ");//開(kāi)始打印最后一行
    for (i = 1; i < row - 1; i++)
    {
        printf("%c ", real_mine[10][i]);
    }
    printf("\n");
}

效果如圖:
掃雷的分析與實(shí)現(xiàn)——C語(yǔ)言

3.完成布雷函數(shù)以及掃雷函數(shù)

代碼如下:

void set_mine()        //給設(shè)計(jì)者棋盤(pán)布雷
{
    int x = 0;
    int y = 0;
    int count = COUNT; //雷總數(shù)
    while (count)      //雷布完后跳出循環(huán)
    {
        int x = rand() % 10 + 1;     //產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
        int y = rand() % 10 + 1;     //產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
        if (real_mine[x][y] == '0')  //找不是雷的地方布雷
        {
            real_mine[x][y] = '1';
            count--;
        }
    }
}
int sweep_mine()//掃雷函數(shù),踩到雷返回1,沒(méi)有踩到雷返回0
{
    int x = 0;
    int y = 0;
    int count = 0;
    printf("輸入坐標(biāo)掃雷\n");
    scanf("%d%d", &x, &y);
    if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判斷輸入坐標(biāo)是否有誤,輸入錯(cuò)誤重新輸入
    {
        if (real_mine[x][y] == '0')//沒(méi)踩到雷
        {
            char ch = count_mine(x, y);
            show_mine[x][y] = ch + '0';//數(shù)字對(duì)應(yīng)的ASCII值和數(shù)字字符對(duì)應(yīng)的ASCII值相差48,即'0'的ASCII值
            open_mine(x, y);
            if (count_show_mine() == COUNT)//判斷剩余未知區(qū)域的個(gè)數(shù),個(gè)數(shù)為雷數(shù)時(shí)玩家贏(yíng)
            {
                return 0;
            }
        }
        else if (real_mine[x][y] == '1')//踩到雷
        {
            return 1;
        }
    }
    else
    {
        printf("輸入錯(cuò)誤重新輸入\n");
    }
    return 0;//沒(méi)踩到雷
}

4.完成防止第一步被炸死的函數(shù)

代碼如下:

void safe_mine()//避免第一次炸死
{
    int x = 0;
    int y = 0;
    char ch = 0;
    int count = 0;
    int ret = 1;
    printf("游戲開(kāi)始\n");
    printf("輸入坐標(biāo)掃雷\n");
    while (1)
    {
        scanf("%d%d", &x, &y);//只能輸入1到10,輸入錯(cuò)誤重新輸入
        if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判斷輸入坐標(biāo)是否有誤
        {
            if (real_mine[x][y] == '1')//第一次踩到雷后補(bǔ)救
            {
                real_mine[x][y] = '0';
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + '0';//數(shù)字對(duì)應(yīng)的ASCII值和數(shù)字字符對(duì)應(yīng)的ASCII值相差48,即'0'的ASCII值
                open_mine(x, y);
                while (ret)//在其余有空的地方設(shè)置一個(gè)雷
                {
                    int x = rand() % 10 + 1;//產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
                    int y = rand() % 10 + 1;//產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
                    if (real_mine[x][y] == '0')//找不是雷的地方布雷
                    {
                        real_mine[x][y] = '1';
                        ret--;
                        break;
                    }
                }break;//跳出此函數(shù)  
            }
            if (real_mine[x][y] == '0')
            {
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + '0';//數(shù)字對(duì)應(yīng)的ASCII值和數(shù)字字符對(duì)應(yīng)的ASCII值相差48,即'0'的ASCII值
                open_mine(x, y);
                break;
            }
        }
        else//坐標(biāo)錯(cuò)誤
        {
            printf("輸入錯(cuò)誤重新輸入\n");
        }
    }
}

5.完成檢測(cè)周?chē)讛?shù)并顯示函數(shù)

int count_mine(int x, int y)//檢測(cè)周?chē)?個(gè)區(qū)域雷的個(gè)數(shù)
{
    int count = 0;
    if (real_mine[x - 1][y - 1] == '1')
        count++;
    if (real_mine[x - 1][y] == '1')
        count++;
    if (real_mine[x - 1][y + 1] == '1')
        count++;
    if (real_mine[x][y - 1] == '1')
        count++;
    if (real_mine[x][y + 1] == '1')
        count++;
    if (real_mine[x + 1][y - 1] == '1')
        count++;
    if (real_mine[x + 1][y] == '1')
        count++;
    if (real_mine[x + 1][y + 1] == '1')
        count++;
    return count;
}

void open_mine(int x, int y)//坐標(biāo)周?chē)归_(kāi)函數(shù)
{
    if (real_mine[x - 1][y - 1] == '0')
    {
        show_mine[x - 1][y - 1] = count_mine(x - 1, y - 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x - 1][y] == '0')
    {
        show_mine[x - 1][y] = count_mine(x - 1, y) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x - 1][y + 1] == '0')
    {
        show_mine[x - 1][y + 1] = count_mine(x - 1, y + 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x][y - 1] == '0')
    {
        show_mine[x][y - 1] = count_mine(x, y - 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x][y + 1] == '0')
    {
        show_mine[x][y + 1] = count_mine(x, y + 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x + 1][y - 1] == '0')
    {
        show_mine[x + 1][y - 1] = count_mine(x + 1, y - 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x + 1][y] == '0')
    {
        show_mine[x + 1][y] = count_mine(x + 1, y) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x + 1][y + 1] == '0')
    {
        show_mine[x + 1][y + 1] = count_mine(x + 1, y + 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
}

6.最后完成判斷玩家贏(yíng)的函數(shù)

代碼如下;

int count_show_mine()//判斷剩余未知區(qū)域的個(gè)數(shù),個(gè)數(shù)為雷數(shù)時(shí)玩家贏(yíng)
{
    int count = 0;
    int i = 0;
    int j = 0;
    for (i = 1; i <= row - 2; i++)
    {
        for (j = 1; j <= col - 2; j++)
        {
            if (show_mine[i][j] == '*')
            {
                count++;
            }
        }
    }
    return count;
}

最后運(yùn)行測(cè)試

查看第一是否可以炸死(根據(jù)布雷圖,輸入有雷坐標(biāo)未被炸死):
掃雷的分析與實(shí)現(xiàn)——C語(yǔ)言

第二步輸入有雷坐標(biāo):
掃雷的分析與實(shí)現(xiàn)——C語(yǔ)言
判斷玩家贏(yíng);
掃雷的分析與實(shí)現(xiàn)——C語(yǔ)言

test.c代碼

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
double  start, finish;
void game()
{
    int ret = 0;
    init_mine();             //初始化玩家棋盤(pán)和設(shè)計(jì)者棋盤(pán)
    set_mine();              //給設(shè)計(jì)者棋盤(pán)布雷
    print_mine();            //打印設(shè)計(jì)者棋盤(pán)(可不打?。?    printf("\n");            
    print_player();          //打印玩家棋盤(pán)
    start = clock();
    safe_mine();             //避免第一次被炸死

    if (count_show_mine() == COUNT)//一步就贏(yíng)的情況
    {
        print_mine();
        printf("玩家贏(yíng)!\n\n");
        return;
     }
    print_player();
    while (1)//循環(huán)掃雷
    {
        int ret = sweep_mine();//掃雷,踩到雷返回1,沒(méi)有踩到雷返回0
        if (count_show_mine() == COUNT)//若玩家棋盤(pán)的'*'個(gè)數(shù)為雷數(shù)時(shí),掃雷完成,游戲勝利
        {
            print_mine();    //打印設(shè)計(jì)者棋盤(pán)
            printf("玩家贏(yíng)!\n\n");
            finish = clock();//取結(jié)束時(shí)間
            printf("用時(shí)%d 秒\n", (int)(finish - start) / CLOCKS_PER_SEC);
            break;
        }
        if (ret)//判斷是否踩到雷
        {
            printf("被雷炸死\t");
            finish = clock();//取結(jié)束時(shí)間
            printf("用時(shí)%d 秒\n", (int)(finish - start) / CLOCKS_PER_SEC);
            print_mine();//打印設(shè)計(jì)者雷陣查看雷的分布
            break;
        }
        print_player();//打印玩家棋盤(pán)
    }
}

int main()
{
    srand((unsigned int)time(NULL));//產(chǎn)生隨機(jī)數(shù)生成器
    int input = 0;
    do
    {
        muen();
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            printf("退出游戲\n");
            break;
        default:
            printf("輸入錯(cuò)誤,重新輸入\n");
            break;
        }
    } while (input);//循環(huán)玩游戲
    system("pause");
    return 0;
}

game.c代碼

#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
char show_mine[row][col] = { 0 };
char real_mine[row][col] = { 0 };

void muen()
{
    printf("*******************************\n");
    printf("*****1.play       0.exit*******\n");
    printf("*******************************\n");
}

void init_mine()//初始化兩個(gè)棋盤(pán)
{
    int i = 0;
    int j = 0;
    for (int i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            show_mine[i][j] = '*';
            real_mine[i][j] = '0';
        }
    }
}

void print_player()//打印玩家棋盤(pán)
{
    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    {
        printf("%d ", i);//打印橫標(biāo)(0--10)
    }
    printf("\n");
    for (i = 1; i <row - 2; i++)//打印豎標(biāo)(1--10)
    {
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        {
            printf("%c ", show_mine[i][j]);//玩家棋盤(pán)數(shù)組
        }
        printf("\n");
    }
    printf("10 ");//開(kāi)始打印最后一行
    for (i = 1; i < row - 1; i++)
    {
        printf("%c ", show_mine[10][i]);
    }
    printf("\n");
}

void print_mine()//打印設(shè)計(jì)者棋盤(pán)
{
    int i = 0;
    int j = 0;
    printf("0  ");
    for (i = 1; i <row - 1; i++)
    {
        printf("%d ", i);
    }
    printf("\n");
    for (i = 1; i <row - 2; i++)
    {
        printf("%d  ", i);
        for (j = 1; j < col - 1; j++)
        {
            printf("%c ", real_mine[i][j]);
        }
        printf("\n");
    }
    printf("10 ");//開(kāi)始打印最后一行
    for (i = 1; i < row - 1; i++)
    {
        printf("%c ", real_mine[10][i]);
    }
    printf("\n");
}

void set_mine()        //給設(shè)計(jì)者棋盤(pán)布雷
{
    int x = 0;
    int y = 0;
    int count = COUNT; //雷總數(shù)
    while (count)      //雷布完后跳出循環(huán)
    {
        int x = rand() % 10 + 1;     //產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
        int y = rand() % 10 + 1;     //產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
        if (real_mine[x][y] == '0')  //找不是雷的地方布雷
        {
            real_mine[x][y] = '1';
            count--;
        }
    }
}
int sweep_mine()//掃雷函數(shù),踩到雷返回1,沒(méi)有踩到雷返回0
{
    int x = 0;
    int y = 0;
    int count = 0;
    printf("輸入坐標(biāo)掃雷\n");
    scanf("%d%d", &x, &y);
    if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判斷輸入坐標(biāo)是否有誤,輸入錯(cuò)誤重新輸入
    {
        if (real_mine[x][y] == '0')//沒(méi)踩到雷
        {
            char ch = count_mine(x, y);
            show_mine[x][y] = ch + '0';//數(shù)字對(duì)應(yīng)的ASCII值和數(shù)字字符對(duì)應(yīng)的ASCII值相差48,即'0'的ASCII值
            open_mine(x, y);
            if (count_show_mine() == COUNT)//判斷剩余未知區(qū)域的個(gè)數(shù),個(gè)數(shù)為雷數(shù)時(shí)玩家贏(yíng)
            {
                return 0;
            }
        }
        else if (real_mine[x][y] == '1')//踩到雷
        {
            return 1;
        }
    }
    else
    {
        printf("輸入錯(cuò)誤重新輸入\n");
    }
    return 0;//沒(méi)踩到雷
}

void safe_mine()//避免第一次炸死
{
    int x = 0;
    int y = 0;
    char ch = 0;
    int count = 0;
    int ret = 1;
    printf("游戲開(kāi)始\n");
    printf("輸入坐標(biāo)掃雷\n");
    while (1)
    {
        scanf("%d%d", &x, &y);//只能輸入1到10,輸入錯(cuò)誤重新輸入
        if ((x >= 1 && x <= 10) && (y >= 1 && y <= 10))//判斷輸入坐標(biāo)是否有誤
        {
            if (real_mine[x][y] == '1')//第一次踩到雷后補(bǔ)救
            {
                real_mine[x][y] = '0';
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + '0';//數(shù)字對(duì)應(yīng)的ASCII值和數(shù)字字符對(duì)應(yīng)的ASCII值相差48,即'0'的ASCII值
                open_mine(x, y);
                while (ret)//在其余有空的地方設(shè)置一個(gè)雷
                {
                    int x = rand() % 10 + 1;//產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
                    int y = rand() % 10 + 1;//產(chǎn)生1到10的隨機(jī)數(shù),在數(shù)組下標(biāo)為1到10的范圍內(nèi)布雷
                    if (real_mine[x][y] == '0')//找不是雷的地方布雷
                    {
                        real_mine[x][y] = '1';
                        ret--;
                        break;
                    }
                }break;//跳出此函數(shù)  
            }
            if (real_mine[x][y] == '0')
            {
                char ch = count_mine(x, y);
                show_mine[x][y] = ch + '0';//數(shù)字對(duì)應(yīng)的ASCII值和數(shù)字字符對(duì)應(yīng)的ASCII值相差48,即'0'的ASCII值
                open_mine(x, y);
                break;
            }
        }
        else//坐標(biāo)錯(cuò)誤
        {
            printf("輸入錯(cuò)誤重新輸入\n");
        }
    }
}

int count_mine(int x, int y)//檢測(cè)周?chē)?個(gè)區(qū)域雷的個(gè)數(shù)
{
    int count = 0;
    if (real_mine[x - 1][y - 1] == '1')
        count++;
    if (real_mine[x - 1][y] == '1')
        count++;
    if (real_mine[x - 1][y + 1] == '1')
        count++;
    if (real_mine[x][y - 1] == '1')
        count++;
    if (real_mine[x][y + 1] == '1')
        count++;
    if (real_mine[x + 1][y - 1] == '1')
        count++;
    if (real_mine[x + 1][y] == '1')
        count++;
    if (real_mine[x + 1][y + 1] == '1')
        count++;
    return count;
}

void open_mine(int x, int y)//坐標(biāo)周?chē)归_(kāi)函數(shù)
{
    if (real_mine[x - 1][y - 1] == '0')
    {
        show_mine[x - 1][y - 1] = count_mine(x - 1, y - 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x - 1][y] == '0')
    {
        show_mine[x - 1][y] = count_mine(x - 1, y) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x - 1][y + 1] == '0')
    {
        show_mine[x - 1][y + 1] = count_mine(x - 1, y + 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x][y - 1] == '0')
    {
        show_mine[x][y - 1] = count_mine(x, y - 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x][y + 1] == '0')
    {
        show_mine[x][y + 1] = count_mine(x, y + 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x + 1][y - 1] == '0')
    {
        show_mine[x + 1][y - 1] = count_mine(x + 1, y - 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x + 1][y] == '0')
    {
        show_mine[x + 1][y] = count_mine(x + 1, y) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
    if (real_mine[x + 1][y + 1] == '0')
    {
        show_mine[x + 1][y + 1] = count_mine(x + 1, y + 1) + '0';//顯示該坐標(biāo)周?chē)讛?shù)
    }
}

int count_show_mine()//判斷剩余未知區(qū)域的個(gè)數(shù),個(gè)數(shù)為雷數(shù)時(shí)玩家贏(yíng)
{
    int count = 0;
    int i = 0;
    int j = 0;
    for (i = 1; i <= row - 2; i++)
    {
        for (j = 1; j <= col - 2; j++)
        {
            if (show_mine[i][j] == '*')
            {
                count++;
            }
        }
    }
    return count;
}

game.h代碼

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

#define row 12
#define col 12
#define COUNT 10//棋盤(pán)中雷的總數(shù)
extern char real_mine[row][col];//布雷數(shù)組

void muen();           //菜單函數(shù)
void init_mine();      //初始化數(shù)組函數(shù)
void print_player();   //打印玩家棋盤(pán)
void print_mine();     //打印設(shè)計(jì)者棋盤(pán) 
void set_mine();       //布雷函數(shù)
int count_mine();      //統(tǒng)計(jì)周?chē)椎膫€(gè)數(shù)
void safe_mine();      //避免第一次被雷炸死的函數(shù)
int  sweep_mine();     //掃雷函數(shù)
void open_mine(int x, int y);//展開(kāi)函數(shù)
int count_show_mine(); //判斷玩家棋盤(pán)剩余未知區(qū)域的個(gè)數(shù)
向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI