在好例子网,分享、交流、成长!
您当前所在位置:首页C/C++ 开发实例C/C++游戏开发 → win32版 扫雷 游戏源码

win32版 扫雷 游戏源码

C/C++游戏开发

下载此实例
  • 开发语言:C/C++
  • 实例大小:2.58M
  • 下载次数:12
  • 浏览次数:152
  • 发布时间:2020-07-05
  • 实例类别:C/C++游戏开发
  • 发 布 人:setsailgo
  • 文件格式:.zip
  • 所需积分:2
 相关标签: win32 扫雷

实例介绍

【实例简介】

该项目基于VS2017开发,基本还原了windows自带的扫雷游戏的全部功能

【实例截图】

from clipboard

【核心代码】

#pragma once
#include <math.h>
#include <queue>


/*
获得每个块周围块的雷数
参数:
mapInfo 雷区块标志数组
row 雷区行数
col 雷区列数
无返回值
*/
void getMineCount(unsigned short int *&mapInfo, int row, int col)
{
unsigned short int *colHisto = new unsigned short int[col];
unsigned short int coreHisto;
int pno = 0, padd = 0, psub = 0;

for (int j = 0; j < col; j )
colHisto[j] = 0;

for (int i = 0; i < row; i )
{
while (padd < (i 2) * col)
{
if (i < row - 1)
colHisto[padd % col] = ((mapInfo[padd] & 0xF000) == MF_MINE) ? 1 : 0;
if (i > 1 && (mapInfo[psub ] & 0xF000) == MF_MINE)
colHisto[padd % col]--;
padd ;
}
coreHisto = 0;
for (int j = 0; j < col; j )
{
while (pno < j 2 i * col)
{
if (j < col - 1)
coreHisto = colHisto[pno % col];
if (j > 1)
coreHisto -= colHisto[(pno - 3) % col];
pno ;
}
if ((mapInfo[pno - 2] & 0xF000) != MF_MINE)
mapInfo[pno - 2] = (mapInfo[pno - 2] & 0x00FF) coreHisto * 0x1000;
}
pno--;
}
}

/*
随机布雷, 除去初始点到的块及周围的块
参数:
mapInfo 雷区块标志数组
seed 随机种子
firstLButtonNo 初始点到的块序号
row 雷区行数
col 雷区列数
count 雷区雷数
无返回值
*/
void initMineCount(unsigned short int *&mapInfo, unsigned int seed, int firstLButtonNo, int row, int col, int count)
{
int brickNumber = row * col;
int n = 0, r;

srand(seed);//设置随机种子
//排除点到的块及其周围随机布雷
while (n < count)
{
r = rand() % brickNumber;
if ((mapInfo[r] & 0xF000) != MF_MINE
&& r != firstLButtonNo
&& r != firstLButtonNo - col
&& r != firstLButtonNo - col 1
&& r != firstLButtonNo 1
&& r != firstLButtonNo col 1
&& r != firstLButtonNo col
&& r != firstLButtonNo col - 1
&& r != firstLButtonNo - 1
&& r != firstLButtonNo - col - 1)
{
mapInfo[r] = (mapInfo[r] & 0x00FF) MF_MINE;
n ;
}
}

getMineCount(mapInfo, row, col);//计算每个块周围的雷数

}

/*
保存游戏数组计算雷区块标志数组
参数:
mapInfo 雷区块标志数组
saveFlags 保存的游戏数组
brickNumber 雷区块数
无返回值
*/
void save2map(unsigned short int *&mapInfo, TCHAR *&saveFlags, int brickNumber)
{
for (int i = 0; i < brickNumber; i )
switch (TCHAR temp = saveFlags[i])
{
case '0':case '3':case '6':
mapInfo[i] = (mapInfo[i] & 0xF000) ((mapInfo[i] & 0x00FF) (temp - '0')) % 9;
break;
case '9':
mapInfo[i] = (mapInfo[i] & 0xF000) MF_NUMBER(mapInfo[i] / 0x1000);
break;
}
}

