【小游戏】写得很烂的没有界面的扫雷

程序设计时做得没有界面的扫雷。

快期末考试了,刚创博客没啥好写的,就放个以前的代码吧。

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <algorithm>
#include <conio.h>
#include <windows.h>
using namespace std;

struct GamePlayer                           //游戏用户
{
    char Name[10];                          //用户名
    char Password[10];                      //密码
    double Time;                            //当前游戏所用时间
    double AllTime;                         //累计游戏时间
    double BestTime;                        //最佳成绩,即最短时间
    int GameCount;                          //总游戏局数
    int NumOfWin;                           //历史胜利次数
    int NumOfLose;                          //历史失败次数
    double Rate;                            //总胜率
}Gameplayer, gameplayer[1010];              //Gameplayer存储当前游戏用户,gameplayer存储用户文件中的用户

struct GRAPH                                //雷区地图
{
    int s[110][110];                        //矩阵存储,0表示没有雷,1表示有雷
    char Show[110][110];                    //显示给用户的雷区地图
    int Row;                                //雷区的行数
    int Col;                                //雷区的列数
    int Lei;                                //雷的个数
}Graph;                                     //雷区地图

struct RANK                                 //存储排行榜
{
    char Name[10];                          //用户名
    double Time;                            //时间
    bool operator < (const RANK& r) const   //重载小于号,使排序更简单
    {
        if(Time != r.Time)                  //先按照时间从小到大排序
            return Time < r.Time;
        else                                //时间相同则按照用户名从短到长排序
        {
            int len1 = strlen(Name);
            int len2 = strlen(r.Name);
            return len1 < len2;
        }
    }
}Rank[6];                                   //用于排名的结构体数组

FILE *Easy, *Medium, *Hard, *Player;        //文件指针,运行前需创建4个文件
char level[10];                             //存储所选的游戏难度,用char数组防止用户输错
int iswin;                                  //存储本局游戏是否赢了
int isok;                                   //用户信息是否合法,若合法则存储用户的位置
int Num;                                    //存储用户文件中的用户个数
bool ison = false;                          //存储用户是否已经登录

void Open();                                //打开程序要用到的文件
void Delay();                               //延时函数
int InitPlayer(int &i);                     //初始化玩家信息,i表示文件中用户的个数,返回玩家在文件中的位置
void InitGraph(int row, int col, int lei);  //初始化雷区,row行col列,lei个雷
bool SelectLevel();                         //选择难度等级,可以自定义
int NumOfMine(int x, int y);                //返回x,y周围的雷的个数
void Display();                             //显示玩家看到的地图
void DisplayPlayer();                       //显示用户信息
void DisplayRank();                         //显示排行榜
bool Sweep(int x, int y, int k);            //扫雷的一次操作,第x行第y列,k表示是否有雷
void Sweep1(int x, int y, int k);           //开局第一次点击,肯定没有雷,如果有会把雷随机到其他地方
bool Judge();                               //判断是否已经赢得游戏
void PlayGame();                            //开始游戏并计时
void SaveRanking();                         //将成绩录入排行榜
void Update();                              //更新用户信息,保存到文件
bool ChangePassword();                      //修改密码
void End();                                 //结束画面
void Close();                               //关闭文件
void Test();                                //测试用函数,开始游戏时可注释
int gotoxyWithFullwidth(short x,short y);   //以控制台左上角为坐标原点,定位光标位置
void setColor(unsigned short ForeColor=7,unsigned short BackGroundColor=0);
                                            //设置字体颜色
