读书人

控制台的探雷程序(C语言)

发布时间: 2012-09-25 09:55:59 作者: rapoo

控制台的扫雷程序(C语言)

// 扫雷程序 C-Free编译通过// by: 瑞 2012-9-20 #include <stdio.h>#include <stdlib.h>#include <iostream>#include <windows.h>#include <time.h>using namespace std;#define CLRSCREENsystem("cls")   // 清屏 #define PAUSESCREEN system("pause") // 屏幕暂停enum winorfial   {RUNING, WIN, FAIL};// 输赢结果enum check_state {UNKNOW, NO, YES, DOUBT};         // 地雷被扫的状态enum mine_in {Y, N};        // 此坑是否真的有地雷typedef struct _mine        // 地雷坑 的结构体定义{    intx,y;            // 地雷坐标    check_stateCheckState;            // 当前地雷被扫的状态    mine_inMineIn;            // 此坑是否真的有地雷    intMineNumAround;            // 周围地雷数目    winorfial(*ChangeState)(struct _mine *ThisMine, check_stateCheckState);// 改变状态函数    void(*MoreAct)(void *p);// 预留功能接口 [接口预留]} MineStruct, *pMineStruct;enum game_grade {USER_DEFINED, EASY, MIDDLE, HARD};// 难度等级:自定义/易/中/难enum game_state {RUN, PAUSE, STOP};// 程序状态:运行/暂停/停止typedef void*histrylist;// 记录玩家英雄榜的链表,时间紧,暂不实现typedef struct _panel// 阵地的结构体定义{    pMineStruct*Mine;            // 地雷表: x*y个雷坑    game_gradeGrade;            // 难度等级    intx, y;            // 阵地的宽和高    intMinesNum;            // 阵地内的地雷数目    intCatchMineNum;                   // 玩家找到的雷数    game_stateGameState;            // 当前游戏状态    winorfial   WinOrFail;                          // 输赢情况    intTimeOutSeconds;            // 超时等待的秒数 [预留]    histrylistHistry;            // 玩家英雄榜 [预留]    char*BackgroundArgv;            // 背景元素Color、Music等 [预留]    void(*InitPanel)(void);// 初始化函数    void(*DestroyPanel)(void);// 销毁函数    void(*ChangeState)(game_state state);// 改变状态函数    void(*GetCtrl)(void);       // 接收玩家的控制命令    void(*Output)(void);           // 输出     void(*OpenBlankMine)(int x,int y);// 打开周围的一片无雷区    void(*ChangeBackground)(char* Argv);// 改变背景函数 [预留]    void(*MoreAct)(void *p);// 预留功能接口 [接口预留]} Panel, *pPanel;Panelpanel;// 阵地(面板)的全局对象 char*str[]={    "扫雷吧!\n游戏说明:\n确定(x,y)位置无雷,输入:x y N\n确定(x,y)位置有雷,输入:x y Y\n怀疑(x,y)位置有雷,输入:x y ?\n",    "当前雷区大小: %d*%d, 地雷数%d\n"};winorfial ChangeMineStateFun(pMineStruct ThisMine, check_stateCheckState){    if(CheckState == NO)    {        if(ThisMine->MineIn == N)            ThisMine->CheckState = NO;        else if(ThisMine->MineIn == Y)            return FAIL;    }    else        ThisMine->CheckState = CheckState;    return RUNING;}// 打开周围空白雷坑void OpenBlankMineFun(int x,int y){    if (x < 0 || x >= panel.x || y < 0 || y >= panel.y)//越界        return;    if(panel.Mine[x][y].MineNumAround > 0)    {        panel.Mine[x][y].CheckState = NO;        return;    }    if(panel.Mine[x][y].CheckState == NO)        return;    if (panel.Mine[x][y].MineIn == N)    {        panel.Mine[x][y].CheckState = NO;        OpenBlankMineFun(x - 1, y - 1);        OpenBlankMineFun(x - 1, y);        OpenBlankMineFun(x - 1, y + 1);        OpenBlankMineFun(x + 1, y - 1);        OpenBlankMineFun(x + 1, y);        OpenBlankMineFun(x + 1, y + 1);        OpenBlankMineFun(x, y + 1);        OpenBlankMineFun(x, y - 1);    }    return;}void OutPutFun(void){    CLRSCREEN;    printf(str[0]);                                     // 游戏说明字符串    printf(str[1], panel.x, panel.y, panel.MinesNum);   // 输出雷区信息        // 检测并输出    int tempWinOrFail = 1;  // 假设赢    printf("    x\t");    for(int x=0; x<panel.x; x++)    {        printf("%d ", x%10);    }    printf("\ny\n\n");    for(int y=0; y<panel.y; y++)    {        printf("%d:\t", y);        for(int x=0; x<panel.x; x++)        {            if(panel.Mine[x][y].MineIn == Y && panel.WinOrFail == FAIL)                         //踩雷了,输出所有雷                printf("* ");            else if(panel.Mine[x][y].MineNumAround != 0 && panel.Mine[x][y].CheckState == NO)   // 输出安全区周边雷数                printf("%d ", panel.Mine[x][y].MineNumAround);            else            {            switch(panel.Mine[x][y].CheckState)                {                case UNKNOW:                    printf("%c ", 'O');                    if(panel.Mine[x][y].MineIn == Y) tempWinOrFail = 0;                    break;                case YES:                    printf("%c ", 'Y');                    if(panel.Mine[x][y].MineIn == N) tempWinOrFail = 0;                    break;                case NO:                    printf("%c ", '-');                    //if(panel.Mine[x][y].MineIn == Y) tempWinOrFail = -1;// 已在changeminestate函数中检测                    break;                case DOUBT:                    printf("%c ", '?');                    if(panel.Mine[x][y].MineIn == Y) tempWinOrFail = 0;                    break;                }            }                        }        printf("\n");    }        if(panel.WinOrFail == FAIL)    {        printf("--->踩雷啦!!!结束\n");        PAUSESCREEN;    }    else if(1 == tempWinOrFail)    {        panel.WinOrFail = WIN;        printf("\n*********恭喜!扫雷完成!*********\n");    }}void GetCtrlFun(void){    int x=-1,y=-1;    char cmd=' ';    do    {        printf("请输入扫雷命令(x y cmd): ");        scanf("%d %d %c",&x, &y, &cmd);        if(cmd >= 'a')  cmd = cmd + ('A'-'a');//转成大写字母    }while (x<0 || x>=panel.x || y<0 || y>=panel.y || !(cmd == 'Y' || cmd == 'N' || cmd == '?'));    if('N' == cmd)    {        panel.OpenBlankMine(x, y);        panel.WinOrFail = panel.Mine[x][y].ChangeState(&panel.Mine[x][y], NO);    }    else if('Y' == cmd)        panel.WinOrFail = panel.Mine[x][y].ChangeState(&panel.Mine[x][y], YES);    else if('?' == cmd)        panel.WinOrFail = panel.Mine[x][y].ChangeState(&panel.Mine[x][y], DOUBT);    fflush(stdin);    //getchar();    panel.Output();    return;}void DestrPanelFun(void){    for(int x=0; x<panel.x; x++)    {    delete [] panel.Mine[x];    }    delete [] panel.Mine;}void InitPanelFun(void){    // TODO: 将此函数中的scanf和printf进行封装,使输入输出不依赖特定平台    int reDo = 0;    printf("by: 瑞 2012-9-20\n");    do    {        printf("请输入游戏难度等级:(可选等级:1,2,3,分别表示由易到难;输入0表示自定义)");        scanf("%d", &panel.Grade);        switch(panel.Grade)        {        case EASY:            panel.x = 10;            panel.y = 10;            panel.MinesNum = 10;            break;        case MIDDLE:            panel.x = 20;            panel.y = 20;            panel.MinesNum = 30;            break;        case HARD:            panel.x = 30;            panel.y = 30;            panel.MinesNum = 60;            break;        case USER_DEFINED:            do            {                // TODO: 此处需要更严格的数据合理性检查                printf("请输入阵地(面板)大小(例如设置8*9的阵地,输入:8 9): ");                scanf("%d%d", &panel.x, &panel.y);                printf("请输入地雷个数(例如设置10个地雷,输入:10): ");                scanf("%d", &panel.MinesNum);                //printf(str[1], panel.x, panel.y, panel.MinesNum);   // 输出雷区信息            }while(panel.x <=0 || panel.y <= 0 || panel.MinesNum <= 0);            break;        default:            reDo = 1;            break;        }    }while(1 == reDo);    panel.WinOrFail = RUNING;    panel.GameState = RUN;    panel.CatchMineNum = 0;    panel.DestroyPanel = DestrPanelFun;    panel.GetCtrl = GetCtrlFun;    panel.Output = OutPutFun;    panel.OpenBlankMine = OpenBlankMineFun;    // 其它预留参数暂不设置    // 动态建立地雷阵地表    panel.Mine = new pMineStruct[panel.x];    for(int x=0; x<panel.x; x++)    {        panel.Mine[x] = new MineStruct[panel.y];        for(int y=0; y<panel.y; y++)        {            panel.Mine[x][y].x = x;            panel.Mine[x][y].y = y;            panel.Mine[x][y].MineIn = N;            panel.Mine[x][y].MineNumAround = 0;            panel.Mine[x][y].CheckState = UNKNOW;            panel.Mine[x][y].ChangeState = ChangeMineStateFun;        }    }    // 随机安放地雷    srand(time(NULL));// 随机种子初始化    for(int i=0; i< panel.MinesNum; i++)    {        int x = rand() % panel.x;        int y = rand() % panel.y;        if(Y == panel.Mine[x][y].MineIn)        {            i--;        }        else        {            panel.Mine[x][y].MineIn = Y;        }    }    // 标记周围的地雷数目    for(int x=0; x<panel.x; x++)    {        for(int y=0; y<panel.y; y++)        {            if(x>0 && y>0 && Y==panel.Mine[x-1][y-1].MineIn)                panel.Mine[x][y].MineNumAround++;            if(x>0 && Y==panel.Mine[x-1][y].MineIn)                panel.Mine[x][y].MineNumAround++;            if(x>0 && y<panel.y-1 && Y==panel.Mine[x-1][y+1].MineIn)                panel.Mine[x][y].MineNumAround++;            if(y>0 && Y==panel.Mine[x][y-1].MineIn)                panel.Mine[x][y].MineNumAround++;            if(y<panel.y-1 && Y==panel.Mine[x][y+1].MineIn)                panel.Mine[x][y].MineNumAround++;            if(x<panel.x-1 && y>0 && Y==panel.Mine[x+1][y-1].MineIn)                panel.Mine[x][y].MineNumAround++;            if(x<panel.x-1 && Y==panel.Mine[x+1][y].MineIn)                panel.Mine[x][y].MineNumAround++;            if(x<panel.x-1 && y<panel.y-1 && Y==panel.Mine[x+1][y+1].MineIn)                panel.Mine[x][y].MineNumAround++;        }    }    // 输出    panel.Output();}void InitGame(void){    panel.InitPanel = InitPanelFun;    panel.InitPanel();}int main(){    InitGame();    while(panel.WinOrFail == RUNING)    {        panel.GetCtrl();    }    PAUSESCREEN;    panel.DestroyPanel();    return 0;}

读书人网 >C语言

热点推荐