Qt 扫雷小游戏学习分享(完结)

Qt 扫雷小游戏学习分享(完结)

首页模拟经营幽默地雷抖音小游戏更新时间:2024-04-10

本文接着上篇的分享继续讲解。

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