int main()                                  //需要事先创建4个txt文件
{
    char Begin[10];                         //存储用户的操作,用char数组防止用户输入错误
    printf("\t===============挖地雷小游戏===============\n");
    printf("\t^_^进入游戏请输入1,退出请输入0\n");

    do                                      //防止用户输入错误
    {
        scanf("%s", Begin);                 //询问用户操作
    }while(Begin[0] != '0' && Begin[0] != '1');

    while(Begin[0] == '1')
    {
        Open();                             //打开文件
        srand((int)time(NULL));             //随机种子
        if(!ison)                           //如果还没有登录
        {
            printf("\t^_^登录或注册请输入1, 查看排行榜请输入2,退出请输入0\n");
            do                              //防止用户输入错误
            {
                scanf("%s", Begin);         //询问用户操作
            }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2');
            if(Begin[0] == '2')
            {
                DisplayRank();              //显示排行榜
                printf("\t^_^登录或注册请输入1,退出请输入0\n");
                do                          //防止用户输入错误
                {
                    scanf("%s", Begin);     //询问用户操作
                }while(Begin[0] != '0' && Begin[0] != '1');
            }
            if(Begin[0] != '1' && Begin[0] != '2')
            {
                Close();
                break;
            }
            isok = InitPlayer(Num);         //初始化用户信息
        }

        system("cls");                      //清屏
        printf("\t===============挖地雷小游戏===============\n");
        printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
        printf("\t^_^开始游戏请输入1,查看用户信息请输入2,查看排行榜请输入3,退出请输入0\n");
        do                                  //防止用户输入错误
        {
            scanf("%s", Begin);             //询问用户操作
        }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '3');

        if(Begin[0] == '0')                 //退出游戏
        {
            Close();
            break;
        }

        else if(Begin[0] == '2')            //查看用户信息
        {
            if(isok == -1)                  //是新用户
            {
                system("cls");              //清屏
                printf("\t===============挖地雷小游戏===============\n");
                printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
                printf("\t用户名:%s\n", Gameplayer.Name);
                printf("\t总游戏时长:0 seconds\n");
                printf("\t最好成绩:NULL seconds\n");
                printf("\t胜利次数:0\n");
                printf("\t失败次数:0\n");
                printf("\t总胜率:0\n");
            }
            else                            //是老用户
                DisplayPlayer();            //显示玩家信息
            printf("\t^_^开始游戏请输入1,查看排行榜请输入2,退出请输入0\n");
            do                              //防止用户输入错误
            {
                scanf("%s", Begin);         //询问用户操作
            }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2');
            if(Begin[0] == '0')             //退出游戏
            {
                Close();
                break;
            }
            else if(Begin[0] == '2')        //查看排行榜
            {
                DisplayRank();              //显示排行榜
                printf("\t^_^开始游戏请输入1,退出请输入0\n");
                do                          //防止用户输入错误
                {
                    scanf("%s", Begin);     //询问用户操作
                }while(Begin[0] != '0' && Begin[0] != '1');
                if(Begin[0] != '1')
                {
                    Close();
                    break;
                }
            }
        }

        else if(Begin[0] == '3')            //查看排行榜
        {
            DisplayRank();                  //显示排行榜
            printf("\t^_^开始游戏请输入1,查看用户信息请输入2,退出请输入0\n");
            do                              //防止用户输入错误
            {
                scanf("%s", Begin);         //询问用户操作
            }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2');
            if(Begin[0] != '1' && Begin[0] != '2')
            {
                Close();
                break;
            }
            else if(Begin[0] == '2')        //查看用户信息
            {
                DisplayPlayer();            //显示用户信息
                printf("\t^_^开始游戏请输入1,退出请输入0\n");
                do                          //防止用户输入错误
                {
                    scanf("%s", Begin);     //询问用户操作
                }while(Begin[0] != '0' && Begin[0] != '1');
                if(Begin[0] != '1')
                {
                    Close();
                    break;
                }
            }
        }

        while(!SelectLevel());              //选择难度或自定义难度
        PlayGame();                         //开始游戏
        SaveRanking();                      //更新排行榜
        Update();                           //更新用户信息
        Delay();                            //延时
        Delay();                            //延时

        system("cls");                      //清屏
        printf("\t===============挖地雷小游戏===============\n");
        printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
        printf("\t^_^继续游戏请输入1,查看用户信息请输入2,查看排行榜请输入3\n\t切换账号请输入4,退出请输入0\n");
        do                                  //防止用户输入错误
        {
            scanf("%s", Begin);             //询问用户操作
        }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '3' && Begin[0] != '4');

        if(Begin[0] == '2')                 //查看用户信息
        {
            DisplayPlayer();                //显示用户信息
            printf("\t^_^继续游戏请输入1,修改密码请输入2,查看排行榜请输入3\n\t切换账号请输入4,退出请输入0\n");
            do                              //防止用户输入错误
            {
                scanf("%s", Begin);         //询问用户操作
            }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '3' && Begin[0] != '4');

            if(Begin[0] == '2')             //用户选择修改密码
            {
                while(!ChangePassword());
                system("cls");              //清屏
                printf("\t===============挖地雷小游戏===============\n");
                printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
                printf("\t修改完成~\n");    //修改完成,给予用户提示
                Delay();                    //延时
                system("cls");              //清屏
                printf("\t===============挖地雷小游戏===============\n");
                printf("\t^_^继续游戏请输入1,查看排行榜请输入2,切换账号请输入4,退出请输入0\n");
                do                          //防止用户输入错误
                {
                    scanf("%s", Begin);     //询问用户操作
                }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4');

                if(Begin[0] == '2')         //查看排行榜
                {
                    DisplayRank();          //显示排行榜
                    printf("\t^_^继续游戏请输入1,切换账号请输入4,退出请输入0\n");
                    do                      //防止用户输入错误
                    {
                        scanf("%s", Begin); //询问用户操作
                    }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '4');
                }
                if(Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4')
                {
                    Close();
                    break;
                }
            }

            else if(Begin[0] == '3')        //查看排行榜
            {
                DisplayRank();              //显示排行榜
                printf("\t^_^继续游戏请输入1,查看用户信息请输入2,切换账号请输入4,退出请输入0\n");
                do                          //防止用户输入错误
                {
                    scanf("%s", Begin);     //询问用户操作
                }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4');

                if(Begin[0] == '2')         //查看用户信息
                {
                    DisplayPlayer();        //显示用户信息
                    printf("\t^_^继续游戏请输入1,修改密码请输入2,切换账号请输入4,退出请输入0\n");
                    do                      //防止用户输入错误
                    {
                        scanf("%s", Begin); //询问用户操作
                    }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4');
                    if(Begin[0] == '2')     //修改密码
                    {
                        while(!ChangePassword());
                        system("cls");      //清屏
                        printf("\t===============挖地雷小游戏===============\n");
                        printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
                        printf("\t修改完成~\n");
                        Delay();            //延时
                        system("cls");      //清屏
                        printf("\t===============挖地雷小游戏===============\n");
                        printf("\t^_^继续游戏请输入1,查看排行榜请输入2,切换账号请输入4,退出请输入0\n");
                        do                  //防止用户输入错误
                        {
                            scanf("%s", Begin);
                        }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4');

                        if(Begin[0] == '2') //查看排行榜
                        {
                            DisplayRank();  //显示排行榜
                            printf("\t^_^继续游戏请输入1,退出请输入0\n");
                            do              //防止用户输入错误
                            {
                                scanf("%s", Begin);
                            }while(Begin[0] != '0' && Begin[0] != '1');
                        }
                    }
                }

                if(Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4')
                {
                    Close();
                    break;
                }
            }

            else if(Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '3' && Begin[0] != '4')
            {
                Close();
                break;
            }
        }
        else if(Begin[0] == '3')            //查看排行榜
        {
            DisplayRank();                  //显示排行榜
            printf("\t^_^继续游戏请输入1,查看用户信息请输入2,修改密码请输入3\n\t切换账号请输入4,退出请输入0\n");
            do                              //防止用户输入错误
            {
                scanf("%s", Begin);         //询问用户操作
            }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '3' && Begin[0] != '4');

            if(Begin[0] == '2')             //查看用户信息
            {
                DisplayPlayer();            //显示用户信息
                printf("\t^_^继续游戏请输入1,修改密码请输入2,切换账号请输入4,退出请输入0\n");
                do                          //防止用户输入错误
                {
                    scanf("%s", Begin);     //询问用户操作
                }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4');
                if(Begin[0] == '2')         //修改密码
                {
                    while(!ChangePassword());
                    system("cls");          //清屏
                    printf("\t===============挖地雷小游戏===============\n");
                    printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
                    printf("\t修改完成~\n");
                    Delay();                //延时
                    system("cls");          //清屏
                    printf("\t===============挖地雷小游戏===============\n");
                    printf("\t^_^继续游戏请输入1,查看排行榜请输入2,切换账号请输入4,退出请输入0\n");
                    do                      //防止用户输入错误
                    {
                        scanf("%s", Begin);
                    }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '4');

                    if(Begin[0] == '2')     //查看排行榜
                    {
                        DisplayRank();      //显示排行榜
                        printf("\t^_^继续游戏请输入1,切换账号请输入4,退出请输入0\n");
                        do                  //防止用户输入错误
                        {
                            scanf("%s", Begin);
                        }while(Begin[0] != '0' && Begin[0] != '1' && Begin[0] != '4');
                    }
                }
            }

            if(Begin[0] != '1' && Begin[0] != '2' && Begin[0] != '3' && Begin[0] != 4)
            {
                Close();
                break;
            }
        }

        if(Begin[0] == '1')                 //继续游戏
        {
            ison = true;                    //已经登录
            system("cls");                  //清屏
            printf("\t===============挖地雷小游戏===============\n");
        }
        if(Begin[0] == '4')                 //切换账号
        {
            ison = false;                   //还未登录
            Begin[0] = '1';
            system("cls");                  //清屏
            printf("\t===============挖地雷小游戏===============\n");
        }
        Close();                            //关闭文件
    }
    End();                                  //结束画面
    return 0;
}

