C语言扫雷小游戏(可选难度,可记录历史成绩)

效果预览
开始界面
简单难度
中等难度
历史成绩
下面附代码

#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include <windows.h>
#include <mmsystem.h>
#pragma comment(lib,"Winmm.lib")
#define Ne 12//定义各种难度下的格子数量及雷的数量
#define Me 15
#define Nm 17
#define Mm 25
#define Nh 22
#define Mh 100

typedef struct nt//定义时间结构体
{
    int Year;
    int Month;
    int Day;
    int Hour;
    int Minute;

}NowTime;

typedef struct rk//定义成绩结构体
{
    char Level;
    float Score;
    NowTime Time;

}Rank;

void InitializationShow(char (*show)[22],int side);//初始化展示面板
void InitializationMines(char (*mines)[22],int side);//初始化雷区
void PrintingBoard(char (*board)[22],int side);//打印面板
void LindMines(char (*mines)[22],int side,int mount);//随机布雷
void Security(char (*mines)[22],int side,int X,int Y);//确保第一次查看区块安全
void Open(char (*show)[22],char (*mines)[22],int side,int X,int Y);//循环展开周围8个区块
void GameMove(char (*show)[22],char (*mines)[22],int side,int mount);//玩家行动模块
void Game(char (*show)[22],char (*mines)[22],int side,int mount);//游戏主程序
void OpenMenu();//开始菜单
void LastMenu();//结尾菜单
void ChangeLevel();//难度转换
void PrintfHistory();//显示历史记录
void ScanfHistory(float t,int mount);//读取成绩录入历史记录文件
int Statistics(char (*mines)[22],int X,int Y);//统计周围8个区块雷的数量
int Calculate(char (*show)[22],int side);//计算剩余为探索区块数量
char ChooseLevel();//选择难度
NowTime GetTime();//获取当前时间

void main()
{
    OpenMenu();
}

NowTime GetTime()
{
    time_t timep;
    struct tm *p;
    NowTime TM;
    time (&timep);
    p=gmtime(&timep);
    TM.Year=1900+p->tm_year;
    TM.Month=1+p->tm_mon;
    TM.Day=p->tm_mday;
    TM.Hour=8+p->tm_hour;
    TM.Minute=p->tm_min;
    return TM;
}

void OpenMenu()
{
    PlaySound(TEXT("BackGroundMusic.wav"),NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);//播放背景音乐
    int FLAG;
    printf("                                           欢迎游玩可选难度扫雷小游戏!\n");
    printf("\n");
    printf("                                    游戏介绍:\n");
    printf("                                    该扫雷小游戏提供简单、中等、困难三种难度。\n");
    printf("                                    简单难度场地大小10*10,内含15个雷;\n");
    printf("                                    中等难度场地大小15*15,内含25个雷;\n");
    printf("                                    困难难度场地大小20*20,内含100个雷。\n");
    printf("\n");
    printf("                                    下面请选择开始游戏、退出游戏或查看排行榜:\n");
    printf("                                         --------------------------\n");
    printf("                                         |1.准备好了,开始游戏!!|\n");
    printf("                                         |2.太困难了,放弃游戏!!|\n");
    printf("                                         |3.   我想看历史记录     |\n");
    printf("                                         --------------------------\n");
    do
    {
        scanf("%d",&FLAG);
        getchar();
        switch (FLAG)
        {
        case 1:
            ChangeLevel();
            break;
        case 2:
            exit(0);
        case 3:
            PrintfHistory();
        default:
            printf("                                    不要逃避,选择吧!!\n");
            break;
        }

    }while(FLAG);

}

void LastMenu()
{
    PlaySound(TEXT("BackGroundMusic.wav"),NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);
    int FLAG;
    printf("                                         --------------------------\n");
    printf("                                         |1.      返回主菜单      |\n");
    printf("                                         |2.      查看历史记录    |\n");
    printf("                                         |3.      退出游戏吧      |\n");
    printf("                                         --------------------------\n");
    do
    {
        scanf("%d",&FLAG);
        getchar();
        switch (FLAG)
        {
        case 1:
            OpenMenu();
        case 2:
            PrintfHistory();
        case 3:
            exit(0);
        default:
            printf("                                    不要乱输,快点选吧!!\n");
            break;
        }

    }while(FLAG);
}