/*
雷区块标志数组计算保存游戏数组
参数:
saveFlags 保存的游戏数组
mapInfo 雷区块标志数组
brickNumber 雷区块数
无返回值
*/
void map2save(TCHAR *&saveFlags, unsigned short int *&mapInfo, int brickNumber)
{
for (int i = 0; i < brickNumber; i )
switch (mapInfo[i] & 0x0F00)
{
case 0x0000:
saveFlags[i] = '0' ((mapInfo[i] & 0x00FF) / 3 * 3 6) % 9;
break;
case 0x0100:
saveFlags[i] = '9';
break;
}
saveFlags[brickNumber] = '\0';
}

/*
初始化动画效果
参数:
row 雷区行数
col 雷区列数
返回值:
firstPaintNo 初始化动画贴图块序列数组
*/
int* getFirstPaintNo(int row, int col)
{
int *firstPaintNo = new int[row * col];
int startNo[4] = { 0,
col - 1 - col % 2,
(row - 1 - row % 2) * col,
(row - row % 2) * col - 1 - col % 2 };
int max = (row >= col) ? row : col;
int min = (row >= col) ? col : row;
int ratio = (int)ceil((float)max / (float)min);
int n = 0, k;

for (int i = 0; i < 2 * max; i )
{
for (int j = 0; j < 2 * min; j )
{
if (i / ratio >= j)
{
for (k = 0; k < 4; k )
{
if (2 * (i - ratio * j) <= max - 1 - ((max == col) ? (k % 2) : (k / 2))
&& 2 * j <= min - 1 - ((max == col) ? (k / 2) : (k % 2)))
{
firstPaintNo[n ] = startNo[k]
((max == col) ? ((k % 2) ? -1 : 1) : ((k / 2) ? -1 : 1)) 
* (i - ratio * j) * 2 * ((max == col) ? 1 : col)
((max == col) ? ((k / 2) ? -1 : 1) : ((k % 2) ? -1 : 1))
* j * 2 * ((max == col) ? col : 1);
}
}
}
}
}

return firstPaintNo;
}


/*
双队列函数
判断条件
参数:
nextPoint 下一个遍历到的块
startPoint 初始点到的块
threshold 判断阈值
row 雷区行数
col 雷区列数
返回值:
是否满足条件
*/
bool require(int nextPoint, int startPoint, float threshold, int row, int col)
{
int pointX = nextPoint % col;
int pointY = nextPoint / col;
int startPointX = startPoint % col;
int startPointY = startPoint / col;
return (pointY - startPointY) * (pointY - startPointY)
(pointX - startPointX) * (pointX - startPointX) <= threshold;//距离是否小于半径
}

/*
双队列函数
判断边界
参数:
nextType 下一个遍历到的块的类型
point 正在遍历的块
row 雷区行数
col 雷区列数
返回值:
是否越过边界
*/
bool edge(int nextType, int point, int row, int col)
{
bool edge[4] = { point >= col, (point % col) < (col - 1),
point < (row - 1) * col, (point % col) > 0 };
return (nextType % 2 == 0) ? edge[nextType / 2]
: (edge[(nextType - 1) / 2] && edge[(nextType 1) % 8 / 2]);
}

/*
双队列函数
初始化两个队列
参数:
startPoint 初始点到的块
flagid 遍历层次标记
fast 快队列
slow 慢队列
no 遍历块序列数组
row 雷区行数
col 雷区列数
无返回值
*/
void dbQueueInit(int startPoint, int flagid, std::queue<int> &fast,
std::queue<int> &slow, int *&no, int row, int col)
{
//点到的块及其周围8个块放入慢队列
for (int k = 0; k < 8; k )
{
int dc = (k % 4 == 0) ? 0 : ((k > 4) ? -1 : 1);
int dr = (k % 4 == 0) ? (k / 2 - 1) : ((k > 4) ? (2 - k % 4) : (k % 4 - 2));
int nextPoint = startPoint dc dr * col;
if (edge(k, startPoint, row, col))
{
slow.push(nextPoint);
slow.push(k);
no[nextPoint row * col] = flagid;
}
}
}

