QT之贪吃蛇

1、开始界面

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

  1. GameStart::GameStart(QDialog *parent)
  2. : QDialog(parent)
  3. {
  4. createWidgets();
  5. setWindowTitle(tr("Snake"));
  6. }

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

  1. beginGame=new QPushButton(tr("start"));
  2. beginGame->setFixedSize(120, 30);
  3. beginGame->setFont(font);
  4. connect(beginGame, SIGNAL(clicked()), this, SLOT(startGame()));
  5. endGame=new QPushButton(tr("end"));
  6. endGame->setFixedSize(120, 30);
  7. endGame->setFont(font);
  8. connect(endGame, SIGNAL(clicked()), this, SLOT(close()));
  9. GameRank=new QPushButton(tr("rank"));
  10. GameRank->setFixedSize(120, 30);
  11. GameRank->setFont(font);
  12. connect(GameRank, SIGNAL(clicked()), this, SLOT(loadRank()));

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

  1. GameLevelCombo=new QComboBox(this);
  2. GameLevelCombo->setFixedSize(120, 30);
  3. GameLevelCombo->setFont(font);
  4. GameLevelCombo->addItem(tr("elementary"));
  5. GameLevelCombo->addItem(tr("intermediate"));
  6. GameLevelCombo->addItem(tr("advanced"));
  7. connect(GameLevelCombo, SIGNAL(activated(const QString &)), this, SLOT(getGameLevel()));

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

  1. NameLabel=new QLabel(tr("player"));
  2. NameLabel->setFixedSize(120, 30);
  3. NameLabel->setFont(font);
  4. NameEdit=new QLineEdit;
  5. NameEdit->setFixedSize(200, 30);
  6. connect(NameEdit, SIGNAL(textChanged(const QString &)), this, SLOT(setName()));

利用QTextEdit来显示排名信息。

  1. RankText=new QTextEdit(this);
  2. RankText->setStyleSheet("background:argb(248, 248, 255, 0%)");
  3. RankLabel=new QLabel(tr("show rank"));
  4. RankLabel->setFixedSize(100, 30);
  5. RankLabel->setFont(font);

布局:

  1. QVBoxLayout *LeftLayout=new QVBoxLayout;
  2. LeftLayout->addWidget(beginGame);
  3. LeftLayout->addWidget(GameRank);
  4. LeftLayout->addWidget(GameLevelCombo);
  5. LeftLayout->addWidget(endGame);
  6. QVBoxLayout *RightLayout=new QVBoxLayout;
  7. RightLayout->addWidget(RankLabel);
  8. RightLayout->addWidget(RankText);
  9. QHBoxLayout *TopLayout=new QHBoxLayout;
  10. TopLayout->addWidget(NameLabel);
  11. TopLayout->addWidget(NameEdit);
  12. QHBoxLayout *BelowLayout=new QHBoxLayout;
  13. BelowLayout->addLayout(LeftLayout);
  14. BelowLayout->addLayout(RightLayout);
  15. QVBoxLayout *MainLayout=new QVBoxLayout;
  16. MainLayout->addLayout(TopLayout);
  17. MainLayout->addLayout(BelowLayout);
  18. setLayout(MainLayout);

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

  1. void GameStart::setName(){
  2. player=NameEdit->text();
  3. }
  4. void GameStart::getGameLevel(){
  5. QString LevelString=GameLevelCombo->currentText();
  6. if(LevelString==tr("elementary"))
  7. GameLevel=1;
  8. else if(LevelString==tr("intermediate"))
  9. GameLevel=2;
  10. else if(LevelString==tr("advanced"))
  11. GameLevel=3;
  12. else
  13. GameLevel=1;
  14. }
  15. void GameStart::loadRank(){
  16. QFile file("H:/soft programme/QTMySnaker/snake/Rank.txt");
  17. if(!file.open(QFile::ReadOnly)){
  18. QMessageBox::warning(this, tr("load rank"), tr("cannot load rank file %1").arg(file.fileName()));
  19. return;
  20. }
  21. QTextStream in(&file);
  22. RankText->setPlainText(in.readAll());
  23. }

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

  1. void GameStart::startGame(){
  2. this->close();
  3. ImageShow ImageShow_M1(player,GameLevel);
  4. ImageShow_M1.exec();
  5. this->show();
  6. this->exec();
  7. }

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

2、游戏界面