void Open()                                 //打开程序要用到的文件
{
    Easy = fopen("Easy.txt", "r+");         //Easy.txt存储简单模式的排行榜
    if(!Easy)                               //若打开失败则输出失败并退出
    {
        printf("Can not open Easy.txt.\n");
        exit(1);
    }
    Medium = fopen("Medium.txt", "r+");     //Medium.txt存储普通模式的排行榜
    if(!Medium)                             //若打开失败则输出失败并退出
    {
        printf("Can not open Medium.txt.\n");
        exit(1);
    }
    Hard = fopen("Hard.txt", "r+");         //Hard.txt存储困难模式的排行榜
    if(!Hard)                               //若打开失败则输出失败并退出
    {
        printf("Can not open Hard.txt.\n");
        exit(1);
    }
    Player = fopen("Player.txt", "r+");     //Player.txt存储用户信息
    if(!Player)                             //若打开失败则输出失败并退出
    {
        printf("Can not open Player.txt.\n");
        exit(1);
    }
}

void Delay()                                //延时函数
{
    for(int t = 0; t < 1e9; t++);
}

int InitPlayer(int &i)                      //初始化玩家信息,i表示文件中用户的个数,返回玩家在文件中的位置
{
    char mm;                                //存储被隐藏的密码
    int p = 0;                              //存储密码位数
    bool Find = false;                      //Find存储是否在文件中找到了用户
    int num;                                //num存储顽疾所在文件中的位置

    system("cls");                          //清屏
    printf("\t===============挖地雷小游戏===============\n");
    printf("\t^_^请输入用户名(不多于10个字符),回车结束。(新用户自动注册)\n");
    printf("\t用户名:");
    scanf("%s", Gameplayer.Name);
    printf("\t^_^请输入密码(不多于10个字符),回车结束。\n");
    printf("\t密码:");

    while(1)                                //输入密码,显示星号*
    {
        mm = getch();                       //输入m且隐藏
        if(mm == '\r')                      //遇到回车,停止输入
        {
            printf("\n");                   //回车被mm吃了,输出回车
            break;                          //退出循环
        }
        if(mm == '\b')                      //遇到退格键
        {
            p--;                            //j往前移一位
            printf("\b \b");                //输出退格然后用空格覆盖原来的*再输出退格
            continue;                       //跳过这次循环
        }
        Gameplayer.Password[p++] = mm;      //将密码赋值给Password
        printf("*");                        //输出'*'
    }
//    printf("%s\n", Gameplayer.Password);    //调试用

    while(~fscanf(Player, "%d", &i))
    {
        fscanf(Player, "%s%s%lf%lf%d%d%d%lf", gameplayer[i].Name, gameplayer[i].Password, &gameplayer[i].AllTime, &gameplayer[i].BestTime,
                                        &gameplayer[i].GameCount, &gameplayer[i].NumOfWin, &gameplayer[i].NumOfLose, &gameplayer[i].Rate);
        if(strcmp(gameplayer[i].Name, Gameplayer.Name) == 0)
        {
            Find = true;
            num = i;
        }
    }

    if(Find)                                //判断密码是否正确
    {
        int j = 1;                          //记录输错了多少次
        while(strcmp(gameplayer[num].Password, Gameplayer.Password) != 0)
        {                                   //如果输入错误,就重新输入
            if(j++ % 3 == 0)                //输错三次,就会要求过一会儿再输入
            {
                printf("\t输错太多啦,歇会儿吧。\n");
                Delay();
                continue;
            }
            printf("\t密码错误,请重新输入密码:");

            p = 0;                          //初始化p与Password
            int len = strlen(Gameplayer.Password);
            for(int k = 0; k < len; k++)
                Gameplayer.Password[k] = '\0';
            while(1)                        //输入密码,显示星号*
            {
                mm = getch();               //输入m且隐藏
                if(mm == '\r')              //遇到回车,停止输入
                {
                    printf("\n");           //回车被mm吃了,输出回车
                    break;                  //退出循环
                }
                if(mm == '\b')              //遇到退格键
                {
                    p--;                    //p往前移一位
                    printf("\b \b");        //输出退格然后用空格覆盖原来的*再输出退格
                    continue;               //跳过这次循环
                }                           //将密码赋值给Password
                Gameplayer.Password[p++] = mm;
                printf("*");                //输出'*'
            }
//            printf("%s\n", Gameplayer.Password);    //调试用
        }
        return num;                         //有玩家信息,返回玩家所在文件中的位置
    }
    else
        return -1;                          //返回-1表示无玩家信息,需要录入
}

