1、俄罗斯方块游戏Main.cpp主程序代码:#include #include #include tetrixwindow.hint main(int argc, char *argv) / 为了能够正常显示中文,设置Tr编码环境为GB2312 (详见wiki) QTextCodec:setCodecForTr(QTextCodec:codecForName(GB2312); / app这个对象用于管理应用级别的资源 QApplication app(argc, argv); app.setStyleSheet(TetrixBoard background-color:lightGray); T
2、etrixWindow window; window.setWindowIcon(QIcon(:/Chrome.ico); window.show(); / 当前时间作为随机种子 qsrand(QTime(0,0,0).secsTo(QTime:currentTime(); return app.exec(); / 程序的事件循环Tetrixboard.h头文件代码:/ 主游戏区类#ifndef TETRIXBOARD_H#define TETRIXBOARD_H#include tetrixpiece.h#include #include #include #include / 前向声明cl
3、ass QLabel;class TetrixBoard : public QFrame精选文档 Q_OBJECTpublic: TetrixBoard(QWidget *parent = 0); void setNextPieceLabel(QLabel *label); QSize sizeHint() const;/最适合大小 QSize minimumSizeHint() const; / 最小限制public slots: / 公有槽 void start(); void pause();signals: / 信号:只需声明,根据参数变化来判断 void scoreChanged(i
4、nt score); void levelChanged(int level); void linesRemovedChanged(int numLines);protected: / 着色、键盘、计时事件:其中着色事件随着update()不断触发 void paintEvent(QPaintEvent *event); void keyPressEvent(QKeyEvent *event); void timerEvent(QTimerEvent *event);private: enum BoardWidth = 10, BoardHeight = 22 ; / 把主游戏区宽分成10等份
5、高分成22等份,也就是说每行有10小矩形,总共有22行 TetrixShape &shapeAt(int x, int y) return board(y * BoardWidth) + x; int timeoutTime() return 1000 / (1 + level); / contentsRect():返回当前布局(QLayout)的矩形,可访问其长、宽 (详见API) / conntentsRect().width()/BoardWidth 把游戏区矩形的宽分成了BoardWidth份 int squareWidth() return contentsRect().width
6、) / BoardWidth; / 同上,把高分成了BoardHeight份 int squareHeight() return contentsRect().height() / BoardHeight; / 此时squareWidth(),squareHeight()分别是分割后的小矩形宽和高精选文档 void clearBoard(); / 清屏 void dropDown(); / 下落事件 void oneLineDown();/ 下落一行 void pieceDropped(int dropHeight); void removeFullLines(); / 移除填满的行 voi
7、d newPiece(); / 新方块 void showNextPiece(); / 显示下一个方块 bool tryMove(const TetrixPiece &newPiece, int newX, int newY); / 判断方块是否可以移动 void drawSquare(QPainter &painter, int x, int y, TetrixShape shape); / 着色 QBasicTimer timer; / 相当于QLabel *nextPieceLabel(QPointer详见API) QPointer nextPieceLabel; bool isStar
8、ted; bool isPaused; bool isWaitingAfterLine; TetrixPiece curPiece; / 当前方块 TetrixPiece nextPiece; / 下一个方块 int curX; int curY; int numLinesRemoved; int numPiecesDropped; int score; int level; TetrixShape boardBoardWidth * BoardHeight;#endif / TETRIXBOARD_HTetrixboard.cpp程序代码:#include #include tetrixbo
9、ard.hTetrixBoard:TetrixBoard(QWidget *parent) : QFrame(parent)精选文档 / 设置游戏区框架风格:内浮雕 setFrameStyle(QFrame:Panel | QFrame:Sunken); / 增加游戏区键盘鼠标等事件的焦点集中 setFocusPolicy(Qt:StrongFocus); isStarted = false; / 初始化:未开始状态 isPaused = false; clearBoard(); / 初始清屏 nextPiece.setRandomShape(); / 下一方块获得一个随机形状/ tetrix
10、piece.h : tetrixpiece.cpp中使用void TetrixBoard:setNextPieceLabel(QLabel *label) nextPieceLabel = label;/ 游戏区合适大小QSize TetrixBoard:sizeHint() const return QSize(BoardWidth*15 + frameWidth()*2, BoardHeight*15 + frameWidth()*2);/ 游戏区最小大小QSize TetrixBoard:minimumSizeHint() const return QSize(BoardWidth*5
11、 frameWidth()*2, BoardHeight*5 + frameWidth()*2);/ 开始事件:slotsvoid TetrixBoard:start() / 如果已暂停,则启动无效 if (isPaused) return;精选文档 isStarted = true; / 标记已开始 isWaitingAfterLine = false; / 此参数为判断是否有方块正在下落,false为有方块正在下落中 / 初始各参数 numLinesRemoved = 0; numPiecesDropped = 0; score = 0; level = 1; clearBoard();
12、 / 清屏 / emit 信号发射:触发对应信号槽内的函数(相关connect()在tetrixwindow.cpp中) emit linesRemovedChanged(numLinesRemoved); emit scoreChanged(score); emit levelChanged(level); newPiece(); / 调用新方块 timer.start(timeoutTime(), this);/ 游戏开始计时/ 暂停事件:slotsvoid TetrixBoard:pause() / 如果未开始,则暂停无效 if (!isStarted) return; / 否则,若未暂
13、停,则赋值为暂停,反之,取消暂停,继续游戏 isPaused = !isPaused; if (isPaused) timer.stop(); / 游戏计时停止 else timer.start(timeoutTime(), this); / 否则继续计时 update(); / 刷新窗口:动态显示画面/ 游戏区方块着色精选文档/ 重定义绘图事件,当调用update()时进行重绘void TetrixBoard:paintEvent(QPaintEvent *event) QFrame:paintEvent(event); QPainter painter(this); QRect rect
14、 contentsRect(); / QRect定义了平面上的矩形 (详见API),是主游戏区 / 暂停的时候显示的信息 if (isPaused) painter.drawText(rect, Qt:AlignCenter, tr(游戏暂停); return; / BoardHeight*squareHeight() 相当于 contentsRect().Height(),是小网格的高 / 因为squareHeight() return contentsRect().Width()/BoardWidth(); / 见tetrixboard.h中的定义 int boardTop = rect
15、bottom() - BoardHeight*squareHeight(); for (int i=0; iBoardHeight; +i) for (int j=0; jBoardWidth; +j) / TetrixShape &shapeAt(int x, int y) return board(y * BoardWidth) + x; TetrixShape shape = shapeAt(j, BoardHeight-i-1); if (shape != NoShape) / rect.left() 返回游戏区矩形左边的x坐标,squareWidth()为小网格的宽度 drawSq
16、uare(painter, rect.left() + j*squareWidth(), boardTop + i*squareHeight(), shape); / 绘图 if (curPiece.shape() != NoShape) for (int i=0; ikey() case Qt:Key_Left: tryMove(curPiece, curX-1, curY); / 左移 break; case Qt:Key_Right: tryMove(curPiece, curX+1, curY); / 右移 break; case Qt:Key_Up: tryMove(curPiece
17、rotatedLeft(),curX,curY); / 方块左转 break; case Qt:Key_Down: dropDown(); / 快速下落 break; default: QFrame:keyPressEvent(event); / 计时时间void TetrixBoard:timerEvent(QTimerEvent *event)精选文档 if (event-timerId() = timer.timerId() / 如果还有方块已下落完毕 if (isWaitingAfterLine) isWaitingAfterLine = false; / 重标记为有方块正在下落 n
18、ewPiece(); / 添加新方块 (timeoutTime(), this); else oneLineDown(); /否则进行下落动作 else QFrame:timerEvent(event); / 清空游戏区所有绘图void TetrixBoard:clearBoard() for (int i=0; i 0) if (!tryMove(curPiece,curX,newY-1) break; -newY; +dropHeight; / 把下落高度传递给此函数精选文档 pieceDropped(dropHeight);/ 正常下落操作void TetrixBoard:oneLine
19、Down() if (!tryMove(curPiece, curX,curY-1) / 如果能移动,则下落一行 pieceDropped(0);/ 正常下落不几分/ 进行方块下落后的行为,如绘图,加分等 参数:下落方块的高度void TetrixBoard:pieceDropped(int dropHeight) for (int i=0; i= 0; -i) bool lineIsFull = true; / 判断是否已满一行 for (int j=0; j BoardWidth; +j) if (shapeAt(j,i)=NoShape) lineIsFull = false; brea
20、k; / 上面所有行下移 if (lineIsFull) +numFullLines; for(int k = i; k BoardHeight-1; +k) for (int j = 0; j BoardWidth; +j) shapeAt(j,k) = shapeAt(j, k+1); / 整行清零 for (int j = 0; j 0) numLinesRemoved += numFullLines; score += 10 * numFullLines; / 同时发送信号至相应的槽 emit linesRemovedChanged(numLinesRemoved); emit sco
21、reChanged(score); (500,this);精选文档 isWaitingAfterLine = true; curPiece.setShape(NoShape); update(); / 新方块void TetrixBoard:newPiece() curPiece = nextPiece; / 预先随机设置好一下块方块 nextPiece.setRandomShape(); showNextPiece(); / 设置其初始下落的位置,在游戏区顶部中央 curX = BoardWidth / 2 + 1; curY = BoardHeight-1 + curPiece.minY(
22、); / 判断其是否还能移动,如果不能,则停止游戏 if (!tryMove(curPiece, curX, curY) curPiece.setShape(NoShape);/ painter.drawText(rect,tr(游戏结束); timer.stop(); isStarted = false; / 展示下一个方块void TetrixBoard:showNextPiece() if (!nextPieceLabel) return; int dx = nextPiece.maxX() - nextPiece.minX() + 1; int dy = nextPiece.maxY(
23、) - nextPiece.minY() + 1; QPixmap pixmap(dx *squareWidth(), dy*squareHeight(); /映射要显示方块像素 QPainter painter(&pixmap); / 开始绘制该方块精选文档 painter.fillRect(pixmap.rect(), nextPieceLabel-palette().background(); / 先绘制要显示方块的背景色 / 再开始绘制方块本身 for (int i = 0; i setPixmap(pixmap);/ 最后加载它/ 判断是否还能移动bool TetrixBoard:t
24、ryMove(const TetrixPiece &newPiece, int newX, int newY) for (int i = 0; i 4; +i) int x = newX + newPiece.x(i); int y = newY - newPiece.y(i); if (x = BoardWidth | y = BoardHeight) return false; if (shapeAt(x,y) != NoShape) / 判断当前位置是否有其他方块 return false; curPiece = newPiece; curX = newX; curY = newY; u
25、pdate(); return true;/ int squareWidth() return contentsRect().width() / BoardWidth; / int squareHeight() return contentsRect().height() / BoardHeight; void TetrixBoard:drawSquare(QPainter &painter, int x,int y,TetrixShape shape)精选文档 / google色彩 static const QRgb colorTable8 = 0x000000, 0x1851ce, 0xc
26、61800, 0xefba00, 0x1851ce, 0x1ba823, 0xc61800, 0x606060 ; QColor color = colorTableint(shape); / 填充单元网格的颜色 / void fillRect(int x, int y, int width, int height, const QColor & color) painter.fillRect(x + 1, y + 1, squareWidth() - 2, squareHeight() - 2, color); painter.setPen(color.light(); / 左上角边框颜色
27、/ void drawLine(int x1, int y1, int x2, int y2) painter.drawLine(x, y + squareHeight() - 1, x, y); painter.drawLine(x, y, x + squareWidth() - 1, y); painter.setPen(color.dark(); / 右下角边框颜色 painter.drawLine(x + 1, y + squareHeight() - 1, x + squareWidth() - 1, y + squareHeight() - 1); painter.drawLine
28、x + squareWidth() - 1, y + squareHeight() - 1, x + squareWidth() - 1, y + 1);Tetrixpiece.h头文件代码:/ 俄罗斯方块类:方块形状/旋转情况#ifndef TETRIXPIECE_H#define TETRIXPIECE_H/ 定义一个枚举类型(0-7):无形状、Z字形、S字形、直线形,T字形,田字形形、L字形,翻转L字形enum TetrixShape NoShape, ZShape,SShape,LineShape,TShape,SquareShape, LShape,MirroredLShape ;
29、class TetrixPiece精选文档public: TetrixPiece() setShape(NoShape); / inline构造函数:初始设置成NoShape void setRandomShape(); / 设置随机规则 void setShape(TetrixShape shape); / 构造方块形状的数据结构 / 通过inline公有函数成员shape()访问私有数据成员pieceShape TetrixShape shape() const return pieceShape; int x(int index) const return coordsindex0; i
30、nt y(int index) const return coordsindex1; int minX() const; int maxX() const; int minY() const; int maxY() const; TetrixPiece rotatedLeft() const; / 左转private: void setX(int index, int x) coordsindex0 = x; void setY(int index, int y) coordsindex1 = y; TetrixShape pieceShape; / 枚举类型创建一个该枚举类型对象 int c
31、oords42;#endif / TETRIXPIECE_HTetrixpiece.cpp程序代码:#include #include tetrixpiece.h#include #include #include / 伪随机函数:利用当前系统时间增加随机性void TetrixPiece:setRandomShape() /QTime time = QTime:currentTime();精选文档 /qsrand( time.msec() + time.second()*1000 );/ 重设随机种子:当前时间为随机变量 setShape(TetrixShape(qrand()%7 + 1)
32、 / 共六种方块形状void TetrixPiece:setShape(TetrixShape shape) / 按TetrixShape枚举顺序构建: / 除NoShape外,每个形状由4个小方块组成,这里每行的四个坐标即4个小方块的坐标,其中横向为X,纵向为Y / ZShape SShape LineShape TShape SquareShape LShape MirroredLShape/ -1 0 1 2 -1 0 1 2 -1 0 1 2 -1 0 1 2 -1 0 1 2 -1 0 1 2 -1 0 1 2/ -1 * -1 * -1 * -1 -1 -1 * * -1 * *
33、/ 0 * * 0 * * 0 * 0 * * * 0 * * 0 * 0 */ 1 * 1 * 1 * 1 * 1 * * 1 * 1 */ 2 2 2 * 2 2 2 2 static const int coordsTable842 = 0, 0 , 0, 0 , 0, 0 , 0, 0 ,/ NoShape 0, -1 , 0, 0 , -1, 0 , -1, 1 , 0, -1 , 0, 0 , 1, 0 , 1, 1 , 0, -1 , 0, 0 , 0, 1 , 0, 2 , -1, 0 , 0, 0 , 1, 0 , 0, 1 , 0, 0 , 1, 0 , 0, 1 , 1, 1 , -1, -1 , 0, -1 , 0, 0 , 0, 1 , 1, -1 , 0, -1 , 0, 0 , 0, 1 ; for (int i=0; i4; i+) for (int j=0; j2; +j) coordsij = coordsTableshapeij; pieceShape = shape;精选文档/ 获取最小X坐标值,QtGlobal:qMinint TetrixPiece:minX() const int min = coords00; for (int i = 1; i 4; +i) min = qMin(min, coo