摘 要: 在簡要介紹掃雷游戲主界面設計的基礎上,給出了一種基于Qt的掃雷游戲的設計與實現(xiàn)方法,并在Qt4.3.2和Red Hat Enterprise Linux 4操作系統(tǒng)下成功實現(xiàn)。經過實驗測試,結果正確,各項功能達到游戲要求。該實現(xiàn)方法對其他基于Qt的游戲開發(fā)起到拋磚引玉的作用,同時對各專業(yè)人員借助Qt快速開發(fā)具備強大計算功能的專業(yè)應用軟件具有重要的意義。
關鍵詞: Qt;掃雷游戲;事件;信號與槽
最初以訓練鼠標操作為目的而設計的掃雷游戲是一款經久不衰的Windows平臺休閑游戲。盡管Windows操作系統(tǒng)經歷數(shù)次換代,變得越來越龐大、復雜,但這個可愛的小游戲在任何版本的Windows操作系統(tǒng)里卻依然保持著原貌,幾乎每個電腦使用者都接觸過[1]。
Qt是諾基亞開發(fā)的一個跨平臺的C++圖形用戶界面應用程序框架。它為應用程序開發(fā)者提供建立藝術級的圖形用戶界面所需的所有功能。Qt是完全面向對象的,很容易擴展,并且允許真正地組件編程。自1996年,Qt進入商業(yè)領域,它已經成為全世界范圍內數(shù)千種成功的應用程序的基礎。Qt也是流行的Linux桌面環(huán)境KDE 的基礎?;旧?,Qt與X Window上的Motif、Openwin、GTK等圖形界面庫和Windows平臺上的MFC、OWL、VCL、ATL屬同類型,但Qt具有優(yōu)良的跨平臺特性、面向對象、豐富的API、大量的開發(fā)文檔等優(yōu)點[2]。
本課題是在Linux系統(tǒng)下設計并開發(fā)的,設計了一款基于Qt環(huán)境的掃雷游戲,使用了C++語言程序。
1 掃雷游戲主界面的設計
游戲主界面由菜單、游戲區(qū)、按鈕區(qū)、信息顯示區(qū)等幾部分構成,如圖1所示。Qt提供了一套完整的GUI模塊,能夠完成基本的Windows窗體應用程序,因此可以簡單地為掃雷程序制作出界面[3]。圖1主要通過子類化QmainWindow創(chuàng)建掃雷游戲應用程序用戶界面。Qt還提供了定時器,能夠完成游戲的計時。
2 鼠標事件的處理
當點擊鼠標左鍵時,設置ok_flag_為true,說明此方塊進行了翻開操作。如果方塊是地雷,發(fā)出一個explode()信號;如果不是地雷,發(fā)出一個safe()信號,同時顯示數(shù)字。這動作應當在ok_flag_無效且mark_flag_也無效的前提下進行,因為如果ok_flag_有效,則說明此方塊已經翻開了,沒有必要重做;如果mark_flag_有效,則說明玩家標志此方塊有雷,不應該去翻開,否則即為自取滅亡。
點擊鼠標右鍵進行旗幟安插或者移除操作應該在ok_flag_無效的前提下進行,因為對于一個已經翻開的方塊,安插毫無意義。
類的定義如下:
class BlockArea:public Qwidget
{
Q_OBJECT
public:
BlockArea(QWidget* parent=0);
private slots:
void slotSafe();
void slotExplode();
private:
int calculateMines(int x,int y)const; //計算以(x,y)為中心的九宮格內的雷數(shù)
private:
QGridLayout* mainLayout;
int row_;
int column_;
int total_block_number_;
int total_mine_number_;
int ok_block_number_;
};
下面是代碼實現(xiàn)部分:
void
Block::mousePressEvent(QMouseEvent* event)
{
if(event->button()==Qt::LeftButton)
{
if(ok_flag_==false&&mark_flag_==false)
{
ok_flag_=true;
if(mine_flag_==true)
{
setPixmap(QPixmap(":/images/mine.png"));
update();
emit explode();
}else{
setPixmap(QPixmap(":/images/mine_"+QString("%1").
arg
(number_)+".png"));
update();
emit safe();
}
}
}else
if(event->button()==Qt::RightButton){
if(ok_flag_==false){
if(mark_flag_==false){
mark_flag_=true;
setPixmap(QPixmap(":/images/flag.png"));
}else{
mark_flag_=false;
setPixmap(QPixmap(":/images/normal.png"));
}
update();
}
}
}
設計的實現(xiàn)比較簡單,需要說明的是本文模擬的鼠標事件并不是單擊而是按下,這對于掃雷已經足夠了。同時,會發(fā)現(xiàn)兩個信號函數(shù)沒有實現(xiàn),這個工作會由moc自動完成,因此不必在.cpp中實現(xiàn),并且它們永遠不會有返回值(即void)。
3 初始化
3.1 雷區(qū)/非雷區(qū)的產生
下面是BlockArea的構造函數(shù):
BlockArea::BlockArea(QWidget* parent)
:QWidget(parent)
{
//下面5行來初始化BlockArea的信息,自定義行數(shù)為10、列數(shù)為10、總格數(shù)為100、雷數(shù)為10。
row_=10;
column_=10;
total_block_number_=row_*column_;
total_mine_number_=10;
ok_block_number_=0;
//下面6行生成一個具有 total_block_number_個元素的bool類型的隨機序列,用來布雷(即確定哪些方塊放雷,哪些不放),因為QtAlgorithms中沒有包含打亂序列的算法,故采用C++的STL里的random_shuffle。
bool mine_flag[total_block_number_];
for(int i=0;i<total_mine_number_;i++)
mine_flag[i]=true;
for(int i=total_mine_number_;i<total_block_number_;i++)
mine_flag[i]=false;
std::random_shuffle(mine_flag,mine_flag+total_block_number_);
//下面4行將方塊放進布局
mainLayout=new QGridLayout(this);
for(int i=0;i<row_;i++)
for(int j=0;j<column_;j++)
mainLayout->addWidget(new Block(mine_flag[i*column_+j]),i,j);
//下面6行設置每個方塊的周圍雷數(shù),并且將信號safe()與槽slotSafe()相聯(lián),信號explode()與槽slotExplode()相聯(lián)。Block* current_block=static_cast<Block*>(mainLayout->itemAtPosition(i,j)->widget());這句話是獲取布局中位于(i,j)位置處的widget*,將其轉換為Block*,static_cast是C++關鍵字,這里執(zhí)行一個下行轉換動作。
for(int i=0;i<row_;i++){
for(int j=0;j<column_;j++){
Block* current_block=static_cast<Block*>(mainLayout->
itemAtPosition(i,j)->widget());
current_block->setNumber(calculateMines(i,j));
connect(current_block,SIGNAL(safe()),this,SLOT(slotSafe
()));
connect(current_block,SIGNAL(explode()),this,SLOT(slot
Explode()));
}
}
3.2 周邊雷數(shù)的計算
要計算(x,y)位置周邊地雷的個數(shù),首先需計算出一個點,然后判斷此點是否落在BlockArea中,如果落在BlockArea中,再判斷是否是雷,如果是,則計數(shù)器加1。
int BlockArea::calculateMines(int x,int y)const
{
int number=0;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
if( (x-1+i>=0) && (x-1+i<row_) && (y-1+j>=0) && (y-1+j<column_) )
if(static_cast<Block*>(mainLayout->itemAtPosition(x-
1+i,y-1+j)->widget())->isMine())
++number;
return number;
}
該掃雷游戲在Qt4和Red Hat Enterprise Linux 4操作系統(tǒng)上成功實現(xiàn),能在Windows和Linux平臺下運行。除能實現(xiàn)基本的左鍵打開、右鍵標記的掃雷功能以外,還能實現(xiàn)計時、自定義游戲難度、作弊、語音提示等擴展功能。經過試驗測試,界面美觀,結果正確,各項功能達到游戲要求。該實現(xiàn)方法對其他基于Qt的游戲開發(fā)起到了拋磚引玉的作用,其中的鍵盤、鼠標等功能的實現(xiàn)方法可用于其他Qt編程,同時對各專業(yè)人員借助Qt快速開發(fā)具備強大計算機功能的專業(yè)應用軟件具有重要的意義。
參考文獻
[1] 陳子為.基于Matlab GUI掃雷游戲的設計與實現(xiàn)[J]. 現(xiàn)代電子技術,2008(24):85-88.
[2] BLANCHETTE J,SUMMERFIELD M.C++ GUI QT4編程(第二版)[M].北京:電子工業(yè)出版社,2008.
[3] 張建強,張秀梅.掃雷游戲策略初探[J]. 數(shù)學教學,2004(6):32-33.
[4] 成潔, 盧紫毅. Linux窗口程序設計——Qt精彩實例分析[M].北京:清華大學出版社,2008.
[5] 趙大偉,肖周芳,張艷.從掃雷游戲淺談一些算法問題[J]. 科技信息,2008(29):69.
[6] 錢會敏,于守秋.自動掃雷算法淺談[J].科技創(chuàng)新導報,2009(31):250.
[7] 劉艷青,蘇桂蓮.基于Qt4的圖形用戶界面程序的設計與實現(xiàn)[J].現(xiàn)代計算機(專業(yè)版),2009(3):170-172.