0


用C语言写个控制台扫雷游戏(附完整代码)

前言

  扫雷游戏大家应该都玩过,虽然win10以后更新了,但还是win7版的好用,在代码写烦了来上几把换换脑子还是不错滴。

  下面用c语言模仿win7版的写一个控制台扫雷游戏。


一、对控制台的控制

  游戏中要对控制台的大小、文字颜色、光标大小、光标位置、鼠标输入等需要进行一些设置,下面列出所需要的一些函数。

1.控制台大小

  控制台大小通过mode命令设置。这个命令中的大小是指行和列的字符数而非像素。

//设置控制台大小voidSetSize(unsigned uCol,unsigned uLine){char cmd[64];sprintf(cmd,"mode con cols=%d lines=%d", uCol, uLine);system(cmd);}

2.控制台颜色

  控制台颜色设置详情可查看: 用C代码设置Windows控制台颜色

//更改文字颜色// color为每一种颜色所代表的数字,范围是0~15voidsetColor(WORD color){
    HANDLE HOutput =GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄SetConsoleTextAttribute(HOutput, color);}

3.控制台光标样式

  更改光标样式要用到结构体CONSOLE_CURSOR_INFO 和控制台API函数SetConsoleCursorInfo,通过这个结构体和函数可以设置光标的可见性和大小。

// 设置光标样式voidSetCursorType(BOOL bVisible){
    HANDLE HOutput =GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO curInfo;
    curInfo.bVisible = bVisible;//更改光标显示状态,TRUE显示光标,FALSE隐藏光标
    curInfo.dwSize =100;// 光标大小1到100之间。 范围从完全填充单元格到单元底部的水平线条。SetConsoleCursorInfo(HOutput,&curInfo);}

4.控制台光标位置

  这个函数用的比较多,用来定位要输出的字符的位置。

//设置光标位置,起点从1开始voidMoveCursorTo(int nCols,int nRows){
    COORD crdLocation ={nCols, nRows};
    HANDLE HOutput =GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出的句柄SetConsoleCursorPosition(HOutput, crdLocation);//设置光标位置}

5.获取控制台光标位置字符

  这个函数用的比较多,用来定位要输出的字符的位置。

/// 提取出窗口中第x行y列的位置的字符/// @return 返回指定位置显示的字符,空白处返回空格charGetCursorStr(int x,int y){
    COORD pos ={x, y};char str =0;
    DWORD read;// HANDLE HOutput = GetStdHandle(STD_OUTPUT_HANDLE); //获取标准输出的句柄ReadConsoleOutputCharacterA(HOutput,&str,1, pos,&read);return str;}

6.控制台显示位置

  通过API函数MoveWindow设置窗口的位置。在设置窗口位置之前,要先取得控制台窗口大小和屏幕大小,通过计算得出屏幕居中的位置。

//居中显示控制台
BOOL MoveConsoleWindow(){//获取屏幕大小
    HDC hdc =GetDC(NULL);int cx =GetDeviceCaps(hdc, DESKTOPHORZRES);//窗口左侧位置int cy =GetDeviceCaps(hdc, DESKTOPVERTRES);//窗口顶部位置ReleaseDC(NULL, hdc);//获取控制台大小
    HWND HOutput =GetConsoleWindow();
    RECT rect;GetWindowRect(HOutput,&rect);int w = rect.right - rect.left;//窗口宽度int h = rect.bottom - rect.top;//窗口高度
    cx =(cx - w)/2;
    cy =(cy - h)/2;returnMoveWindow(HOutput, cx, cy, w, h, TRUE);}

7.控制台鼠标操作设置

  除了上面,还需要对控制台的鼠标操作进行屏蔽。

#defineDISABLE_QUICK_EDIT_MODE0x01#defineDISABLE_INSERT_MODE0x02#defineDISABLE_MOUSE_INPUT0x03#defineDISABLE_ALL(DISABLE_QUICK_EDIT_MODE | DISABLE_INSERT_MODE | DISABLE_MOUSE_INPUT)//执行控制台相关设置voidCloseConsoleMode(UINT uTag){
    HANDLE HInput =GetStdHandle(STD_INPUT_HANDLE);//这里用标准输入设备
    DWORD mode;GetConsoleMode(HInput,&mode);if(uTag & DISABLE_QUICK_EDIT_MODE)
        mode &=~ENABLE_QUICK_EDIT_MODE;//移除快速编辑模式if(uTag & DISABLE_INSERT_MODE)
        mode &=~ENABLE_INSERT_MODE;//移除插入模式if(uTag & DISABLE_MOUSE_INPUT)
        mode &=~ENABLE_MOUSE_INPUT;//移除鼠标输入SetConsoleMode(HInput, mode);}