void ChangeLevel()
{
    PlaySound(TEXT("GamingMusic.wav"),NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);
    char ShowBoard[22][22],MinesBoard[22][22];
    char LEVEL;
    LEVEL=ChooseLevel();
    if(LEVEL=='E'||LEVEL=='e')
    {
        Game(ShowBoard,MinesBoard,Ne,Me);
    }
    else if(LEVEL=='M'||LEVEL=='m')
    {
        Game(ShowBoard,MinesBoard,Nm,Mm);
    }
    else if(LEVEL=='H'||LEVEL=='h')
    {
        Game(ShowBoard,MinesBoard,Nh,Mh);
    }
}

char ChooseLevel()
{
    char LEVEL;
    printf("                                    请选择你想游玩的难度(简单:E(e)/中等:M(m)/困难:H(h)):");
    for(;;)
    {
        scanf("%c",&LEVEL);
        getchar();
        if(LEVEL=='H'||LEVEL=='M'||LEVEL=='E'||LEVEL=='h'||LEVEL=='m'||LEVEL=='e')
            break;
        else
        {
            printf("                                    请按照正确的格式输入难度:");
        }
    }
    return LEVEL;
}

void Game(char (*show)[22],char (*mines)[22],int side,int mount)
{
        InitializationShow(show,side);
        InitializationMines(mines,side);
        printf("                                    场地面积为%d*%d,场上一共有%d个雷,小心了!!\n",side-2,side-2,mount);
        PrintingBoard(show,side);
        LindMines(mines,side,mount);
        GameMove(show,mines,side,mount);
}

void InitializationShow(char (*show)[22],int side)
{
    int i,j;
    for(i=1;i<side-1;i++)
    {
        for(j=1;j<side-1;j++)
            show[i][j]='*';
    }
    for(i=0,j=0;i<side;i++)//用“X”填充周围,便于测试和调试
        show[i][j]='X';
    for(i=0,j=0;j<side;j++)
        show[i][j]='X';
    for(i=side-1,j=0;j<side;j++)
        show[i][j]='X';
    for(i=0,j=side-1;i<side;i++)
        show[i][j]='X';
}

void InitializationMines(char (*mines)[22],int side)
{
    int i,j;
    for(i=1;i<side-1;i++)
    {
        for(j=1;j<side-1;j++)
            mines[i][j]='0';
    }
    for(i=0,j=0;i<side;i++)//用“X”填充周围,便于测试和调试
        mines[i][j]='X';
    for(i=0,j=0;j<side;j++)
        mines[i][j]='X';
    for(i=side-1,j=0;j<side;j++)
        mines[i][j]='X';
    for(i=0,j=side-1;i<side;i++)
        mines[i][j]='X';
}

void PrintingBoard(char (*board)[22],int side)
{
	int i=0,j=0,k=0;
	printf("                                 %2d |",0);
    for(i=1;i<side-1;i++)
    {
        printf("%2d |",i);//打印行数
    }
    printf("\n");
    printf("                                 ");
    for(i=0;i<side;i++)
        printf("----");
    printf("\n");
    for(i=1;i<side-1;i++)
    {
        printf("                                 %2d |",i);//打印列数
        for(j=1;j<side-1;j++)
        {
            printf(" %c |",board[i][j]);
        }
        printf("%2d |",i);
        printf("\n");
        printf("                                 ");
        for(k=0;k<side;k++)
            printf("----");
        printf("\n");
    }
}

void LindMines(char (*mines)[22],int side,int mount)
{
    int x=0,y=0,COUNT;
    COUNT=mount;
    srand((int)time(NULL));//随机种子保证每次布雷不同
	while(COUNT)
	{
		int x=rand()%(side-2)+1;
		int y=rand()%(side-2)+1;
		if(mines[x][y]=='0')
        {
            mines[x][y]='1';
			COUNT--;
        }
    }
}

