C语言实现minesweeper扫雷

本文介绍了一个使用C语言编写的简单扫雷程序。通过二维数组存储扫雷地图,利用FOR循环遍历并计算每个格子周围九宫格内的炸弹数量。程序中处理了边界条件,包括第一行、最后一行、第一列和最后一列的特殊情况。虽然功能基础,但提供了进一步扩展和完善的可能。
摘要由CSDN通过智能技术生成

首先说一下,我的这个小程序没有用什么算法,就是一个很小白的程序,求不喷。

先说一下思路,我是计划用一个二维数组来储存一切数据,即一个扫雷图的全部数据。一切都在这个二维数组里操作。废话不多说,先上程序。

#include <stdio.h>
#include <stdlib.h>     //包含srand()和rand()函数

#define SIZE 9          //数组大小(SIZE * SIZE)

_Bool life = 1;         //标志是否Gameover

void setbomb(char (*array)[SIZE]);              //设定炸弹的位置

void setnum(char (*array)[SIZE]);      //计算炸弹数

int countbomb_square(char (*array)[SIZE], int x, int y);   //计算每个九宫格的炸弹数

void check(char (*array)[SIZE], int x, int y);        //接受输入和操作

void printpic(char (*array)[SIZE]);              //打印图像

int main(void)
{
    int x = 0, y = 0;       //储存用户输入的位置
    char array[SIZE][SIZE] = {{0}};

    setbomb(array);

    setnum(array);

    while(1){
        printpic(array);      //打印图像

        if(0 == life)          //判断是否Gameover
	    break;

        printf("Enter your chosen in formatted(x y): ");
        if(0 == scanf("%d%d", &x, &y))
            break;

        check(array, x, y);   //处理输入
    }

    if(life)
        printf("You win!\n");
    else
        printf("You lost!\n");

    return 0;
}

void setbomb(char (*array)[SIZE])
{
    int index1 = 0, index2 = 0;
    int temp;

    srand((unsigned int)time(NULL));

    for(index1 = 0; index1 < SIZE; index1++){
        for(index2 = 0; index2 < SIZE; index2++){
            temp = rand() % 90;

            if((60 < temp) && (temp < 90))            // 1/3 的空格设有炸弹
                array[index1][index2] = -1;
        }
    }
}

void setnum(char (*array)[SIZE])
{
    int index1 = 0, index2 = 0;

    for(index1 = 0; index1 < SIZE; index1++){
        for(index2 = 0; index2 < SIZE; index2++){
            if(-1 == array[index1][index2])
                array[index1][index2] += 10;              //数字大于8的空格不可见
            else
                array[index1][index2] = countbomb_square(array, index1, index2) + 10;
        }
    }
}

int countbomb_square(char (*array)[SIZE], int row, int column)
{
    int count = 0;
    int start_row, final_row;
    int start_column, final_column, temp_column;

    if(0 != row && SIZE - 1 != row)               //有三种可能,最大的可能是中间的空格
        start_row = row - 1, final_row = row + 1;
    else if(0 == row)                       //在第一行的空格
        start_row = row, final_row = row + 1;
    else if(SIZE - 1 == row)                //在最后一行的空格
        start_row = row - 1, final_row = row;

    if(0 != column && SIZE - 1 != column)               //也有三种可能,中间的空格
        start_column = column - 1, final_column = column + 1;
    else if(0 == column)                      //在第一列的空格
        start_column = column, final_column = column + 1;
    else if(SIZE - 1 == column)               //在最后一列的空格
        start_column = column - 1, final_column = column;

    temp_column = start_column;
    for(; start_row <= final_row; start_row++){
        start_column = temp_column;

        for(; start_column <= final_column; start_column++){
            if((-1 == array[start_row][start_column]) || ( -1 + 10 == array[start_row][start_column]))
                count++;                              //未处理的炸弹格式-1,但处理过的炸弹格+10等于9
        }
    }

    return count;
}

void check(char (*array)[SIZE], int x, int y)
{
    if((0 <= array[x][y]) && (array[x][y] <= 8))       //空格已打开,已可见
        return;

    if(-1 == array[x][y] - 10){    //Gameover, 更改life的值
        array[x][y] -= 10;
        life = 0;
    }
    else if(8 < array[x][y])
        array[x][y] -= 10;        //打开空格
}

void printpic(char (*array)[SIZE])
{
    int index1 = 0, index2 = 0;

    system("cls");

    printf("|*");
    for(index1 = 0; index1 < SIZE; index1++)
        printf("|%d", index1);
    printf("|\n");

    for(index1 = 0; index1 < SIZE; index1++){
        for(index2 = 0; index2 < SIZE; index2++)
            printf("---");
        printf("\n|%d", index1);

        for(index2 = 0; index2 < SIZE; index2++){
            if(8 < array[index1][index2])              //大于8,不可见
                printf("| ");
            else if((0 <= array[index1][index2]) && (array[index1][index2] <= 8))  //非炸弹格
                printf("|%d", array[index1][index2]);
            else if(-1 == array[index1][index2])              //炸弹格
                printf("|*");
        }

        printf("|\n");
    }
}



实现方法是在二维数组内随机填入炸弹(用值-1表示),再逐个元素计算在以它为中心的九宫格内的炸弹数并填入数字,之后把所有的格子隐藏起来,按玩家的输入打开,如果选中炸弹就游戏结束。

程序的核心是计算九宫格内的炸弹数,以下是详细讲解。

用FOR循环来遍历整个二维数组,对每个元素即格子计算炸弹数。


以每个格子为中心的九宫格就如上图所示,行从Row-1行开始到Row+1行,列从Column-1到Column+1,用两个FOR循环来实现九宫格的遍历。还有一个前提,中心的格子,即(Row,Column)没有炸弹,即如果格子有炸弹就跳过这个格子。

还有一些特殊情况,即第一行和最后一行,第一列和最后一列。因为行和列互不影响,所以可以分开处理。

先处理行。


如图所示,行有三种情况,第一行,最后一行和中间的格子。

    if(0 != row && SIZE - 1 != row)               //有三种可能,最大的可能是中间的空格
        start_row = row - 1, final_row = row + 1;
    else if(0 == row)                       //在第一行的空格
        start_row = row, final_row = row + 1;
    else if(SIZE - 1 == row)                //在最后一行的空格
        start_row = row - 1, final_row = row;

接着是列的处理,也是三种情况,第一,最后,中间,和行的一样。


以下是代码

    if(0 != column && SIZE - 1 != column)               //也有三种可能,中间的空格
        start_column = column - 1, final_column = column + 1;
    else if(0 == column)                      //在第一列的空格
        start_column = column, final_column = column + 1;
    else if(SIZE - 1 == column)               //在最后一列的空格
        start_column = column - 1, final_column = column;


确定行和列的起始和结束之后,就是九宫格内逐个遍历,计算过炸弹的数量并填入格子内。
    temp_column = start_column;
    for(; start_row <= final_row; start_row++){
        start_column = temp_column;

        for(; start_column <= final_column; start_column++){
            if((-1 == array[start_row][start_column]) || ( -1 + 10 == array[start_row][start_column]))
                count++;                              //未处理的炸弹格式-1,但处理过的炸弹格+10等于9
        }
    }

因为列在每个内循环里都要重新开始,为了效率,添加了一个变量temp_column储存它。

核心的东西已经讲完了,这是一个简陋的扫雷程序,没有标志炸弹位置的功能,也没有打开空格的功能,但可以自己添加上去,自己完善它,就说到这里吧。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值