1.先看ui图 和标签
2.代码注意点
子窗口:是标签的父窗口,否则显示不出来16个标签
因为Label继承了QLabel,如果不写QLabel(parent)情况下,不能把ui->widget变成Label的父类
就不能显示16个格子
同步分数的时候,分数大于最高,要best=score否则存储不了
label.h
#ifndef LABEL_H
#define LABEL_H
#include <QLabel>
#include <QWidget>
class Label : public QLabel
{
public: //父类
explicit Label(int row,int column,QWidget *parent=0);
~Label();
void setValue(int value);
};
#endif // LABEL_H
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include"label.h"
#include<QKeyEvent>
#include<iostream>
QT_BEGIN_NAMESPACE
namespace Ui {
class Widget;
}
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
void randNumber(void);
int checkStatus(void);
void sync(void);//数据同步到Label中
void save(void);
void load(void);
void up(void);
void down(void);
void left(void);
void right(void);
void keyReleaseEvent(QKeyEvent *event);//按键事件
private slots:
void on_pushButton_clicked();
private:
Ui::Widget *ui;
Label *labs[4][4];
//必须得初始化,不然会产生随机数
short arr[4][4]={};
bool is_move;
int score;
int best;
};
#endif // WIDGET_H
label.cpp
#include "label.h"
// ui->widget //必须要实例化
Label::Label(int row,int column,QWidget *parent):QLabel(parent)//?? 把ui->widget变成QLabel
{
//设置大小,位置,字体的颜色,背景
//窗口大小 parent=QWidget
this->resize((parent->width()-50)/4,(parent->height()-50)/4);
//样式表
this->setStyleSheet("background-color:rgb(205,193,180);;font: 75 16pt\"Segoe UI Black\"");
this->setAlignment(Qt::AlignCenter);
this->move(10+(this->width()+10)*column,10+(this->height()+10)*row);
}
Label::~Label()
{
}
void Label::setValue(int value)
{
char strValue[11];
sprintf(strValue,"%d",value);
this->setText(strValue);
QString qss = "background-color: rgb(205, 193, 180);font: 75 16pt \"Segoe UI Black\";";
switch(value)
{
case 0:
qss += "background-color: rgb(205, 193, 180);color:rgb(205, 193, 180);";
break;
case 2:
qss += "background-color: rgb(238, 228, 218);color:rgb(119, 110, 101);";
break;
case 4:
qss += "background-color: rgb(237, 224, 200);color:rgb(119, 110, 101);";
break;
case 8:
qss += "background-color: rgb(242, 177, 121);color:rgb(249, 246, 242);";
break;
case 16:
qss += "background-color: rgb(245, 149, 99);color:rgb(249, 246, 242);";
break;
case 32:
qss += "background-color: rgb(246, 124, 95);color:rgb(249, 246, 242);";
break;
case 64:
qss += "background-color: rgb(246, 94, 59);color:rgb(249, 246, 242);";
break;
case 128:
qss += "background-color: rgb(237, 207, 114);color:rgb(249, 246, 242);";
break;
case 256:
qss += "background-color: rgb(237, 204, 97);color:rgb(249, 246, 242);";
break;
case 512:
qss += "background-color: rgb(237, 200, 80);color:rgb(249, 246, 242);";
break;
case 1024:
qss += "background-color: rgb(237, 197, 63);color:rgb(249, 246, 242);";
break;
case 2048:
qss += "background-color: rgb(237, 194, 46);color:rgb(249, 246, 242);";
break;
}
this->setStyleSheet(qss);
}
widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include<fstream>
#include<QDebug>
#include<QFile>
Widget::Widget(QWidget *parent)
: QWidget(parent),score(0),best(0)
, ui(new Ui::Widget)
{
ui->setupUi(this);
for(int row=0;row<4;row++)
{
for(int column=0;column<4;column++)
{ //子窗口:是标签的父窗口
labs[row][column]=new Label(row,column,ui->widget1);
//labs[row][column]->setText("2");
}
}
// arr[0][0] = 1024;
// arr[0][1] = 1024;
// sync();
// is_move=true;
// randNumber();
load();
}
Widget::~Widget()
{
delete ui;
if(0 == checkStatus())
save();
std::ofstream ofs("best.dat");
ofs.write((char*)&best,sizeof(best));
ofs.close();
}
void Widget::randNumber()
{
// is_move = true;//给个初值,用于测试
while (is_move)
{
int row = rand()%4; //四行四列
int column = rand()%4;
if(!arr[row][column])
{
arr[row][column]=2;
sync();
return;
}
}
}
//检查游戏的状态:0继续,1胜利,2,失败
int Widget::checkStatus()
{
bool flag=false;
for(int row=0;row<4;row++)
{
for(int column=0;column<4;column++)
{
if(2048== arr[row][column])
{
return 1;
}
if(0== arr[row][column])
{
flag=true;
}
}
}
if(flag==true)
return 0;
for(int row=0;row<3;row++)
{
for(int column=0;column<3;column++)
{
if(arr[row][column] == arr[row][column+1]||
arr[row][column] == arr[row+1][column])
{
return 0;
}
}
}
for(int row=3;row>0;row--)
{
for(int column=3;column>0;column--)
{
if(arr[row][column] == arr[row][column-1]||
arr[row][column] == arr[row-1][column])
{
return 0;
}
}
}
return 2;
}
//同步数组,分数,最高分
void Widget::sync()
{
//同步数组到Label
for(int row=0;row<4;row++)
{
for(int column=0;column<4;column++)
{
labs[row][column]->setValue(arr[row][column]);
}
}
//同步分数
char str[11];
sprintf(str,"%d",score);
ui->lab_score->setText(str);
//最高分
if(score>best)
{
best=score;//不能忘记
ui->lab_best->setText(str);
}
}
//写是输出 of
void Widget::save()
{
std::ofstream ofs("game2048.dat");
ofs.write((char*)arr,sizeof(arr));
ofs.write((char*)&score,sizeof(score));
ofs.close();
}
//读是输入 in
void Widget::load()
{
std::ifstream ifs("game2048.dat");
if(ifs.good())
{
ifs.read((char*)arr,sizeof(arr));
ifs.read((char*)&score,sizeof(score));
ifs.close();
remove("game2048.dat");
sync();
}
else
{
on_pushButton_clicked();
}
ifs.open("best.dat");
if(ifs.good())
{
ifs.read((char*)&best,sizeof(best));
}
else
{
best=0;
}
char str[11];
sprintf(str,"%d",best);
ui->lab_best->setText(str);
ifs.close();
}
void Widget::up()
{
for(int y=0;y<4;y++)
{
int end = 0;
for(int x=1;x<4;x++)
{
for(int i=x;i>end;i--)
{
if(arr[i][y] && arr[i][y] == arr[i-1][y])
{
arr[i-1][y] *= 2;
arr[i][y] = 0;
end = i;
score += arr[i-1][y];
is_move = true;
}
else if(arr[i][y] && !arr[i-1][y])
{
arr[i-1][y] = arr[i][y];
arr[i][y] = 0;
is_move = true;
}
}
}
}
}
void Widget::down()
{
for(int y=0;y<4;y++)
{
int end = 3;
for(int x=2;x>=0;x--)
{
for(int i=x;i<end;i++)
{
if(arr[i][y] && arr[i][y] == arr[i+1][y])
{
arr[i+1][y] *= 2;
arr[i][y] = 0;
end = i;
score += arr[i+1][y];
is_move = true;
}
else if(arr[i][y] && !arr[i+1][y])
{
arr[i+1][y] = arr[i][y];
arr[i][y] = 0;
is_move = true;
}
}
}
}
}
void Widget::left()
{
for(int x=0;x<4;x++)
{
int end = 0;
for(int y=1;y<4;y++)
{
for(int i=y;i>end;i--)
{
if(arr[x][i] && arr[x][i] == arr[x][i-1])
{
arr[x][i-1] *= 2;
arr[x][i] = 0;
end = i;
score += arr[x][i-1];
is_move = true;
}
else if(arr[x][i] && !arr[x][i-1])
{
arr[x][i-1] = arr[x][i];
arr[x][i] = 0;
is_move = true;
}
}
}
}
}
void Widget::right()
{
for(int x=0;x<4;x++)
{
int end = 3;
for(int y=2;y>=0;y--)
{
for(int i=y;i<end;i++)
{
if(arr[x][i] && arr[x][i] == arr[x][i+1])
{
arr[x][i+1] *= 2;
arr[x][i] = 0;
end = i;
score += arr[x][i+1];
is_move = true;
}
else if(arr[x][i] && !arr[x][i+1])
{
arr[x][i+1] = arr[x][i];
arr[x][i] = 0;
is_move = true;
}
}
}
}
}
void Widget::keyReleaseEvent(QKeyEvent *event)
{
is_move=false;
switch(event->key())
{
case Qt::Key_Up:up();break;
case Qt::Key_Down:down();break;
case Qt::Key_Left:left();break;
case Qt::Key_Right:right();break;
}
randNumber();
//获取当前游戏状态
int status = checkStatus();
if(0 == status)
return;
if(1 == status)
{
//this->close();//暂时设置赢了的话,关闭窗口
QMessageBox msgBox;
msgBox.setText("恭喜游戏胜利");
msgBox.setInformativeText("还想再来一局吗?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
switch (ret)
{
case QMessageBox::Yes:
on_pushButton_clicked();
break;
case QMessageBox::No:
this->close();
break;
}
}
if(2 == status)
{
//this->close();//暂时设置赢了的话,关闭窗口
QMessageBox msgBox;
msgBox.setText("游戏失败");
msgBox.setInformativeText("还想再来一局吗?");
msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
msgBox.setDefaultButton(QMessageBox::Yes);
int ret = msgBox.exec();
switch (ret)
{
case QMessageBox::Yes:
on_pushButton_clicked();
break;
case QMessageBox::No:
this->close();
break;
}
}
}
void Widget::on_pushButton_clicked()
{
memset(arr,0,sizeof(arr));
score=0;
is_move=true;
randNumber();
}
main.cpp
#include "widget.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}