void InitGraph(int row, int col, int lei)   //初始化雷区,row行col列,lei个雷
{
    Graph.Row = row;                        //row行
    Graph.Col = col;                        //col列
    Graph.Lei = lei;                        //lei雷的个数
    for(int i = 0; i < Graph.Row; i++)
    {
        for(int j = 0; j < Graph.Col; j++)
        {
            Graph.s[i][j] = 0;              //初始化雷区为0
            Graph.Show[i][j] = '.';         //初始化显示给用户的雷区为'.'
        }
    }

    int x, y;                               //随机在(x,y)处生成雷
    for(int i = 0; i < Graph.Lei; )         //随机雷所在行列,直到满足个数
    {
        x = rand() % Graph.Row;             //随机行
        y = rand() % Graph.Col;             //随机列
        if(Graph.s[x][y] == 1)              //如果随机到了相同的行列
            continue;                       //就跳过这个点重新随机
        else
        {
            Graph.s[x][y] = 1;              //将随机点置为1
            i++;                            //已经布置的地雷个数+1
        }
    }
}

bool SelectLevel()                          //选择难度等级,可以自定义
{
    system("cls");                          //清屏
    printf("\t===============挖地雷小游戏===============\n");
    printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
    printf("\t简单 1 普通 2 困难 3 自定义(没有排行榜) 4\n");
    printf("\t简单难度:5*5,2颗雷。\n");
    printf("\t普通难度:7*7,5颗雷。\n");
    printf("\t困难难度:10*10,15颗雷。\n");

    do                                      //防止用户输入错误
    {
        scanf("%s", level);                 //询问用户操作
    }while(level[0] != '1' && level[0] != '2' && level[0] != '3' && level[0] != '4');

    if(level[0] == '1')                     //难度1为5*5,2颗雷
        InitGraph(5, 5, 2);
    else if(level[0] == '2')                //难度2为7*7,5颗雷
        InitGraph(7, 7, 5);
    else if(level[0] == '3')                //难度3为10*10,15颗雷
        InitGraph(10, 10, 15);
    else if(level[0] == '4')                //自定义
    {
        printf("\t请输入行数,列数,地雷个数(用空格隔开,换行结束)\n");
        printf("\t行数太多影响游戏体验哦~最好不超过10行\n");
        int row, col, lei;
        scanf("%d%d%d", &row, &col, &lei);
        InitGraph(row, col, lei);           //调用初始化雷区的函数
    }
    else                                    //输入错误
        return false;
    return true;
}

int NumOfMine(int x, int y)                 //返回x,y周围的雷的个数
{
    if(Graph.s[x][y] == 1)                  //如果自己是雷
        return -1;                          //就返回-1
    int num = 0;                            //初始化周围雷的个数为0
    if(x-1>=0 && y-1>=0 && Graph.s[x-1][y-1]==1)
        num++;                              //左上角有雷则num++
    if(x+1<Graph.Row && y-1>=0 && Graph.s[x+1][y-1]==1)
        num++;                              //左下角有雷则num++
    if(x-1>=0 && y+1<Graph.Col && Graph.s[x-1][y+1]==1)
        num++;                              //右上角有雷则num++
    if(x+1<Graph.Row && y+1<Graph.Col && Graph.s[x+1][y+1]==1)
        num++;                              //右下角有雷则num++
    if(x - 1 >= 0 && Graph.s[x - 1][y] == 1)
        num++;                              //上面有雷则num++
    if(y - 1 >= 0 && Graph.s[x][y - 1] == 1)
        num++;                              //左边有雷则num++
    if(x + 1 < Graph.Row && Graph.s[x + 1][y] == 1)
        num++;                              //下面有雷则num++
    if(y + 1 < Graph.Col && Graph.s[x][y + 1] == 1)
        num++;                              //右边有雷则num++
    return num;                             //返回x,y周围雷的个数
}

void Test()                                 //测试用函数,开始游戏时可注释
{
    printf("雷区,10表示:\n");
    for(int i = 0; i < Graph.Row; i++)
    {
        for(int j = 0; j <Graph.Col; j++)
        {
            printf("%d ", Graph.s[i][j]);
        }
        printf("\n");
    }
    printf("\n去掉安全区后的雷区:\n");
    for(int i = 0; i < Graph.Row; i++)
    {
        for(int j = 0; j <Graph.Col; j++)
        {
            if(Graph.s[i][j] == 0)
                printf("  ");
            else
                printf("%d ", Graph.s[i][j]);
        }
        printf("\n");
    }
    printf("\n显示周围的雷数目:\n");
    for(int i = 0; i < Graph.Row; i++)
    {
        for(int j = 0; j <Graph.Col; j++)
        {
            int num = NumOfMine(i, j);
            if(num == -1)
                printf("* ");
            else if(num == 0)
                printf("  ");
            else
                printf("%d ", num);
        }
        printf("\n");
    }
    printf("\n");
}

