扫雷

C语言马上学完,找了个课设的题目练练手。
一、功能描述:
1、使用方格显示,利于坐标输入。
2、分三个级别的难度。(初级 10个雷,中级 20个雷 ,高级 35)
3、第一次输入如果是雷,就随机移到非雷区,保证第一次不会被炸死。
4、可以显示一周雷的个数。
5、可以标记雷、取消标记。
6、输入坐标如果一周无雷,即展开,遇到有雷就停止展开。
7、保证屏幕上不累计出现多框图,每次显示前做清屏处理。
二、采用多文件方式实现,分为主函数,游戏函数,头文件函数
这里写图片描述
三、代码展示:
1、game.h

#ifndef __GAME_H__
#define __GAME_H__

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

#define ROW 10
#define COL 10
#define ROWS ROW+2
#define COLS COL+2
#define mine_count 10
#define mid_count mine_count+10
#define high_count mine_count+25

int select_level(); //选择等级
void init_str(char arr[ROWS][COLS],int row,int col,int set);  //初始化数组
void display_board(char arr[ROWS][COLS],int row,int col);  //打印数组
void insert_mine(char arr[ROWS][COLS],int row,int col,int count);  //布雷
void clear_mine(char minearr[ROWS][COLS],char showarr[ROWS][COLS],int number);  //展开
int get_minecount(char arr[ROWS][COLS],int x,int y);  //统计雷
void open_board(char showmine[ROW][COLS],char minearr[ROWS][COLS],int x,int y);  //展开
int sign_mine(char arrshow[ROWS][COLS],char arrmine[ROWS][COLS],int num);  //标记
int cancel_sign(char arrshow[ROWS][COLS],char arrmine[ROWS][COLS],int num);  //取消标记

#endif //__GAME_H__

2、main.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void print_menu()
{
    printf("****************************welcome you !****************************\n");
    printf("********************   1、play          0、exit  ********************\n");
    printf("****************************good   luck !****************************\n");
}

void game()
{
    int number = 0;
    char mine[ROWS][COLS]={0};  //放雷的数组
    char show[ROWS][COLS]={0};  //显示的数组
    number = select_level();
    init_str(mine,ROWS,COLS,'0');  //初始化雷组
    init_str(show,ROWS,COLS,'*');  //初始化非雷组
    display_board(show,ROW,COL);  //显示
    insert_mine(mine,ROW,COL,number);  //布雷
    //display_board(mine,ROW,COL);  //显示雷数组,用于测试
    clear_mine(mine,show,number);  //排雷
}

int main ()
{
    int input = 0;
    srand((unsigned)time(NULL));  //产生种子,布雷时使用
    do 
    {
        print_menu();
        printf("please select:>");
        scanf("%d",&input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            break;
        default:
            printf("enter error !\n");
        }
    } while (input);
    return 0;
}

3、game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

int select_level()  //选择等级
{
    int input= 0;
    int num = 0;
    int flag = 1;
    printf("*************************   1、Simple (10 mines)   *************************\n");
    printf("*************************   2、Middle (15 mines)   *************************\n");
    printf("*************************   3、trouble(35 mines)   *************************\n");
    while (flag)
    {
        printf("please select:>");
        scanf("%d",&input);
        switch (input)
        {
        case 1:
            {
                num=mine_count;
                flag = 0;
                break;
            }
        case 2:
            {
                num=mid_count;
                flag = 0;
                break;
            }
        case 3:
            {
                num=high_count;
                flag = 0;
                break;
            }
        default:
            printf("enter error !\n");
        }
    }
    return num;
}

void init_str(char arr[ROWS][COLS],int row,int col,int set)  //初始化雷的数组和显示的数组

{
    int i = 0;
    int j = 0;
    for (i=0; i<row; i++)
    {
        for (j=0; j<col; j++)
        {
            arr[i][j]=set;  
        }
    }
}

void display_board(char arr[ROWS][COLS],int row,int col)  //打印显示数组
{
    int i = 0;
    int j = 0;
    printf("   ");
    for (i=1; i<=row; i++)
    {
        printf(" %d  ",i);
    }
    printf("\n");
    printf("  ");
    for (i=0; i<row; i++)
    {
        printf("----");
    }
    printf("\n");
    for (i=1; i<=row; i++)
    {
        printf("%2d|",i);
        for (j=1; j<=col; j++)
        {
            printf(" %c |",arr[i][j]);
        }
        printf("\n");
        printf("  ");
        for (j=0; j<row; j++)
        {
            printf("----");
        }
        printf("\n");
    }
}

void insert_mine(char arr[ROWS][COLS],int row,int col,int count) //布雷

{
   int x = 0;
   int y = 0;
   while (count)
   {
      x=(rand()%row)+1;  //判断坐标是否合法
      y=(rand()%col)+1;
      if (arr[x][y]=='0')
      {
          arr[x][y]='1';
          count--;
      }
   }
}

 int get_minecount(char arr[ROWS][COLS],int x,int y)  //统计雷的个数

 {
     return (arr[x][y-1]+arr[x][y+1]
     +arr[x-1][y-1]+arr[x-1][y]+arr[x-1][y+1]
     +arr[x+1][y-1]+arr[x+1][y]+arr[x+1][y+1]-8*'0');

 }

 void open_board(char showarr[ROW][COLS],char minearr[ROWS][COLS],int x,int y)  //展开
 {
     int count = 0;
     int i = 0;
     int j = 0;
     if (showarr[x][y]=='*')  //防止重复展开
     {
         count = get_minecount(minearr,x,y);
         if (count!=0)  //雷的个数不为零就停止
         {
             showarr[x][y]=count+'0';
         }
         else
         {
             showarr[x][y]=' ';
             for (i=-1;i<=1; i++)
             {
                 for (j=-1; j<=1; j++)
                 {
                     if (x + i >= 1 && x + i <=ROW && y + j >= 1 && y + j <=COL)  //递归展开时不能越界
                     {
                         if (i!=j)
                         {
                             open_board(showarr,minearr,x+i,y+j);  //递归调用
                         }
                     }
                 }
             }
         }
     }
 }