二、游戏界面

1.游戏难度选择界面

  win版的扫雷有3种难度和自定义难度,这里通过选择界面选择游戏难度。
先看看效果
选择界面_自定义

1.1 基本定义

  定义结构体保存游戏的格子数量和地雷数量。

#defineCONSOLEWIDTH80//控制台宽度#defineCONSOLEHEIGHT40//控制台高度#defineDEFCOLOR0x7//控制台默认文字颜色typedefstruct_point{short x;short y;} Point;//格子大小typedefstruct_MapSize{
    Point MapSize;//格子数量short Mine_Count;//地雷数量} Map_Size;//按照win扫雷定义尺寸和雷数
Map_Size defMapSize[3]={{{9,9},10},{{16,16},40},{{30,16},99}};

1.2显示标题信息

  • 使用setColor更改文字颜色
  • sprintf给buf输出字符宽度控制居中显示。
  • 显示输出后文字颜色改回默认颜色
voidPrintName(){system("cls");setColor(0x2);char buf[100];int l =(CONSOLEWIDTH -20)/2+20;sprintf(buf,"\n%%%ds\n", l);printf(buf,"欢迎来到扫雷小游戏");sprintf(buf,"%%%ds\n",(CONSOLEWIDTH -16)/2+16);printf(buf,"-- by Apull --");setColor(DEFCOLOR);}

1.3显示难度选项

  • 不同难度使用不同颜色显示
  • 游戏界面中横向格子之间用空格隔开,因此在选定难度后,横向格子数量需要翻倍,更改为MapSize.MapSize.x * 2 - 1
//难度选择voidChoose(){
    MapSize = defMapSize[0];PrintName();printf("\t\t选择游戏难度:\n");setColor(0xA);printf("\t\t  1、初级:%dx%d,共%d个地雷\n", defMapSize[0].MapSize.x, defMapSize[0].MapSize.y, defMapSize[0].Mine_Count);setColor(0xE);printf("\t\t  2、中级:%dx%d,共%d个地雷\n", defMapSize[1].MapSize.x, defMapSize[1].MapSize.y, defMapSize[1].Mine_Count);setColor(0xc);printf("\t\t  3、高级:%dx%d,共%d个地雷\n", defMapSize[2].MapSize.x, defMapSize[2].MapSize.y, defMapSize[2].Mine_Count);setColor(0x9);printf("\t\t  4、自定义难度\n");setColor(DEFCOLOR);printf("\t\t  0、退出\n");printf("\t\t输入你的选择(回车默认选择1): ");char ch;
    BOOL inputOK = TRUE;while(inputOK){
        ch =_getch();switch(ch){case'1':case Key_ENTER:
            MapSize = defMapSize[0];
            inputOK = FALSE;break;case'2':
            MapSize = defMapSize[1];
            inputOK = FALSE;break;case'3':
            MapSize = defMapSize[2];
            inputOK = FALSE;break;case'4':printf("\n");
            MapSize.MapSize.y =OptMines("\t\t  高度:",9,24);
            MapSize.MapSize.x =OptMines("\t\t  宽度:",9,30);
            MapSize.Mine_Count =OptMines("\t\t  雷数:",10,668);
            inputOK = FALSE;break;case'0':case Key_ESC:EXIT(0);break;default:break;}}
    MapSize.MapSize.x = MapSize.MapSize.x *2-1;}

1.4 选择自定义难度

  • 为了防止输入错误后的无限循环,这里使用字符串接收输入,再转换成int类型。
  • 设定地雷数量是所有格子数量的20%
  • 输入错误使用红色文字提示
//自定义难度intOptMines(char*str,int min,int max){int x;char buf[20]={0};if(max >30)// max > 30 表示输入的是雷数{
        max =(int)(MapSize.MapSize.x * MapSize.MapSize.y *0.2);//地雷数量是所有格子数的20%}while(TRUE){printf(str);printf("(%d-%d):", min, max);gets_s(buf,20);if(buf[0]=='0')EXIT(0);
        x =atoi(buf);if(x < min || x > max){setColor(0x04);printf("\t\t输入超出范围,请重新输入。\n");setColor(DEFCOLOR);}elsereturn x;}}