void Security(char (*mines)[22],int side,int X,int Y)
{
    if(mines[X][Y]=='1')
    {
        int x=0,y=0,COUNT=1;
        srand((int)time(NULL));
	    while(COUNT)
	   {
		  int x=rand()%(side-2)+1;
		  int y=rand()%(side-2)+1;
		  if(mines[x][y]=='0')
            {
                mines[x][y]='1';
			    COUNT--;
            }
       }
       mines[X][Y]=='0';
    }
}

void Open(char (*show)[22],char (*mines)[22],int side,int X,int Y)
{
    int Mine=0;
    Mine=Statistics(mines,X,Y);
    if(Mine==0)
    {
        show[X][Y]=' ';
        if (X-1>0&&Y>0&&show[X-1][Y]=='*')
            Open(show,mines,side,X-1,Y);//反复展开直到不能展开为止

        if (X-1>0&&Y+1<side-1&&show[X-1][Y+1]=='*')
            Open(show,mines,side,X-1,Y+1);

        if (X>0&&Y+1<side-1&&show[X][Y+1]=='*')
            Open(show,mines,side,X,Y+1);

        if (X+1<10&&Y+1<side-1&&show[X+1][Y+1]=='*')
            Open(show,mines,side,X+1,Y+1);

        if (X+1<side-1&&Y>0&&show[X+1][Y]=='*')
            Open(show,mines,side,X+1,Y);

        if (X+1<side-1&&Y-1>0&&show[X+1][Y-1]=='*')
            Open(show,mines,side,X+1,Y-1);

        if (X>0&&Y-1>0&&show[X][Y-1]=='*')
            Open(show,mines,side,X,Y-1);

        if (X-1>0&&Y-1>0&&show[X-1][Y-1]=='*')
            Open(show,mines,side,X-1,Y-1);

    }
       else
        {
            show[X][Y]=Statistics(mines,X,Y)+'0';
        }
}

int Statistics(char (*mines)[22],int X,int Y)
{
    int COUNT=0;
    if(mines[X-1][Y]=='1')
        COUNT++;
    if(mines[X-1][Y-1]=='1')
        COUNT++;
    if(mines[X-1][Y+1]=='1')
        COUNT++;
    if(mines[X][Y+1]=='1')
        COUNT++;
    if(mines[X][Y-1]=='1')
        COUNT++;
    if(mines[X+1][Y]=='1')
        COUNT++;
    if(mines[X+1][Y-1]=='1')
        COUNT++;
    if(mines[X+1][Y+1]=='1')
        COUNT++;
    return COUNT;
}

int Calculate(char (*show)[22],int side)
{
    int i,j,COUNT=0;
    for(i=1;i<side-1;i++)
    {
        for(j=1;j<side-1;j++)
        {
            if(show[i][j]=='*')
                COUNT++;
        }
    }
    return COUNT;
}

void GameMove(char (*show)[22],char (*mines)[22],int side,int mount)
{
    int X,Y;
    float time;
    clock_t start,end;//计时
    for(;;)//第一次查看同时确保第一次绝对安全
    {
        printf("                                    请输入你想查看的坐标(X,Y):");
        scanf("%d,%d",&X,&Y);
        start=clock();
        getchar();
        if(X>=1&&X<=(side-2)&&Y>=1&&Y<=(side-2))
            break;
        else
            printf("                                    请按照格式输入正确的坐标!!");
    }
     printf("\a");
     Security(mines,side,X,Y);
     Open(show,mines,side,X,Y);
     PrintingBoard(show,side);
     printf("                                    当前已点亮%d个区块,剩余%d个区块,加油!!\n",(side-2)*(side-2)-Calculate(show,side),Calculate(show,side)-mount);
    for(;;)
    {
        printf("                                    请输入请输入你想查看的坐标(X,Y):");
        scanf("%d,%d",&X,&Y);
        getchar();
        if(show[X][Y]!='*')
        {
            printf("                                    这个区块已经被点亮了哟!!\n");
            continue;
        }
        if(X>=1&&X<=side-2&&Y>=1&&Y<=side-2)
        {
            if(mines[X][Y]=='1')
            {
                end=clock();
                PrintingBoard(mines,side);
                printf("                                    BOOM!!!\n你踩到雷了!!用时%f秒!!\n",((double)end-start)/CLK_TCK);
                PlaySound(TEXT("BoomMusic.wav"),NULL,SND_FILENAME | SND_ASYNC | SND_LOOP);
                system("pause");
                printf("\n");
                LastMenu();
            }
            else if(mines[X][Y]=='0')
            {
                printf("\a");
                Open(show,mines,side,X,Y);
                PrintingBoard(show,side);
                if(Calculate(show,side)==mount)
                {
                    end=clock();
                    PrintingBoard(mines,side);
                    time=((double)end-start)/CLK_TCK;
                    printf("                                    扫雷成功!!用时%f秒!!\n",time);
                    ScanfHistory(time,mount);
                    printf("\n");
                    LastMenu();
                }
                else
                    printf("                                    当前已点亮%d个区块,剩余%d个区块,加油!!\n",(side-2)*(side-2)-Calculate(show,side),Calculate(show,side)-mount);
            }
        }
        else
        {
            printf("                                    请按照格式输入正确的坐标!!");
        }
    }
}