void Display()                              //显示玩家看到的地图
{
    system("cls");                          //清屏
    printf("\t===============挖地雷小游戏===============\n");
    printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
    printf("\t地图大小:%d * %d  雷的数目:%d\n", Graph.Row, Graph.Col, Graph.Lei);

    if(Graph.Row <= 5)                      //输入第一行的数字,方便用户看行列
        printf("\t\t\t");
    else if(Graph.Row <= 10)
        printf("\t\t");
    else if(Graph.Row <= 20)
        printf("\t");
    printf("    ");
    for(int i = 1; i <= Graph.Col; i++)
    {
        printf("%d ", i);
    }
    printf("\n\n");

    for(int i = 0; i < Graph.Row; i++)
    {
        if(Graph.Row <= 5)
            printf("\t\t\t");
        else if(Graph.Row <= 10)
            printf("\t\t");
        else if(Graph.Row <= 20)
            printf("\t");
        if(i >= 9)                          //是两位数
        {
            printf("%d  ", i + 1);
        }
        else
        {
            printf("%d   ", i + 1);         //输入第一列的数字,方便用户看行列
        }
        for(int j = 0; j < Graph.Col; j++)
        {
            printf("%c ", Graph.Show[i][j]);
        }
        printf("\n");
    }
}

void DisplayPlayer()                        //显示用户信息
{
    system("cls");                          //清屏
    printf("\t===============挖地雷小游戏===============\n");
    printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
    printf("\t用户名:%s\n", gameplayer[isok].Name);
    printf("\t总游戏时长:%.2f seconds\n", gameplayer[isok].AllTime);
    printf("\t最好成绩:%.2f seconds\n", gameplayer[isok].BestTime);
    printf("\t游戏局数:%d\n", gameplayer[isok].GameCount);
    printf("\t胜利次数:%d\n", gameplayer[isok].NumOfWin);
    printf("\t失败次数:%d\n", gameplayer[isok].NumOfLose);
    printf("\t总胜率:%.2f\n", gameplayer[isok].Rate);
}

void PlayGame()                             //开始游戏并计时
{
    int x, y, k;                            //x,y是用户输入的行列,k是用户输出的有无地雷
    bool ok = 0;                            //ok存储是否踩雷
    bool first = true;                      //first表示是否是第一次点击
    double t;                               //t用来存储所用时间
    clock_t start, finish;                  //start,finish用来计时
//    Test();                               //调用测试函数,测试时可开启
    Display();                              //给用户显示雷区
    start = clock();                        //开始计时

    while(1)
    {
        printf("\t请输入k x y,k为1表示在(x,y)点有雷,k为0表示在(x,y)点没有雷\n");
        printf("\t如果输入之后按了回车,雷区没有变化,那就是你输入错啦~\n");
        scanf("%d%d%d", &k, &x, &y);
        if(first)                           //如果是第一次输入
        {
            if(k == 0)                      //如果用户判定没有雷
            {
                Sweep1(x - 1, y - 1, k);    //保证第一次一定不踩雷
                Display();                  //给用户显示雷区
                first = false;              //first置为false
                continue;                   //进行下一次输入
            }
            else                            //如果用户判定有雷
                first = false;              //first置为false
        }

        ok = Sweep(x - 1, y - 1, k);
        if(ok == false)                     //ok = false表示踩雷了
        {
            iswin = 0;
            system("cls");                  //清屏
            printf("\t===============挖地雷小游戏===============\n");
            printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
            setColor(12, 0);                //设置为红色
            printf("\tGame Over.\n");       //游戏失败
            Delay();                        //延时
            setColor(7, 0);                 //设置颜色
            finish = clock();               //结束计时
            Gameplayer.Time = (double)(finish - start) / CLOCKS_PER_SEC;
            return;                         //记录时间
        }
        if(Judge())                         //赢了
        {
            iswin = 1;
            system("cls");                  //清屏
            printf("\t===============挖地雷小游戏===============\n");
            printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
            setColor(12, 0);                //设置为红色
            printf("\tYou win!\n");         //游戏胜利
            setColor(7, 0);                 //设置颜色
            finish = clock();               //结束计时
            Gameplayer.Time = (double)(finish - start) / CLOCKS_PER_SEC;
            printf("\tUsing %f seconds!\n", Gameplayer.Time);
            return;                         //记录时间
        }
        else
            Display();                      //给用户显示雷区
    }
}

bool Sweep(int x, int y, int k)             //扫雷的一次操作,第x行第y列,k表示是否有雷
{
    if(x < 0 || x >= Graph.Row)             //已超出边界
        return true;
    if(y < 0 || y >= Graph.Col)             //已超出边界
        return true;
    if(Graph.Show[x][y] != '.')             //如果已经翻开过
    {
        if(Graph.Show[x][y] == '@' && k == 0)
        {
            Graph.Show[x][y] = '.';         //如果已经标记过,就取消标记
            return true;
        }
        else                                //已经翻开过此点,跳过
            return true;
    }

    int num = NumOfMine(x, y);              //周围雷的个数
    if(k == 1)                              //如果玩家判定是地雷
    {
        Graph.Show[x][y] = '@';             //直接标记
        return true;
    }
    else                                    //如果玩家判定不是地雷
    {
        if(num == -1)                       //踩雷了,返回false
            return false;
        else if(num > 0)                    //周围的8格有雷
        {
            Graph.Show[x][y] = (char)num + '0';
            return true;
        }
        else                                //周围的8格没有雷
        {                                   //标记为0并判断周围八格
            Graph.Show[x][y] = '0';         //标记为0
            Sweep(x - 1, y - 1, k);         //判断左上角
            Sweep(x - 1, y, k);             //判断上面
            Sweep(x - 1, y + 1, k);         //判断右上角
            Sweep(x, y - 1, k);             //判断左边
            Sweep(x, y + 1, k);             //判断右边
            Sweep(x + 1, y - 1, k);         //判断左下角
            Sweep(x + 1, y, k);             //判断下面
            Sweep(x + 1, y + 1, k);         //判断右下角
        }
    }
}

