欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

扫雷

程序员文章站 2022-04-07 21:54:23
...

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,更重要的是增进感情。

相关标签: 扫雷