QT学习(六)QT之贪吃蛇

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/anpingbo/article/details/65028219

1、开始界面


对话框设置:设置对话框控件以及标题

1.        GameStart::GameStart(QDialog*parent)

2.            :QDialog(parent)

3.        {

4.         

5.            createWidgets();

6.            setWindowTitle(tr("Snake"));

7.        }

设置3个按钮,连接三种操作:开始游戏,获得历史排名,结束游戏。

8.            beginGame=newQPushButton(tr("start"));

9.            beginGame->setFixedSize(120,30);

10.        beginGame->setFont(font);

11.        connect(beginGame,SIGNAL(clicked()),this,SLOT(startGame()));

12.     

13.        endGame=newQPushButton(tr("end"));

14.        endGame->setFixedSize(120,30);

15.        endGame->setFont(font);

16.        connect(endGame,SIGNAL(clicked()),this,SLOT(close()));

17.     

18.        GameRank=newQPushButton(tr("rank"));

19.        GameRank->setFixedSize(120,30);

20.        GameRank->setFont(font);

21.        connect(GameRank,SIGNAL(clicked()),this,SLOT(loadRank()));

设置游戏等级选项,含有3个等级。

22.        GameLevelCombo=newQComboBox(this);

23.        GameLevelCombo->setFixedSize(120,30);

24.        GameLevelCombo->setFont(font);

25.        GameLevelCombo->addItem(tr("elementary"));

26.        GameLevelCombo->addItem(tr("intermediate"));

27.        GameLevelCombo->addItem(tr("advanced"));

28.        connect(GameLevelCombo,SIGNAL(activated(constQString&)),this,SLOT(getGameLevel()));

设置label和lineedit,用于输入玩家姓名。

29.        NameLabel=newQLabel(tr("player"));

30.        NameLabel->setFixedSize(120,30);

31.        NameLabel->setFont(font);

32.        NameEdit=newQLineEdit;

33.        NameEdit->setFixedSize(200,30);

34.        connect(NameEdit,SIGNAL(textChanged(constQString&)),this,SLOT(setName()));

利用QTextEdit来显示排名信息。

35.        RankText=newQTextEdit(this);

36.        RankText->setStyleSheet("background:argb(248,248,255,0%)");

37.        RankLabel=newQLabel(tr("showrank"));

38.        RankLabel->setFixedSize(100,30);

39.        RankLabel->setFont(font);

布局:

40.        QVBoxLayout*LeftLayout=newQVBoxLayout;

41.        LeftLayout->addWidget(beginGame);

42.        LeftLayout->addWidget(GameRank);

43.        LeftLayout->addWidget(GameLevelCombo);

44.        LeftLayout->addWidget(endGame);

45.     

46.        QVBoxLayout*RightLayout=newQVBoxLayout;

47.        RightLayout->addWidget(RankLabel);

48.        RightLayout->addWidget(RankText);

49.     

50.        QHBoxLayout*TopLayout=newQHBoxLayout;

51.        TopLayout->addWidget(NameLabel);

52.        TopLayout->addWidget(NameEdit);

53.     

54.     

55.        QHBoxLayout*BelowLayout=newQHBoxLayout;

56.        BelowLayout->addLayout(LeftLayout);

57.        BelowLayout->addLayout(RightLayout);

58.     

59.        QVBoxLayout*MainLayout=newQVBoxLayout;

60.        MainLayout->addLayout(TopLayout);

61.        MainLayout->addLayout(BelowLayout);

62.        setLayout(MainLayout);

玩家名字获得、获得排名信息、产生游戏等级的函数实现:

63.    voidGameStart::setName(){

64.        player=NameEdit->text();

65.     

66.    }

67.     

68.     

69.    voidGameStart::getGameLevel(){

70.        QStringLevelString=GameLevelCombo->currentText();

71.        if(LevelString==tr("elementary"))

72.            GameLevel=1;

73.        elseif(LevelString==tr("intermediate"))

74.            GameLevel=2;

75.        elseif(LevelString==tr("advanced"))

76.            GameLevel=3;

77.        else

78.            GameLevel=1;

79.    }

80.     

81.     

82.     

83.     

84.    voidGameStart::loadRank(){

85.        QFilefile("H:/softprogramme/QTMySnaker/snake/Rank.txt");

86.        if(!file.open(QFile::ReadOnly)){

87.            QMessageBox::warning(this,tr("loadrank"),tr("cannotloadrankfile%1").arg(file.fileName()));

88.            return;

89.        }

90.         QTextStreamin(&file);

91.         RankText->setPlainText(in.readAll());

92.     

93.    }

对于游戏界面调出,则要求能够隐藏当前对话框,并且终止当前线程,而可以去执行游戏界面的线程,那么需要在游戏界面重新实现一个执行函数exec()。

94.    voidGameStart::startGame(){

95.     

96.        this->close();

97.     

98.        ImageShowImageShow_M1(player,GameLevel);

99.        ImageShow_M1.exec();

100.   

101.      this->show();

102.      this->exec();

103.   

104.   

105.  }