/*
双队列函数
运行双队列
参数:
point 正在遍历的块
type 正在遍历的块的类型
startPoint 初始点到的块
threshold 判断阈值
flagid 遍历层次标记
fast 块队列
slow 慢队列
no 遍历块序列数组
row 雷区行数
col 雷区列数
无返回值
*/
void dbQueueRun(int point, int type, int startPoint, float threshold, int flagid,
std::queue<int> &fast, std::queue<int> &slow, int *&no, int row, int col)
{
/*int start = 0, end = 5;
if (point < startPoint && (startPoint - point) % col == 0)
{
start = 2;
end = 3;
}*/
for (int k = 0; k < 5; k )//块下层遍历的5个方向
{
int nextType = (type 6 k) % 8;//类型, 方向
int dc = (nextType % 4 == 0) ? 0 : ((nextType > 4) ? -1 : 1);
int dr = (nextType % 4 == 0) ? (nextType / 2 - 1) : ((nextType > 4) ? (2 - nextType % 4) : (nextType % 4 - 2));
int nextPoint = point dc dr * col;//序号
if (edge(nextType, point, row, col) && no[nextPoint row * col] == 0)
{
if (require(nextPoint, startPoint, threshold, row, col))//判断条件
{
fast.push(nextPoint);
fast.push(nextType);
}
else
{
slow.push(nextPoint);
slow.push(nextType);
}
no[nextPoint row * col] = flagid;
}
}
}

/*
双队列函数
双队列层次遍历, 实现平面圆形扩散
参数:
startPoint 初始点到的块
endRequire 遍历类型
mapInfo 雷区块标志数组
row 雷区行数
col 雷区列数
返回值:
no 遍历块序列数组
*/
int* dbQueue(int startPoint, int endRequire, unsigned short int *&mapInfo, int row, int col)
{
std::queue<int> fast, slow;
float r = 0;//初始半径0
int point, type;
int i = 0, flagid = 1;

int *no = new int[2 * row * col];
for (int k = 0; k < row * col; k ) {
no[k] = -1;
no[k row * col] = 0;
}

dbQueueInit(startPoint, flagid, fast, slow, no, row, col);

while (!slow.empty() || !fast.empty())
{
while (!fast.empty())
{
point = fast.front();
fast.pop();
type = fast.front();
fast.pop();

if (endRequire == 0)//遍历类型0:冲开没有雷的块
{
no[i ] = point;
if ((mapInfo[point] & 0xF000) != MF_ZEROMINE)
continue;
}
else if (endRequire == 1)//遍历类型1:雷爆炸
{
if ((mapInfo[point] & 0xF000) == MF_MINE)
no[i ] = point;
}

dbQueueRun(point, type, startPoint, r * r, flagid, fast, slow, no, row, col);
}

r = r 0.618f;//半径增长
if (!slow.empty() && require(slow.front(), startPoint, r * r, row, col))
flagid ;//遍历层次加1

while (!slow.empty() && require(slow.front(), startPoint, r * r, row, col))
{
point = slow.front();
slow.pop();
type = slow.front();
slow.pop();

if (endRequire == 0)//遍历类型0:冲开没有雷的块
{
no[i ] = point;
if ((mapInfo[point] & 0xF000) != MF_ZEROMINE)
continue;
}
else if (endRequire == 1)//遍历类型1:雷爆炸
{
if ((mapInfo[point] & 0xF000) == MF_MINE)
no[i ] = point;
}

dbQueueRun(point, type, startPoint, r * r, flagid, fast, slow, no, row, col);
}
}

return no;
}


/*
点到雷数为零的块, 获得冲开块的序列
参数:
startPoint 初始点到的块
mapInfo 雷区块标志数组
row 雷区行数
col 雷区列数
返回值:
冲开块的序列数组
*/
int* getZeroDevelopNo(int startPoint, unsigned short int *&mapInfo, int row, int col)
{
return dbQueue(startPoint, 0, mapInfo, row, col);
}

