日期:2014-05-17 浏览次数:20846 次
最近花了个把星期左右把Windows xp的扫雷实现了一下,在这里写下设计思路与大概实现。这个是下载地址,
欢迎大家下载试玩,http://kuai.xunlei.com/d/LTACJFIRFVKB。其实其中还有有个隐藏的bug。看看你能不能发现,哈哈。源代码我以后会补上,暂时不能上传,请各位谅解!
既然是游戏的话,只有会玩了才有可能知道是怎么实现的!数字n代表以它为中心3*3的方格范围内
有n个雷。主要就是根据这个来判断是否有雷。然后是空格子的话就代表它周围没有雷。然后就是鼠标的各种事件了。下面这个是一个列表。
之后主要是按照这个写的,也有些改动,但是不大。
1.左键按下
1.1.右键按下
3*3方格变形
1.2.右键未被按下
当前方格变形
LBtnDown = TRUE;
2.右键按下
2.1.左键按下
3*3方格变形
2.1.左键未被按下
当前方格变形
RBtnDown = TRUE;
3.左键弹起
3.1.之前左右键按下
3.1.1.该数字的雷被找到
调用展开算法 右键弹起失效
RBtnDown = FALSE;
3.1.2.没找到
3*3方格复原 右键弹起失效
标记标多了也会调用展开算法
RBtnDown = FALSE;
3.2.之前左键按下
当前位置方格调用展开算法
LBtnDown = FALSE;
4.右键弹起
4.1.之前左右键按下
4.1.1.该数字的雷被找到
调用展开算法 左键弹起失效
LBtnDown = FALSE;
4.1.2.没找到
3*3方格复原 左键弹起失效
标记标多了也会调用展开算法
LBtnDown = FALSE;
RBtnDown = FALSE;
5.鼠标滚动
5.1.左键按下
5.1.1.右键按下
3*3方格移动
5.1.2.右键弹起
一个方格移动
这个是雷区初始化的代码。主要就是先写边界,然后把前面n个元素改成雷,最后随机分布。
void CMineView::SetMine()
{
int i, j, currenti, currentj, i1, i2, j1, j2;
currenti = m_mine.minenumber % m_mine.width;
if (currenti == 0) {//刚好除尽
currenti = m_mine.minenumber/m_mine.width;
currentj = m_mine.width;
for (i = 1; i <= currenti; i++) {
for (j = 1; j <= m_mine.width; j++) {
m_mineMax[i][j] = -1;//初始化雷区
}
}
currenti++;
currentj = 1;
} else {//除不尽
currenti = (m_mine.minenumber/m_mine.width)+1;
currentj = m_mine.minenumber%m_mine.width;
for (i = 1; i < currenti; i++) {
for (j = 1; j <= m_mine.width; j++) {
m_mineMax[i][j] = -1;//初始化雷区
}
}
for (j = 1; j <= currentj; j++) {
m_mineMax[currenti][j] = -1;//初始化雷区
}
currentj++;
}
//初始化不是雷区的区域
for (j = currentj; j <= m_mine.width; j++) {
m_mineMax[currenti][j] = 0;
}
++currenti;
for (i = currenti; i <= m_mine.height; i++) {
for (j = 1; j <= m_mine.width; j++) {
m_mineMax[i][j] = 0;
}
}
srand(time(NULL));
for (i = m_mine.height * m_mine.width - 1; i >= 2; --i) {//布雷
currenti = rand() % i;//产生的随机位置
if (i%m_mine.width == 0) {//除的尽
i1 = i / m_mine.width;
j1 = m_mine.width;
} else {//除不尽
i1 = (i / m_mine.width) + 1;
j1 = i % m_mine.width;
}
if (currenti == 0) {//就是第一个
i2 = 1;
j2 = 1;
} else {
if (currenti%m_mine.width == 0) {//除的尽
i2 = currenti / m_mine.width;
j2 = m_mine.width;
} else {//除不尽
i2 = (currenti / m_mine.width) + 1;
j2 = currenti % m_mine.width;
}
}
Swap(&m_mineMax[i1][j1], &m_mineMax[i2][j2]);
}
}
展开算法的主要思路就是用一个大的数组(包括虚拟边界)保存该算法对每一个方格的访问次数的计数。
==1就不在访问,分8个方向递归探测。碰到雷或者边界就返回。具体代码如下:
//8个方向探测
void CMineView::StretchMine(int i, int j)
{
if (m_mineVisit[i][j] == 1) {//走过的路不