为了熟悉qt的相关知识,我用了大约8个小时的时间用qt再次写了一遍贪吃蛇。
因为qt的机制和平时写的程序流程不同,所以程序中可能没有遵守代码规范。
运行效果:
程序内除了实现贪吃蛇的基本功能外,还添加了记录得分、调节游戏速度、重新开始游戏等功能。
游戏内容使用qpainter类进行绘制。
编译环境:
windows qt 5.9.0 qt creator 4.3.0
思路:
数组存储蛇节点坐标的贪吃蛇游戏思路。
因为编写过程中使用了分文件编写,且qt框架的其他部分较多,这里仅展示程序实现主要代码。
代码:
mainwindow.h 主窗口类头文件
#ifndef widget_h #define widget_h #include <qwidget> #include <qpainter> //画家类 #include "snake.h" //蛇类 #include <qkeyevent> //键盘事件 #include "food.h" //食物类 #include <qtimer> //定时器类 namespace ui { class widget; } class widget : public qwidget { q_object public: explicit widget(qwidget *parent = 0); ~widget(); //绘图事件 void paintevent(qpaintevent *); //游戏结束的情况 void gameover(); private: ui::widget *ui; snake snake; //蛇对象 char key = 'd'; //接收键值,初始向右 food food; //食物对象 //创建定时器 qtimer *timer = new qtimer(this); bool gameflag = false;//游戏结束标记 int score = 0; //记录得分 int timerspeed = 200; //定时器速度 bool bugflag = false; //用于解决操控过快导致撞死自己的bug的标志 //键盘事件,改变键值 void keypressevent(qkeyevent *ev); }; #endif // widget_h
mainwindow.cpp函数实现
#include "mainwindow.h" #include "ui_widget.h" #include <qlabel> #include <qpushbutton> //主窗口构造函数 widget::widget(qwidget *parent) : qwidget(parent), ui(new ui::widget) { ui->setupui(this); //初始化出.ui界面 //一个格子宽高25像素,地图宽高600像素,每行有24个格子 //设置固定窗口大小 setfixedsize(1000,600); //设置得分标签控件的属性 ui->label->setfont(qfont("黑体", 20, qfont::bold, false)); //设置游戏速度标签内容 ui->label_2->setfont(qfont("楷体", 16, qfont::bold, false)); ui->label_2->settext("游戏速度:"); //滑动条控件,这里将数值按一定比例放大缩小 ui->horizontalslider->setvalue(200 >> 2); //监听滑动条控件滑动时,改变定时器速度为滑动条的值 connect(ui->horizontalslider,qslider::valuechanged,[=]() { timerspeed = ui->horizontalslider->value() << 2; }); //设置重新开始按钮属性和内容 ui->pushbutton_3->setfont(qfont("黑体",12)); ui->pushbutton_3->settext("重新开始"); //监听重新开始按钮 connect(ui->pushbutton_3,qpushbutton::clicked,[=]() { snake.reset(); //重置蛇 score = 0; //得分清0 key = 'd'; //key值向右 timerspeed = 200 << 2;//重置游戏速度 timer->start(timerspeed);//重置定时器 ui->horizontalslider->setvalue(200 >> 2);//重置滑动条 gameflag = false; //重置游戏结束标志 }); //开启定时器 timer->start(timerspeed); //监听定时器的信号,执行表达式内容 connect(timer,&qtimer::timeout,[=]() { timer->start(timerspeed); //调整定时器的速度 snake.move(key); //蛇移动函数 //吃到食物的情况 (food.getfoodx() == snake.snakevec.at(0).x && food.getfoody() == snake.snakevec.at(0).y) ? score++, food.randfood(): //得分+1,随机产生一个食物坐标 snake.snakevec.pop_back(); //删除蛇尾 gameover(); //游戏失败的情况 update(); //调用绘图函数 //更新标签控件的文本内容 ui->label->settext(qstring("得分:%1").arg(score)); }); } //游戏失败情况 void widget::gameover() { //撞墙失败 if(snake.snakevec.at(0).x >= 24 * 25 || snake.snakevec.at(0).x < 0 || snake.snakevec.at(0).y < 0 || snake.snakevec.at(0).y >= 24 * 25) { gameflag = true; timer->stop(); //暂停定时器 return; } //撞自己失败 for(int i = 1; i < snake.snakevec.size(); i++) { if(snake.snakevec.at(0).x == snake.snakevec.at(i).x && snake.snakevec.at(0).y == snake.snakevec.at(i).y) gameflag = true, timer->stop(); } } //绘图事件 void widget::paintevent(qpaintevent *) { //创建画家对象,指定绘图设备为this主窗口 qpainter painter(this); //设置画刷为红色 qbrush brush1(qt::red); //让画家使用画刷 painter.setbrush(brush1); //画食物 painter.drawrect(qrect(food.getfoodx(),food.getfoody(),25,25)); //设置画刷为黑色 qbrush brush2(qt::blue); painter.setbrush(brush2); //遍历蛇坐标容器,画出代表蛇身的矩形 for(auto snakenodei : snake.snakevec) //蛇头画圆形 (snakenodei.x == snake.snakevec.at(0).x && snakenodei.y == snake.snakevec.at(0).y) ? //蛇头画圆形 painter.setrenderhint(qpainter::antialiasing), //用抗锯齿画圆 painter.drawellipse(qpoint(snakenodei.x + 12,snakenodei.y + 12),12,12): //蛇身画矩形 painter.drawrect(qrect(snakenodei.x,snakenodei.y,25,25)); bugflag = false; //在画出蛇之后将标志设为假 //设置画刷为黑色 qbrush brush3(qcolor(128, 64, 0)); painter.setbrush(brush3); //画出墙壁 for(int i = 0; i < 24; i++) painter.drawrect(qrect(25 * 25, i * 25, 25, 25)); //游戏结束时的绘图 if(gameflag) { //设置文字属性 qfont font("楷体", 80, qfont::bold, false); painter.setfont(font); //使用字体 painter.drawtext(qrect(240, 200, 1000, 500), "游戏结束"); //画出游戏结束文字 } } //键盘事件,改变贪吃蛇移动方向 void widget::keypressevent(qkeyevent *ev) { if(bugflag) //bug标志为真直接返回 return; switch (ev->key()) { case qt::key_w: if(key == 's') break; //按下与当前方向相反按键时break key = 'w'; bugflag = true; break; //按键之后将标志设为真 case qt::key_s: if(key == 'w') break; key = 's'; bugflag = true; break; case qt::key_a: if(key == 'd') break; key = 'a'; bugflag = true; break; case qt::key_d: if(key == 'a') break; key = 'd'; bugflag = true; break; case qt::key_space: //空格键暂停,这里有点问题 timer->stop(); break; default: //其他键重启定时器 timer->start(timerspeed); } } //析构 widget::~widget() { delete ui; }
snake.h 蛇类头文件
#ifndef snake_h #define snake_h #include <qwidget> #include <qvector> //qt动态数组类 class snake : public qwidget { q_object private: //蛇坐标结构 struct snakecoor { int x; int y; }; public: explicit snake(qwidget *parent = nullptr); //蛇坐标容器 qvector<snakecoor> snakevec; //蛇移动主要函数 void move(char key); //根据key值确定蛇的移动方向 void detedirmove(char key, snakecoor &nexthead); //重置蛇 void reset(); signals: public slots: }; #endif // snake_h
snake.cpp 蛇类函数实现
#include "snake.h" //构造函数初始化一条蛇 snake::snake(qwidget *parent) : qwidget(parent) { snakecoor snakenode; //临时结构变量用于创建蛇 for (int i = 5; i >= 0; i--) //从右向左创建5节蛇身,容器的第一个元素为蛇头 { snakenode.x = 25 * 8 + i * 25;//每个格子宽25像素 snakenode.y = 25 * 8; snakevec.push_back(snakenode);//将蛇节点插入到数组中 } } //确定蛇的移动方向,确定新蛇头的坐标位置 inline void snake::detedirmove(char key, snakecoor &nexthead) { switch (key) { case 'w': //新蛇头坐标根据旧蛇头坐标改变 nexthead.x = snakevec.front().x; nexthead.y = snakevec.front().y - 25; break; case 's': nexthead.x = snakevec.front().x; nexthead.y = snakevec.front().y + 25; break; case 'a': nexthead.x = snakevec.front().x - 25; nexthead.y = snakevec.front().y; break; case 'd': nexthead.x = snakevec.front().x + 25; nexthead.y = snakevec.front().y; } } //蛇移动主要函数 void snake::move(char key) { snakecoor nexthead; //创建一个新的蛇头 detedirmove(key, nexthead); //确定新蛇头的位置 snakevec.insert(snakevec.begin(), nexthead); //将新蛇头插入到容器头部 } //重置蛇函数 void snake::reset() { snakevec.clear(); //清空容器 //初始化蛇 snakecoor snakenode; for (int i = 5; i >= 0; i--) { snakenode.x = 25 * 8 + i * 25; snakenode.y = 25 * 8; snakevec.push_back(snakenode); } }
food.h 食物类头文件
#ifndef food_h #define food_h #include <qwidget> class food : public qwidget { q_object public : int food_x = 0; //食物坐标 int food_y = 0; public: explicit food(qwidget *parent = nullptr); void randfood(); //随机产生食物坐标 int getfoodx(); //返回食物坐标 int getfoody(); signals: public slots: }; #endif // food_h
food.cpp 食物类函数实现
#include "food.h" #include <ctime> food::food(qwidget *parent) : qwidget(parent) { randfood(); //创建对象时产生就一个随机坐标 } //随机产生食物坐标 void food::randfood() { srand((unsigned)time(null)); food_x = (rand() % 24) * 25; food_y = (rand() % 24 )* 25; } //获取食物的坐标 int food::getfoodx() { return food_x; } int food::getfoody() { return food_y; }
以上就是c/c++开发分享QT实现贪吃蛇游戏的全部内容,希望对大家的学习有所帮助,也希望大家多多支持<计算机技术网(www.ctvol.com)!!>。
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/c-cdevelopment/609348.html