2 游戏界面

游戏界面

2.1 基本定义

2.1.1 定义地雷格子结构

  结构体struct _mine中定义一个格子要显示的字符、周围8个方向上地雷数量以及格子本身的状态。

//定义地雷格子状态enumMine_STATU{
    HIDDEN_SAFE, 
    VISIBLE_SAFE,
    HIDDEN_MINE
};//地雷格子定义typedefstruct_mine{char ch;char hasMines;enumMine_STATU statu;} Mine;#defineFLAG'@'//标记的地雷#defineMAPNORMAL'o'//正常格子#defineMINEICO'*'//地雷

2.1.2 填充地雷格子

  使用二维数组minefield存储每个格子,根据难度选择给二维数组分配内存大小。

Mine **minefield =NULL;//格子数组//生成格子数组,并填充显示字符
Mine **initMapArr(){
    Mine **minefield =(Mine **)calloc(MapSize.MapSize.y,sizeof(Mine *));if(minefield ==NULL){printf("内存分配错误!");EXIT(-1);}for(int i =0; i < MapSize.MapSize.y; i++){
        minefield[i]=(Mine *)calloc(MapSize.MapSize.x,sizeof(Mine));if(minefield ==NULL){printf("内存分配错误!");EXIT(-1);}for(int j =0; j < MapSize.MapSize.x; j++){

            minefield[i][j].ch =(j %2)?' ': MAPNORMAL;}}return minefield;}

2.1.3 产生地雷

  • 使用动态数组MinesPos保存地雷所在位置
  • 用随机数产生地雷
  • 检索重复项,有重复的则重新生成地雷。
Point *MinesPos =NULL;//地雷所在位置
Point *FindMinesPos =NULL;//标记的地雷所在位置int MineCount =0;//地雷总数//产生地雷voidinit_Mine(Point *point,int MineCount){
    Point pot;for(int i =0, j; MineCount > i;){do{
            pot.x =rand()% MapSize.MapSize.x;}while(pot.x %2!=0);

        pot.y =rand()% MapSize.MapSize.y;for(j =0; j < i; j++){if(point[j].x == pot.x && point[j].y == pot.y)break;}if(i == j){
            point[i].x = pot.x;
            point[i].y = pot.y;
            i++;}}}

2.1.4 将地雷放置到格子中

  数组MinesPos中保存着地雷的坐标,直接在格子中把这些坐标标记为地雷。

//写入雷的位置voidinit_Map(Mine **minefield, Point *point,int MineCount){for(int i =0; i < MineCount; i++){
        minefield[point[i].y][point[i].x].statu = HIDDEN_MINE;
        minefield[point[i].y][point[i].x].hasMines =-1;}}

2.1.5 计算周围地雷数量

  • 按行列扫描所有格子
  • 对一个格子的周围8个位置的地雷数量进行统计
  • 将统计数量保存到格子的hasMines属性中
//计算周围地雷数量voidcalMine(Mine **minefield){int count;for(int i =0; i < MapSize.MapSize.y; i++){for(int j =0; j < MapSize.MapSize.x; j +=2){if(minefield[i][j].statu == HIDDEN_MINE)continue;

            count =0;if(i >0&& j >1&& minefield[i -1][j -2].statu == HIDDEN_MINE)//左上角
                count++;if(i >0&& minefield[i -1][j].statu == HIDDEN_MINE)//上面
                count++;if(i >0&& j < MapSize.MapSize.x -2&& minefield[i -1][j +2].statu == HIDDEN_MINE)//右上角
                count++;if(j < MapSize.MapSize.x -1&& minefield[i][j +2].statu == HIDDEN_MINE)//右面
                count++;if(i < MapSize.MapSize.y -1&& j < MapSize.MapSize.x -2&& minefield[i +1][j +2].statu == HIDDEN_MINE)//右下角
                count++;if(i < MapSize.MapSize.y -1&& minefield[i +1][j].statu == HIDDEN_MINE)//下面
                count++;if(i < MapSize.MapSize.y -1&& j >0&& minefield[i +1][j -2].statu == HIDDEN_MINE)//左下角
                count++;if(j >0&& minefield[i][j -2].statu == HIDDEN_MINE)//左面
                count++;
                
            minefield[i][j].hasMines = count;}}}

