今天发布源代码,由于写在一个文件里非常乱,所以分三个文件写

绘图和鼠标函数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语言新手写扫雷源代码的更多相关文章

  1. C语言新手写扫雷攻略1

    工欲善其事,必先利其器,首先要准备好开发环境,既然是C语言,那就不是WinAPI的扫雷,就是纯的C语言开发,但是以前的C都是TC开发的,现在用肯定是过时很久了,但是也是有解决办法的,某些大神开发出Ea ...

  2. C语言新手写扫雷攻略4

    今天写的是游戏过程的函数,基本的算法前面都解释过了,今天是实现基本的功能 补充一下前面需要用到的头文件 #include<conio.h> //_kbhit() #include<s ...

  3. C语言新手写扫雷攻略3

    界面绘制好后,雷数也布置了,接下来就是游戏的运行过程了,今天先不说具体过程,再来看看需要用到的辅助函数 先是简单的画红旗,鼠标右键的功能是画红旗,至此我们都是在使用函数自己绘图,效率是低,但有助于理解 ...

  4. C语言新手写扫雷攻略2

    接下来是游戏的功能设计,要有扫雷的基本功能,左键点击雷区,右键红旗标记,并且可以统计雷数,可以重新开始,以下是游戏的功能初始 void Game(void) { while (1) { if (FLA ...

  5. 写给C语言新手的话

    首先声明啊,写这个是因为一些加我QQ的朋友问我学习经验,我才写的. 另外,如果是二级党,那么请用谭浩强老师的书.然后你就可以不用看了.倒不是有偏见,而是我写的这个东西,根本不是为了考试,而是为了和新手 ...

  6. (转)Python新手写出漂亮的爬虫代码1——从html获取信息

    https://blog.csdn.net/weixin_36604953/article/details/78156605 Python新手写出漂亮的爬虫代码1初到大数据学习圈子的同学可能对爬虫都有 ...

  7. 阿望教你用vue写扫雷(超详细哦)

    前言 话说阿望还在大学时,某一天寝室突然停网了,于是和室友两人不约而同地打开了扫雷,比相同难度下谁更快找出全部的雷,玩得不亦乐乎,就这样,扫雷伴我们度过了断网的一周,是整整一周啊,不用上课的那种,可想 ...

  8. (转)Python新手写出漂亮的爬虫代码2——从json获取信息

    https://blog.csdn.net/weixin_36604953/article/details/78592943 Python新手写出漂亮的爬虫代码2——从json获取信息好久没有写关于爬 ...

  9. Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建;学习Python语言,利用Python语言来写测试用例。加油!!!

    Python+selenium测试环境成功搭建,简单控制浏览器(firefox)接下来,继续学习其他浏览器上的测试环境搭建:学习Python语言,利用Python语言来写测试用例.加油!!!

随机推荐

  1. 理解webpack中的process.env.NODE_ENV

    参考资料 一. process 要理解 process.env.NODE_ENV 就必须要了解 process,process 是 node 的全局变量,并且 process 有 env 这个属性,但 ...

  2. VIEW当中自定义属性的使用

    主要有三种方法可以实现自定义属性. 第一种方法,直接设置属性值,通过attrs.getAttributeResourceValue拿到这个属性值. (1)在xml文件中设置属性值 [html] vie ...

  3. 升级到Xcode 5.1和iOS 7遇到的各种问题及解决办法汇总:

    <iOS 企业证书部署无效的问题>:http://t.cn/8s7ILWZ <clipsToBounds 属性默认值变了>:http://weibo.com/165881473 ...

  4. tomcat的stratup小黑框名字修改

    Tomcat的bin目录下:catalina.out文件, TITLE就是Tomcat startup窗口的名称,282行默认是:Tomcat.这里建议改成“服务名+端口号”的方式,看起来一目了然.因 ...

  5. 再次安装双linux系统及kali的grub修复!

    打算下学期不带笔记本,平时编程上网本就够了,也就看看一般的算法,于是那上网本装centos7和kali,上网本是APU,但是这两个版本的linux都支持的不错. 先安装centos,由于熟悉了linu ...

  6. 项目集成swagger,并暴露指定端点给swagger

    项目集成swagger 一:思考: 1.swagger解决了我们什么问题? 传统开发中,我们在开发完成一个接口后,为了测试我们的接口,我们通常会编写单元测试,以测试我们的接口的可用性,或者用postm ...

  7. msfpayload的用法

    daniel@daniel-mint ~/msf/metasploit-framework $ ruby msfpayload windows/exec CMD=calc.exe C WARNING: ...

  8. 前端学习笔记——引入css文件、样式优先级

    CSS样式的引用方式有三种:行间样式表>内部样式表>外部样式表. 如果只有一种样式,那么优先级“由内到外 由近到远” 1.行间样式表--内联方式 内联方式指的是直接在 HTML 标签中的  ...

  9. 自动化运维Shell入门

    运维shell 作用 项目部署 项目监控 什么是shell shell是一个程序,/bin/bash/,是一个命令解释器所有linux命令都由他来执行,打开终端就进入了 shell的交互式命令 运行方 ...

  10. InnoDB B树 锁

    InnoDB B树 叶子=>主键+数记录非叶子=>主键1+主键3...主键4 事务和行锁 索引项加锁 相等条件来访问更新数据,避免使用范围条件 (1)InnoDB的行销是基于索引实现的,如 ...