void Sweep1(int x, int y, int k)            //开局第一次点击,肯定没有雷,如果有会把雷随机到其他地方
{
    int i = 0, p, q;                        //i存储已经重新生成的雷的个数,(p,q)为重新随机生成雷的坐标
    if(Graph.s[x][y] == 1)                  //如果开局第一次点击到了地雷
    {
        Graph.s[x][y] = 0;                  //把该点雷移除,重新随机一个雷
        while(i != 1)
        {
            p = rand() % Graph.Row;
            q = rand() % Graph.Col;
            if(Graph.s[p][q] == 1)          //如果随机到了已经有雷的地方
                continue;                   //就跳过,进行下一次随机
            else
            {
                Graph.s[p][q] = 1;
                i++;
            }
        }
    }
    Sweep(x, y, k);                         //调用Sweep进行一次扫雷操作
}

bool Judge()                                //判断是否已经赢得游戏
{                                           //赢得游戏的条件是,如果有n个地雷
    for(int i = 0; i < Graph.Row; i++)      //则所有有地雷的点都被标记了@
    {                                       //且一共有n个@标记
        for(int j = 0; j < Graph.Col; j++)
        {                                   //如果有雷还没有被@标记,则还未赢得游戏
            if(Graph.s[i][j] == 1 && Graph.Show[i][j] != '@')
                return false;               //如果有被@标记的地方不是雷,则还未赢得游戏
            if(Graph.s[i][j] == 0 && Graph.Show[i][j] == '@')
                return false;
        }
    }
    return true;                            //赢得游戏,返回true
}

void DisplayRank()                          //显示排行榜
{
    int i = 0;                              //记录排行榜中用户数量
    system("cls");                          //清屏
    printf("\t===============挖地雷小游戏===============\n");

    rewind(Easy);
    rewind(Medium);
    rewind(Hard);

    if(fscanf(Easy, "%d", &i) == EOF)       //若排行榜为空
    {
        printf("\t简单难度排行榜为空\n");
    }
    else
    {
        printf("\t简单难度排行榜:\n");
        while(~fscanf(Easy, "%d", &i))
        {
            fscanf(Easy, "%s%lf", Rank[i].Name, &Rank[i].Time);
            printf("\t第%d名:\t%s——%.2f seconds\n", i, Rank[i].Name, Rank[i].Time);
            i++;
        }
    }
    printf("\n");

    if(fscanf(Medium, "%d", &i) == EOF)     //若排行榜为空
    {
        printf("\t普通难度排行榜为空\n");
    }
    else
    {
        printf("\t普通难度排行榜:\n");
        while(~fscanf(Medium, "%d", &i))
        {
            fscanf(Medium, "%s%lf", Rank[i].Name, &Rank[i].Time);
            printf("\t第%d名:\t%s——%.2f seconds\n", i, Rank[i].Name, Rank[i].Time);
            i++;
        }
    }
    printf("\n");

    if(fscanf(Hard, "%d", &i) == EOF)       //若排行榜为空
    {
        printf("\t困难难度排行榜为空\n");
    }
    else
    {
        printf("\t困难难度排行榜:\n");
        while(~fscanf(Hard, "%d", &i))
        {
            fscanf(Hard, "%s%lf", Rank[i].Name, &Rank[i].Time);
            printf("\t第%d名:\t%s——%.2f seconds\n", i, Rank[i].Name, Rank[i].Time);
            i++;
        }
    }
    printf("\n");
}