/*
点到雷, 获得雷爆炸贴图的序列
参数:
startPoint 初始点到的雷
mapInfo 雷区块标志数组
bmpNumber 爆炸效果贴图数
row 雷区行数
col 雷区列数
count 雷区雷数
返回值:
test 雷爆炸贴图的序列数组
*/
int* getMineDevelopNo(int startPoint, unsigned short int *&mapInfo, int bmpNumber, int row, int col, int count)
{
int *no = dbQueue(startPoint, 1, mapInfo, row, col);

std::queue<int> run;
int np = 0, n = 0;//np 同一个遍历层次元素个数
int t = 0, i = 0, f = 0;//f 遍历层次
int d, type;//type 爆炸第几张贴图

int *test = new int[3 * count * bmpNumber];
for (int k = 0; k < 3 * count * bmpNumber; k ) {
test[k] = -1;
}

//第一个元素进队列
if (i < row * col && no[i] != -1)
{
run.push(no[i]);
run.push(1);
f = no[no[i] row * col];
np ;//遍历层次元素个数加1
i ;
}
//同一个遍历层次的元素进队列
while (i < row * col && no[i] != -1 && no[no[i] row * col] == f)
{
run.push(no[i]);
run.push(1);
np ;//遍历层次元素个数加1
i ;
}
if (i < row * col && no[i] != -1)
{
f = no[no[i] row * col];
}

while (!run.empty())
{
d = run.front();
run.pop();
type = run.front();
run.pop();

test[t] = d;//位置序号
test[t count * bmpNumber] = type;//爆炸第几张贴图
test[t 2 * count * bmpNumber] = run.size();//队列元素个数, 用来控制爆炸效果延时
t ;

if (type < bmpNumber)
{
run.push(d);
run.push(type 1);
}

if (type == 1)//第一张贴图
{
np--;//这个遍历层次元素个数减1
if (i < row * col && no[i] != -1 && no[no[i] row * col] == f)//下一个遍历层次的一个元素进队列
{
run.push(no[i]);
run.push(1);
n ;
i ;
}
if (np == 0)//遍历层次元素个数为0
{
while (i < row * col && no[i] != -1 && no[no[i] row * col] == f)//下一个遍历层次剩下的元素进队列
{
run.push(no[i]);
run.push(1);
n ;
i ;
}
if (i < row * col && no[i] != -1)
{
f = no[no[i] row * col];
}
np = n;
n = 0;
}
}
}

return test;
}



标签: win32 扫雷

实例下载地址

win32版 扫雷 游戏源码

不能下载?内容有错? 点击这里报错 + 投诉 + 提问

好例子网口号:伸出你的我的手 — 分享

网友评论

发表评论

(您的评论需要经过审核才能显示)

查看所有0条评论>>

小贴士

感谢您为本站写下的评论,您的评论对其它用户来说具有重要的参考价值,所以请认真填写。

  • 类似“顶”、“沙发”之类没有营养的文字,对勤劳贡献的楼主来说是令人沮丧的反馈信息。
  • 相信您也不想看到一排文字/表情墙,所以请不要反馈意义不大的重复字符,也请尽量不要纯表情的回复。
  • 提问之前请再仔细看一遍楼主的说明,或许是您遗漏了。
  • 请勿到处挖坑绊人、招贴广告。既占空间让人厌烦,又没人会搭理,于人于己都无利。

关于好例子网

本站旨在为广大IT学习爱好者提供一个非营利性互相学习交流分享平台。本站所有资源都可以被免费获取学习研究。本站资源来自网友分享,对搜索内容的合法性不具有预见性、识别性、控制性,仅供学习研究,请务必在下载后24小时内给予删除,不得用于其他任何用途,否则后果自负。基于互联网的特殊性,平台无法对用户传输的作品、信息、内容的权属或合法性、安全性、合规性、真实性、科学性、完整权、有效性等进行实质审查;无论平台是否已进行审查,用户均应自行承担因其传输的作品、信息、内容而可能或已经产生的侵权或权属纠纷等法律责任。本站所有资源不代表本站的观点或立场,基于网友分享,根据中国法律《信息网络传播权保护条例》第二十二与二十三条之规定,若资源存在侵权或相关问题请联系本站客服人员,点此联系我们。关于更多版权及免责申明参见 版权及免责申明

;
报警