本文接着上篇的分享继续讲解。
1、实现格子翻转
鼠标左键点击格子,实现格子翻转——当格子不是地雷(0~8)的时候,格子会显示其周围的地雷数,并将其周围8个没有地雷的格子翻转;若发现某格子周围地雷数为0时,会递归“点击”其周围的8个格子。当格子是地雷(99)的时候,将会显示游戏结束的界面。实现过程如下——
在头文件mainscene.h添加如下代码
#include <QMouseEvent>
#include <QMessageBox>
在类中添加鼠标按键事件函数以及左键递归函数的定义
void mousePressEvent(QMouseEvent *event);
void LeftPress(int x, int y);
void gameOver();
在mainwindow.cpp实现它们
void MainWindow::mousePressEvent(QMouseEvent *event)
{
int x = event->x();
int y = event->y();
if(event->button() == Qt::LeftButton) //判断是鼠标左键按下
{
if(y>24) //格子的y坐标大于24
{
x /= 20;
y = (y-40)/20; //转换成二维格子的坐标
if(grid[x][y] == 99) //碰到地雷了
{
gameOver();
}
else
{
if(grid[x][y]<=8)
{
LeftPress(x, y);
}
}
}
}
}
void MainWindow::LeftPress(int x, int y) //递归点击周围八个格子
{
for(int m=x-1; m<=x 1; m )
{
for(int n=y-1; n<=y 1; n )
{
if(m<0 || n<0 || m>=GRID_X || n>=GRID_Y) //越界
continue;
if(grid[m][n]<10) //未被操作过的格子
{
grid[m][n] = 100;
if(grid[m][n] == 100)
LeftPress(m, n);
}
}
}
int num = 0;
for(int i=0; i<GRID_X; i )
{
for(int j=0; j<GRID_Y; j )
{
if(grid[i][j]>=100 && grid[i][j]<=108)
{
num ;
if(num>=250) //判断是否胜利 300个格子,50个地雷
{
for(int x=0; x<GRID_X; x )
{
for(int y=0; y<GRID_Y; y )
{
if(grid[x][y] == 99)
{
grid[x][y] = 100 55;
}
else
{
grid[x][y] = 100;
}
}
}
nMine = 0;
m_timer.stop();
update();
QMessageBox::information(NULL, "提示", "恭喜,你赢了!!", QMessageBox::Yes, QMessageBox::Yes);
break;
}
}
}
}
update();
}
void MainWindow::gameOver()
{
for(int x=0; x<GRID_X; x )
{
for(int y=0; y<GRID_Y; y )
{
if(grid[x][y] == 99 || grid[x][y] == 145)
{
grid[x][y] = 100; //将地雷和插旗的格子翻开
}
}
}
m_face = 0;
m_timer.stop();
update();
QMessageBox::information(NULL, "提示", "完了,你被炸死了!!", QMessageBox::Yes, QMessageBox::Yes);
}
测试运行,效果如下
2、实现游戏重新开始
鼠标左键点击顶部的表情,便可实现游戏重新开始,实现过程如下——
在mousePressEvent函数里面的if(event->button() == Qt::LeftButton)判断后的代码代码修改如下——
if(event->button() == Qt::LeftButton)
{
if(x>=187 && x<=211 && y>0 && y<=24) //顶部表情的位置
restart(); //重新开始游戏,此函数已在前面实现(上一篇分享)
else if(y>24)
{
x /= 20;
y = (y-40)/20;
if(grid[x][y] == 99)
{
gameOver();
}
else
{
if(grid[x][y]<=8)
{
LeftPress(x, y);
}
}
}
}
测试运行,鼠标左键点击顶部表情,可以看到界面被恢复到最初的状态。
3、插红旗
当我们确定某一格子是地雷时,便可点击鼠标右键插上红旗。当插上50面后,游戏便会结束,并显示扫雷结果,实现过程如下——
在mousePressEvent函数最后添加如下代码
else if(event->button() == Qt::RightButton) //鼠标右键点击,前面跟着的是鼠标左击判断
{
x /= 20;
y = (y-40)/20;
rightPress(x, y);
}
接下来实现rightPress函数
void MainWindow::rightPress(int x, int y)
{
if(grid[x][y] >=0 && grid[x][y] <= 8) //红旗标记未被点击过的格子
{
nMine--; //左上角的地雷数目显示减1
grid[x][y] = 50;
}
else if(grid[x][y] >= 50 && grid[x][y] <= 58) //已被插上红旗的格子(没有雷),再次点击,便会取消红旗
{
nMine ; //左上角的地雷数目显示加1
grid[x][y] -= 50;
}
else if(grid[x][y] == 99) //红旗标记地雷
{
nMine--;
grid[x][y] = 145;
}
else if(grid[x][y] == 145) //取消红旗标记(该格子有雷)
{
if(nMine <50) //地雷最多为50个
{
nMine ;
}
grid[x][y] = 99;
}
if(nMine==0) //已插50面红旗,计算游戏结果
{
int num =0;
for(int i; i<GRID_X; i )
{
for(int j=0; j<GRID_Y; j )
{
if(grid[i][j] == 145) //判断多少地雷被插上红旗
{
num ;
}
grid[i][j] = 100;
}
}
if(num < 50) //没有标记50个地雷,游戏失败
{
m_face -= 1; //伤心表情
m_timer.stop(); //游戏计时定时器停止
update(); //刷新画面
QMessageBox::information(NULL, "提示", "完了,你被炸死了!!", QMessageBox::Yes, QMessageBox::Yes);
}
else //游戏胜利
{
m_timer.stop();
update();
QMessageBox::information(NULL, "提示", "恭喜,你赢了!!", QMessageBox::Yes, QMessageBox::Yes);
}
}
update();
}
测试运行,效果图如下
至此,本游戏的基本功能已基本完成,虽然有一些隐藏的bug,老码私下再修改,便不在这里讲述了。大家可编译自己的代码,好好地体验一下自己敲的游戏。下图是老码玩的一次结果——
若想要源码,可关注并私信老码!!!
Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved