QT实现2048小游戏

您所在的位置:网站首页 qt写2048游戏 QT实现2048小游戏

QT实现2048小游戏

2023-09-02 15:29| 来源: 网络整理| 查看: 265

QT环境:QT5.2.0,Qt Creator3.0.0

1.自定义方块类

class Square : public QGraphicsItem { public: explicit Square(QPoint pos,QString text,QString background_color); QString getText() {return text;} void updatePos(QPoint pos); void updateText(QString text,QString background_color); void updateBox(QPoint pos,QString text,QString background_color); enum {Type = UserType + 1}; int type() const; private : QRectF boundingRect() const; void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); QString text; QString color; };

Square::Square(QPoint pos,QString text,QString background_color) : QGraphicsItem() { setPos(pos); this->text = text; this->color = background_color; setFlag(QGraphicsItem::ItemIsFocusable); } int Square::type() const { return Type; } QRectF Square::boundingRect() const { int penWidth = 1; return QRectF(0-penWidth/2,0-penWidth/2,105+penWidth,105+penWidth); } void Square::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) { Q_UNUSED(option); Q_UNUSED(widget); //画背景 painter->setPen(QColor(color)); painter->setBrush(QBrush(QColor(color))); painter->drawRect(QRect(0,0,105,105)); //设置字体 字号 switch(text.length()) { case 1: painter->setFont(QFont(QString::fromLocal8Bit("微软雅黑"),50,QFont::Bold)); break; case 2: painter->setFont(QFont(QString::fromLocal8Bit("微软雅黑"),40,QFont::Bold)); break; case 3: painter->setFont(QFont(QString::fromLocal8Bit("微软雅黑"),35,QFont::Bold)); break; case 4: painter->setFont(QFont(QString::fromLocal8Bit("微软雅黑"),30,QFont::Bold)); break; default: break; } //设置字体颜色 if(text.toInt() == 2 || text.toInt() == 4) { painter->setPen(QColor("#7c736a")); } else if(text.toInt() >= 8) { painter->setPen(QColor("#fff7eb")); } painter->drawText(QRect(0,0,105,105),Qt::AlignCenter,text); } void Square::updatePos(QPoint pos) { setPos(pos); update(boundingRect()); } void Square::updateText(QString text,QString background_color) { this->text = text; this->color = background_color; update(boundingRect()); } void Square::updateBox(QPoint pos,QString text,QString background_color) { this->text = text; this->color = background_color; setPos(pos); update(boundingRect()); }

2.自定义视图类

class GameView : public QGraphicsView { Q_OBJECT public: explicit GameView(); ~GameView(); private: QGraphicsScene *g_scene; QMap colorBox; void createGrid(); void createColorBox(); void startGame(); void restartGame(); bool upMerge(); bool downMerge(); bool leftMerge(); bool rightMerge(); bool newSquare(); void countEmpty(QList &empty_index); bool checkSucceeded(); bool checkFinished(); void keyPressEvent(QKeyEvent * event); void drawBackground(QPainter * painter, const QRectF & rect); public slots: }; GameView::GameView() : QGraphicsView() { g_scene = new QGraphicsScene(); g_scene->setSceneRect(0,0,500,500); setScene(g_scene); setCacheMode(QGraphicsView::CacheBackground); setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); createGrid(); createColorBox(); startGame(); } GameView::~GameView() { } void GameView::createGrid() { int penWidth = 16; QPen pen(QBrush(Qt::SolidPattern),penWidth,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin); pen.setColor(QColor("#b8af9e")); for(int i = 0;i < 5;i ++) { g_scene->addLine(i*(105 + penWidth)+penWidth/2,0,i*(105 + penWidth)+penWidth/2,500,pen); } for(int j = 0;j < 5;j ++) { g_scene->addLine(0,j*(105 + penWidth)+penWidth/2,500,j*(105 + penWidth)+penWidth/2,pen); } } void GameView::createColorBox() { colorBox.insert(0,tr("#ccc0b2")); colorBox.insert(2,tr("#eee4da")); colorBox.insert(4,tr("#ece0c8")); colorBox.insert(8,tr("#f2b179")); colorBox.insert(16,tr("#f59563")); colorBox.insert(32,tr("#f57c5f")); colorBox.insert(64,tr("#f65d38")); colorBox.insert(128,tr("#edc171")); colorBox.insert(256,tr("#edcc61")); colorBox.insert(512,tr("#ecc850")); colorBox.insert(1024,tr("#edc53f")); colorBox.insert(2048,tr("#efc4ef")); } void GameView::startGame() { int index1,index2; int num1,num2; //随机生成位置(16个方格,0~15编号) index1 = qrand()%16; index2 = qrand()%16; while(index2 == index1) { index2 = qrand()%16; } //随机生成2或4(随机生成0,1,则0代表2,1代表4) num1 = qrand()%2==0 ? 2 : 4; num2 = qrand()%2==0 ? 2 : 4; QPoint pos1((index1%4)*(105+16)+16,(index1/4)*(105+16)+16); QPoint pos2((index2%4)*(105+16)+16,(index2/4)*(105+16)+16); g_scene->addItem(new Square(pos1,QString::number(num1),colorBox.value(num1))); g_scene->addItem(new Square(pos2,QString::number(num2),colorBox.value(num2))); } void GameView::restartGame() { QList list = scene()->items(0,0,500,500,Qt::IntersectsItemShape,Qt::AscendingOrder); foreach(QGraphicsItem *item,list) { scene()->removeItem(item); delete item; item = NULL; } createGrid(); startGame(); } bool GameView::upMerge() { bool can_move = false; for(int i = 0;i < 4;i ++) for(int j = 0;j < 4;j ++) { QList current = scene()->items(i*(105+16)+16,j*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()items(i*(105+16)+16,k*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(next.count()getText() == c_square->getText()) { int num = c_square->getText().toInt()*2; c_square->updateText(QString::number(num),colorBox.value(num)); scene()->removeItem(n_square); delete n_square; n_square = NULL; can_move = true; } break; } } for(int i = 0;i < 4;i ++) { int empty_count = 0; for(int j = 0;j < 4;j ++) { QList current = scene()->items(i*(105+16)+16,j*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()updatePos(QPoint(square->pos().x(),square->pos().y()-empty_count*(105+16))); if(empty_count > 0) { can_move = true; } } } viewport()->update(); return can_move; } bool GameView::downMerge() { bool can_move = false; for(int i = 0;i = 0;j --) { QList current = scene()->items(i*(105+16)+16,j*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()= 0;k --) { QList next = scene()->items(i*(105+16)+16,k*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(next.count()getText() == c_square->getText()) { int num = c_square->getText().toInt()*2; c_square->updateText(QString::number(num),colorBox.value(num)); scene()->removeItem(n_square); delete n_square; n_square = NULL; can_move = true; } break; } } for(int i = 0;i < 4;i ++) { int empty_count = 0; for(int j = 3;j >= 0;j --) { QList current = scene()->items(i*(105+16)+16,j*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()updatePos(QPoint(square->pos().x(),square->pos().y()+empty_count*(105+16))); if(empty_count>0) { can_move = true; } } } viewport()->update(); return can_move; } bool GameView::leftMerge() { bool can_move = false; for(int i = 0;i < 4;i ++) for(int j = 0; j < 4;j ++) { QList current = scene()->items(j*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()items(k*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(next.count()getText() == n_square->getText()) { int num = c_square->getText().toInt()*2; c_square->updateText(QString::number(num),colorBox.value(num)); scene()->removeItem(n_square); delete n_square; n_square = NULL; can_move = true; } break; } } for(int i = 0;i < 4;i ++) { int empty_count = 0; for(int j = 0;j < 4;j ++) { QList current = scene()->items(j*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()updatePos(QPoint(square->pos().x()-empty_count*(105+16),square->pos().y())); if(empty_count>0) { can_move = true; } } } viewport()->update(); return can_move; } bool GameView::rightMerge() { bool can_move = false; for(int i = 0;i < 4;i ++) for(int j = 3; j>= 0;j --) { QList current = scene()->items(j*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()= 0;k --) { QList next = scene()->items(k*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(next.count()getText() == n_square->getText()) { int num = c_square->getText().toInt()*2; c_square->updateText(QString::number(num),colorBox.value(num)); scene()->removeItem(n_square); delete n_square; n_square = NULL; can_move = true; } break; } } for(int i = 0;i < 4;i ++) { int empty_count = 0; for(int j = 3;j >= 0;j --) { QList current = scene()->items(j*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(current.count()updatePos(QPoint(square->pos().x()+empty_count*(105+16),square->pos().y())); if(empty_count>0) { can_move = true; } } } viewport()->update(); return can_move; } bool GameView::newSquare() { QList empty_index; countEmpty(empty_index); int num = qrand()%2==0 ? 2 : 4; int index = qrand()%empty_index.count(); QPoint pos(empty_index[index].first*(105+16)+16,empty_index[index].second*(105+16)+16); g_scene->addItem(new Square(pos,QString::number(num),colorBox.value(num))); countEmpty(empty_index); if(empty_index.count() items(i*(105+16)+16,j*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(list.count() items(i*(105+16)+16,j*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); if(list.count() >= 1) { Square *square = qgraphicsitem_cast(list[0]); if(square->getText().toInt() == 2048) { QMessageBox::information(this,QStringLiteral("好消息"),QStringLiteral("恭喜完成,太厉害啦!"),QMessageBox::Ok); return true; } } } return false; } bool GameView::checkFinished() { QList current; QList next; Square *c_square; Square *n_square; for(int i = 0;i < 4;i ++) for(int j = 0;j < 3;j ++) { current.clear(); next.clear(); current = scene()->items(i*(105+16)+16,j*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); next = scene()->items(i*(105+16)+16,(j+1)*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); c_square = qgraphicsitem_cast(current[0]); n_square = qgraphicsitem_cast(next[0]); if(c_square->getText() == n_square->getText()) { return false; } current.clear(); next.clear(); current = scene()->items(j*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); next = scene()->items((j+1)*(105+16)+16,i*(105+16)+16,105,105,Qt::IntersectsItemShape,Qt::AscendingOrder); c_square = qgraphicsitem_cast(current[0]); n_square = qgraphicsitem_cast(next[0]); if(c_square->getText() == n_square->getText()) { return false; } } QMessageBox::information(this,QStringLiteral("游戏结束"),QStringLiteral("游戏结束..."),QMessageBox::Ok); return true; } void GameView::keyPressEvent(QKeyEvent * event) { switch(event->key()) { case Qt::Key_Up: if(upMerge()) { if(checkSucceeded() || !newSquare()) { restartGame(); } } break; case Qt::Key_Down: if(downMerge()) { if(checkSucceeded() || !newSquare()) { restartGame(); } } break; case Qt::Key_Left: if(leftMerge()) { if(checkSucceeded() || !newSquare()) { restartGame(); } } break; case Qt::Key_Right: if(rightMerge()) { if(checkSucceeded() || !newSquare()) { restartGame(); } } break; default: QGraphicsView::keyPressEvent(event); break; } } void GameView::drawBackground(QPainter * painter, const QRectF & rect) { painter->setBrush(QBrush(QColor("#ccc0b2"))); painter->drawRect(QRect(sceneRect().x(),sceneRect().y(),sceneRect().width(),sceneRect().height())); }

最后剩下的就是把view显示到mainwindow上:

MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); setWindowTitle(tr("2048")); setIconSize(QSize(48,48)); setFixedSize(542,542); setWindowIcon(QIcon(tr("://resources/window_ico_48.png"))); ui->center->addWidget(new GameView()); }

总结:

代码中有许多不完善的地方,比如方块合并没有特效、没有移动轨迹;新方块的出现太突兀和随机;合并算法比较累赘;程序逻辑不够清晰。甚至存在许多没有发现的错误。不管怎样,作为代码小菜鸟算是抛砖引玉了,请给位大牛指教!!!

附上效果图一张:



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3