如果仅仅是游戏界面用show()函数,则游戏界面不会产生控件,仅仅会出现一个主窗口。这就是模式和非模式显示,模式不仅显示界面而且会锁定在这个界面上,从而执行操作。一般QDialog有自己的exec()函数,而QWidget没有,这就需要在QWidget中实现一个。

2、游戏界面

 
 
初始化、定义计时器:

106.  ImageShow::ImageShow(constQStringplayer,constintgame_level):

107.      player(player),game_level(game_level){

108.   

109.   

110.      setWindowTitle(tr("InGame..."));

111.      setFixedSize(ROWS+20,COLUMNS+50);

112.      InitSnake();

113.   

114.      Timer=newQTimer(this);

115.      connect(Timer,SIGNAL(timeout()),this,SLOT(timeout()));

116.      Timer->start(1000/game_level);

117.   

118.  }

119.  voidImageShow::InitSnake(){

120.   

121.      game_score=0;

122.      IsOver=false;

123.      direction=3;//right

124.   

125.      body_x=newvector<char>;

126.      body_y=newvector<char>;

127.   

128.      for(inti=4;i>=1;i--){

129.          body_x->push_back(1);

130.          body_y->push_back(i);//初始化具有1个蛇头和3个蛇身的蛇

131.   

132.      }

133.      food_x=3;

134.      food_y=5;

135.   

136.   

137.  }

138.  voidImageShow::timeout(){

139.   

140.       IsOver=walk();

141.       if(IsOver==true){

142.           Timer->stop();

143.   

144.   

145.           intr=QMessageBox::warning(this,tr("saverank"),tr("gemeisover!\n"

146.                                                               "Doyouwanttosavethegameresults?"),

147.                                       QMessageBox::Yes|QMessageBox::No);

148.            if(r==QMessageBox::Yes)

149.              saveRank();

150.           return;

151.       }

152.   

153.       update();

154.   

155.   

156.  }

根据游戏等级,产生了不同时间限定,时间到就会去执行蛇行走,然后再绘制图像,通过调用了update函数实现绘制事件。

157.  boolImageShow::walk(){

158.   

159.   

160.   

161.      switch(direction){

162.      case1:{

163.          body_x->insert(body_x->begin(),(*body_x)[0]);

164.          body_x->pop_back();

165.          body_y->insert(body_y->begin(),(*body_y)[0]-1);

166.          body_y->pop_back();

167.          break;

168.      }//左移动

169.      case2:{

170.          body_x->insert(body_x->begin(),(*body_x)[0]-1);

171.          body_x->pop_back();

172.          body_y->insert(body_y->begin(),(*body_y)[0]);

173.          body_y->pop_back();

174.          break;

175.      }//向上移动

176.      case3:{

177.          body_x->insert(body_x->begin(),(*body_x)[0]);

178.          body_x->pop_back();

179.          body_y->insert(body_y->begin(),(*body_y)[0]+1);

180.          body_y->pop_back();

181.          break;

182.      }//向右移动

183.      case4:{

184.          body_x->insert(body_x->begin(),(*body_x)[0]+1);

185.          body_x->pop_back();

186.          body_y->insert(body_y->begin(),(*body_y)[0]);

187.          body_y->pop_back();

188.          break;

189.      }//向下移动

190.   

191.      default:;

192.   

193.   

194.      }

195.   

196.   

197.      if(((*body_x)[0]==food_x)&&((*body_y)[0]==food_y)){

198.          body_x->push_back(body_x->back());

199.          body_y->push_back(body_y->back());

200.          game_score++;

201.          produce();

202.      }//吃下食物

203.   

204.      if(((*body_x)[0]==0)||((*body_x)[0]==(ROWS/8))||((*body_y)[0]==0)||((*body_y)[0]==(COLUMNS/8))){

205.   

206.   

207.          returntrue;//蛇撞墙,游戏失败

208.   

209.      }

210.      returnfalse;

211.   

212.   

213.   

214.   

215.  }

