文章以及源码均为原创,当然欢迎转载,转载请加说明
用VS编写的Qt项目,欢迎阅读讨论,源码如下
tetris.h
#ifndef TETRIS_H
#define TETRIS_H
#include <QtWidgets/QWidget>
#include "ui_tetris.h"
#include <QPushButton>
#include <QPainter>
#include <QKeyEvent>
#include <iostream>
#include <assert.h>
#include <time.h>
#include <conio.h>
#include <windows.h>
#pragma execution_character_set("utf-8")
enum ShapeCode :int
{
Shape0, Shape1, Shape2, Shape3, Shape4, Shape5, Shape6, Shape7, Shape8, Shape9,
Shape10, Shape11, Shape12, Shape13, Shape14, Shape15, Shape16, Shape17, Shape18
};
const QColor Color0(145, 100, 202);
const QColor Color1(255, 127, 80);
const QColor Color2(255, 0, 255);
const QColor Color3(0, 255, 255);
const QColor Color4(255, 128, 0);
const QColor Color5(218, 112, 214);
const QColor Color6(138, 43, 226);
const int ROWNUM = 20;//游戏区域方块行数
const int COLNUM = 10;//游戏区域方块列数
const int BLOCKSIDELENGTH = 20;//方块边长
const int XLEFT = 40;//游戏区左边界X坐标
const int XRIGHT = XLEFT+BLOCKSIDELENGTH*COLNUM;//游戏区右边界X坐标
const int YUP = 100;//游戏区上边界Y坐标
const int YDOWN = YUP+BLOCKSIDELENGTH*ROWNUM;//游戏区下边界Y坐标
const int XINIT = XLEFT+(((COLNUM-4)/2)+1)*BLOCKSIDELENGTH;//图形生成时第一个方块左上角的X坐标
const int YINIT = YUP-BLOCKSIDELENGTH*2;//图形生成时第一个方块左上角的Y坐标
const int WINW = XRIGHT + BLOCKSIDELENGTH+230;//窗口宽度
const int WINH = YDOWN + BLOCKSIDELENGTH+30;//窗口高度
//方块
class CBlock
{
public:
CBlock();
~CBlock();
void Draw(QPainter &I_Painter) const;
void Create(int I_X, int I_Y, const QColor& I_Color, bool I_IsExist, int I_Row, int I_Col);
void SetX(int I_X);
int GetX() const;
void SetY(int I_Y);
int GetY() const;
void SetRow1(int I_Row1);
int GetRow1() const;
void SetRow2(int I_Row2);
int GetRow2() const;
void SetCol(int I_Col);
int GetCol() const;
void SetColor(const QColor& I_Color);
QColor GetColor() const;
void SetIsExist(bool I_IsExist);
bool GetIsExist() const;
void Copy(const CBlock&I_Block);
private:
int m_X;//左上角X坐标
int m_Y;//左上角Y坐标
int m_Row1;//行1,下落时有可能在两行中间,如果当前刚好位于某一行,则row1=row2;
int m_Row2;//行2
int m_Col;//列
QColor m_Color;//颜色
bool m_IsExist;//是否存在
};
//图形
class CFigure
{
public:
CFigure();
CFigure(CFigure &I_Figure);
~CFigure();
void Draw(QPainter &I_Painter) const;
void DropDown();//下落
void DropDown(int I_Row);
void Move(char I_Direction);//左右移动
void Vary();//形状变化
void SetIsExist(bool I_IsExist);
bool GetIsExist() const;
void Create();
CBlock *Get_m_Block();
ShapeCode *Get_m_Shape();
int GetNextShape() const;
protected:
void Set_m_Block(ShapeCode I_ShapeCode);
private:
CBlock m_Block[4];
bool m_IsExist;//是否存在
int m_NextShape;//下一个变化形状
ShapeCode m_Shape[4];//形状列表
};
class CTetris : public QWidget
{
Q_OBJECT
public:
CTetris(QWidget *parent = 0);
~CTetris();
protected:
void paintEvent(QPaintEvent *);
void timerEvent(QTimerEvent *);
void keyPressEvent(QKeyEvent *I_Event);
void keyReleaseEvent(QKeyEvent *I_Event);
void Start();
void Over();
void Draw();
bool CheckDropDown();//检查能否下落
bool CheckDropDownS();
int CalDropDownRow();//计算下落行数
bool CheckMove(char I_Direction);//检查能否左右移动
bool CheckVary();//检查能否形状变化
bool IsOver();
void FixFigure();//固定图形
void Eliminate(int I_Row);//消除
void CalculateScore();//计算得分
signals:
void GameOverSignal();
private:
Ui::CTetrisClass ui;
QPushButton m_StartButton;
QPainter m_Painter;
bool m_IsStart;
CFigure m_Figure;
CBlock m_BlockArr[ROWNUM][COLNUM];
int m_Score;
public slots:
void GameStartSlot();
void GameOverSlot();
};
//顺转
//0
//■■
//■■
//1
//■■■■
//2
//■
//■
//■
//■
//3
// ■
//■■■
//4
//■
//■■
//■
//5
//■■■
// ■
//6
// ■
//■■
// ■
//7
//■■■
// ■
//8
// ■
// ■
//■■
//9
//■
//■■■
//10
//■■
//■
//■
//11
//■■■
//■
//12
//■■
// ■
// ■
//13
// ■
//■■■
//14
//■
//■
//■■
//15
//■■
// ■■
//16
// ■
//■■
//■
//17
// ■■
//■■
//18
//■
//■■
// ■
#endif // TETRIS_H
tetris.cpp
#include "tetris.h"
CBlock::CBlock()
{
m_IsExist = false;
}
CBlock::~CBlock()
{
}
void CBlock::Draw(QPainter &I_Painter) const
{
if (m_IsExist)
{
QBrush Brush(m_Color);
I_Painter.setBrush(Brush);
Brush.setStyle(Qt::SolidPattern);
I_Painter.drawRect(m_X, m_Y, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
}
}
void CBlock::Create(int I_X, int I_Y, const QColor& I_Color, bool I_IsExist, int I_Row, int I_Col)
{
m_X = I_X;
m_Y = I_Y;
m_Row1 = I_Row;
m_Row2 = I_Row;
m_Col = I_Col;
m_Color = I_Color;
m_IsExist = I_IsExist;
}
void CBlock::SetX(int I_X)
{
m_X = I_X;
}
int CBlock::GetX() const
{
return m_X;
}
void CBlock::SetY(int I_Y)
{
m_Y = I_Y;
}
int CBlock::GetY() const
{
return m_Y;
}
void CBlock::SetRow1(int I_Row1)
{
m_Row1 = I_Row1;
}
int CBlock::GetRow1() const
{
return m_Row1;
}
void CBlock::SetRow2(int I_Row2)
{
m_Row2 = I_Row2;
}
int CBlock::GetRow2() const
{
return m_Row2;
}
void CBlock::SetCol(int I_Col)
{
m_Col = I_Col;
}
int CBlock::GetCol() const
{
return m_Col;
}
void CBlock::SetColor(const QColor& I_Color)
{
m_Color = I_Color;
}
QColor CBlock::GetColor() const
{
return m_Color;
}
void CBlock::SetIsExist(bool I_IsExist)
{
m_IsExist = I_IsExist;
}
bool CBlock::GetIsExist() const
{
return m_IsExist;
}
void CBlock::Copy(const CBlock&I_Block)
{
m_X = I_Block.GetX();
m_Y = I_Block.GetY();
m_Row1 = I_Block.GetRow1();
m_Row2 = I_Block.GetRow2();
m_Col = I_Block.GetCol();
m_Color = I_Block.GetColor();
m_IsExist = I_Block.GetIsExist();
}
CFigure::CFigure()
{
m_IsExist = false;
}
CFigure::CFigure(CFigure &I_Figure)
{
for (int i = 0; i < 4; i++)
{
m_Block[i].Copy((I_Figure.Get_m_Block())[i]);
m_Shape[i] = I_Figure.Get_m_Shape()[i];
}
m_IsExist = I_Figure.GetIsExist();
m_NextShape = I_Figure.GetNextShape();
}
CFigure::~CFigure()
{
}
void CFigure::Draw(QPainter &I_Painter) const
{
for (int i = 0; i < 4; i++)
{
m_Block[i].Draw(I_Painter);
}
}
void CFigure::DropDown()
{
for (int i = 0; i < 4; i++)
{
m_Block[i].SetY(m_Block[i].GetY() + 5);
if (!((m_Block[i].GetY() - YUP) % BLOCKSIDELENGTH))
{
m_Block[i].SetRow1(m_Block[i].GetRow2());
}
else
{
if (m_Block[i].GetRow1() == m_Block[i].GetRow2())
{
m_Block[i].SetRow2(m_Block[i].GetRow2() + 1);
}
}
}
}
void CFigure::DropDown(int I_Row)
{
for (int i = 0; i < 4; i++)
{
if (!((m_Block[i].GetY() - YUP) % BLOCKSIDELENGTH))
{
m_Block[i].SetY(m_Block[i].GetY() + I_Row*BLOCKSIDELENGTH);
}
else
{
m_Block[i].SetY(YUP + (I_Row + ((m_Block[i].GetY() - YUP) / BLOCKSIDELENGTH) + 1)*BLOCKSIDELENGTH);
}
m_Block[i].SetRow2(m_Block[i].GetRow2() + I_Row);
m_Block[i].SetRow1(m_Block[i].GetRow2());
}
}
void CFigure::Move(char I_Direction)
{
if ('A' == I_Direction || 'a' == I_Direction)
{
for (int i = 0; i < 4; i++)
{
m_Block[i].SetX(m_Block[i].GetX() - BLOCKSIDELENGTH);
m_Block[i].SetCol(m_Block[i].GetCol() - 1);
}
}
else if ('D' == I_Direction || 'd' == I_Direction)
{
for (int i = 0; i < 4; i++)
{
m_Block[i].SetX(m_Block[i].GetX() + BLOCKSIDELENGTH);
m_Block[i].SetCol(m_Block[i].GetCol() + 1);
}
}
}
void CFigure::Vary()
{
switch (m_Shape[m_NextShape])
{
case Shape0:
break;
case Shape1:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 2);
m_Block[2].SetY(m_Block[0].GetY());
m_Block[2].SetRow1(m_Block[0].GetRow1());
m_Block[2].SetRow2(m_Block[0].GetRow2());
m_Block[2].SetCol(m_Block[0].GetCol() + 2);
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 3);
m_Block[3].SetY(m_Block[0].GetY());
m_Block[3].SetRow1(m_Block[0].GetRow1());
m_Block[3].SetRow2(m_Block[0].GetRow2());
m_Block[3].SetCol(m_Block[0].GetCol() + 3);
break;
case Shape2:
m_Block[1].SetX(m_Block[0].GetX());
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol());
m_Block[2].SetX(m_Block[0].GetX());
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[2].SetCol(m_Block[0].GetCol());
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 3);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 3);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 3);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape3:
m_Block[1].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol() - 1);
m_Block[2].SetX(m_Block[0].GetX());
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol());
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol() + 1);
break;
case Shape4:
m_Block[1].SetX(m_Block[0].GetX());
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol());
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol() + 1);
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape5:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 2);
m_Block[2].SetY(m_Block[0].GetY());
m_Block[2].SetRow1(m_Block[0].GetRow1());
m_Block[2].SetRow2(m_Block[0].GetRow2());
m_Block[2].SetCol(m_Block[0].GetCol() + 2);
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol() + 1);
break;
case Shape6:
m_Block[1].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol() - 1);
m_Block[2].SetX(m_Block[0].GetX());
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol());
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape7:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 2);
m_Block[2].SetY(m_Block[0].GetY());
m_Block[2].SetRow1(m_Block[0].GetRow1());
m_Block[2].SetRow2(m_Block[0].GetRow2());
m_Block[2].SetCol(m_Block[0].GetCol() + 2);
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 2);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol() + 2);
break;
case Shape8:
m_Block[1].SetX(m_Block[0].GetX());
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol());
m_Block[2].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[2].SetCol(m_Block[0].GetCol() - 1);
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape9:
m_Block[1].SetX(m_Block[0].GetX());
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol());
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol() + 1);
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 2);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol() + 2);
break;
case Shape10:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX());
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol());
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape11:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 2);
m_Block[2].SetY(m_Block[0].GetY());
m_Block[2].SetRow1(m_Block[0].GetRow1());
m_Block[2].SetRow2(m_Block[0].GetRow2());
m_Block[2].SetCol(m_Block[0].GetCol() + 2);
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape12:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol() + 1);
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol() + 1);
break;
case Shape13:
m_Block[1].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH * 2);
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol() - 2);
m_Block[2].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol() - 1);
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape14:
m_Block[1].SetX(m_Block[0].GetX());
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol());
m_Block[2].SetX(m_Block[0].GetX());
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[2].SetCol(m_Block[0].GetCol());
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol() + 1);
break;
case Shape15:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol() + 1);
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH * 2);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol() + 2);
break;
case Shape16:
m_Block[1].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol() - 1);
m_Block[2].SetX(m_Block[0].GetX());
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol());
m_Block[3].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol() - 1);
break;
case Shape17:
m_Block[1].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[1].SetY(m_Block[0].GetY());
m_Block[1].SetRow1(m_Block[0].GetRow1());
m_Block[1].SetRow2(m_Block[0].GetRow2());
m_Block[1].SetCol(m_Block[0].GetCol() + 1);
m_Block[2].SetX(m_Block[0].GetX() - BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol() - 1);
m_Block[3].SetX(m_Block[0].GetX());
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[3].SetCol(m_Block[0].GetCol());
break;
case Shape18:
m_Block[1].SetX(m_Block[0].GetX());
m_Block[1].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[1].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[1].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[1].SetCol(m_Block[0].GetCol());
m_Block[2].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[2].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH);
m_Block[2].SetRow1(m_Block[0].GetRow1() + 1);
m_Block[2].SetRow2(m_Block[0].GetRow2() + 1);
m_Block[2].SetCol(m_Block[0].GetCol() + 1);
m_Block[3].SetX(m_Block[0].GetX() + BLOCKSIDELENGTH);
m_Block[3].SetY(m_Block[0].GetY() + BLOCKSIDELENGTH * 2);
m_Block[3].SetRow1(m_Block[0].GetRow1() + 2);
m_Block[3].SetRow2(m_Block[0].GetRow2() + 2);
m_Block[3].SetCol(m_Block[0].GetCol() + 1);
break;
default:
break;
}
m_NextShape = (m_NextShape + 1) % 4;
}
void CFigure::SetIsExist(bool I_IsExist)
{
m_IsExist = I_IsExist;
return;
}
bool CFigure::GetIsExist() const
{
return m_IsExist;
}
void CFigure::Create()
{
if (m_IsExist)
{
return;
}
srand(time(nullptr));
int Shape = rand() % 7;
switch (Shape)
{
case 0:
Set_m_Block(Shape0);
m_Shape[0] = Shape0;
m_Shape[1] = Shape0;
m_Shape[2] = Shape0;
m_Shape[3] = Shape0;
break;
case 1:
Set_m_Block(Shape1);
m_Shape[0] = Shape1;
m_Shape[1] = Shape2;
m_Shape[2] = Shape1;
m_Shape[3] = Shape2;
break;
case 2:
Set_m_Block(Shape3);
m_Shape[0] = Shape3;
m_Shape[1] = Shape4;
m_Shape[2] = Shape5;
m_Shape[3] = Shape6;
break;
case 3:
Set_m_Block(Shape7);
m_Shape[0] = Shape7;
m_Shape[1] = Shape8;
m_Shape[2] = Shape9;
m_Shape[3] = Shape10;
break;
case 4:
Set_m_Block(Shape11);
m_Shape[0] = Shape11;
m_Shape[1] = Shape12;
m_Shape[2] = Shape13;
m_Shape[3] = Shape14;
break;
case 5:
Set_m_Block(Shape15);
m_Shape[0] = Shape15;
m_Shape[1] = Shape16;
m_Shape[2] = Shape15;
m_Shape[3] = Shape16;
break;
case 6:
Set_m_Block(Shape17);
m_Shape[0] = Shape17;
m_Shape[1] = Shape18;
m_Shape[2] = Shape17;
m_Shape[3] = Shape18;
break;
default:
break;
}
m_NextShape = 1;
m_IsExist = true;
}
void CFigure::Set_m_Block(ShapeCode I_ShapeCode)
{
switch (I_ShapeCode)
{
case Shape0:
m_Block[0].Create(XINIT, YINIT, Color0, true, -2, 4);
m_Block[1].Create(XINIT + BLOCKSIDELENGTH, YINIT, Color0, true, -2, 5);
m_Block[2].Create(XINIT, YINIT + BLOCKSIDELENGTH, Color0, true, -1, 4);
m_Block[3].Create(XINIT + BLOCKSIDELENGTH, YINIT + BLOCKSIDELENGTH, Color0, true, -1, 5);
break;
case Shape1:
m_Block[0].Create(XINIT, YINIT, Color1, true, -2, 4);
m_Block[1].Create(XINIT + BLOCKSIDELENGTH, YINIT, Color1, true, -2, 5);
m_Block[2].Create(XINIT + BLOCKSIDELENGTH * 2, YINIT, Color1, true, -2, 6);
m_Block[3].Create(XINIT + BLOCKSIDELENGTH * 3, YINIT, Color1, true, -2, 7);
break;
case Shape3:
m_Block[0].Create(XINIT, YINIT, Color2, true, -2, 4);
m_Block[1].Create(XINIT - BLOCKSIDELENGTH, YINIT + BLOCKSIDELENGTH, Color2, true, -1, 3);
m_Block[2].Create(XINIT, YINIT + BLOCKSIDELENGTH, Color2, true, -1, 4);
m_Block[3].Create(XINIT + BLOCKSIDELENGTH, YINIT + BLOCKSIDELENGTH, Color2, true, -1, 5);
break;
case Shape7:
m_Block[0].Create(XINIT, YINIT, Color3, true, -2, 4);
m_Block[1].Create(XINIT + BLOCKSIDELENGTH, YINIT, Color3, true, -2, 5);
m_Block[2].Create(XINIT + BLOCKSIDELENGTH * 2, YINIT, Color3, true, -2, 6);
m_Block[3].Create(XINIT + BLOCKSIDELENGTH * 2, YINIT + BLOCKSIDELENGTH, Color3, true, -1, 6);
break;
case Shape11:
m_Block[0].Create(XINIT, YINIT, Color4, true, -2, 4);
m_Block[1].Create(XINIT + BLOCKSIDELENGTH, YINIT, Color4, true, -2, 5);
m_Block[2].Create(XINIT + BLOCKSIDELENGTH * 2, YINIT, Color4, true, -2, 6);
m_Block[3].Create(XINIT, YINIT + BLOCKSIDELENGTH, Color4, true, -1, 4);
break;
case Shape15:
m_Block[0].Create(XINIT, YINIT, Color5, true, -2, 4);
m_Block[1].Create(XINIT + BLOCKSIDELENGTH, YINIT, Color5, true, -2, 5);
m_Block[2].Create(XINIT + BLOCKSIDELENGTH, YINIT + BLOCKSIDELENGTH, Color5, true, -1, 5);
m_Block[3].Create(XINIT + BLOCKSIDELENGTH * 2, YINIT + BLOCKSIDELENGTH, Color5, true, -1, 6);
break;
case Shape17:
m_Block[0].Create(XINIT, YINIT, Color6, true, -2, 4);
m_Block[1].Create(XINIT + BLOCKSIDELENGTH, YINIT, Color6, true, -2, 5);
m_Block[2].Create(XINIT - BLOCKSIDELENGTH, YINIT + BLOCKSIDELENGTH, Color6, true, -1, 3);
m_Block[3].Create(XINIT, YINIT + BLOCKSIDELENGTH, Color6, true, -1, 4);
break;
default:
break;
}
}
CBlock *CFigure::Get_m_Block()
{
return m_Block;
}
ShapeCode *CFigure::Get_m_Shape()
{
return m_Shape;
}
int CFigure::GetNextShape() const
{
return m_NextShape;
}
CTetris::CTetris(QWidget *parent)
: QWidget(parent)
{
ui.setupUi(this);
connect(&m_StartButton, &QPushButton::clicked, this, &CTetris::GameStartSlot);
connect(this, &CTetris::GameOverSignal, this, &CTetris::GameOverSlot);
setFixedSize(WINW, WINH);
m_StartButton.setParent(this);
m_StartButton.setText("开始游戏");
m_StartButton.move(15, 0);
startTimer(100);
this->grabKeyboard();
m_IsStart = false;
}
CTetris::~CTetris()
{
}
void CTetris::GameStartSlot()
{
m_StartButton.setEnabled(false);
Start();
}
void CTetris::GameOverSlot()
{
Over();
m_StartButton.setEnabled(true);
}
void CTetris::paintEvent(QPaintEvent *)
{
if (m_IsStart)
{
Draw();
}
}
void CTetris::timerEvent(QTimerEvent *)
{
if (m_IsStart)
{
//下落
if (CheckDropDown())//可以下落
{
m_Figure.DropDown();
update();
}
else//不能下落
{
if (IsOver())
{
emit this->GameOverSignal();
}
else
{
FixFigure();
CalculateScore();
update();
}
}
}
}
void CTetris::keyPressEvent(QKeyEvent *I_Event)
{
if (m_IsStart)
{
char Key = I_Event->key();
switch (Key)
{
case 'A':
case 'a':
case 'D':
case 'd':
if (CheckMove(Key))
{
m_Figure.Move(Key);
update();
}
break;
case 'W':
case 'w':
if (CheckVary())
{
m_Figure.Vary();
update();
}
break;
case 'S':
case 's':
if (CheckDropDownS())
{
m_Figure.DropDown(CalDropDownRow());
update();
}
break;
default:
break;
}
}
}
void CTetris::keyReleaseEvent(QKeyEvent *I_Event)
{
}
void CTetris::Start()
{
if (m_IsStart)
{
return;
}
m_Figure.Create();
m_Score = 0;
m_IsStart = true;
}
void CTetris::Over()
{
m_IsStart = false;
m_Figure.SetIsExist(false);
for (int i = 0; i < ROWNUM; i++)
{
for (int j = 0; j < COLNUM; j++)
{
m_BlockArr[i][j].SetIsExist(false);
}
}
}
void CTetris::Draw()
{
m_Painter.begin(this);
QPen Pen(Qt::black);
QBrush Brush(QColor(255, 165, 0));
m_Painter.setPen(Pen);
m_Painter.setBrush(Brush);
Brush.setStyle(Qt::SolidPattern);
//绘制游戏界面整体框架
for (int X = XINIT - BLOCKSIDELENGTH*3; X < XINIT + BLOCKSIDELENGTH * 5; X += BLOCKSIDELENGTH)
{
m_Painter.drawRect(X, YUP - BLOCKSIDELENGTH*3 - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
}
for (int X = XLEFT; X < XINIT-BLOCKSIDELENGTH * 2; X += BLOCKSIDELENGTH)
{
m_Painter.drawRect(X, YUP - BLOCKSIDELENGTH - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
}
for (int X = XINIT+BLOCKSIDELENGTH*4; X < XRIGHT; X += BLOCKSIDELENGTH)
{
m_Painter.drawRect(X, YUP - BLOCKSIDELENGTH - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
}
for (int X = XLEFT; X < XRIGHT; X += BLOCKSIDELENGTH)
{
m_Painter.drawRect(X, YDOWN + 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
}
for (int Y = YUP; Y < YDOWN; Y += BLOCKSIDELENGTH)
{
m_Painter.drawRect(XLEFT - BLOCKSIDELENGTH - 5, Y, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XRIGHT + 5, Y, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XRIGHT + 215, Y, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
}
for (int X = XRIGHT + 30; X < XRIGHT + 210; X += BLOCKSIDELENGTH)
{
m_Painter.drawRect(X, YUP - BLOCKSIDELENGTH - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(X, YDOWN + 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(X, YUP + 100, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
}
m_Painter.drawRect(XLEFT - BLOCKSIDELENGTH - 5, YUP - BLOCKSIDELENGTH - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XRIGHT + 5, YUP - BLOCKSIDELENGTH - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XLEFT - BLOCKSIDELENGTH - 5, YDOWN + 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XRIGHT + 5, YDOWN + 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XRIGHT + 215, YUP - BLOCKSIDELENGTH - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XRIGHT + 215, YDOWN + 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XINIT - BLOCKSIDELENGTH * 3, YUP - BLOCKSIDELENGTH * 2 - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawRect(XINIT + BLOCKSIDELENGTH * 4, YUP - BLOCKSIDELENGTH * 2 - 5, BLOCKSIDELENGTH, BLOCKSIDELENGTH);
m_Painter.drawLine(XLEFT, YUP, XRIGHT, YUP);
m_Painter.drawLine(XLEFT, YUP, XLEFT, YDOWN);
m_Painter.drawLine(XRIGHT, YUP, XRIGHT, YDOWN);
m_Painter.drawLine(XLEFT, YDOWN, XRIGHT, YDOWN);
//绘制提示区
char Str[24] = { 0 };
sprintf_s(Str, "得分:%d", m_Score);
m_Painter.drawText(XRIGHT + 60, YUP + 60, Str);
m_Painter.drawText(XRIGHT + 60, YUP + 160, "W:调整形状");
m_Painter.drawText(XRIGHT + 60, YUP + 200, "A:左移");
m_Painter.drawText(XRIGHT + 60, YUP + 240, "D:右移");
m_Painter.drawText(XRIGHT + 60, YUP + 280, "S:下落");
//绘制游戏区
for (int i = 0; i < ROWNUM; i++)
{
for (int j = 0; j < COLNUM; j++)
{
m_BlockArr[i][j].Draw(m_Painter);
}
}
m_Figure.Draw(m_Painter);
m_Painter.end();
}
bool CTetris::CheckDropDown()
{
CBlock *pBlock;
pBlock = m_Figure.Get_m_Block();
if (pBlock[0].GetRow1() == pBlock[0].GetRow2())
{
for (int i = 0; i < 4; i++)
{
if ((ROWNUM - 1) == pBlock[i].GetRow1() || (0<=(pBlock[i].GetRow1() + 1)&&m_BlockArr[pBlock[i].GetRow1() + 1][pBlock[i].GetCol()].GetIsExist()))
{
return false;
}
}
}
return true;
}
bool CTetris::CheckDropDownS()
{
CBlock *pBlock;
pBlock = m_Figure.Get_m_Block();
for (int i = 0; i < 4; i++)
{
if (0 > pBlock[i].GetRow1())
{
return false;
}
}
return true;
}
int CTetris::CalDropDownRow()
{
int Row = 0;
bool DropFlag = true;
CBlock *pBlock;
pBlock = m_Figure.Get_m_Block();
while (true)
{
Row++;
DropFlag = true;
for (int i = 0; i < 4; i++)
{
if ((ROWNUM-1) < (pBlock[i].GetRow2() + Row) || m_BlockArr[pBlock[i].GetRow2() + Row][pBlock[i].GetCol()].GetIsExist())
{
DropFlag = false;
}
}
if (!DropFlag)
{
Row--;
break;
}
}
return Row;
}
bool CTetris::CheckMove(char I_Direction)
{
CBlock *pBlock;
pBlock = m_Figure.Get_m_Block();
for (int i = 0; i < 4; i++)
{
if (0 > pBlock[i].GetRow1())
{
return false;
}
}
if ('A' == I_Direction || 'a' == I_Direction)
{
for (int i = 0; i < 4; i++)
{
if (0 == pBlock[i].GetCol() || m_BlockArr[pBlock[i].GetRow2()][pBlock[i].GetCol() - 1].GetIsExist() || m_BlockArr[pBlock[i].GetRow1()][pBlock[i].GetCol() - 1].GetIsExist())
{
return false;
}
}
}
else if ('D' == I_Direction || 'd' == I_Direction)
{
for (int i = 0; i < 4; i++)
{
if ((COLNUM-1) == pBlock[i].GetCol() || m_BlockArr[pBlock[i].GetRow2()][pBlock[i].GetCol() + 1].GetIsExist() || m_BlockArr[pBlock[i].GetRow1()][pBlock[i].GetCol() + 1].GetIsExist())
{
return false;
}
}
}
return true;
}
bool CTetris::CheckVary()
{
CBlock *pBlockTemp;
pBlockTemp = m_Figure.Get_m_Block();
for (int i = 0; i < 4; i++)
{
if (0 > pBlockTemp[i].GetRow1())
{
return false;
}
}
CFigure TempFigure(m_Figure);
TempFigure.Vary();
CBlock *pBlock;
pBlock = TempFigure.Get_m_Block();
for (int i = 0; i < 4; i++)
{
if (0 > pBlock[i].GetCol() || (COLNUM-1) < pBlock[i].GetCol()
|| 0 > pBlock[i].GetRow1() || (ROWNUM-1) < pBlock[i].GetRow1()
|| 0 > pBlock[i].GetRow2() || (ROWNUM - 1) < pBlock[i].GetRow2()
|| m_BlockArr[pBlock[i].GetRow1()][pBlock[i].GetCol()].GetIsExist()
|| m_BlockArr[pBlock[i].GetRow2()][pBlock[i].GetCol()].GetIsExist())
{
return false;
}
}
return true;
}
void CTetris::Eliminate(int I_Row)
{
for (int i = I_Row; i > 0; i--)
{
for (int j = 0; j < COLNUM; j++)
{
m_BlockArr[i][j].SetColor(m_BlockArr[i - 1][j].GetColor());
m_BlockArr[i][j].SetIsExist(m_BlockArr[i - 1][j].GetIsExist());
}
}
for (int j = 0; j < COLNUM; j++)
{
m_BlockArr[0][j].SetIsExist(false);
}
}
void CTetris::CalculateScore()
{
CBlock *pBlock;
pBlock = m_Figure.Get_m_Block();
bool IsEliminate = true;
int MinRow = pBlock[0].GetRow1();
int MaxRow = pBlock[3].GetRow1();
for (int i = MinRow; i <= MaxRow; i++)
{
for (int j = 0; j < COLNUM; j++)
{
if (!(m_BlockArr[i][j].GetIsExist()))
{
IsEliminate = false;
}
}
if (IsEliminate)
{
Eliminate(i);
m_Score += 10;
}
IsEliminate = true;
}
m_Figure.Create();
}
bool CTetris::IsOver()
{
CBlock *pBlock;
pBlock = m_Figure.Get_m_Block();
for (int i = 0; i < 4; i++)
{
assert(pBlock[i].GetRow1() == pBlock[i].GetRow2());
if (0 == pBlock[i].GetRow1())
{
return true;
}
}
return false;
}
void CTetris::FixFigure()
{
CBlock *pBlock;
pBlock = m_Figure.Get_m_Block();
for (int i = 0; i < 4; i++)
{
assert(pBlock[i].GetRow1() == pBlock[i].GetRow2());
m_BlockArr[pBlock[i].GetRow1()][pBlock[i].GetCol()].Copy(pBlock[i]);
}
m_Figure.SetIsExist(false);
}
main.cpp
#include "tetris.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CTetris w;
w.show();
return a.exec();
}版权声明:本文为lionel_z原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。