急求C语言编译的扫雷小游戏 无敌版(如扫雷),附带源代码和注释。

>> 扫雷游戏
用c语言编写的扫雷游戏,这是程序的源代码
用c语言编写的扫雷游戏,这是程序的源代码
所属分类:
下载地址:
saolei.rar文件大小:1.17 kB
分享有礼! 》
请点击右侧的分享按钮,把本代码分享到各社交媒体。
通过您的分享链接访问Codeforge,每来2个新的IP,您将获得0.1 积分的奖励。
通过您的分享链接,每成功注册一个用户,该用户在Codeforge上所获得的每1个积分,您都将获得0.2 积分的分成奖励。
用c语言编写的扫雷游戏,这是程序的源代码-Minesweeper game with the c language de-mining game, which is the source code
Sponsored links
源码文件列表
温馨提示: 点击源码文件名可预览文件内容哦 ^_^
4.56 kB13-12-09 22:04
(提交有效评论获得积分)
评论内容不能少于15个字,不要超出160个字。
评价成功,多谢!
下载saolei.rar
CodeForge积分(原CF币)全新升级,功能更强大,使用更便捷,不仅可以用来下载海量源代码马上还可兑换精美小礼品了
您的积分不足,优惠套餐快速获取 30 积分
10积分 / ¥100
30积分 / ¥200原价 ¥300 元
100积分 / ¥500原价 ¥1000 元
订单支付完成后,积分将自动加入到您的账号。以下是优惠期的人民币价格,优惠期过后将恢复美元价格。
支付宝支付宝付款
微信钱包微信付款
更多付款方式:、
您本次下载所消耗的积分将转交上传作者。
同一源码,30天内重复下载,只扣除一次积分。
鲁ICP备号-3 runtime:Elapsed:ms - init:0.1;find:18.5;t:12.8;tags:0.3;related:152.3;comment:0.1; 27.69
登录 CodeForge
还没有CodeForge账号?
Switch to the English version?
^_^"呃 ...
Sorry!这位大神很神秘,未开通博客呢,请浏览一下其他的吧Qt小游戏开发:扫雷
继续把Qt小游戏写一下~
整体的代码结构,游戏逻辑类和游戏界面类分离,采用MVC的思想。
1 定义游戏数据结构
游戏地图实际上是由一个个方块组成的二维矩阵,每个方块存储数字、雷或者标记的情况,另外还要定义一些游戏的运行状态枚举
// ---------------- 全局定义变量 ---------------- //
// 方块的状态,未挖掘,翻开,标记,雷出现,错误标记
enum BlockState
WRONG_BOMB
// 雷方块类
struct MineBlock
BlockState curS // 当前状态
int valueF // 数值,0到8, -1表示雷
// 游戏状态,分为未完,有错误标记、输、赢四种
enum GameState
// 游戏难度,有低级、中级、高级
enum GameLevel
// 游戏默认参数
const int kRow = 15;
const int kCol = 20;
const int kMineCount = 50;
const int kTime = 0;
// ----------------------------------------------- //
2 创建游戏逻辑类
一个游戏逻辑类包括地图,游戏状态等,以及一些控制函数
class GameModel
GameModel();
virtual ~GameModel();
void digMine(int m, int n); //挖雷, m是行, n是列
void markMine(int m, int n); // 标记雷
void createGame(int row = kRow, int col = kCol, int mineCount = kMineCount, GameLevel level = MEDIUM); // 初始化游戏
void restartGame();
// 按当前参数重新开始游戏
void checkGame(); // 检查游戏输赢
std::vector<std::vector& gameM // 游戏地图
int mR // 地图行数
int mC // 地图列数
int totalMineN // 雷数
int curMineN
// 当前雷数(仅用于显示)
int timerS // 计时(秒)
GameState gameS // 当前游戏状态
GameLevel gameL // 当前游戏难度
};</std::vector
3 游戏逻辑
(1)游戏初始化
void GameModel::createGame(int row, int col, int mineCount, GameLevel level)
// 先清空已经有的游戏地图
gameMap.clear();
// 设置成员变量
totalMineNumber = mineC
curMineNumber = mineC
gameState = PLAYING;
gameLevel =
timerSeconds = 0;
// 初始化雷方块
for(int i = 0; i & mR i++)
//添加每行的block
std::vector lineB
for(int j = 0; j & mC j++)
MineBlock mineB
mineBlock.curState = UN_DIG; // 默认都是未挖掘
mineBlock.valueFlag = 0; // 默认都是0
lineBlocks.push_back(mineBlock);
gameMap.push_back(lineBlocks);
// 随机布雷
srand((unsigned int)time(0));
int k = totalMineN
while(k & 0)
// 埋雷并防止重叠
int pRow = rand() % mR
int pCol = rand() % mC
if(gameMap[pRow][pCol].valueFlag != -1)
gameMap[pRow][pCol].valueFlag = -1;
k--; // 如果原来就有雷重新循环
// 计算雷周围的方块数字
for(int i = 0; i & mR i++)
for(int j = 0; j & mC j++)
// 周围八个方块(排除自己,在地图范围内)的数字根据雷的数目叠加
// y为行偏移量,x为列偏移量
// 前提条件是本方块不是雷
if(gameMap[i][j].valueFlag != -1)
for(int y = -1; y &= 1; y++)
for(int x = -1; x &= 1; x++)
if(i + y &= 0
&& i + y & mRow
&& j + x &= 0
&& j + x & mCol
&& gameMap[i + y][j + x].valueFlag == -1
&& !(x == 0 && y == 0))
// 方块数字加1
gameMap[i][j].valueFlag++;
随机布雷计算方块数字
void GameModel::digMine(int m, int n)
// 正常方块且没有被翻开过,标记为已挖
if(gameMap[m][n].valueFlag & 0
&& gameMap[m][n].curState == UN_DIG)
gameMap[m][n].curState = DIGGED;
// 遇到空白块(数字0)就递归挖雷,如果踩雷就爆掉,游戏结束
if(gameMap[m][n].valueFlag == 0
&& gameMap[m][n].curState == UN_DIG)
gameMap[m][n].curState = DIGGED;
for(int y = -1; y &= 1; y++)
for(int x = -1; x &= 1; x++)
if(m + y &= 0
&& m + y & mRow
&& n + x &= 0
&& n + x & mCol
&& !(x == 0 && y == 0))
digMine(m + y, n + x);
if(gameMap[m][n].valueFlag == -1)
gameState = OVER;
gameMap[m][n].curState = BOMB;
// 检查游戏输赢,并作调整
checkGame();
递归挖雷挖到雷游戏结束
(3)标记方块
void GameModel::markMine(int m, int n)
// 如果标记错了,就记为错误标记,在ui层游戏结束时做绘制区分
// 注意这里有个逻辑,如果一个方块标记两次会回到未挖掘的状态
if(gameMap[m][n].curState == UN_DIG)
if(gameMap[m][n].valueFlag == -1)
gameMap[m][n].curState = MARKED;
gameState = FAULT;
gameMap[m][n].curState = WRONG_BOMB;
curMineNumber--; // 挖对了雷就减1
else if(gameMap[m][n].curState == MARKED || gameMap[m][n].curState == WRONG_BOMB)
gameMap[m][n].curState = UN_DIG;
gameState = PLAYING;
curMineNumber++; // 雷数加回来
// 检查游戏输赢,并作调整
checkGame();
标记雷,并且当前显示雷数跟着减标记错误了会把游戏状态设置成FAULT如果挖完了且挖对了游戏就赢了
(4)检查游戏状态
void GameModel::checkGame()
// 游戏结束,显示所有雷
if(gameState == OVER)
// 输了就显示所有的雷以及标错的雷
for(int i = 0; i & mR i++)
for(int j = 0; j & mC j++)
if(gameMap[i][j].valueFlag == -1)
gameMap[i][j].curState = BOMB;
// 如果雷排完了,且所有方块都挖出或者标记
if(gameState != FAULT)
for(int i = 0; i & mR i++)
for(int j = 0; j & mC j++)
if(gameMap[i][j].curState == UN_DIG)
gameState = PLAYING;
// 否则既没有错误标记游戏状态又不是输或者进行中,游戏就是赢了
gameState = WIN;
这个函数每次在挖雷和标记雷时都要调用每次检查都要更新游戏状态
4 游戏界面类
游戏界面其实就是在window里面不断重绘,并且设置鼠标点击监听
class MainGameWindow : public QMainWindow
explicit MainGameWindow(QWidget *parent = 0);
~MainGameWindow();
protected:
virtual void paintEvent(QPaintEvent *event);
// 界面重绘
virtual void mousePressEvent(QMouseEvent *event);
// 鼠标控制
Ui::MainGameWindow *
GameModel * // 游戏
QLabel *timeL // 计时数字
void handleGameState(GameModel *game); // 处理游戏状态
private slots:
void onStartGameClicked();
// 开始游戏
void onLevelChooseClicked();
// 选择游戏难度
void onQuitClicked();
// 退出游戏
void updateTimer();
5 游戏界面控制
(1)启动时设置一些元素并初始化游戏模型
MainGameWindow::MainGameWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainGameWindow)
ui-&setupUi(this);
// 创建计时数字标签
timeLabel = new QLabel(this);
// 关联信号槽
connect(ui-&actionStart, SIGNAL(triggered(bool)), this, SLOT(onStartGameClicked()));
connect(ui-&actionBasic, SIGNAL(triggered(bool)), this, SLOT(onLevelChooseClicked()));
connect(ui-&actionMedium, SIGNAL(triggered(bool)), this, SLOT(onLevelChooseClicked()));
connect(ui-&actionHard, SIGNAL(triggered(bool)), this, SLOT(onLevelChooseClicked()));
connect(ui-&actionQuit, SIGNAL(triggered(bool)), this, SLOT(onQuitClicked()));
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(updateTimer()));
// 创建游戏初始化游戏,设置好参数,默认是中级,启动计时器
// 定义窗口大小(必须放在游戏创建之后后面,该函数设置后大小不可变动,窗口强制重绘)
game = new GameM
game-&createGame();
setFixedSize(game-&mCol * blockSize + offsetX * 2, game-&mRow * blockSize + offsetY * 2 + spaceY);
timeLabel-&setGeometry(game-&mCol * blockSize + offsetX * 2 - 80, spaceY / 2, 80, 20);
timeLabel-&setText(&Time: & + QString::number(game-&timerSeconds) + & s&);
timer-&start(1000);
这里面关联了一些button的的信号槽,初始化了界面和游戏模型,设置一个定时器用于游戏计时。
(2)窗口重绘
void MainGameWindow::paintEvent(QPaintEvent *event)
QPainter painter(this);
QPixmap bmpBlocks(&:/res/blocks.bmp&);
QPixmap bmpFaces(&:/res/faces.bmp&);
QPixmap bmpFrame(&:/res/frame.bmp&);
QPixmap bmpNumber(&:/res/timenumber.bmp&);
// 绘制笑脸
switch(game-&gameState)
case OVER:
painter.drawPixmap((game-&mCol * blockSize + offsetX * 2) / 2 - 12, spaceY / 2, bmpFaces, 0 * 24, 0, 24, 24); // 24是笑脸的边长,锚点在左上,因为工具栏占了些,所以看起来不再中间
case PLAYING:
painter.drawPixmap((game-&mCol * blockSize + offsetX * 2) / 2 - 12, spaceY / 2, bmpFaces, 1 * 24, 0, 24, 24);
painter.drawPixmap((game-&mCol * blockSize + offsetX * 2) / 2 - 12, spaceY / 2, bmpFaces, 2 * 24, 0, 24, 24);
painter.drawPixmap((game-&mCol * blockSize + offsetX * 2) / 2 - 12, spaceY / 2, bmpFaces, 1 * 24, 0, 24, 24);
// 绘制剩余雷数
int n = game-&curMineN
int posX = (game-&mCol * blockSize + offsetX * 2) / 2 - 50; // 最后一位数字的横坐标
if(n &= 0) // 如果雷数为0或者减到0以下,单独绘制
painter.drawPixmap(posX, spaceY / 2, bmpNumber, n * 20, 0, 20, 28); // 20是数字的宽,28是高
while(n & 0) // 如果是多位数
painter.drawPixmap(posX - 20, spaceY / 2, bmpNumber, n % 10 * 20, 0, 20, 28); // 每次从后面绘制一位
posX -= 20;
// 绘制雷区
for(int i = 0; i & game-&mR i++)
for(int j = 0; j & game-&mC j++)
switch(game-&gameMap[i][j].curState)
// 根据不同的方块状态绘制,算出在bmp中的偏移量
case UN_DIG:
painter.drawPixmap(j * blockSize + offsetX, i * blockSize + offsetY + spaceY , bmpBlocks, blockSize * 10, 0, blockSize, blockSize);
case DIGGED:
painter.drawPixmap(j * blockSize + offsetX, i * blockSize + offsetY + spaceY, bmpBlocks, blockSize * game-&gameMap[i][j].valueFlag, 0, blockSize, blockSize);
case MARKED:
painter.drawPixmap(j * blockSize + offsetX, i * blockSize + offsetY + spaceY, bmpBlocks, blockSize * 11, 0, blockSize, blockSize);
case BOMB:
painter.drawPixmap(j * blockSize + offsetX, i * blockSize + offsetY + spaceY, bmpBlocks, blockSize * 9, 0, blockSize, blockSize);
case WRONG_BOMB:
if(game-&gameState == PLAYING || game-&gameState == FAULT)
// 如果还在游戏中就显示旗子
painter.drawPixmap(j * blockSize + offsetX, i * blockSize + offsetY + spaceY, bmpBlocks, blockSize * 11, 0, blockSize, blockSize);
else if(game-&gameState == OVER)
// 如果游戏已经结束,就显示标错了
painter.drawPixmap(j * blockSize + offsetX, i * blockSize + offsetY + spaceY, bmpBlocks, blockSize * 12, 0, blockSize, blockSize);
// 处理游戏状态
handleGameState(game);
根据游戏的状态和游戏模型中各方块的情况、计时器的情况,进行针对性的重绘,实现游戏界面更新。
这里面用到了位图偏移量绘制。
(3)鼠标控制
void MainGameWindow::mousePressEvent(QMouseEvent *event)
if(event-&y() & spaceY + offsetY)
int x = event-&x();
int y = event-&y();
// 此时判断是否点击笑脸
if(x &= (game-&mCol * blockSize + offsetX * 2) / 2 - 12
&& x &= (game-&mCol * blockSize + offsetX * 2) / 2 + 12
&& y &= spaceY / 2
&& y &= spaceY / 2 + 24)
game-&restartGame(); // 重玩
timer-&start(1000);
timeLabel-&setText(&Time: & + QString::number(game-&timerSeconds) + & s&); // 每次重玩都将计时显示为0s
else if(game-&gameState != OVER && game-&gameState != WIN)
// 游戏没输或没赢才接受点击
// 此时判断点击的是哪个方块
// 获得点击坐标
int px = event-&x() - offsetX;
int py = event-&y() - offsetY - spaceY;
// 换算成方格索引
int row = py / blockS
int col = px / blockS
// 根据不同情况响应
switch(event-&button())
case Qt::LeftButton:
game-&digMine(row, col);
update(); // 每次点击都要重绘
case Qt::RightButton:
game-&markMine(row, col);
做了简单的碰撞检测,左键挖雷,右键标记。
(4)选择难度
void MainGameWindow::onLevelChooseClicked()
QAction *actionSender = (QAction *)dynamic_cast(sender());
if(actionSender == ui-&actionBasic)
qDebug() && &basic&;
// 先设置游戏模型
game-&createGame(8, 10, 15, BASIC);
else if(actionSender == ui-&actionMedium)
qDebug() && &medium&;
game-&createGame(15, 20, 50, MEDIUM);
else if(actionSender == ui-&actionHard)
qDebug() && &hard&;
game-&createGame(20, 30, 100, HARD);
// 重新计时
timer-&start(1000);
// 再刷新UI,窗口大小改变会强制重绘
timeLabel-&setText(&Time: & + QString::number(game-&timerSeconds) + & s&);
timeLabel-&setGeometry(game-&mCol * blockSize + offsetX * 2 - 80, spaceY / 2, 80, 20);
setFixedSize(game-&mCol * blockSize + offsetX * 2, game-&mRow * blockSize + offsetY * 2 + spaceY);
选择难度里面可以根据信号槽中的信号类型,设置不同的难度,直接对game设置参数,方便快捷。
void MainGameWindow::updateTimer()
// 计时器计时
game-&timerSeconds++;
timeLabel-&setText(&Time: & + QString::number(game-&timerSeconds) + & s&);
qDebug() && game-&timerS
游戏结束可以看到计时成绩网站已改版,请使用新地址访问:
saolei 用C语言实现扫雷游戏,代码简单,并带有注释。 Game Program
238万源代码下载-
&文件名称: saolei
& & & & &&]
&&所属分类:
&&开发工具: C-C++
&&文件大小: 230 KB
&&上传时间:
&&下载次数: 0
&&提 供 者:
&详细说明:用C语言实现扫雷游戏,代码简单,并带有注释。-Implemented in C language minesweeping game, simple code, with comments.
文件列表(点击判断是否您需要的文件,如果是垃圾请在下面评价投诉):
&&扫雷&&....\Debug&&....\.....\mian.obj&&....\.....\vc60.idb&&....\.....\vc60.pdb&&....\.....\扫雷.exe&&....\.....\扫雷.ilk&&....\.....\扫雷.pch&&....\.....\扫雷.pdb&&....\mian.cpp&&....\扫雷.dsp&&....\扫雷.dsw&&....\扫雷.ncb&&....\扫雷.opt&&....\扫雷.plg
&输入关键字,在本站238万海量源码库中尽情搜索:当前位置:
文件名称:c-language-Minesweeper-code
所属分类:
资源属性:
Windows,,,WORD
上传时间:
文件大小:
浏览/下载:
160次 / 0次
提 供 者:
相关连接:
下载说明:
别用迅雷下载,失败请重下,重下不扣分!
c语言小游戏代码扫雷代码
用c语言编写的扫雷游戏代码以供同学们的学习与交流之用
-c language game code Minesweeper code
(系统自动生成,下载前可以参看下载内容)下载文件列表
c语言小游戏代码-扫雷代码.doc
暂无评论内容.
*快速评论:
和说明不符
不是源码或资料
纯粹是垃圾
*内  容:
*验 证 码:
搜珍网是交换下载平台,下载的内容请自行研究使用或咨询上传人.
资源属性分别代表:系统平台,开发平台,开发语言,文件格式四部分.
本站已设置防盗链,请勿用迅雷、QQ旋风等多线程下载软件下载资源,下载后用进行解压.
如果您发现此软件无法下载,请稍后再次尝试;或者.
本站提供下载的内容为网上收集或会员上传提供,若无意中侵犯了您的版权,.
如下载前有疑问,可以通过点击"提供者"的名字,查看对方的联系方式,联系对方咨询.
如下载后发现下载的内容跟说明不相乎,可以联系本站的客服,经确认可以退回消费了的积分.
联系我们网站
·电话:(0)
All Rights Reserved.}

我要回帖

更多关于 经典扫雷小游戏 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信