先来看下整体效果截图:
有问题可以加我QQ:2273864757 进行交流学习
1.1 整体结构
- 将整个界面抽象为一个4*4的二维矩阵,矩阵存储当前格的数字,若为空则置0。
- 随机在空白区域产生一个随机数,随着得分的不断增加,产生大数字的概率逐渐增大。
- 根据按键输入,读入方向键。并调用合并函数进行合并。
2.2 界面搭建
界面抽象为一个4*4的二维矩阵,我们采用Qt自带的方法进行样式和风格进行设置:
// set default size
resize(650,450);
// create the main layout
mainLayout = new QVBoxLayout();
setLayout(mainLayout);
// will be created in drawBoard()
boardLayout = NULL;
// create the game and register as observer
game = new Game(4);
game->registerObserver(this);
// create the gui board and draw it
gui_board.resize(game->getGameBoard()->getDimension());
for (int i = 0; i < game->getGameBoard()->getDimension(); ++i)
gui_board[i].resize(game->getGameBoard()->getDimension());
for (int i = 0; i < game->getGameBoard()->getDimension(); ++i)
for (int j = 0; j < game->getGameBoard()->getDimension(); ++j)
gui_board[i][j] = NULL;
drawBoard();
// create the score widget and add it to the board
score = new QLabel(QString("SCORE: %1").arg(game->getScore()));
score->setStyleSheet("QLabel { color: rgb(235,224,214); font: 16pt; }");
score->setFixedHeight(50);
mainLayout->insertWidget(1, score, 0, Qt::AlignRight);
// style sheet of the board
setStyleSheet("QGameBoard { background-color: rgb(187,173,160) }");
connect(gameOverWindow.getResetBtn(), SIGNAL(clicked()), this, SLOT(resetGame()));
2.3 键盘按钮事件处理
在游戏开始之后,键盘事件分为上、下、左、右进行操作,对各个格子的数字进行移动。
void QGameBoard::keyPressEvent(QKeyEvent *event)
{
switch (event->key()) {
case Qt::Key_Up:
game->move(UP);
break;
case Qt::Key_Left:
game->move(LEFT);
break;
case Qt::Key_Right:
game->move(RIGHT);
break;
case Qt::Key_Down:
game->move(DOWN);
break;
}
}
//*************************************************************
void Board::move(Direction direction)
{
Board pre_move_board(*this);
prepareForNextMove();
switch (direction) {
case UP:
for (int i = 0; i < dimension; ++i)
for (int j = 0; j < dimension; ++j)
moveVertically(i,j,UP);
break;
case DOWN:
for (int i = dimension-1; i >= 0; --i)
for (int j = 0; j < dimension; ++j)
moveVertically(i,j,DOWN);
break;
case LEFT:
for (int i = 0; i < dimension; ++i)
for (int j = 0; j < dimension; ++j)
moveHorizontally(i,j,LEFT);
break;
case RIGHT:
for (int i = 0; i < dimension; ++i)
for (int j = dimension-1; j >= 0; --j)
moveHorizontally(i,j, RIGHT);
}
// if the board has changed (and there was no tile collision), place a new tile
if (changed(pre_move_board) /*&& !tileCollisionLastRound*/) {
QVector<int> newpos = freePosition();
board[newpos[0]][newpos[1]] = new Tile();
}
notifyObservers();
}
2.4 界面绘制与得分统计
通过键盘移动事件操作来控制游戏,在操作过程中对得分进行统计,并在界面进行显示;
void QGameBoard::drawBoard()
{
delete boardLayout;
boardLayout = new QGridLayout();
for (int i = 0; i < game->getGameBoard()->getDimension(); ++i) {
for (int j = 0; j < game->getGameBoard()->getDimension(); ++j) {
delete gui_board[i][j];
gui_board[i][j] = new QTile(game->getGameBoard()->getTile(i,j));
boardLayout->addWidget(gui_board[i][j], i, j);
gui_board[i][j]->draw();
}
}
mainLayout->insertLayout(0, boardLayout);
}
void QGameBoard::resetGame()
{
game->restart();
drawBoard();
score->setText(QString("SCORE: %1").arg(game->getScore()));
gameOverWindow.hide();
}