今天发布源代码,由于写在一个文件里非常乱,所以分三个文件写
绘图和鼠标函数graph.h
/*绘图与鼠标相关函数*/ #include<graphics.h> #include <easyx.h> void DrawEmpty(int, int, int, int);//初始化空格子界面的函数 void DrawSmile(void);//画笑脸的函数 void DrawRedFlag(int, int);//右键画红旗的函数 int MouseX, MouseY;//鼠标的x,y坐标 MOUSEMSG m;//鼠标结构变量,接受鼠标消息 void DrawSmile(void) { setfillstyle(BS_SOLID); setfillcolor(YELLOW); fillellipse(90, 5, 110, 25);//绘制椭圆(笑脸)函数,参数为椭圆外切矩形的左上右下角坐标 setfillstyle(BS_SOLID); setfillcolor(BLACK);//画眼睛 fillellipse(93, 13, 97, 17); fillellipse(103, 13, 107, 17); bar(97, 20, 103, 21);//画嘴巴 } void DrawRedFlag(int i, int j) { setfillstyle(BS_SOLID); setfillcolor(RED); bar(8 + j * 20, 35 + i * 20, 8 + j * 20 + 5, 35 + i * 20 + 5); setcolor(BLACK); line(8 + j * 20, 35 + i * 20, 8 + j * 20, 35 + i * 20 + 10); } void DrawEmpty(int i, int j, int mode, int color) //画出16*16的小格 { setfillstyle(BS_SOLID); setfillcolor(color); if (mode == 0) { bar(10 + j * 20 - 8, 40 + i * 20 - 8, 10 + j * 20 + 8, 40 + i * 20 + 8); } else if (mode == 1) { bar(10 + j * 20 - 7, 40 + i * 20 - 7, 10 + j * 20 + 7, 40 + i * 20 + 7); } } void MouseGetXY(void)//获得鼠标的位置 { m = GetMouseMsg(); MouseX = m.x; MouseY = m.y; }
辅助计算函数auxiliary.h
/*辅助函数*/ #include <conio.h> //_kbhit() struct { int num;//格子当前状态,1表示有雷,0表示无雷或已经显示数字 int roundnum;//统计格子周围的雷数 int flag;//右键按下显示红旗标志,0表示没有,1表示有 }Mine[10][10]; int mineNUM;//统计处理过的格子数 TCHAR randmineNUM[100];//显示数字的字符串 /*统计每个格子周围的雷数*/ int MineStatistics(int i, int j) { int nNUM = 0; if (i == 0 && j == 0)//左上角格子的统计 { if (Mine[0][1].num == 1) nNUM++; if (Mine[1][0].num == 1) nNUM++; if (Mine[1][1].num == 1) nNUM++; } else if (i == 0 && j == 9)//右上角格子的统计 { if (Mine[0][8].num == 1) nNUM++; if (Mine[1][9].num == 1) nNUM++; if (Mine[1][8].num == 1) nNUM++; } else if (i == 9 && j == 0)//左下角格子的统计 { if (Mine[8][0].num == 1) nNUM++; if (Mine[9][1].num == 1) nNUM++; if (Mine[8][1].num == 1) nNUM++; } else if (i == 9 && j == 9)//右下角格子的统计 { if (Mine[9][8].num == 1) nNUM++; if (Mine[8][9].num == 1) nNUM++; if (Mine[8][8].num == 1) nNUM++; } else if (j == 0)//左边第一列格子的统计 { if (Mine[i][j + 1].num == 1) nNUM++; if (Mine[i + 1][j].num == 1) nNUM++; if (Mine[i - 1][j].num == 1) nNUM++; if (Mine[i - 1][j + 1].num == 1) nNUM++; if (Mine[i + 1][j + 1].num == 1) nNUM++; } else if (j == 9)//右边第一列格子的统计 { if (Mine[i][j - 1].num == 1) nNUM++; if (Mine[i + 1][j].num == 1) nNUM++; if (Mine[i - 1][j].num == 1) nNUM++; if (Mine[i - 1][j - 1].num == 1) nNUM++; if (Mine[i + 1][j - 1].num == 1) nNUM++; } else if (i == 0)//第一行格子的统计 { if (Mine[i + 1][j].num == 1) nNUM++; if (Mine[i][j - 1].num == 1) nNUM++; if (Mine[i][j + 1].num == 1) nNUM++; if (Mine[i + 1][j - 1].num == 1) nNUM++; if (Mine[i + 1][j + 1].num == 1) nNUM++; } else if (i == 9)//最后一行格子的统计 { if (Mine[i - 1][j].num == 1) nNUM++; if (Mine[i][j - 1].num == 1) nNUM++; if (Mine[i][j + 1].num == 1) nNUM++; if (Mine[i - 1][j - 1].num == 1) nNUM++; if (Mine[i - 1][j + 1].num == 1) nNUM++; } else//普通格子的统计 { if (Mine[i - 1][j].num == 1) nNUM++; if (Mine[i - 1][j + 1].num == 1) nNUM++; if (Mine[i][j + 1].num == 1) nNUM++; if (Mine[i + 1][j + 1].num == 1) nNUM++; if (Mine[i + 1][j].num == 1) nNUM++; if (Mine[i + 1][j - 1].num == 1) nNUM++; if (Mine[i][j - 1].num == 1) nNUM++; if (Mine[i - 1][j - 1].num == 1) nNUM++; } return nNUM;//把格子周围一共有多少雷数的统计结果返回 } void ShowWhite(int i, int j)//显示无雷区的空白部分 { if (Mine[i][j].flag == 1 || Mine[i][j].num == 0)//如果有红旗或该格处理过就不对该格进行任何判断 return; mineNUM--;//显示过数字或者空格的格子就表示多处理了一个格子,当所有格子都处理过了表示胜利 if (Mine[i][j].roundnum == 0 && Mine[i][j].num != 1)//显示空格 { DrawEmpty(i, j, 1, WHITE); Mine[i][j].num = 0; } else if (Mine[i][j].roundnum != 0)//输出雷数 { DrawEmpty(i, j, 1, WHITE); _stprintf_s(randmineNUM, _T("%d"), Mine[i][j].roundnum); setcolor(RED); outtextxy(6 + j * 20, 32 + i * 20, randmineNUM); Mine[i][j].num = 0;//已经输出雷数的格子用0表示已经用过这个格子 return; } /*8个方向递归显示所有的空白格子*/ if (i != 0 && Mine[i - 1][j].num != 1) ShowWhite(i - 1, j); if (i != 0 && j != 9 && Mine[i - 1][j + 1].num != 1) ShowWhite(i - 1, j + 1); if (j != 9 && Mine[i][j + 1].num != 1) ShowWhite(i, j + 1); if (j != 9 && i != 9 && Mine[i + 1][j + 1].num != 1) ShowWhite(i + 1, j + 1); if (i != 9 && Mine[i + 1][j].num != 1) ShowWhite(i + 1, j); if (i != 9 && j != 0 && Mine[i + 1][j - 1].num != 1) ShowWhite(i + 1, j - 1); if (j != 0 && Mine[i][j - 1].num != 1) ShowWhite(i, j - 1); if (i != 0 && j != 0 && Mine[i - 1][j - 1].num != 1) ShowWhite(i - 1, j - 1); }
主函数main.cpp
#include<stdio.h> #include"graph.h" #include"auxiliary.h" #include<stdlib.h> //rand(),srand() #include<time.h> //srand((unsigned)time(NULL)) void Game(void);//游戏主程序 void GameBegin(void);//游戏开始 void GamePlay(void);//游戏执行过程 void GameOver(void);//游戏结束 void GameWin(void);//游戏胜利 int PLAY = 0;//是否第一次玩游戏的标志 int FLAG = 1;//游戏失败后是否重新开始的标志 int AGAIN = 0;//游戏中途重新开始的标志 int main(void) { initgraph(200, 230, SHOWCONSOLE);//初始化游戏界面和大小 Game();//运行游戏 closegraph();//关闭图形界面 } void Game(void) { while (1) { if (FLAG == 1) { GameBegin();//绘制出游戏界面并判断是否玩过和重新开始 GamePlay();//游戏过程的函数 if (AGAIN == 1) { AGAIN = 0; continue; } } FLAG = 0; if (m.uMsg == WM_LBUTTONDOWN)//鼠标左键按下事件 { MouseGetXY(); if (MouseX > 90 && MouseX<110 && MouseY>5 && MouseY < 25) { FLAG = 1; continue; } } if (_kbhit())//判断有按键退出 { break; } } } void GameBegin(void) { int i, j; cleardevice(); PLAY = 1; mineNUM = 0; setfillstyle(BS_SOLID);//此处用法和TC不同 setfillcolor(WHITE); bar(0, 0, 200, 230); //设置背景区域 for (i = 0; i < 10; i++) //绘制每个雷区(小格) { for (j = 0; j < 10; j++) { DrawEmpty(i, j, 0, LIGHTGRAY); } } DrawSmile();//画出中间的笑脸 srand((unsigned)time(NULL));//根据时间给随机数不同的种子数 for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { Mine[i][j].num = rand() % 8;//随机数产生范围0-7 if (Mine[i][j].num == 1) { mineNUM++; } else { Mine[i][j].num = 2; } printf("%3d", Mine[i][j].num); Mine[i][j].flag = 0; } printf(" "); _stprintf_s(randmineNUM, _T("%d"), mineNUM);//将minrNUM转换成字符串类型 setbkcolor(WHITE); setcolor(RED); settextstyle(16, 0, _T("0")); outtextxy(2, 2, randmineNUM); } mineNUM = 100 - mineNUM; } void GamePlay(void)/*游戏过程*/ { int i, j, Num = 0;/*Num用来接收统计函数返回一个格子周围有多少地雷*/ for (i = 0; i < 10; i++) for (j = 0; j<10; j++) Mine[i][j].roundnum = MineStatistics(i, j);/*统计每个格子周围有多少地雷*/ while (!_kbhit()) { m = GetMouseMsg(); switch (m.uMsg) { case WM_LBUTTONDOWN: { MouseGetXY(); if (MouseX>90 && MouseX<110 && MouseY>5 && MouseY<25)/*重新来*/ { MessageBox(NULL, TEXT("重新开始成功"), TEXT("YES"), MB_OK); AGAIN = 1; return; } if (MouseX>0 && MouseX<200 && MouseY>30 && MouseY < 230)/*当前鼠标位置在格子范围内*/ { j = (MouseX) / 20;/*x坐标*/ i = (MouseY - 30) / 20;/*y坐标*/ if (Mine[i][j].flag == 1)/*如果格子有红旗则左键无效*/ continue; if (Mine[i][j].num != 0)/*如果格子没有处理过*/ { if (Mine[i][j].num == 1)/*鼠标按下的格子是地雷*/ { GameOver();/*游戏失败*/ break; } else/*鼠标按下的格子不是地雷*/ { Num = MineStatistics(i, j); if (Num == 0)/*周围没地雷就用递归算法来显示空白格子*/ ShowWhite(i, j); else/*按下格子周围有地雷*/ { _stprintf_s(randmineNUM, _T("%d"), Num);/*输出当前格子周围的雷数*/ DrawEmpty(i, j, 1, WHITE); setcolor(RED); outtextxy(6 + j * 20, 32 + i * 20, randmineNUM); mineNUM--; } Mine[i][j].num = 0;/*点过的格子周围雷数的数字变为0表示这个格子已经用过*/ if (mineNUM < 1)/*胜利了*/ { GameWin(); break; } } } } } case WM_RBUTTONDOWN: { MouseGetXY(); if (MouseX > 0 && MouseX<200 && MouseY>30 && MouseY < 230)/*当前鼠标位置在格子范围内*/ { j = (MouseX) / 20;/*x坐标*/ i = (MouseY - 30) / 20;/*y坐标*/ //MessageBox(NULL, TEXT("右键测试"), TEXT("YES"), MB_OK); if (Mine[i][j].flag == 0 && Mine[i][j].num != 0)/*本来没红旗现在显示红旗*/ { DrawRedFlag(i, j); Mine[i][j].flag = 1; } else if (Mine[i][j].flag == 1)/*有红旗标志再按右键就红旗消失*/ { DrawEmpty(i, j, 0, LIGHTGRAY); Mine[i][j].flag = 0; } } } } } } void GameOver(void) { int i, j; for (i = 0; i < 10; i++) { for (j = 0; j < 10; j++) { if (Mine[i][j].num == 1)//显示所有地雷 { DrawEmpty(i, j, 0, WHITE); setfillstyle(BS_SOLID); setfillcolor(RED); fillellipse(3 + j * 20, 33 + i * 20, 17 + j * 20, 47 + i * 20); setbkcolor(WHITE); setcolor(RED); settextstyle(16, 0, _T("宋体")); outtextxy(2, 2, _T("输了请重来")); } } } } void GameWin(void) { setbkcolor(WHITE); setcolor(RED); settextstyle(16, 0, _T("宋体")); outtextxy(2, 2, _T("你赢了")); }更多功能正在完善,To be continued!!