初始化、定义计时器:

  1. ImageShow::ImageShow(const QString player, const int game_level):
  2. player(player), game_level(game_level){
  3. setWindowTitle(tr("In Game..."));
  4. setFixedSize(ROWS+20, COLUMNS+50);
  5. InitSnake();
  6. Timer=new QTimer(this);
  7. connect(Timer, SIGNAL(timeout()),this, SLOT(timeout()));
  8. Timer->start(1000/game_level);
  9. }
  1. void ImageShow::InitSnake(){
  2. game_score = 0;
  3. IsOver=false;
  4. direction=3;//right
  5. body_x = new vector<char>;
  6. body_y = new vector<char>;
  7. for (int i = 4; i >= 1; i--) {
  8. body_x->push_back(1);
  9. body_y->push_back(i);//初始化具有1个蛇头和3个蛇身的蛇
  10. }
  11. food_x = 3;
  12. food_y = 5;
  13. }
  1. void ImageShow::timeout(){
  2. IsOver=walk();
  3. if(IsOver == true){
  4. Timer->stop();
  5. int r=QMessageBox::warning(this,tr("save rank"), tr("geme is over!\n"
  6. "Do you want to save the game results?"),
  7. QMessageBox::Yes|QMessageBox::No);
  8. if(r==QMessageBox::Yes)
  9. saveRank();
  10. return;
  11. }
  12. update();
  13. }

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

  1. bool ImageShow::walk() {
  2. switch (direction) {
  3. case 1: {
  4. body_x->insert(body_x->begin(), (*body_x)[0]);
  5. body_x->pop_back();
  6. body_y->insert(body_y->begin(), (*body_y)[0] - 1);
  7. body_y->pop_back();
  8. break;
  9. }//左移动
  10. case 2: {
  11. body_x->insert(body_x->begin(), (*body_x)[0] - 1);
  12. body_x->pop_back();
  13. body_y->insert(body_y->begin(), (*body_y)[0]);
  14. body_y->pop_back();
  15. break;
  16. }//向上移动
  17. case 3: {
  18. body_x->insert(body_x->begin(), (*body_x)[0]);
  19. body_x->pop_back();
  20. body_y->insert(body_y->begin(), (*body_y)[0] + 1);
  21. body_y->pop_back();
  22. break;
  23. }//向右移动
  24. case 4: {
  25. body_x->insert(body_x->begin(), (*body_x)[0] + 1);
  26. body_x->pop_back();
  27. body_y->insert(body_y->begin(), (*body_y)[0]);
  28. body_y->pop_back();
  29. break;
  30. }//向下移动
  31. default: ;
  32. }
  33. if (((*body_x)[0] == food_x) && ((*body_y)[0] == food_y)) {
  34. body_x->push_back(body_x->back());
  35. body_y->push_back(body_y->back());
  36. game_score++;
  37. produce();
  38. }//吃下食物
  39. if (((*body_x)[0] == 0) || ((*body_x)[0] == (ROWS/8)) || ((*body_y)[0] == 0) || ((*body_y)[0] == (COLUMNS/8))) {
  40. return true;//蛇撞墙,游戏失败
  41. }
  42. return false;
  43. }
  1. void ImageShow::paintEvent(QPaintEvent *){
  2. QPainter *painter = new QPainter(this);
  3. painter->setRenderHint(QPainter::Antialiasing, true);
  4. QPen ThinPen(palette().foreground(), 1);
  5. QColor LightSlateBlue(132, 112, 255);
  6. QPen ThickPen(LightSlateBlue, 4);
  7. painter->save();
  8. painter->translate(10, 40);
  9. painter->setPen(ThickPen);
  10. painter->setBrush(LightSlateBlue);
  11. painter->drawLine(0, 0, ROWS, 0);
  12. painter->drawLine(0, 0, 0, COLUMNS);
  13. painter->drawLine(ROWS, 0, ROWS, COLUMNS);
  14. painter->drawLine(0, COLUMNS, ROWS, COLUMNS);
  15. painter->restore();
  16. QColor brown(255,64,64);
  17. QPen textPen(brown, 4);
  18. painter->setPen(textPen);
  19. QFont font=painter->font();
  20. font.setPixelSize(20);
  21. painter->setFont(font);
  22. const QRect rectangle1=QRect(50, 2, 150, 25);
  23. QRect boundingrect;
  24. painter->drawText(rectangle1, 0, player, &boundingrect);
  25. const QRect rectangle2=QRect(130, 2, 150, 25);
  26. painter->drawText(rectangle2, 0, tr("Game Level: %1").arg(game_level), &boundingrect);
  27. const QRect rectangle3=QRect(300, 2, 150, 25);
  28. painter->drawText(rectangle3, 0, tr("game score: %1").arg(game_score), &boundingrect);
  29. painter->save();
  30. painter->rotate(270);
  31. painter->translate(-40, 10);
  32. QPoint FoodPoint(-food_x*8,food_y*8);
  33. QRadialGradient RadialGradient(-food_x*8, food_y*8, 6, -food_x*8, food_y*8);
  34. RadialGradient.setColorAt(0, Qt::green);
  35. RadialGradient.setColorAt(1.0, Qt::darkGreen);
  36. painter->setPen(Qt::NoPen);
  37. painter->setBrush(RadialGradient);
  38. painter->drawEllipse(FoodPoint, 6, 6);
  39. QPoint SnakeHeadPoint(-8*((*body_x)[0]), 8*((*body_y)[0]));
  40. QConicalGradient ConicalGradient(-8*((*body_x)[0]), 8*((*body_y)[0]), 270);
  41. ConicalGradient.setColorAt(0,Qt::red);
  42. ConicalGradient.setColorAt(1,Qt::darkRed);
  43. painter->setPen(ThinPen);
  44. painter->setBrush(ConicalGradient);
  45. painter->drawEllipse(SnakeHeadPoint, 5, 5);
  46. QColor LightSalmon(255,160,122);
  47. painter->setPen(ThinPen);
  48. painter->setBrush(LightSalmon);
  49. for(int i=1;i<body_x->size();i++){
  50. painter->drawRect(-8*((*body_x)[i])-4, 8*((*body_y)[i])-4,8,8);
  51. }
  52. painter->restore();
  53. }

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

  1. void ImageShow::keyPressEvent(QKeyEvent *KeyEvent){
  2. switch(KeyEvent->key()){
  3. case Qt::Key_Left: {direction = 1;break;}
  4. case Qt::Key_Up:{direction=2;break;}
  5. case Qt::Key_Right:{direction=3;break;}
  6. case Qt::Key_Down:{direction=4;break;}
  7. default:break;
  8. }
  9. QWidget::keyPressEvent(KeyEvent);
  10. }

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

  1. void ImageShow::saveRank(){
  2. archive archive_now;
  3. archive archive_history[10];
  4. int archive_num=0;
  5. string PlayerString=player.toStdString();
  6. strcpy(archive_now.player_temp, PlayerString.c_str());
  7. archive_now.game_leve_temp=game_level;
  8. archive_now.game_score_temp=game_score;
  9. QFile File("H:/soft programme/QTMySnaker/snake/Rank.txt");
  10. if(!File.open(QIODevice::ReadWrite))
  11. return;
  12. QTextStream InOut(&File);
  13. while(!File.atEnd()){
  14. QString player_string;
  15. InOut>>player_string>>archive_history[archive_num].game_leve_temp
  16. >>archive_history[archive_num].game_score_temp;
  17. string PlayerString=player_string.toStdString();
  18. strcpy(archive_history[archive_num].player_temp, PlayerString.c_str());
  19. archive_num++;
  20. }
  21. for(int i=0;i<=archive_num;i++){
  22. if(archive_now.game_score_temp>archive_history[i].game_score_temp){
  23. for(int j=archive_num;j>=i+1;j--){
  24. archive_history[j]=archive_history[j-1];
  25. }
  26. archive_history[i]=archive_now;
  27. break;
  28. }
  29. else if(i==archive_num){
  30. archive_history[archive_num]=archive_now;
  31. }
  32. }
  33. for(int i=0;i<=archive_num;i++){
  34. InOut<<archive_history[i].player_temp<<‘\t‘
  35. <<archive_history[i].game_leve_temp<<‘\t‘
  36. <<archive_history[i].game_score_temp<<‘\n‘;
  37. }
  38. File.close();
  39. }

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

  1. void ImageShow::exec(){
  2. this->show();
  3. QEventLoop loop;
  4. m_loop=&loop;
  5. loop.exec();
  6. }
  7. void ImageShow::closeEvent(QCloseEvent *event){
  8. this->hide();
  9. m_loop->exit();
  10. event->accept();
  11. }
时间: 2024-08-10 23:30:43

QT之贪吃蛇的相关文章

Qt版贪吃蛇游戏

Qt版贪吃蛇游戏 转载请标明出处:牟尼的专栏 http://blog.csdn.net/u012027907 最近在学习Qt,用了一个多月的时间掌握了Qt中最基本的知识,也完成了<Qt版音乐播放器>.<Qt版贪吃蛇游戏>.<Qt版双人俄罗斯方块>以及<Qt版科学计算器>等,之前在VC下写过这些程序,所以在Qt下只是改变了显示等语句,我写过<C++版贪吃蛇游戏>.<VC版贪吃蛇游戏>,当时将与显示等无关的东西封装起来,在Qt下直接用,只

QT实现贪吃蛇

board.h #ifndef BOARD_H #define BOARD_H #define MAX_X 40 #define MAX_Y 30 #define NORMAL_LABEL 0//普通label #define BORDER_LABEL 1//边界label #define SNAKE_LABEL 2//蛇身label #define FOOD_LABEL 3//食物label #include <QWidget> #include <QLabel> #includ

Qt小游戏开发:贪吃蛇

周末没事,手写小游戏继续~ 预览 步骤 1 定义数据结构 逻辑与界面分离,游戏场景是个二维数组区域,贪吃蛇是若干个连续的坐标点集合,用动态链表维护,果实是一个随机坐标点. const int BLOCK_SIZE=25; //单个方块单元的边长 const int MARGIN=5; //场景边距 const int AREA_ROW=15; //场景行数 const int AREA_COL=15; //场景列数 QPoint foodPoint; //果实出现坐标 QList<QPoint>