2.1.6 其他变量

Point StatuRow;//状态显示行位置clock_tstart_t,end_t;//记录游戏时间//格子范围,限定地雷显示和操作的范围int top =0, left =0, right =0, bottom =0;

2.2 显示游戏介绍

  显示游戏介绍,并返回显示的行数。

// 输出游戏介绍intintro(){int line =3;//加上之前的标题信息2行
    line +=7;
    StatuRow.y = line -2;
    StatuRow.x = left;PrintName();//显示标题信息printf("\t\t游戏方法介绍:\n");setColor(0xE);printf("\t\t  W、S、A、D/↑、↓、←、→");setColor(DEFCOLOR);printf(":控制光标上下左右移动\n");setColor(0xE);printf("\t\t  PageUP、PageDown、Home、End");setColor(DEFCOLOR);printf(":控制光标跳到四边位置\n");setColor(0xE);printf("\t\t  空格");setColor(DEFCOLOR);printf(":打开当前格子");setColor(0xE);printf("  R");setColor(DEFCOLOR);printf(":回到选择界面");setColor(0xE);printf("  ESC");setColor(DEFCOLOR);printf(":结束游戏\n");ShowStatu();printf("\n\n");return line;}

2.3 显示游戏状态

  显示游戏信息和游戏时间,光标移动到要输出的位置,输出内容覆盖就内容,完成状态刷新。
  在输出状态的时候要移动光标,游戏过程中会看到光标跳到状态显示位置后有会跳回格子中,为避免这种情况,在开始输出状态时使用SetCursorType隐藏光标,输出完毕后再显示光标

//显示游戏状态voidShowStatu(){staticinttotal_t=0;end_t=clock();total_t=(end_t-start_t)/ CLOCKS_PER_SEC;SetCursorType(FALSE);MoveCursorTo(StatuRow.x, StatuRow.y);printf("\t\t共有雷数:%-3d  剩余雷数:%-3d  用时:%ds   ", MapSize.Mine_Count, MineCount,total_t);SetCursorType(TRUE);}

2.4 显示地雷格子

  • 根据上面显示的信息行数得到地图格子要显示的起始行
  • 根据上面基本定义的宽度CONSOLEWIDTH计算居中显示的起始列
  • 每一行光标移动到左边起始列后输出行
//确定绘制地雷格子范围voidDrawMine(){
    left = right = bottom =0;
    top =intro();drawMap(minefield);

    right = MapSize.MapSize.x + left;
    bottom += MapSize.MapSize.y + top -1;MoveCursorTo(left, top);start_t=clock();//开始计时}//绘制地雷格子和外框,设置各边范围voiddrawMap(Mine **minefield){int l =(CONSOLEWIDTH - MapSize.MapSize.x)/2-4;if(l %2==0)
        l++;int t = top;MoveCursorTo(l, t++);printf("┌");for(int i =0; i <= MapSize.MapSize.x; i++)printf("─");printf("┐\n");MoveCursorTo(l, t++);// 输出中间部分for(int i =0; i < MapSize.MapSize.y; i++){printf("│ ");for(int j =0; j < MapSize.MapSize.x; j++){printf("%c", minefield[i][j].ch);}printf("│\n");MoveCursorTo(l, t++);}printf("└");for(int i =0; i <= MapSize.MapSize.x; i++)printf("─");printf("┘\n");

    top +=1;
    left = l +2;}

  至此地雷界面绘制基本完成,下面来看看操作部分。

三、游戏操作

1 游戏按键输入

1.1 定义按键

  定义出后面要用到达按键变量

//按键定义enumKB_KEY{
    Key_FN =0xE0,// 功能键标志
    Key_Up =0x48,// 向上方向键   
    Key_Down =0x50,// 向下方向键
    Key_Left =0x4b,// 向左方向键
    Key_Right =0x4d,// 向右方向键
    Key_Home =0x47,// Home键
    Key_End =0x4f,// End键
    Key_PageUp =0x49,// PageUp键
    Key_PageDown =0x51,// PageDown键
    Key_ESC =0x1B,// ESC键
    Key_ENTER =0xD,// 回车键
    Key_SPACE =0x20,// 空格键
    Key_A ='A',
    Key_a ='a',
    Key_D ='D',
    Key_d ='d',
    Key_W ='W',
    Key_w ='w',
    Key_S ='S',
    Key_s ='s',
    Key_R ='R',
    Key_r ='r'} KEY;