int sign_mine(char arrshow[ROWS][COLS],char arrmine[ROWS][COLS],int num)  //标记

{
    int x = 0;
    int y = 0;
    while (1)
    {
        printf("please enter coordinate:");
        scanf("%d%d",&x,&y);
        if (x>=1 && x<=ROW && y>=1 && y<=COL && arrshow[x][y]=='*' && arrshow[x][y]!='-')  //合法标记
        {
            arrshow[x][y]='-';
            if (arrmine[x][y]=='1')
            {
                num--;
            }
            break;
        }
        else
            printf("enter error !\n");
    }
    return num;
}

int cancel_sign(char arrshow[ROWS][COLS],char arrmine[ROWS][COLS],int num)  //取消标记
{
    int x = 0;
    int y = 0;
    while (1)
    {
        printf("please enter coordinate(example:2 2):>");
        scanf("%d%d",&x,&y);
        if (x>=1 && x<=ROW && y>=1 && y<=COL && arrshow[x][y]!='*' && arrshow[x][y]=='-') //防止重复标记和错误标记
        {
            arrshow[x][y]='*';
            if (arrmine[x][y]=='1')
            {
                num++;
            }
            break;
        }
        else
            printf("enter error !\n");
    }
    return num;
}

void clear_mine(char minearr[ROWS][COLS],char showarr[ROWS][COLS],int number)  //排雷
{
    int x = 0;
    int y = 0;
    int x0 = 0;
    int y0 = 0;
    int flag = 0;
    while (number)  
    {
        printf("please enter coordinate(example 2 2):>");
        scanf("%d%d",&x,&y);
        //防止重复输入和错误输入,被标记处不能展开
        if (x>=1 && x<=ROW && y>=1 && y<=COL && showarr[x][y]=='*' && showarr[x][y]!='-')  
        {
            flag++;
            if (flag==1 && minearr[x][y]=='1')  //第一次不被炸死,增加可玩性
            {
                minearr[x][y]='0';
                    while (1)
                    {
                        x0=(rand()%ROW)+1;  //判断坐标是否合法
                        y0=(rand()%COL)+1;
                        if (minearr[x0][y0]=='0')
                        {
                            minearr[x0][y0]='1';  //移走第一个雷
                            break;
                        }
                    }
            }
            if (minearr[x][y]=='1')
            {
                printf("\n**************************** game over ! ****************************\n");
                display_board(minearr,ROW,COL);  //显示雷
                break;
            }
            else  //输入坐标不是雷
            {
                int tmp = 1;
                system("cls");  //清屏
                open_board(showarr,minearr,x,y);  //展开不是雷的区域
                display_board(showarr,ROW,COL); 
                while (tmp)
                {
                    printf("\n****************************  是 否 标 记  ****************************\n");
                    printf("*********************** 1、yes  2、cancel 0、no ***********************\n");
                    printf("please select:>");
                    scanf("%d",&tmp);
                    //根据需求标记、取消标记和不标记
                    switch (tmp)
                    {
                    case 1:
                        {
                            number=sign_mine(showarr,minearr,number);  //标记雷
                            if (number==0)
                            {
                                tmp=0;
                                display_board(showarr,ROW,COL);
                                printf("**************************** you  win ! ****************************\n\n");
                                break;
                            }
                            system("cls");  //清屏
                            display_board(showarr,ROW,COL);
                            break;
                        }
                    case 2:
                        {
                            number = cancel_sign(showarr,minearr,number);
                            if (number==0)
                            {
                                tmp=0;
                                display_board(showarr,ROW,COL);
                                printf("**************************** you  win ! ****************************\n\n");
                                break;
                            }
                            system("cls");  //清屏
                            display_board(showarr,ROW,COL);
                            break;
                        }
                    case 0:
                        break;
                    default:
                        printf("enter error !\n");
                        break;
                    }
                }
            }
        }
        else 
            printf("enter error !\n");
    }
}

四、效果展示:
1、菜单展示
这里写图片描述
2、排雷开始
这里写图片描述
3、展开图展示
这里写图片描述
4、游戏胜利
这里写图片描述
5、游戏失败
这里写图片描述
五、本项目难点展示(难点是展开部分)

void open_board(char showarr[ROW][COLS],char minearr[ROWS][COLS],int x,int y)  //展开
 {
     int count = 0;
     int i = 0;
     int j = 0;
     if (showarr[x][y]=='*')  //防止重复展开
     {
         count = get_minecount(minearr,x,y);
         if (count!=0)  //雷的个数不为零就停止
         {
             showarr[x][y]=count+'0';
         }
         else
         {
             showarr[x][y]=' ';
             for (i=-1;i<=1; i++)
             {
                 for (j=-1; j<=1; j++)
                 {
                     if (x + i >= 1 && x + i <=ROW && y + j >= 1 && y + j <=COL)  //递归展开时不能越界
                     {
                         if (i!=j)  //只要衡纵坐标不等就递归展开
                         {
                             open_board(showarr,minearr,x+i,y+j);  //递归调用
                         }
                     }
                 }
             }
         }
     }
 }

六、学习了c语言感觉很爽,女朋友天天写我玩的游戏,还能帮我找bug,更重要的是增进感情。

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙跃十二

写的不错,给点鼓励

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值