216.  voidImageShow::paintEvent(QPaintEvent*){

217.   

218.      QPainter*painter=newQPainter(this);

219.      painter->setRenderHint(QPainter::Antialiasing,true);

220.   

221.      QPenThinPen(palette().foreground(),1);

222.   

223.      QColorLightSlateBlue(132,112,255);

224.      QPenThickPen(LightSlateBlue,4);

225.   

226.      painter->save();

227.      painter->translate(10,40);

228.      painter->setPen(ThickPen);

229.      painter->setBrush(LightSlateBlue);

230.      painter->drawLine(0,0,ROWS,0);

231.      painter->drawLine(0,0,0,COLUMNS);

232.      painter->drawLine(ROWS,0,ROWS,COLUMNS);

233.      painter->drawLine(0,COLUMNS,ROWS,COLUMNS);

234.   

235.      painter->restore();

236.   

237.   

238.      QColorbrown(255,64,64);

239.      QPentextPen(brown,4);

240.      painter->setPen(textPen);

241.      QFontfont=painter->font();

242.      font.setPixelSize(20);

243.      painter->setFont(font);

244.      constQRectrectangle1=QRect(50,2,150,25);

245.      QRectboundingrect;

246.      painter->drawText(rectangle1,0,player,&boundingrect);

247.      constQRectrectangle2=QRect(130,2,150,25);

248.      painter->drawText(rectangle2,0,tr("GameLevel:%1").arg(game_level),&boundingrect);

249.      constQRectrectangle3=QRect(300,2,150,25);

250.      painter->drawText(rectangle3,0,tr("gamescore:%1").arg(game_score),&boundingrect);

251.   

252.      painter->save();

253.      painter->rotate(270);

254.      painter->translate(-40,10);

255.   

256.      QPointFoodPoint(-food_x*8,food_y*8);

257.   

258.      QRadialGradientRadialGradient(-food_x*8,food_y*8,6,-food_x*8,food_y*8);

259.      RadialGradient.setColorAt(0,Qt::green);

260.      RadialGradient.setColorAt(1.0,Qt::darkGreen);

261.      painter->setPen(Qt::NoPen);

262.      painter->setBrush(RadialGradient);

263.      painter->drawEllipse(FoodPoint,6,6);

264.   

265.      QPointSnakeHeadPoint(-8*((*body_x)[0]),8*((*body_y)[0]));

266.      QConicalGradientConicalGradient(-8*((*body_x)[0]),8*((*body_y)[0]),270);

267.      ConicalGradient.setColorAt(0,Qt::red);

268.      ConicalGradient.setColorAt(1,Qt::darkRed);

269.      painter->setPen(ThinPen);

270.      painter->setBrush(ConicalGradient);

271.      painter->drawEllipse(SnakeHeadPoint,5,5);

272.   

273.      QColorLightSalmon(255,160,122);

274.      painter->setPen(ThinPen);

275.      painter->setBrush(LightSalmon);

276.   

277.      for(inti=1;i<body_x->size();i++){

278.          painter->drawRect(-8*((*body_x)[i])-4,8*((*body_y)[i])-4,8,8);

279.   

280.      }

281.   

282.      painter->restore();

283.   

284.   

285.   

286.   

287.  }

对于蛇的移动和控制,通过重载keyPressEvent函数来实现。

288.  voidImageShow::keyPressEvent(QKeyEvent*KeyEvent){

289.   

290.      switch(KeyEvent->key()){

291.      caseQt::Key_Left:{direction=1;break;}

292.      caseQt::Key_Up:{direction=2;break;}

293.      caseQt::Key_Right:{direction=3;break;}

294.      caseQt::Key_Down:{direction=4;break;}

295.      default:break;

296.      }

297.   

298.   

299.       QWidget::keyPressEvent(KeyEvent);

300.   

301.  }

保存游戏结果,并且将原来游戏历史记录根据得分高低排序。

302.  voidImageShow::saveRank(){

303.   

304.      archivearchive_now;

305.      archivearchive_history[10];

306.      intarchive_num=0;

307.   

308.      stringPlayerString=player.toStdString();

309.      strcpy(archive_now.player_temp,PlayerString.c_str());

310.      archive_now.game_leve_temp=game_level;

311.      archive_now.game_score_temp=game_score;

312.   

313.      QFileFile("H:/softprogramme/QTMySnaker/snake/Rank.txt");

314.      if(!File.open(QIODevice::ReadWrite))

315.          return;

316.      QTextStreamInOut(&File);

317.      while(!File.atEnd()){

318.          QStringplayer_string;

319.          InOut>>player_string>>archive_history[archive_num].game_leve_temp

320.                  >>archive_history[archive_num].game_score_temp;

321.          stringPlayerString=player_string.toStdString();

322.          strcpy(archive_history[archive_num].player_temp,PlayerString.c_str());

323.          archive_num++;

324.      }

325.   

326.   

327.   

328.   

329.      for(inti=0;i<=archive_num;i++){

330.   

331.          if(archive_now.game_score_temp>archive_history[i].game_score_temp){

332.            for(intj=archive_num;j>=i+1;j--){

333.   

334.                archive_history[j]=archive_history[j-1];

335.            }

336.              archive_history[i]=archive_now;

337.              break;

338.          }

339.          elseif(i==archive_num){

340.              archive_history[archive_num]=archive_now;

341.          }

342.   

343.      }

344.   

345.      for(inti=0;i<=archive_num;i++){

346.          InOut<<archive_history[i].player_temp<<'\t'

347.              <<archive_history[i].game_leve_temp<<'\t'

348.             <<archive_history[i].game_score_temp<<'\n';

349.      }

350.      File.close();

351.   

352.   

353.  }

接下来就是如何让这个界面能够在开始界面点击开始后可以执行,通过利用一个QEventLoop,可以将执行锁定住,然后为了退出循环,则可以通过关闭事件来调用其退出。

354.  voidImageShow::exec(){

355.   

356.      this->show();

357.      QEventLooploop;

358.      m_loop=&loop;

359.      loop.exec();

360.   

361.   

362.  }

363.   

364.  voidImageShow::closeEvent(QCloseEvent*event){

365.      this->hide();

366.      m_loop->exit();

367.      event->accept();

368.   

369.  }

猜你喜欢

转载自blog.csdn.net/anpingbo/article/details/65028219
今日推荐