熟悉QT,将教程里代码稍稍改了一下
哔哩哔哩2048教程——视频里有详细的教程
源文件
文章目录
一、MainWindow构造函数
1、设置窗口大小及标题
ui->setupUi(this);
this->setFixedSize(320,480);
this->setWindowTitle("2048");
2、按钮
(1)定义3*
3和4*
4按钮,设置大小,通过connect方法设置游戏的size
// 3*3按钮
QPushButton* size_btn_3 = new QPushButton("3X3");
size_btn_3->move(50,80);
size_btn_3->setParent(this);
size_btn_3->setFixedSize(80,30);
connect(size_btn_3,SIGNAL(clicked()),this,SLOT(ensureSize3()));
// 4*4按钮
QPushButton* size_btn_4 = new QPushButton("4X4");
size_btn_4->setFixedSize(80,30);
size_btn_4->setParent(this);
size_btn_4->move(180,80);
connect(size_btn_4,SIGNAL(clicked()),this,SLOT(ensureSize4()));
(2)确定游戏大小的槽函数
// 3*3
void MainWindow::ensureSize3()
{
size = 3;
button->setText("开始游戏");
}
// 4*4
void MainWindow::ensureSize4()
{
size =4;
button->setText("开始游戏");
}
3、提示语句
主页面的提示语句
remind_1 = new QLabel("先选择大小,再点击开始游戏",this);
remind_2 = new QLabel("WASD控制方向",this);
remind_1->setGeometry(60,150,200,30);
remind_2->setGeometry(60,170,100,30);
4、开始按钮
定义开始按钮,通过connect方法实现点击开始按钮初始化游戏界面
// 开始按钮
button = new QPushButton("开始游戏",this);
button->setGeometry(60,400,200,50);
connect(button,SIGNAL(clicked()),this,SLOT(start()));
二、初始化(start槽函数)
1、若未选择size则提示错误并返回
void MainWindow::start(){
if(size == 0){
QMessageBox::warning(this,"提示!","请先选择游戏类型!");
return;
}
2、设置提示语句为空
remind_1->setText(" ");
remind_2->setText(" ");
3、初始化游戏格子及分数,并将按钮值设为重新开始
score = 0; // 分数清零
for(int i = 0;i < size;i++){
for(int j = 0;j < size;j++){
if(size == 3)
lattice_3[i][j] = 0;
else if(size == 4)
lattice_4[i][j] =0;
}
}
button->setText("重新开始");
4、生成随机格子的行与列,再生成随机数2或4填入随机格子中;将状态设为true并update重新刷新界面
int rand_i = qrand()%size; // 生成格子的随机行
int rand_j = qrand()%size; // 生成格子的随机列
// 随机生成2,4
Rand_2_4 rand;
int rand_number = rand.rand();
if(size == 3)
lattice_3[rand_i][rand_j] = rand_number;
else if(size == 4)
lattice_4[rand_i][rand_j] = rand_number;
state = true;
update();
}
三、绘制功能-paintEvent函数
1、绘制背景图片及分数
void MainWindow::paintEvent(QPaintEvent *){
QPainter paint(this);
// 设置背景图片
QPixmap pix;
pix.load(":/res/background.jpg");
paint.drawPixmap(0,0,this->width(),this->height(),pix);
paint.setFont(QFont("微软雅黑",20,700,false));
QString str_score;
paint.drawText(QPoint(30,50),"分数 "+QString::number(score));
2、对格子二维数组进行循环,根据格子值设置画刷颜色对格子上色,如果值不为0则将值画出,若为0则不将其画出
// 格子实现0 2 4 8 16 32 64 128 256 512 1024 2048
for(int i=0;i < size;i++){
for(int j=0;j < size;j++){
paint.setPen(Qt::transparent);
if(size == 3)
value = lattice_3[i][j];
else if(size == 4)
value = lattice_4[i][j];
// 根据值设置格子刷子颜色
switch (value) {
case 0: paint.setBrush(QBrush(QColor(204,202,202,80))); break;
case 2: paint.setBrush(QBrush(QColor(255,252,227,210))); break;
case 4: paint.setBrush(QBrush(QColor(255,241,140,210))); break;
case 8: paint.setBrush(QBrush(QColor(255,243,26,210))); break;
case 16: paint.setBrush(QBrush(QColor(128,255,252,210))); break;
case 32: paint.setBrush(QBrush(QColor(38,255,250,210))); break;
case 64: paint.setBrush(QBrush(QColor(35,254,150,210))); break;
case 128: paint.setBrush(QBrush(QColor(0,200,60,210))); break;
case 256: paint.setBrush(QBrush(QColor(255,51,51,210))); break;
case 512: paint.setBrush(QBrush(QColor(255,2,2,210))); break;
case 1024: paint.setBrush(QBrush(QColor(96,78,254,210))); break;
case 2048: paint.setBrush(QBrush(QColor(48,24,254,210))); break;
default: paint.setBrush(QBrush(QColor(254,1,159,210))); break;
}
int x = 70,y = 150;
if(size == 4){
x = 40;
y = 120;
}
paint.drawRect(i*60+x,j*60+y,55,55); // 对格子上色
if(value != 0){
paint.setPen(Qt::black);
paint.setFont(QFont("微软雅黑",10,700,false));
//在方块中 绘制Text, 并且文本位置位于中部
paint.drawText(QRectF(i*60+x,j*60+y,55,55),QString::number(value),QTextOption(Qt::AlignCenter));
}
}
}
}
四、按键操作
根据键入的值调用相关函数进行操作
void MainWindow::keyPressEvent(QKeyEvent *event){
if(!state)
return;
switch(event->key()){
case Qt::Key_W: // 按上键
pressUp();
break;
case Qt::Key_S: // 按下键
pressDown();
break;
case Qt::Key_A: // 按左键
pressLeft();
break;
case Qt::Key_D: // 按右键
pressRight();
break;
default:
return;
}
myrand();
update(); // 强制界面刷新
}
五、移动相加
以向上为例,下、左、右均相同
- 执行先移动再相加
- 将移动相加分别分为3
*
3和4*
4
1、移动
void MainWindow::pressUp()
{
// 向上移动
for(int i = 0;i < size;i++){
for(int j = 1;j < size;j++){ // 从左上第二行开始向上移动
// 3*3
if(size == 3){
if(lattice_3[i][j] == 0) // 为0跳过
continue;
for(int k = 0;k < j;k++){
if(lattice_3[i][k] == 0){ // 查看上面是否有格子可以移动
lattice_3[i][k] = lattice_3[i][j];
lattice_3[i][j] = 0;
break;
}
}
}
// 4*4
else if(size == 4){
。。。// 与3*3操作相同
}
}
}
2、相加
// 向上相加
for(int i = 0;i < size;i++){
for(int j = 0;j < size;j++){
// 3*3
if(size == 3){ // 上面的格子等于下面的格子
if(lattice_3[i][j] == lattice_3[i][j+1]){
lattice_3[i][j] = lattice_3[i][j]*2; // 上面的格子加倍
lattice_3[i][j+1] = 0; // 下面的格子置0
score += lattice_3[i][j];
for(int k = j+2;k < size;k++) // 将后面的格子往前一个格子移栋
lattice_3[i][k-1] = lattice_3[i][k];
}
}
// 4*4
else if(size == 4){
。。。 // 与3*3操作相同
}
}
}
}
六、寻找空白格子,判断游戏是否结束
1、找出空白格子(即值为0处),并将格子的位置信息存入结构体中
void MainWindow::myrand()
{
// 找出空白格子
int i = 0,j = 0; // 记录空白格子位置
int number = 0; // 记录空白格子个数
// 储存空白格子位置
struct Position site_3[3*3];
struct Position site_4[4*4];
for(i = 0;i < size;i++){
for(int j = 0;j < size;j++){
if(size == 3){
if(lattice_3[i][j] == 0){ // 若为0则代表为空白格子
site_3[number].i = i;
site_3[number].j = j;
number++;
}
}
else if(size == 4){
if(lattice_4[i][j] == 0){
site_4[number].i = i;
site_4[number].j = j;
number++;
}
}
}
}
2、判断游戏是否结束
//判断游戏是否结束
if (number == 0) {
// 上下相邻是否有相等的
for(i = 0;i < size;i++) {
for(j = 0;j < (size-1);j++) {
if(size == 3){
if(lattice_3[i][j] == lattice_3[i][j+1])
return;
}
else if(size == 4){
if(lattice_4[i][j] == lattice_4[i][j+1])
return;
}
}
}
// 左右相邻是否有相等的
for(j = 0;j < size;j++) {
for(i = 0;i < (size-1);i++) {
if(size == 3){
if(lattice_3[i][j] == lattice_3[i+1][j]){
return;
}
}
else if(size == 4){
if(lattice_4[i][j] == lattice_4[i+1][j]){
return;
}
}
}
}
QMessageBox::warning(this,"Game Over!","游戏结束!");
return;
}
3、获取随机的格子,将生成的随机数放入格子
// 随机获取空白格子
int site_rand = qrand()%number;
// 随机生成2,4
Rand_2_4 ran;
int rand_number = ran.rand();
int x,y;
if(size == 3){
x = site_3[site_rand].i;
y = site_3[site_rand].j;
lattice_3[x][y] = rand_number;
}
else if(size == 4){
x = site_4[site_rand].i;
y = site_4[site_rand].j;
lattice_4[x][y] = rand_number;
}
}
七、效果图
1、主界面
2、游戏界面
(1)3*
3
(2)4*
4
八、打包
2048
提取码:oxtk