1.2 读取按键输入

  • 需要注意的是方向键的输入,方向键是先输入0xE0或0,再输入对应的键值,因此输入方向键的输入需要读取2次才能确定。
  • 使用rowcol记录当前光标位置,列使用奇数位,因此列的移动要±2。
  • 检测移动后光标会不会超出现实范围,如果有超出情况则取消移动。
  • 回车 标记地雷
  • 空格 点开地雷格子
  • R 结束游戏回到选择界面
  • ESC 退出游戏
int row = top;//行int col = left;//列char ch;int chInput =0;int isGame =1;//游戏继续标志int x, y;while(isGame){if(_kbhit()!=0)//当_kbhit返回值不为0的时候,代表用户有按键按下。{
        chInput =_getch();if(chInput == Key_FN || chInput ==0)// 方向键读2次
            chInput =_getch();switch(chInput)//控制操作{case'a':case'A':case Key_Left:
            col -=2;if(col <= left)
                col = left;break;case'd':case'D':case Key_Right:
            col +=2;if(col >= right)
                col = right -1;break;case'w':case'W':case Key_Up:
            row--;if(row <= top)
                row = top;break;case's':case'S':case Key_Down:
            row++;if(row >= bottom)
                row = bottom;break;case Key_SPACE://空格点开...break;case Key_ENTER://标记地雷...break;case Key_Home://跳到第一列
            col = left;break;case Key_End://跳到最后一列
            col = right -1;break;case Key_PageUp://跳到第一行
            row = top;break;case Key_PageDown://跳到最后一行
            row = bottom;break;case Key_ESC://退出游戏
            isGame =0;break;case Key_R:case Key_r://复位到选择界面init();DrawMine();break;default://其他输入字符不动作break;}MoveCursorTo(col, row);}Sleep(150);ShowStatu();MoveCursorTo(col, row);}

2 标记地雷

  • 回车 标记地雷。
  • 读取光标处的字符,光标处是未点开格子则标记地雷。
  • 标记的地雷坐标保存到FindMinesPos数组中。
  • 如果该位置已标记则取消标记,同时从FindMinesPos数组中删除。
  • 标记后判断所有的地雷是否都已标记,如果都已标记则判赢
  • 标记后光标右移到下一个地雷格子
case Key_ENTER://标记地雷if(flagMine(row, col))GameOver(WIN_GAME);
    col +=2;if(col >= right)
        col = right -1;break;
//标记地雷
BOOL flagMine(int row,int col){char ch;
    BOOL iswin = FALSE;
    ch =GetCursorStr(col, row);//获取光标处字符if(ch == FLAG && MineCount < MapSize.Mine_Count)//切换已标记{
        FindMinesPos[MineCount].x = FindMinesPos[MineCount].y =-1;setColor(DEFCOLOR);putchar(MAPNORMAL);
        MineCount++;}elseif(ch == MAPNORMAL && MineCount >0){
        MineCount--;
        FindMinesPos[MineCount].x = col - left;
        FindMinesPos[MineCount].y = row - top;setColor(0xC);putchar(FLAG);if(MineCount ==0){int i;for(i =0; i < MapSize.Mine_Count; i++)// 确定是否标记了所有的雷{if(findMine4Pos(FindMinesPos[i].x, FindMinesPos[i].y)== FALSE)break;}
            iswin = i == MapSize.Mine_Count;}}setColor(DEFCOLOR);ShowStatu();//更新标记的雷数MoveCursorTo(col, row);return iswin;}

3 点开地雷操作

3.1 点开地雷格子

  • 空格 点开地雷格子
  • 读取光标位置字符,如果是已标记地雷则结束点开操作。
  • 如果点开的位置是地雷,游戏结束,显示游戏结束画面
  • 点开位置安全,则自动点开相连的安全区域。
  • 自动点开后判断是否一点开所有安全区,判断胜负。
  • 点开后光标右移到下一个地雷格子
case Key_SPACE://空格点开
    x = col - left;
    y = row - top;
    ch =GetCursorStr(col, row);if(ch == FLAG)//忽略点开已标记地雷break;if(minefield[y][x].statu == HIDDEN_MINE)//点开雷,游戏结束{
        isGame =GameOver(LOSS_GAME);
        row = top;
        col = left;continue;}else//自动点开连续的安全区{SetCursorType(FALSE);OpenMine(y, x);SetCursorType(TRUE);if(isWin()){
            isGame =GameOver(WIN_GAME);
            row = top;
            col = left;continue;}}

    col +=2;if(col >= right)
        col = right -1;break;