QT下的贪吃蛇

QT写的贪吃蛇,学习于https://www.devbean.net/2012/12/qt-study-road-2-snake-1/ 建议就学习一下开发思想,开发游戏还是用专门的编译器. 多加了墙,暂停和开始,方向相反当碰撞没有思路解决,有空的时候再弄一下 源码地址:https://github.com/QKSword/Snake-game-QT 原文地址:https://www.cnblogs.com/QKSword/p/8538514.html

C语言之贪吃蛇(curses库函数)

上大学学习编程的初始目的就是冲着游戏来的~不过在刚学习C语言的时候,完全无法利用所学知识弄出一个可玩的游戏╮(╯_╰)╭,学了1年后仍然对最简单的贪吃蛇没有思路(当然不是说没有打代码的思路,而是没有办法弄出动态的东西,而且当时往算法那走了~),直到如今大二,利用寒假的一点时间入门Linux的时候,发现了curses库函数!当我看明白它的作用时,拍案而起,TM这玩意不就是我梦寐以求的可实现界面的东东么!当我学了一点点就觉悟到,用一个move()和printw()函数就完全可以把贪吃蛇这种级别的写出

qtday03 简单版的贪吃蛇游戏

//snakegame.h #ifndef SNAKEGAME_H #define SNAKEGAME_H #include<QList> #include<QtWidgets/QLabel> #include<QtWidgets/QDialog> #include<QKeyEvent> #include<QTimer> /*枚举,表示方向*/ enum Direction{D_UP,D_DOWN,D_LEFT,D_RIGHT}; class S

数据结构大作业-贪吃蛇

这次数据结构课程我的大作业选择的是贪吃蛇,最初我想了很久到底用什么语言来写贪吃蛇,最后想到java实现图形界面是最方便的,因为JDK里已经有AWT和SWING两个类可以实现图形界面,C语言我会用一个叫easyX的图形库,但是我感觉这个图形库用起来挺麻烦的,c++的话,我还不会用QT,MFC,之类的.这个课程供我们选择的就只有这三门语言,最后我选择了java. 由于我是这学期刚学的java,而且一个星期只有一节java课,一共只学了只有七八周的样子,所以java学的不怎么精,对有些类的理解其实我的

easyx图形库做贪吃蛇游戏

编程总是对着一个黑窗口,可以说是非常乏味了,于是喵喵就翻出来了以前用easyx图形库做图形界面的贪吃蛇游戏. 不过大家只是当做提高编程的乐趣来学习吧,想进一步做的话可以学习QT,还有其他的框架. 这是一个easyx图形库的学习教程,建议大家学完再看本文: https://www.easyx.cn/skills/List.aspx?id=7 首先看一下效果图: 实现的功能: 基本的吃食物长大,撞墙死亡,特殊食物,游戏暂停,重开游戏,记分数的功能. 游戏最高分的记录. 游戏关卡的选择. 加了游戏的音

C语言学习必须拥有学习路线,不然你就只会写贪吃蛇

C语言学习必须拥有学习路线,不然你就只会写贪吃蛇这些天一直有人问我,c语言好学吗?我是个新手,该如何学习? 其实,这类问题困扰着很多新手.在如何学习之前,我们想简单的了解一下什么是C语言: C语言是一种计算机程序设计语言.它既有高级语言的特点,又具有汇编语言的特点.它可以作为系统设计语言,编写工作系统应用程序,也可以作为应用程序设计语言,编写不依赖计算机硬件的应用程序.创一个小群,供大家学习交流聊天如果有对学C++方面有什么疑惑问题的,或者有什么想说的想聊的大家可以一起交流学习一起进步呀.也希望