void SaveRanking()                          //将成绩录入排行榜
{
    int i = 0;                              //用来记录已经读取的排行榜中用户数
    if(iswin == 1)                          //胜利,则与排行榜比较
    {
        rewind(Easy);                       //文件位置指针移动至文件开头
        rewind(Medium);                     //文件位置指针移动至文件开头
        rewind(Hard);                       //文件位置指针移动至文件开头

        if(level[0] == '1')                 //难度等级为1
        {                                   //如果原排行榜为空
            if(fscanf(Easy, "%d", &i) == EOF)
            {                               //直接将用户信息写入文件
                strcpy(Rank[0].Name, Gameplayer.Name);
                Rank[0].Time = Gameplayer.Time;
                rewind(Easy);
                fprintf(Easy, "1\t%s\t%.2f\n", Rank[0].Name, Rank[0].Time);
            }

            else                            //如果原排行榜不为空
            {                               //则将排行榜读入Rank[]
                rewind(Easy);               //文件位置指针移动至文件开头
                while(~fscanf(Easy, "%d", &i))
                {
                    i--;
                    fscanf(Easy, "%s%lf", Rank[i].Name, &Rank[i].Time);
                }                           //将此次游戏信息也存入Rank[]
                strcpy(Rank[++i].Name, Gameplayer.Name);
                Rank[i].Time = Gameplayer.Time;
                sort(Rank, Rank + i + 1);   //排序
                rewind(Easy);               //文件位置指针移动至文件开头
                if(i >= 4)                  //排行榜中大于等于五个人
                {                           //依次写入前五名
                    for(int j = 0; j < 5; j++)
                        fprintf(Easy, "%d\t%s\t%.2f\n", j + 1, Rank[j].Name, Rank[j].Time);
                }
                else                        //排行榜中小于五个人
                {                           //依次写入
                    for(int j = 0; j < i + 1; j++)
                        fprintf(Easy, "%d\t%s\t%.2f\n", j + 1, Rank[j].Name, Rank[j].Time);
                }
            }
        }

        if(level[0] == '2')                 //难度等级为2
        {                                   //如果原排行榜为空
            if(fscanf(Medium, "%d", &i) == EOF)
            {                               //直接将用户信息写入文件
                strcpy(Rank[0].Name, Gameplayer.Name);
                Rank[0].Time = Gameplayer.Time;
                rewind(Medium);
                fprintf(Medium, "1\t%s\t%.2f\n", Rank[0].Name, Rank[0].Time);
            }

            else                            //如果原排行榜不为空
            {                               //则将排行榜读入Rank[]
                rewind(Medium);             //文件位置指针移动至文件开头
                while(~fscanf(Medium, "%d", &i))
                {
                    i--;
                    fscanf(Medium, "%s%lf", Rank[i].Name, &Rank[i].Time);
                }                           //将此次游戏信息也存入Rank[]
                strcpy(Rank[++i].Name, Gameplayer.Name);
                Rank[i].Time = Gameplayer.Time;
                sort(Rank, Rank + i + 1);   //排序
                rewind(Medium);             //文件位置指针移动至文件开头
                if(i >= 4)                  //排行榜中大于等于五个人
                {                           //依次写入前五名
                    for(int j = 0; j < 5; j++)
                        fprintf(Medium, "%d\t%s\t%.2f\n", j + 1, Rank[j].Name, Rank[j].Time);
                }
                else                        //排行榜中小于五个人
                {                           //依次写入
                    for(int j = 0; j < i + 1; j++)
                        fprintf(Medium, "%d\t%s\t%.2f\n", j + 1, Rank[j].Name, Rank[j].Time);
                }
            }
        }

        if(level[0] == '3')                 //难度等级为3
        {                                   //如果原排行榜为空
            if(fscanf(Hard, "%d", &i) == EOF)
            {                               //直接将用户信息写入文件
                strcpy(Rank[0].Name, Gameplayer.Name);
                Rank[0].Time = Gameplayer.Time;
                rewind(Hard);
                fprintf(Medium, "1\t%s\t%.2f\n", Rank[0].Name, Rank[0].Time);
            }

            else                            //如果原排行榜不为空
            {                               //则将排行榜读入Rank[]
                rewind(Hard);               //文件位置指针移动至文件开头
                while(~fscanf(Hard, "%d", &i))
                {
                    i--;
                    fscanf(Hard, "%s%lf", Rank[i].Name, &Rank[i].Time);
                }                           //将此次游戏信息也存入Rank[]
                strcpy(Rank[++i].Name, Gameplayer.Name);
                Rank[i].Time = Gameplayer.Time;
                sort(Rank, Rank + i + 1);   //排序
                rewind(Hard);               //文件位置指针移动至文件开头
                if(i >= 4)                  //排行榜中大于等于五个人
                {                           //依次写入前五名
                    for(int j = 0; j < 5; j++)
                        fprintf(Hard, "%d\t%s\t%.2f\n", j + 1, Rank[j].Name, Rank[j].Time);
                }
                else                        //排行榜中小于五个人
                {                           //依次写入
                    for(int j = 0; j < i + 1; j++)
                        fprintf(Hard, "%d\t%s\t%.2f\n", j + 1, Rank[j].Name, Rank[j].Time);
                }
            }
        }
    }
}

void Update()                               //更新用户信息,保存到文件
{
    if(isok == -1)                          //是新用户
    {
        isok = ++Num;                       //更新Num和isok
        fseek(Player, 0L, SEEK_END);        //将文件位置指针移动到文件末尾
        strcpy(gameplayer[isok].Name, Gameplayer.Name);
        strcpy(gameplayer[isok].Password, Gameplayer.Password);
        gameplayer[isok].AllTime = Gameplayer.Time;
        gameplayer[isok].BestTime = Gameplayer.Time;
        gameplayer[isok].GameCount = 1;
        if(iswin == 1)                      //更新用户各项数据
        {
            gameplayer[isok].NumOfWin = 1;
            gameplayer[isok].NumOfLose = 0;
            gameplayer[isok].Rate = 1;
        }
        else
        {
            gameplayer[isok].NumOfWin = 0;
            gameplayer[isok].NumOfLose = 1;
            gameplayer[isok].Rate = 0;
        }                                   //将用户数据写入文件
        fprintf(Player, "%d\t%s\t%s\t%.2f\t%.2f\t%d\t%d\t%d\t%.2f\n", isok, gameplayer[isok].Name, gameplayer[isok].Password, gameplayer[isok].AllTime,
                gameplayer[isok].BestTime, gameplayer[isok].GameCount, gameplayer[isok].NumOfWin, gameplayer[isok].NumOfLose, gameplayer[isok].Rate);
    }

    else                                    //是老用户
    {                                       //更新用户各项数据
        gameplayer[isok].AllTime += Gameplayer.Time;
        gameplayer[isok].BestTime = min(gameplayer[isok].BestTime, Gameplayer.Time);
        gameplayer[isok].GameCount++;
        if(iswin == 1)
            gameplayer[isok].NumOfWin++;
        else
            gameplayer[isok].NumOfLose++;
        gameplayer[isok].Rate = (double)gameplayer[isok].NumOfWin / (gameplayer[isok].NumOfLose + gameplayer[isok].NumOfWin);
        rewind(Player);                     //讲文件位置指针移动至文件开头
        for(int j = 1; j <= Num; j++)       //讲用户数据写入文件
            fprintf(Player, "%d\t%s\t%s\t%.2f\t%.2f\t%d\t%d\t%d\t%.2f\n", j, gameplayer[j].Name, gameplayer[j].Password, gameplayer[j].AllTime,
                gameplayer[j].BestTime, gameplayer[isok].GameCount, gameplayer[j].NumOfWin, gameplayer[j].NumOfLose, gameplayer[j].Rate);
    }
}

