首页 > 代码库 > C语言新手写扫雷源代码
C语言新手写扫雷源代码
今天发布源代码,由于写在一个文件里非常乱,所以分三个文件写
绘图和鼠标函数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("\n"); _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!!
C语言新手写扫雷源代码
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。