3.2 自动展开安全区域

  • 递归对当前格子周围的安全区域进行展开操作
  • 递归到边界或已点开区域终止
  • 点开时使用不用的颜色显示格子周围地雷数。
  • 格子周围地雷数为0的显示为空格’ ’
//自动打开安全区voidOpenMine(int row,int col){int x =0;
    x = col + left;int y =0;
    y = row + top;char ch =0;if(row <0|| row >= MapSize.MapSize.y)return;if(col <0|| col >= MapSize.MapSize.x)return;if(minefield[row][col].statu == VISIBLE_SAFE)return;if(minefield[row][col].hasMines ==0)
        ch =' ';elseif(minefield[row][col].hasMines >0)
        ch = minefield[row][col].hasMines +'0';elsereturn;if(minefield[row][col].hasMines >=0){MoveCursorTo(x, y);int n = minefield[row][col].hasMines;switch(n){case1:setColor(0x9);//淡蓝色break;case2:setColor(0x2);//绿色break;case3:setColor(0xC);//淡红色break;case4:setColor(0x1);//蓝色break;case5:setColor(0x4);//红色break;case6:setColor(0xD);//淡紫色break;case7:setColor(0x5);//紫色break;case8:setColor(0x6);//黄色break;}putchar(ch);setColor(DEFCOLOR);
        minefield[row][col].ch = ch;
        minefield[row][col].statu = VISIBLE_SAFE;if(ch !=' ')return;}if(row >1)OpenMine(row -1, col);if(col < MapSize.MapSize.x)OpenMine(row, col +2);if(row < MapSize.MapSize.y)OpenMine(row +1, col);if(col >=2&& col %2==0)OpenMine(row, col -2);}

四、游戏胜负

1 胜负判定

  • 游戏过程中如果点开了地雷,则直接判负。
  • 比对所有未点开的地雷格子和地雷数组的坐标,如果刚好符合则判赢。
//检查标记地雷是否都正确
BOOL isWin(){
    BOOL iswin = FALSE;int cnt =0;for(int i =0; i < MapSize.MapSize.y; i++){for(int j =0; j < MapSize.MapSize.x; j++){if(minefield[i][j].ch == MAPNORMAL){if(findMine4Pos(j, i)== FALSE){
                    i = MapSize.MapSize.y +1;break;}
                cnt++;}}}

    iswin = cnt == MapSize.Mine_Count;return iswin;}

2 胜负界面

  • 外部函数判断胜负后传递胜负结果变量给GameOver函数。
  • 根据参数使用不同颜色显示不同提示。
  • 光标定位到地雷格子往下2行位置输出胜负信息。
  • 根据提示返回是否继续游戏
//胜负结果变量enumGAME_RESULT{
    WIN_GAME,
    LOSS_GAME
};//游戏结束画面
BOOL GameOver(enumGAME_RESULT statu){MoveCursorTo(0, bottom +2);if(statu == WIN_GAME){// system("color 2F");//改变背景为绿色showMine(TRUE);setColor(0x02);printf("\t    恭喜,你找出了所有的地雷!\n");}if(statu == LOSS_GAME){// system("color 4F"); //改变背景为红色showMine(FALSE);setColor(0x04);printf("\t    哦吼,踩到雷了!\n");}setColor(DEFCOLOR);

    BOOL rst = FALSE;char ch;printf("\n\t  是否重新开始游戏(Y/N): ");fflush(stdin);do{
        ch =_getch();if(ch =='Y'|| ch =='y'|| ch == Key_ENTER){init();DrawMine();
            rst = TRUE;break;}elseif(ch =='N'|| ch =='n'|| ch == Key_ESC){
            rst = FALSE;break;}}while(TRUE);return rst;}

  胜利界面
胜利界面

  失败界面
失败界面


五、总结

  没有总结

  完整代码已上传到GitCode,需要的移步 https://gitcode.net/apull/Mines_Console


本文转载自: https://blog.csdn.net/apull/article/details/127719987
版权归原作者 浪客 所有, 如有侵权,请联系我们删除。

“用C语言写个控制台扫雷游戏(附完整代码)”的评论:

还没有评论