void ScanfHistory(float t,int mount)
{
    Rank R1;
    R1.Time=GetTime();
    R1.Score=t;
    FILE *fp;
    if(mount==Me)
        R1.Level='E';
    else if(mount==Mm)
        R1.Level='M';
    else if(mount==Mh)
        R1.Level=='H';
    fp=fopen("History.txt","a");
    fprintf(fp,"%c  %f  %d\\%d\\%d %d:%d\n", R1.Level, R1.Score, R1.Time.Year,R1.Time.Month,R1.Time.Day,R1.Time.Hour,R1.Time.Minute);
    fclose(fp);
}

void PrintfHistory()
{
    Rank R2[1000],temp;
    int N,i,j,p1=0,p2=0,p3=0;
    FILE *fp;
    char x,A[1000];
    fp=fopen("History.txt","r");
    while (!feof(fp))
	{
		x=fgetc(fp);
		if (x=='\n')
			N++;
	}
	rewind(fp);
	Rank *Out=NULL;
	Out=(Rank*)malloc(sizeof(Rank)*(N+1));
	for (i=0;i<N;i++)
	{
		fgets(A,1000,fp);
		sscanf(A,"%c  %f  %d\\%d\\%d %d:%d\n", &Out[i].Level, &Out[i].Score, &Out[i].Time.Year,&Out[i].Time.Month,&Out[i].Time.Day,&Out[i].Time.Hour,&Out[i].Time.Minute);
	}
	fclose(fp);

	for(i=0;i<N;i++)
    {
        for(j=i+1;j<N;j++)
        {
            if(Out[i].Score>Out[j].Score)
            {
                temp=Out[i];
                Out[i]=Out[j];
                Out[j]=temp;
            }
        }
    }
    printf("                                         简单难度历史记录为:\n\n");
    printf("                                   排名  成绩          时间\n\n");
    for(i=0;i<10;i++)
    {
        if(Out[i].Level=='E')
        {
            p1++;
            printf("                                    ");
            printf("%d  %f  %d\\%d\\%d %d:%d\n", p1, Out[i].Score, Out[i].Time.Year,Out[i].Time.Month,Out[i].Time.Day,Out[i].Time.Hour,Out[i].Time.Minute);
        }
    }
    printf("\n");
    printf("                                         中等难度历史记录为:\n\n");
    printf("                                   排名  成绩          时间\n\n");
    for(i=0;i<10;i++)
    {
        if(Out[i].Level=='M')
        {
            p2++;
            printf("                                    ");
            printf("%d  %f  %d\\%d\\%d %d:%d\n", p2, Out[i].Score, Out[i].Time.Year,Out[i].Time.Month,Out[i].Time.Day,Out[i].Time.Hour,Out[i].Time.Minute);
        }
    }
    printf("\n");
    printf("                                         困难难度历史记录为:\n\n");
    printf("                                   排名  成绩          时间\n\n");
    for(i=0;i<10;i++)
    {
        if(Out[i].Level=='H')
        {
            p3++;
            printf("                                    ");
            printf("%d  %f  %d\\%d\\%d %d:%d\n", p3, Out[i].Score, Out[i].Time.Year,Out[i].Time.Month,Out[i].Time.Day,Out[i].Time.Hour,Out[i].Time.Minute);
        }
    }
    LastMenu();
}
  • 8
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值