2048的实现,还有很多功能没有加,以后有时间再弄,比起普通的游戏添加了向斜的四个方向滑动的功能
Game_1024_Window.h
#ifndef GAME_1024_WINDOW_H
#define GAME_1024_WINDOW_H
#include <QMainWindow>
#include "QGraphicsView"
#include "gamecontroller.h"
namespace Ui {
class Game_1024_Window;
}
class Game_1024_Window : public QMainWindow
{
Q_OBJECT
public:
explicit Game_1024_Window(QWidget *parent = 0);
void initscene();
void initbackground();
~Game_1024_Window();
private:
Ui::Game_1024_Window *ui;
QGraphicsScene *scene;
QGraphicsView *view;
void add_bottom_Line();
public:
GameController *controller;
};
#endif // GAME_1024_WINDOW_H
#ifndef GAMECONTROLLER_H
#define GAMECONTROLLER_H
#include <QObject>
#include "number_block.h"
#include "QVector"
#include "QPointF"
#include "QMap"
#include "QPropertyAnimation"
#include "QParallelAnimationGroup"
struct change
{
change(int a = 0,int b = 0,int c = 0,int d = 0):x1(a),y1(b),x2(c),y2(d){}
int x1,y1,x2,y2;
};
class GameController : public QObject
{
Q_OBJECT
using MyType = QVector<QVector<Number_block*> >;
using TestType = QVector<QVector<int> >;
public:
bool slide(QString);
bool Gameover();
void add_item();
explicit GameController(QGraphicsScene*,QObject *parent = 0);
~GameController();
protected:
bool eventFilter(QObject*,QEvent*);
private:
int N = 4;
int game_scores;
bool valuechanged;
int count;
MyType matrix;
TestType data;
QMap<QString,change> direction;
QGraphicsScene *scene;
QGraphicsTextItem* scores;
QPropertyAnimation* anim;
QParallelAnimationGroup group;
void recover();
void handlekeyPressed(QKeyEvent *event);
};
#endif // GAMECONTROLLER_H
#ifndef NUMBER_BLOCK_H
#define NUMBER_BLOCK_H
#include "QGraphicsObject"
#include "QObject"
#include "QPointF"
class GameController;
class Number_block: public QGraphicsObject
{
public:
friend class GameController;
Number_block(int = 0,qreal x = 0,qreal y = 0);
~Number_block();
void paint(QPainter * painter, const QStyleOptionGraphicsItem * option, QWidget * widget = 0)
Q_DECL_OVERRIDE;
QRectF boundingRect() const Q_DECL_OVERRIDE;
private:
size_t number;
int get_index(int);
};
#endif // NUMBER_BLOCK_H
#include "game_1024_window.h"
#include "ui_game_1024_window.h"
#include "QTextStream"
#include"QString"
Game_1024_Window::Game_1024_Window(QWidget *parent) :
QMainWindow(parent), ui(new Ui::Game_1024_Window),
scene(new QGraphicsScene(this)),view(new QGraphicsView(scene,this)),
controller(new GameController(scene,this))
{
ui->setupUi(this);
resize(400,400);
view->setMinimumSize(350, 350);
view->setMaximumSize(300, 300);
setCentralWidget(view);
view->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
initscene();
initbackground();
}
Game_1024_Window::~Game_1024_Window()
{
delete ui;
}
void Game_1024_Window:: initscene()
{
scene->setSceneRect(-150,-150,300,300);
}
void Game_1024_Window::initbackground()
{
scene->setBackgroundBrush(QBrush(Qt::lightGray));
add_bottom_Line();
}
void Game_1024_Window::add_bottom_Line()
{
QPen pen = QPen(Qt::white, 5, Qt::SolidLine, Qt::RoundCap);
for(int i = 0;i!=4;++i)
{
int y = -100+50*i;
scene->addLine(-100,y,100,y,pen);
scene->addLine(y,-100,y,100,pen);
}
scene->addLine(100,-100,100,100,pen);
scene->addLine(-100,100,100,100,pen);
}
#include "gamecontroller.h"
#include "QGraphicsView"
#include "QKeyEvent"
#include "QSharedPointer"
#include "QPropertyAnimation"
#include "QEventLoop"
#include "time.h"
#include "QDebug"
#include "QTimer"
int N = 4;
bool inline isgood(int x){return ((x!=N&&x!=-1)?true:false);}
GameController::GameController(QGraphicsScene *sce,QObject *parent) : QObject(parent),
matrix( MyType (4)),data(TestType(4)),count(3),game_scores(0),
scene(sce),scores(new QGraphicsTextItem)
{
connect(&group,QAbstractAnimation::finished,this,recover);
scene->addItem(scores);
scores->setFont(QFont("Times", 20, QFont::Bold));
scores->setPos(50, -160);
scores->setHtml(tr("<font color = white >%1</font>").arg(game_scores));
for(int i = 0;i!=4;++i)
for(int j = 0;j!=4;++j)
{
data[i].push_back(0);
matrix[i].push_back(0);
}
matrix[3][0] = new Number_block(2,-75,75);
scene->addItem(matrix[3][0]);
data[3][0] = 2,data[3][1] = 2,data[3][2] = 2;
matrix[3][1] = new Number_block(2,-25,75);
scene->addItem(matrix[3][1]);
matrix[3][2] = new Number_block(2,25,75);
scene->addItem(matrix[3][2]);
int N = 4;
direction.insert("up", change(-1, 0, 1, 0) );
direction.insert( "down", change(1, 0, N - 2, 0));
direction.insert( "left", change(0,-1 , 0, 1));
direction.insert( "right", change(0, 1, 0, N-2) );
direction.insert("leftup", change(-1, -1, 1, 1) );
direction.insert( "rightdown", change(1, 1, N-2, N-2) );
direction.insert( "leftdown", change(1, -1, N-2, 1) );
direction.insert( "rightup", change(-1, 1, 1, N-2) );
scene->installEventFilter(this);
}
GameController::~GameController()
{
}
bool GameController:: slide(QString ms)
{
group.clear();
int N = 4;
int de_i = direction[ms].x1,de_j = direction[ms].y1;
auto beg_row = direction[ms].x2,beg_col = direction[ms].y2;
auto de_row = (beg_row==N-2) ? -1 : 1,de_col = (beg_col==N-2) ? -1 : 1;
valuechanged = false;
TestType isnewvalue(N);
for ( int i = 0;i!=4;++i)
isnewvalue[i].resize(N);
for (size_t i = beg_row; isgood(i);i+=de_row)
for (size_t j = beg_col; isgood(j); j+=de_col)
{
bool ismoved = false;
bool ismerged = false;
if (!data[i][j])
continue;
int temp_i = i, temp_j = j;
anim = new QPropertyAnimation(matrix[i][j],"pos");
if (!data[i + de_i][j + de_j])
{
ismoved = true;
valuechanged = true;
while (isgood(i + de_i) && isgood(j + de_j)&&!data[i + de_i][j + de_j] )
i += de_i,j += de_j;
anim->setDuration(250);
anim->setKeyValueAt(0,QPoint(-75+50*temp_j,-75+50*temp_i));
anim->setKeyValueAt(0.5,QPoint(-75+50*j,-75+50*i));
auto temp = data[i][j];
data[i ][j] = data[temp_i][temp_j];
data[temp_i][temp_j] = temp;
}
if (isgood(i+de_i)&&isgood(j+de_j)&&(data[i][j] ==
data[i + de_i][j + de_j])&&
!isnewvalue[i+de_i][j+de_j])
{
ismerged = true;
if(!ismoved)
{
anim->setDuration(250);
anim->setKeyValueAt(0,QPoint(-75+50*j,-75+50*i));
}
anim->setEndValue(QPoint(-75+50*(j+de_j),-75+50*(i+de_i)));
data[i][j] = 0;
data[i + de_i][j + de_j] *= 2;
game_scores += data[i+de_i][j+de_j];
isnewvalue[i + de_i][j + de_j] = 1;
--count;
valuechanged = true;
}
if(!ismerged)
{
anim->setDuration(anim->duration()*2);
anim->setEndValue(QPoint(-75+50*j,-75+50*i));
}
group.addAnimation(anim);
i = temp_i, j = temp_j;
}
return valuechanged;
}
bool GameController::eventFilter(QObject* obj,QEvent* event)
{
if(event->type()==QEvent::KeyPress)
{
handlekeyPressed(static_cast<QKeyEvent*>(event));
return true;
}
else
return QObject::eventFilter(obj,event);
}
void GameController::handlekeyPressed(QKeyEvent *event)
{
QString ms;
if(event->modifiers()==Qt::NoModifier)
{
switch( event->key())
{
case Qt::Key_Left: ms = "left";break;
case Qt::Key_Right: ms ="right";break;
case Qt::Key_Up:ms = "up";break;
case Qt::Key_Down:ms = "down"; break;
}
}
else if (event->modifiers()==Qt::ControlModifier)
{
switch( event->key())
{
case Qt::Key_Left: ms = "leftup";break;
case Qt::Key_Right: ms ="rightup";break;
}
}
else
{
switch( event->key())
{
case Qt::Key_Left: ms = "leftdown";break;
case Qt::Key_Right: ms ="rightdown";break;
}
}
if(!ms.isEmpty())
{
slide(ms);
group.start();
}
}
void GameController:: recover()
{
for(int i = 0;i!=4;++i)
for(int j = 0;j!=4;++j)
{
if(!matrix[i][j])
{
if(data[i][j]){
matrix[i][j] = new Number_block(data[i][j],-75+50*j,-75+50*i);
scene->addItem(matrix[i][j]);
}
}
else if(!data[i][j])
{
scene->removeItem(matrix[i][j]);
delete matrix[i][j];
matrix[i][j] = 0;
}
else if(data[i][j]!=matrix[i][j]->number)
{
matrix[i][j]->number = data[i][j];
matrix[i][j]->setPos(-75+50*j,-75+50*i);
}
else
matrix[i][j]->setPos(-75+50*j,-75+50*i);
}
scene->update();
if(valuechanged)
add_item();
if(valuechanged&&Gameover())
{
qDebug()<<"gameover\n";
group.clear();
game_scores = 0;
for(int i = 0;i!=4;++i)
for(int j = 0;j!=4;++j)
{
data[i][j] = 0;
scene->removeItem(matrix[i][j]);
delete matrix[i][j];
matrix[i][j] = 0;
}
count = 0;
add_item();
}
scores->setHtml(tr("<font color = white >%1</font>").arg(game_scores));
}
void GameController::add_item()
{
int x, y;
srand(time(0));
int n = 0;
while (count != N*N&&n != 1)
{
do{
x = rand() % N;
y = rand() % N;
} while (data[x][y]);
matrix[x][y] = new Number_block((count % 2) ? 2 : 4,-75+50*y,-75+50*x);
scene->addItem(matrix[x][y]);
data[x][y] = matrix[x][y]->number;
++count;
++n;
}
}
bool GameController::Gameover()
{
if(count!=N*N)
return false;
for(int i = 0;i!=4;++i)
for(int j = 0;j!=4;++j)
{
if(j<=2&&data[i][j] == data[i][j+1])
return false;
if(i<=2&&data[i][j] == data[i+1][j])
return false;
}
return true;
}
#include "number_block.h"
#include "QPainter"
#include "QString"
#include "QObject"
Number_block::Number_block(int num, qreal x, qreal y):number(num)
{
setPos(x,y);
}
Number_block::~Number_block()
{
}
void Number_block:: paint(QPainter * painter,
const QStyleOptionGraphicsItem *, QWidget *)
{
QColor digitBkg[11] = {QColor::fromRgb(0xEE, 0xE5, 0xDB), QColor::fromRgb(0xEC, 0xE0, 0xC8),
QColor::fromRgb(0xF2, 0xAF, 0x78), QColor::fromRgb(0xEE, 0x8A, 0x54),
QColor::fromRgb(0xFE, 0x76, 0x5E), QColor::fromRgb(0xE7, 0x58, 0xC),
QColor::fromRgb(0xFF, 0x66, 0x66), QColor::fromRgb(0xF1, 0xCF, 0x48),
QColor::fromRgb(0xCC, 0x33, 0x33), QColor::fromRgb(0xE3, 0xB9, 0x11),
QColor::fromRgb(0xFF, 0x00, 0x00)};
if(number!=0)
{
int index = get_index(number);
painter->setPen(digitBkg[index]);
painter->setBrush(QBrush(digitBkg[index]));
painter->drawRect(boundingRect());
painter->setFont(QFont("Microsoft YaHei UI",10,QFont::Black));
painter->setPen(Qt::black);
painter->drawText(boundingRect(), Qt::AlignCenter, tr("%1").arg(number));
}
}
QRectF Number_block:: boundingRect()const
{
return QRect(-20,-20,40,40);
}
int Number_block::get_index(int x)
{
int i = -1;
while(x)
{
x = x>>2;
++i;
}
return i;
}
#include "game_1024_window.h"
#include <QApplication>
#include "QTextStream"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Game_1024_Window w;
w.show();
return a.exec();
}
![这里写图片描述](https://img-blog.csdn.net/20160223170559952)