沉默了一周我終于復(fù)活了,這回給大家?guī)?lái)的是掃雷产舞。先說(shuō)明一下魂奥,這個(gè)掃雷是我在ubuntu下用c++編寫,qt制作的易猫,如果windows系統(tǒng)需要用qt在windows下編譯生成的.exe文件才能運(yùn)行耻煤。而且用到了一些控件所以有些代碼不能直接復(fù)制使用。如果有需要的朋友可以評(píng)論留郵箱我把整個(gè)項(xiàng)目發(fā)過(guò)去,雖然做的很一般哈蝇。話不多說(shuō)先看幾個(gè)截圖棺妓。
初始界面沒(méi)做好,只能點(diǎn)easy正確炮赦,難度在后面改怜跑。
點(diǎn)開easy后出現(xiàn)了我們游戲界面,8x8 8個(gè)雷吠勘⌒苑遥基本掃雷的操作都有,不解釋了剧防,直接上圖植锉。
左上角的菜單里有選項(xiàng)可以重開,選擇難度峭拘,結(jié)束游戲俊庇。
下面是代碼,分的文件比較多鸡挠。
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include"myscene.h"
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
virtual ~MainWindow();
private slots:
void on_actionExit_triggered();
void on_actionRestart_triggered();
void on_actionHard_triggered();
void on_actionEx_triggered();
void on_actionEasy_triggered();
private:
Ui::MainWindow *ui;
myscene sc;
};
#endif // MAINWINDOW_H
myitem.h//單位的頭文件
#ifndef MYITEM_H
#define MYITEM_H
#include<unistd.h>
#include <QGraphicsPixmapItem>
#include <QCloseEvent>
class myitem : public QGraphicsPixmapItem
{
public:
int aright;//判斷右鍵點(diǎn)擊次數(shù)
int aleft;//判斷左鍵是否點(diǎn)擊過(guò)
myitem(int x,int y);
virtual ~myitem(){}
protected:
int m_x;
int m_y;
void mousePressEvent(QGraphicsSceneMouseEvent *event);
void mousePressEvent2();
void gameover();
};
#endif // MYITEM_H
myscene.h//場(chǎng)景暇赤,地圖
#ifndef MYSCENE_H
#define MYSCENE_H
#include<vector>
#include<myitem.h>
#include <QGraphicsScene>
using namespace std;
typedef vector<myitem*> irow;
typedef vector<irow> imap;
class myscene : public QGraphicsScene
{
Q_OBJECT
public:
explicit myscene(QObject *parent = 0);
virtual ~myscene(){removeAllTheiMx();}
imap iMx;
void removeAllTheiMx();
void resetAllTheiMx();
signals:
public slots:
private:
};
#endif // MYSCENE_H
startgame.h
#ifndef STARTGAME_H
#define STARTGAME_H
#include <QDialog>
#include <QMainWindow>
#include"mainwindow.h"
#include<QDebug>
namespace Ui {
class startgame;
}
class startgame : public QDialog
{
Q_OBJECT
public:
explicit startgame(QWidget *parent = 0);
virtual ~startgame();
private slots:
void on_pusheasy_clicked();
void on_pushnormal_clicked();
private:
Ui::startgame *ui;
};
#endif // STARTGAME_H
tywmodel.h//布雷
#ifndef TYWMODEL_H
#define TYWMODEL_H
#include<vector>
using namespace std;
typedef vector<int> mrow;
typedef vector<mrow> mmap;
class tywmodel
{
public:
tywmodel();
virtual ~tywmodel(){mMx.clear();}
mmap mMx;
void tywclear();//清理地雷用于重置前
void tywreset();//重置地雷
};
#endif // TYWMODEL_H
main.cpp
#include "mainwindow.h"
#include <QApplication>
#include"tywmodel.h"
#include"startgame.h"
int tywwidth=8;//第一次打開時(shí)默認(rèn)簡(jiǎn)單模式的數(shù)據(jù),寬度
int tywlength=8;//高度宵凌,豎著的
int tywtrap=8;//地雷數(shù)量
int win=56;//勝利條件鞋囊,56個(gè)非雷區(qū)域被點(diǎn)開
int nandu=1;//一開始用于記錄難度,后來(lái)直接用做判斷是否踩過(guò)雷
tywmodel m;//一個(gè)雷的二維容器
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
startgame q;//顯示第一個(gè)窗口瞎惫,其實(shí)這個(gè)沒(méi)啥用溜腐,可以注掉這行和下一行
q.exec();//阻塞顯示q,q不關(guān)后面不出來(lái)瓜喇。
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "myscene.h"
#include"myitem.h"
#include "tywmodel.h"
#include <stdlib.h>
#include <time.h>
extern int tywwidth;
extern int tywlength;
extern int win;
extern int tywtrap;
extern int nandu;
extern tywmodel m;
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->graphicsView->setScene(&sc);
sc.setSceneRect(sc.itemsBoundingRect());// 下面3行代碼是自動(dòng)調(diào)整窗口大小自適應(yīng)的
ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_actionExit_triggered()
{
close();
}
void MainWindow::on_actionRestart_triggered()//點(diǎn)擊重新開始
{
win=tywlength*tywlength-tywtrap;
sc.removeAllTheiMx();//先清除之前的東西
m.tywclear();
nandu=1;
sc.resetAllTheiMx();//再賦值
m.tywreset();
}
void MainWindow::on_actionHard_triggered()
{
sc.removeAllTheiMx();
m.tywclear();
tywwidth=16;//數(shù)據(jù)必須在這里改挺益,如果放在前面,清除時(shí)對(duì)應(yīng)不上出錯(cuò)
tywlength=12;
tywtrap=40;
nandu=2;
win=tywwidth*tywlength-tywtrap;//重置勝利條件
sc.resetAllTheiMx();
m.tywreset();
sc.setSceneRect(sc.itemsBoundingRect());// xiamian 3 hang zi dong tiaozheng chuangkou daxiao
ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
}
void MainWindow::on_actionEx_triggered()//ex難度乘寒,后面也是不同難度而已
{
sc.removeAllTheiMx();
m.tywclear();
tywwidth=25;
tywlength=20;
tywtrap=110;
win=tywwidth*tywlength-tywtrap;
nandu=3;
sc.resetAllTheiMx();
m.tywreset();
sc.setSceneRect(sc.itemsBoundingRect());// xiamian 3 hang zi dong tiaozheng chuangkou daxiao
ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
}
void MainWindow::on_actionEasy_triggered()
{
sc.removeAllTheiMx();
m.tywclear();
tywwidth=8;
tywlength=8;
tywtrap=8;
nandu=1;
win=tywwidth*tywlength-tywtrap;
sc.resetAllTheiMx();
m.tywreset();
sc.setSceneRect(sc.itemsBoundingRect());// xiamian 3 hang zi dong tiaozheng chuangkou daxiao
ui->graphicsView->setFixedSize(sc.sceneRect().width() +5,sc.sceneRect().height()+5);
this->resize(ui->graphicsView->width(),ui->graphicsView->height()+ 39);
}
myitem.cpp 單位控制望众,單獨(dú)一個(gè)格子的設(shè)定。
#include "myitem.h"
#include<QPixmap>
#include<QGraphicsSceneMouseEvent>
#include<QMessageBox>
#include<QDebug>
#include "tywmodel.h"
#include"myscene.h"
extern tywmodel m;
extern int tywwidth;
extern int tywlength;
extern int win;
extern int tywtrap;
extern int nandu;
myitem::myitem(int x,int y)
{
QPixmap t("mine2.png");
m_x=x;m_y=y;
aright=0;
aleft=0;
setPixmap(t);
}
//鼠標(biāo)點(diǎn)擊事件
void myitem:: mousePressEvent(QGraphicsSceneMouseEvent *event)
{
((myscene*)scene())->iMx;
if(aleft==1)//判斷是否被左鍵點(diǎn)擊過(guò)
{
return;//是伞辛,返回不屌
}
if(event->button()==Qt::LeftButton)//如果是左鍵點(diǎn)擊
{
mousePressEvent2();//調(diào)用函數(shù)烂翰,單獨(dú)寫出去方便遞歸
}
if(event->button()==Qt::RightButton) // 右鍵點(diǎn)擊
{
if(aright==0)//沒(méi)點(diǎn)擊過(guò)插旗,點(diǎn)擊過(guò)取消小旗
{
QPixmap t("miner.png");
setPixmap(t);
aright=1;
}
else
{
QPixmap t("mine2.png");
setPixmap(t);
aright=0;
}
}
}
void myitem:: mousePressEvent2()
{
int i=0,j=0;
if(aleft==1)
{
return;
}
aleft=1;
switch(m.mMx[m_x][m_y])//判斷是什么并顯示對(duì)應(yīng)圖片
{
case 0:
{
QPixmap t("mine0.png");
setPixmap(t);win--;break;
}
case 1:
{
QPixmap t("1.png");
setPixmap(t);win--;break;
}
case 2:
{
QPixmap t("2.png");win--;
setPixmap(t);break;
}
case 3:
{
QPixmap t("3.png");win--;
setPixmap(t);break;
}
case 4:
{
QPixmap t("4.png");win--;
setPixmap(t);break;
}
case 5:
{
QPixmap t("5.png");win--;
setPixmap(t);break;
}
case 6:
{
QPixmap t("6.png");win--;
setPixmap(t);break;
}
case 7:
{
QPixmap t("7.png");win--;
setPixmap(t);break;
}
case 8:
{
QPixmap t("8.png");win--;
setPixmap(t);break;
}
case -1:
{
QPixmap t("BOOM.png");
setPixmap(t);break;
}
}
if(win==0)//勝利
{
if(nandu != 0)//沒(méi)有踩過(guò)雷
//時(shí)間后來(lái)忘做了蚤氏,加一個(gè)計(jì)時(shí)器就好了甘耿。這里時(shí)間顯示是固定的(假的)
{QMessageBox::Cancel==QMessageBox::information(NULL,"You win","time 00:48",QMessageBox::Cancel|QMessageBox::Ok);}
}
if(m.mMx[m_x][m_y]==0)//如果是0對(duì)周圍自動(dòng)展開
{
int myrow;
int mycolumn;
for(i=-1;i<2;i++)
{
for(j=-1;j<2;j++)
{
if(i==0&&j==0)
continue;
myrow=m_x+i;
mycolumn=m_y+j;
//防止越界進(jìn)行判斷
if(myrow<0||mycolumn<0||myrow>=tywwidth||mycolumn>=tywlength)
continue;
((myscene*)scene())->iMx[myrow][mycolumn]->mousePressEvent2();
}
}
}
if(m.mMx[m_x][m_y]==-1)//踩雷,觸發(fā)游戲結(jié)束函數(shù)
{
win+=100;
if(nandu==0)
return;
gameover();
}
}
void myitem::gameover()//打開所有格子竿滨,提示重新開始
{
int i,j;
nandu=0;
int myrow,mycolumn;
for(i=0;i<tywwidth;i++)
{
for(j=0;j<tywlength;j++)
{
myrow=i;
mycolumn=j;
if(myrow<0||mycolumn<0||myrow>=tywwidth||mycolumn>=tywlength)
continue;
((myscene*)scene())->iMx[myrow][mycolumn]->mousePressEvent2();
}
}
QMessageBox::Cancel==QMessageBox::information(NULL,"You lose","Please restart!",QMessageBox::Cancel|QMessageBox::Ok);
}
myscene.cpp 場(chǎng)景
#include "myscene.h"
#include"myitem.h"
extern int tywwidth;
extern int tywlength;
myscene::myscene(QObject *parent) :
QGraphicsScene(parent)
{
int i,j;//按照給定的全局變量長(zhǎng)寬擺放各個(gè)單位格子
for(i=0;i<tywwidth;i++)
{
iMx.push_back(irow(tywlength));
for(j=0;j<tywlength;j++)
{
iMx[i][j] = new myitem(i,j);
iMx[i][j]->setPos(iMx[i][j]->boundingRect().width()*i, iMx[i][j]->boundingRect().height()*j);
addItem(iMx[i][j]);
}
}
}
void myscene::removeAllTheiMx()//清除所有格子佳恬,才能重來(lái)
{
for(int i=0;i<tywwidth;i++)
{
for(int j=0;j<tywlength;j++)
{
removeItem(iMx[i][j]);
delete iMx[i][j];
}
}
iMx.clear();
}
void myscene::resetAllTheiMx()//重新造捏境,代碼重復(fù)可以整理。
{
int i,j;
for(i=0;i<tywwidth;i++)
{
iMx.push_back(irow(tywlength));
for(j=0;j<tywlength;j++)
{
iMx[i][j] = new myitem(i,j);
iMx[i][j]->setPos(iMx[i][j]->boundingRect().width()*i, iMx[i][j]->boundingRect().height()*j);
addItem(iMx[i][j]);
}
}
}
startgame.cpp 這個(gè)可以無(wú)視掉毁葱,沒(méi)啥大用垫言。
#include "startgame.h"
#include "ui_startgame.h"
#include <QLabel>
#include <QMovie>
#include"tywmodel.h"
extern int tywwidth;
extern int tywlength;
extern int tywtrap;
extern int win;
extern int nandu;
extern tywmodel m;
startgame::startgame(QWidget *parent) :
QDialog(parent),
ui(new Ui::startgame)
{
ui->setupUi(this);
QMovie *movie =new QMovie("fm2.png");
ui->label->setMovie(movie);
movie->start();
}
startgame::~startgame()
{
delete ui;
}
void startgame::on_pusheasy_clicked()
{
close();
}
void startgame::on_pushnormal_clicked()
{
close();
}
tywmodel.cpp 布置地雷(具體哪個(gè)是雷)
#include "tywmodel.h"
#include "myscene.h"
#include"myitem.h"
#include <stdlib.h>
#include <time.h>
extern int tywwidth;
extern int tywlength;
extern int tywtrap;
int suiji(int a)//取1-a的隨機(jī)整數(shù)。這個(gè)可以不用倾剿。
{
int rp;
int i = 0;
while (i < 10){
srand((unsigned)time(NULL));
rp = 1 + rand() % a;
i++;
}
return rp;
}
tywmodel::tywmodel() //先創(chuàng)造二維容器vector
{
for(int i= 0;i<tywwidth;i++)
{
mMx.push_back(mrow(tywlength));
for(int j=0;j<tywlength;j++)
{
mMx[i][j] = 0;
}
}
srand(time(NULL));隨機(jī)
for(int i=0;i<tywtrap;)
{
int x = rand()%tywwidth;
int y = rand()%tywlength;
if(mMx[x][y]!=-1)
{
i++;mMx[x][y]=-1;//如果是雷骏掀,對(duì)周圍格子+1,需判斷是否越界柱告,是否周圍是雷(雷不能+1,-1是雷)
if((x-1>=0)&&(x-1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x-1][y-1]!=-1))mMx[x-1][y-1]++;
if((x-1>=0)&&(x-1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x-1][y]!=-1))mMx[x-1][y]++;
if((x-1>=0)&&(x-1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x-1][y+1]!=-1))mMx[x-1][y+1]++;
if((x>=0)&&(x<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x][y-1]!=-1))mMx[x][y-1]++;
if((x>=0)&&(x<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x][y+1]!=-1))mMx[x][y+1]++;
if((x+1>=0)&&(x+1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x+1][y-1]!=-1))mMx[x+1][y-1]++;
if((x+1>=0)&&(x+1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x+1][y]!=-1))mMx[x+1][y]++;
if((x+1>=0)&&(x+1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x+1][y+1]!=-1))mMx[x+1][y+1]++;
}
}
}
void tywmodel::tywclear()//清除與重置笑陈,為了再次重開使用际度。
{
mMx.clear();
}
void tywmodel::tywreset()
{
for(int i= 0;i<tywwidth;i++)
{
mMx.push_back(mrow(tywlength));
for(int j=0;j<tywlength;j++)
{
mMx[i][j] = 0;
}
}
srand(time(NULL));
for(int i=0;i<tywtrap;)
{
int x = rand()%tywwidth;
int y = rand()%tywlength;
if(mMx[x][y]!=-1)
{
i++;mMx[x][y]=-1;
if((x-1>=0)&&(x-1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x-1][y-1]!=-1))mMx[x-1][y-1]++;
if((x-1>=0)&&(x-1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x-1][y]!=-1))mMx[x-1][y]++;
if((x-1>=0)&&(x-1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x-1][y+1]!=-1))mMx[x-1][y+1]++;
if((x>=0)&&(x<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x][y-1]!=-1))mMx[x][y-1]++;
if((x>=0)&&(x<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x][y+1]!=-1))mMx[x][y+1]++;
if((x+1>=0)&&(x+1<tywwidth)&&(y-1>=0)&&(y-1<tywlength)&&(mMx[x+1][y-1]!=-1))mMx[x+1][y-1]++;
if((x+1>=0)&&(x+1<tywwidth)&&(y>=0)&&(y<tywlength)&&(mMx[x+1][y]!=-1))mMx[x+1][y]++;
if((x+1>=0)&&(x+1<tywwidth)&&(y+1>=0)&&(y+1<tywlength)&&(mMx[x+1][y+1]!=-1))mMx[x+1][y+1]++;
}
}
}
還有兩個(gè)窗口界面,相應(yīng)的控件需自行拖入涵妥,給個(gè)截圖乖菱。
看似簡(jiǎn)簡(jiǎn)單單的游戲還需要這么多東西。這期間遇到了不少bug蓬网,前面的路還有很長(zhǎng)窒所。