bool ChangePassword()                       //修改密码
{
    char ch1[10], ch2[10];                  //ch1存储第一次输入的密码,ch2存储第二次输入的密码
    char mm;                                //存储被隐藏的密码
    int p = 0;                              //存储密码位数

    system("cls");                          //清屏
    printf("\t===============挖地雷小游戏===============\n");
    printf("\t\t\t\t用户:%s\n", Gameplayer.Name);
    printf("\t请输入新密码,密码不超过10个字符:");

    while(1)                                //输入新密码,显示星号*
    {
        mm = getch();                       //输入m且隐藏
        if(mm == '\r')                      //遇到回车,停止输入
        {
            printf("\n");                   //回车被mm吃了,输出回车
            ch1[p] = '\0';                  //给ch1数组结尾符'\0'
            break;                          //退出循环
        }
        if(mm == '\b')                      //遇到退格键
        {
            p--;                            //j往前移一位
            printf("\b \b");                //输出退格然后用空格覆盖原来的*再输出退格
            continue;                       //跳过这次循环
        }
        ch1[p++] = mm;                      //将密码赋值给Password
        printf("*");                        //输出'*'
    }
//    printf("%s\n", ch1);                    //调试用

    p = 0;
    printf("\t请再次输入新密码:");         //再次输入新密码
    while(1)                                //输入密码,显示星号*
    {
        mm = getch();                       //输入m且隐藏
        if(mm == '\r')                      //遇到回车,停止输入
        {
            printf("\n");                   //回车被mm吃了,输出回车
            ch2[p] = '\0';                  //给ch2数组结尾符'\0'
            break;                          //退出循环
        }
        if(mm == '\b')                      //遇到退格键
        {
            p--;                            //j往前移一位
            printf("\b \b");                //输出退格然后用空格覆盖原来的*再输出退格
            continue;                       //跳过这次循环
        }
        ch2[p++] = mm;                      //将密码赋值给Password
        printf("*");                        //输出'*'
    }
//    printf("%s\n", ch2);                    //调试用

    if(strcmp(ch1, ch2) != 0)               //比较两次输入是否相同
    {
        printf("\t输入有误!\n");            //若不同则重新输入
        Delay();                            //延时
        return false;
    }
    strcpy(gameplayer[isok].Password, ch1); //更新用户的密码
    rewind(Player);                         //将文件位置指针移动至文件开头
    for(int j = 1; j <= Num; j++)           //将更新后的用户数据写入文件
            fprintf(Player, "%d\t%s\t%s\t%.2f\t%.2f\t%d\t%d\t%d\t%.2f\n", j, gameplayer[j].Name, gameplayer[j].Password, gameplayer[j].AllTime,
                gameplayer[j].BestTime, gameplayer[j].GameCount, gameplayer[j].NumOfWin, gameplayer[j].NumOfLose, gameplayer[j].Rate);
    return true;
}

void Close()                                //关闭文件
{
    fclose(Easy);                           //关闭Easy.txt文件
    fclose(Medium);                         //关闭Mediun.txt文件
    fclose(Hard);                           //关闭Hard.txt文件
    fclose(Player);                         //关闭Player.txt文件
}

void End()                                  //结束画面
{
    system("cls");                          //清屏
    printf("-------------------------------------------------------------\n");
    printf("-------------------------------------------------------------\n");

    for(int i = 1; i <= 5; i++)             //画菱形
    {
        printf("\t");
        for(int j = 6; j > i; j--)
        {
            printf(" ");
        }
        for(int k = 1; k <= 2 * i - 1; k++)
        {
            printf("*");
        }
        printf("\n");
    }
    for(int i = 1; i <= 6; i++)
    {
        printf("\t");
        for(int j = 1; j <= i - 1; j++)
        {
            printf(" ");
        }
        for(int k = 1; k <= 13 - 2 * i; k++)
        {
            printf("*");
        }
        printf("\n");
    }

    gotoxyWithFullwidth(8, 2);              //定位坐标
    printf("\t挖地雷小游戏        *");
    gotoxyWithFullwidth(8, 3);              //定位坐标
    printf("\t制作者:           ***");
    gotoxyWithFullwidth(8, 4);              //定位坐标
    printf("\tB16040224         *****");
    gotoxyWithFullwidth(9, 5);              //定位坐标
    printf("\t赵立昌           *******");
    gotoxyWithFullwidth(9, 6);              //定位坐标
    printf("\tB16040216       *********");
    gotoxyWithFullwidth(9, 7);              //定位坐标
    printf("\t刘奎炎         ***********");
    gotoxyWithFullwidth(8, 8);              //定位坐标
    printf("\t                *********");
    gotoxyWithFullwidth(8, 9);              //定位坐标
    printf("\t                 *******");
    gotoxyWithFullwidth(8, 10);              //定位坐标
    printf("\t谢谢使用~~~       *****");
    gotoxyWithFullwidth(8, 11);              //定位坐标
    printf("\t                   ***");
    gotoxyWithFullwidth(8, 12);             //定位坐标
    printf("\t                    *\n");
    printf("-------------------------------------------------------------\n");
    printf("-------------------------------------------------------------\n");
}

int gotoxyWithFullwidth(short x, short y)   //以控制台左上角为坐标原点,定位光标位置
{
    static COORD cd;
    cd.X = (x << 1);
    cd.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), cd);
    return 0;
}

void setColor(unsigned short ForeColor,unsigned short BackGroundColor)
{
    //获取当前窗口句柄,设置颜色
    HANDLE handle=GetStdHandle(STD_OUTPUT_HANDLE);
    SetConsoleTextAttribute(handle,ForeColor+BackGroundColor*0x10);
}

 

 

 

 

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值