最近看了一本软件工程方面的书籍,由于书中缺乏完整的实例,所以想从一个小项目入手以期能对软件工程多一点实践认识 ,首先我看了Qt5.6.3自带的俄罗斯方块例子(在我电脑里面的路径是C:\Qt\Qt5.6.3\Examples\Qt-5.6.3\widgets\widgets\tetrix),还有一个俄罗斯方块的Java教学视频(地址:http://www.iqiyi.com/playlist420417802.html),打算将Qt版的Tetrix俄罗斯方块改写成Java版,下面是具体的过程。

一.  需求(软件功能的文字描述)

二. 需求分析(找对象)

三.  概要设计

3.1 数据模型

3.2 类的设计

四. 详细功能的设计

4.1 数据初始化

4.2 界面绘制

4.3 左右移动功能设计

4.4 下落功能设计

4.5 旋转功能设计

4.6 状态检测功能设计

五. 总结

一.  明确业务需求

用自然语言,将业务功能描述清楚

Tetris 专用词  俄罗斯方块

Tetromino 专用词 4格方块

俄罗斯方块的基本规则:

1)一个用于摆放小型正方形的平面虚拟场地,其标准大小:

行宽为10,列高为22,以每个小正方形为单位。

2)一组由4个小型正方形组成的规则图形,英文称为Tetromino,中文通称为方块共有7种,分别为ZShape, SShape, LineShape ,TShape, SquareShape , LShape , MirroredShape,空白则称为NoShape。

LineShape: 一次最多消除四层

MirroredShape: 最多消除三层,或消除两层

LShape:最多消除三层,或消除两层

SquareShape:消除一至二层

SShape:最多两层,容易造成孔洞

ZShape:最多两层,容易造成孔洞

TShape:最多两层

3)玩家操作有:旋转方块,以格子为单位左右移动方块,让方块加速下落。

4)方块移动到区域最下方或是着陆到其他方块上无法移动时,就会固定在该处,而新的方块出现在区域上方开始落下。

5)当区域中某一列横向格子全部由方块填满,则该行会消失并成为玩家的得分。删除的行数以及落下的块数越多,得分指数上升。

6)当固定的方块堆到区域最上方以至于新方块无法移动时游戏结束。

7)一般来说,游戏还会提示下一个要落下的方块,熟练的玩家会计算下一个方块,评估要如何进行。由于游戏能不断进行下去对商业游戏不太理想,所以一般还会随着游戏的进行不断提高方块的下落速度。

8)预先设置的随机发生器不断地将不同种类的方块输出到区域顶部。

9)不同形状的方块对应不同的颜色以增加画面效果。

二. 业务分析

根据流程图找出有哪些业务对象

窗口

|— TetrixBoard(俄罗斯方块)

|— score 累计分数

|— numLinesRemoved 移除的行数

|— board(游戏区域22行X10列)

|— TetrixPiece

|—curPiece正在下落的(4格方块,有7种形态)

|— newPiece下一个准备下落的方块

这里没有设计Cell类,以防止Tetris ,Tetromino, Cell 三个层次的类相互耦合,有利于明晰设计思路

三. 概要设计

1) 数据模型

设计方块类TetrixPiece,一切业务对象转换为数字表示,类的属性有自身的相对坐标coords[][],形状变量pieceShape,颜色变量color,在游戏区域的网格坐标gridX、gridY以及在窗口的位置坐标x、y等,方法有判断是否可以移动的tryMove(),方块移动函数drop()、moveLeft()、moveRight()、rotate(),检测当前方块状态函数changeStatus()等。

2)类的设计

TetrixPiece

属性

|—tb  对主窗口类TetrixBoard对象的引用,因为要用到主类的一些方法

|—coordsTable[][]  各种形状的方块对应的内部坐标表

|—stoped 方块是否停止的布尔变量

|—speedup 方块是否加速下落的布尔变量

|—x 方块在窗口的位置坐标,从左到右增大

|—y 方块在窗口的位置坐标,从上到下增大

|—gridX 方块在游戏区域的网格坐标,从左到右增大

|—gridY 方块在游戏区域的网格坐标,从下到上增大

|—color 方块的颜色

|—colorArr[] 各种方块对应的颜色表

|—pieceShape 方块的形状

|—coords[][] 方块的内部小格子坐标

方法

     |—TetrixPiece(TetrixBoard tb) 构造函数

|—setRandomShape() 初始化时随机设定方块类的形状

|—setShape(int shape) 设定方块的形状

|—x(int index) 读取指定的小方格的内部坐标

|—y(int index) 读取指定的小方格的内部坐标

|—minX() 方块的最小内部坐标

|—minY() 方块的最小内部坐标

|—maxX() 方块的最大内部坐标

|—maxY() 方块的最大内部坐标

|—drawNewPiece(Graphics g) 在预览区域画出下一个方块

|—draw(Graphics g) 画出当前方块

|—drop() 当前方块下落

|—rotate() 当前方块旋转90度

|—changeStatus() 检测当前方块状态

|—pieceDropped() 检测是否可以消行,统计成绩和升级

|—moveLeft() 当前方块左移

|—moveRight () 当前方块右移

|—tryMove(int newX, int newY) 判断当前方块可否向指定方向移动

|—keyPressed(KeyEvent e) 键盘按下事件响应

|—keyReleased(KeyEvent e) 键盘松开事件响应

TetrixBoard

属性

|— x 窗口位置

|— y 窗口位置

|— board[] 纪录游戏区域方块的位置

|— dropHeight 方块下落次数

|— numPiecesDropped 下落的方块个数

|— numLinesRemoved 移除的行数

|— isStarted  游戏是否开始

|— isPaused 游戏是否暂停

|— score 游戏成绩

|— level 当前等级

|— offScreenImage 双缓冲刷新屏幕用到的变量

|— curPiece 当前方块对象

|— newPiece 下一个方块对象

|— mf 文本字体对象

|— launcher() 主类初始化函数

|— update(Graphics g) 双缓冲刷新屏幕函数

|— drawSquare(Graphics g, int x, int y, int Shape) 画出一个指定颜色和位置的小方格,用于显示游戏区域累计的方块

|— paint(Graphics g) 系统自动调用的重绘函数

内部类

|— paintThread implements Runnable 绘制多线程内部类,用于控制新方块的生成和时间点

|— keyMonitor extends KeyAdapter 按键事件内部类

方法

        |— launcher() 初始化函数

|— clearBoard() 初始化时清空纪录方块位置的数组

|— removeFullLines() 通过更新方块位置纪录数组实现消行

|— main(String[] args) 程序主函数

四. 详细功能设计

1)数据初始化

设定主窗口的位置、大小、标题、背景、可见性、窗口监听器和键盘事件监听器等,初始化两个方块对象,指定它们的颜色和形状,清空纪录方块位置的数组。

2)界面绘制

在指定位置绘制一个200x440大小的矩形作为方块活动区域,在窗口右上角绘制下一个方块的预览图,在窗口右下角显示成绩、等级、按键提示信息。

3)方块左右移动功能设计

方法名:moveRight()

输入:curPiece 正在下落的方块

输出:curPiece 正在下落的方块

过程:如果正在下落的方块能够向右移动一下就移动,否则原地不动。如果没有超出边界或者没有压住另外一个方块,就可以移动。

如果移动成功,方块的x坐标要加上一个SIZE,gridX坐标则加1。

算法:

1)将gridX的坐标先尝试加1;

2)检测方块的各个小方格坐标是否超出边界或是碰上了已有的方块;

3)如果没有就更新方块坐标,否则方块坐标保持不变。

4)下落功能设计

方法名:drop()

   输入:curPiece 正在下落的方块

输出:curPiece 正在下落的方块

过程:如果方块能够向下移动一下就移动,否则原地不动。如果没有超出边界或者没有压住另外一个方块,就可以移动。

如果移动成功,方块的y坐标要加上一个SIZE,gridY坐标则减1。

算法:

1)将gridY的坐标先尝试减1;

2)检测方块的各个小方格坐标是否超出边界或是碰上了已有的方块;

3)如果没有就更新方块坐标,否则方块坐标保持不变。

5)旋转功能设计

方法名:rotate()

   输入:curPiece 正在下落的方块

输出:curPiece 正在下落的方块

过程:如果方块能够顺时针旋转90度就旋转,否则原地不动。如果没有超出边界或者没有压住另外一个方块,就可以旋转。

如果旋转成功,方块的各小方格内部x坐标变成原来的-y坐标,内部y坐标变成原来的x坐标。

算法:

1)将方块的各小方格坐标预先做变换;

2)检测方块的各个小方格坐标是否超出边界或是碰上了已有的方块;

3)如果没有就更新方块各小方格坐标,否则保持不变。

6)方块状态检测功能设计

方法名:changeStatus()

   输入:curPiece 正在下落的方块

输出:curPiece 正在下落的方块

过程:如果方块能够向下移动就返回,否则将方块停止状态变量设置为真,如果游戏没有结束就统计成绩,然后更新方块位置纪录数组,最后检测是否可以消行,如果能消行就再次更新方块位置纪录数组实现消行。

算法:

1)使用tryMove()函数检测是否能下落,如果不能将stoped状态变量设置为true,否则返回;

2)在stoped为true时,如果isStarted状态变量为真就进入pieceDroped()函数;

3)在pieceDroped()函数中先更新方块位置纪录数组board[]数组,将刚刚停止的方块“登记在册”,然后进入主类中的removeFullLines()函数;

4)在removeFullLines()函数中通过board[]数组先检查是否有满行的情况,有则再次更新board[]数组实现消行;

5)更新成绩和等级以及相关变量的值。

五. 总结

本次设计有以下几个地方值得一提:

1) 设计思路为自顶向下,框架就是TetrixBoard类和TetrixPiece两个类,一个类相当于一个模块,所以需要提高模块的内聚性,减少模块的耦合性,特别要尽量避免一个模块同多个模块之间的耦合,因此就本例来说,设计的类少一些更适合。

2)实现思路为迭代设计,TetrixBoard类和TetrixPiece两个类的属性和方法可以逐步添加。

3)为了避免屏幕闪烁,这里使用了java的双缓冲绘图技术(update()函数),其原理是先在内存中分配一个和我们动画窗口一样大的空间(缓冲区),然后利用getGraphics()方法去获得双缓冲画笔,接着利用双缓冲画笔在缓冲区中绘制我们想要的东西,最后将缓冲区一次性的绘制到窗体中显示出来,这样在我门的动画窗口上面显示出来的图像就非常流畅了。

4)在方块的移动,旋转,下落,以及消行中用到了一个非常重要的函数tryMove(),原理是利用方块的内部坐标计算出在假想位置的方块的各小方格的网格坐标,然后判断是否越界或是已被其他方块占据,这也是为什么使用三套坐标的原因,窗口坐标用于绘图,网格坐标和内部坐标用于逻辑判断。

5)方块形状数组的设计是一个三维数组,第一维是方块形状,第二维是方块内部的四个小方格的序号,第三维是小方格的横坐标和纵坐标,每个方块的内部原点坐标是(0,0),这样旋转时便于坐标变换。另外方块的形状和颜色是一一对应的,便于在重绘已经落下的方块时同时获取形状和颜色。

附录:源代码

TetrixPiece.java

package tetris;
import java.util.Random;
import java.lang.Math;
import java.awt.event.*;
import java.awt.*;

public class TetrixPiece {//TetrisClient的引用
    TetrixBoard tb;// 定义落下的方块的形状,包含NoShapepublic static int NoShape = 0, ZShape = 1, SShape = 2, LineShape =3,TShape = 4, SquareShape = 5, LShape = 6, MirroredShape = 7;public static int[][][] coordsTable = {{ { 0, 0 },   { 0, 0 },   { 0, 0 },   { 0, 0 } },{ { 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 } }};// 大小public static final int SIZE = 20;    // 下落的补偿public static final int SPEED = 20;// 是否停止public boolean stoped = false;// 是否按下向下键public boolean speedup = false;// 出现的位置,包括绝对位置和网格坐标public int x, y;public int gridX, gridY;private Color color = null;// 颜色数组public static Color[] colorArr = {new Color(255,20,147),new Color(0,0,139),new Color(139,0,0),new Color(128,128,0),new Color(56,94,15),new Color(0,128,128),new Color(139,101,8),new Color(255,99,71)};// 声明形状变量private int pieceShape;// 声明方块类的坐标变量,右四个小方块的相对坐标组成private int coords[][] = new int[4][2];// 构造函数public TetrixPiece(TetrixBoard tb) {this.tb = tb;setRandomShape();}// 随机设定方块类的形状public void setRandomShape() {Random r = new Random();int shapeIndex = r.nextInt(7) + 1;setShape(shapeIndex);} // 设定方块类的指定形状public void setShape(int shape) {// 设定方块对象的各小方块的坐标for (int i = 0; i < 4; i++) {for (int j = 0; j < 2; ++j)coords[i][j] = coordsTable[shape][i][j];}// 设定方块对象的形状pieceShape = shape;this.color = colorArr[shape];gridX = TetrixBoard.GRID_WIDTH / 2 + 1;gridY = TetrixBoard.GRID_HEIGHT - 1 + minY();x = TetrixBoard.CORRECT_X + gridX * SIZE;y = TetrixBoard.CORRECT_Y + (TetrixBoard.GRID_HEIGHT - 1 - gridY) * SIZE;}// 读取指定的小方块的x坐标public int x(int index) {return coords[index][0];}// 读取指定的小方块的y坐标public int y(int index) {return coords[index][1];}// 方块类的最小x坐标public int minX() {int min = coords[0][0];for (int i = 1; i < 4; ++i)min = Math.min(min, coords[i][0]);return min;}// 方块类的最大x坐标public int maxX() {int max = coords[0][0];for (int i = 1; i < 4; ++i)max = Math.max(max, coords[i][0]);return max;}// 方块类的最小y坐标public int minY() {int min = coords[0][1];for (int i = 1; i < 4; ++i)min = Math.min(min, coords[i][1]);return min;}// 方块类的最大y坐标public int maxY() {int max = coords[0][1];for (int i = 1; i < 4; ++i)max = Math.max(max, coords[i][1]);return max;}// 画出下一个方块public void drawNewPiece(Graphics g) {g.setColor(color);for(int i=0; i<4; i++) {Graphics2D g2 = (Graphics2D)g;g2.setStroke(new BasicStroke(3.0f));g2.drawRect(300 + x(i) * SIZE, 100 + y(i) * SIZE, SIZE-5, SIZE-5);g.fillRect(300 + x(i) * SIZE + 4, 100 + y(i) * SIZE + 4, SIZE - 12, SIZE - 12);}}// 画出当前方块public void draw(Graphics g) {g.setColor(color);for(int i=0; i<4; i++) {Graphics2D g2 = (Graphics2D)g;g2.setStroke(new BasicStroke(3.0f));g2.drawRect(x + x(i) * SIZE, y + y(i) * SIZE, SIZE-5, SIZE-5);g.fillRect(x + x(i) * SIZE + 4, y + y(i) * SIZE + 4, SIZE - 12, SIZE - 12);}}// 下落方法public void drop() {if(tryMove(gridX , gridY - 1) && !stoped) {y += SPEED;gridY -= 1;tb.dropHeight++;}}// 检测当前状态public void changeStatus() {if (!tryMove(gridX, gridY -1)) {stoped = true;if(tb.isStarted) pieceDropped();}}// 累积掉落块的次数并累计成绩public void pieceDropped(){//纪录已停止方块的位置信息for (int i = 0; i < 4; ++i) {int x = gridX + coords[i][0];int y = gridY - coords[i][1];tb.board[x + y * TetrixBoard.GRID_WIDTH] = pieceShape;}// 检测是否可以消行
        tb.removeFullLines();++tb.numPiecesDropped;if (tb.numPiecesDropped % 25 == 0) {++tb.level;}tb.score = tb.numPiecesDropped * 2 + tb.dropHeight;}// 方块类向左旋转90度public void rotate() {// 方块为田字形则直接返回TetrixPiece对象if (pieceShape == SquareShape || stoped)return ;// 假定可以选择并修改坐标for (int i = 0; i < 4; ++i) {int temp = coords[i][0];coords[i][0] = -coords[i][1];coords[i][1] = temp;}// 如果旋转测试失败则改回原来的坐标if(!tryMove(gridX, gridY)) {for (int i = 0; i < 4; ++i) {int temp = coords[i][0];coords[i][0] = coords[i][1];coords[i][1] = -temp;}}}// 向左移动public void moveLeft() {if(tryMove(gridX - 1, gridY) && !stoped) {x -= SIZE;gridX -= 1;}}// 向右移动public void moveRight() {if(tryMove(gridX + 1, gridY) && !stoped) {x += SIZE;gridX += 1;}}public boolean tryMove(int newX, int newY) {for (int i = 0; i < 4; ++i) {int x = newX + x(i);int y = newY - y(i);if (x < 0|| x >= TetrixBoard.GRID_WIDTH || y < 0 || y >= TetrixBoard.GRID_HEIGHT )return false;if (tb.board[x + y * 10] != NoShape)return false;}return true;}// 按键事件public void keyPressed(KeyEvent e) {int key = e.getKeyCode();if(key == KeyEvent.VK_Q){//退出当前的Java进程System.exit(0);}//如果暂停并且按键是[C]就继续动作if(tb.isPaused){if(key==KeyEvent.VK_C)    tb.isPaused = false;return;}switch(key) {case KeyEvent.VK_LEFT:moveLeft();tb.repaint();break;case KeyEvent.VK_RIGHT:moveRight();tb.repaint();break;case KeyEvent.VK_SPACE:rotate();tb.repaint();break;case KeyEvent.VK_DOWN:speedup = true;tb.repaint();break;case KeyEvent.VK_P:tb.isPaused = true;                }}// 按键事件public void keyReleased(KeyEvent e) {if(e.getKeyCode() == KeyEvent.VK_DOWN) {speedup = false;}}
}

TetrixBoard.java

package tetris;
import java.awt.*;
import java.awt.event.*;import java.awt.Font;public class TetrixBoard extends Frame {// 声明变量,窗口位置int x = 100;int y = 100;// 方块运动窗口为15x20格,以数组纪录其被窗口填充状况public int board[] = new int [220];// 下落次数public int dropHeight = 0;public int numPiecesDropped = 0;// 移除的行数public int numLinesRemoved = 0;// 开始游戏public boolean isStarted = true;// 暂停public boolean isPaused = false;// 总成绩public int score = 0;// 当前等级public int level = 0;// 程序窗口大小public static final int WIDTH = 400;public static final int HEIGHT = 500;// 游戏区域起始坐标public static final int CORRECT_X = 20;public static final int CORRECT_Y = 30;//游戏区域大小public static final int RECT_WIDTH = 200;public static final int RECT_HEIGHT = 440;//游戏区域网格大小public static final int GRID_WIDTH = 10;public static final int GRID_HEIGHT = 22;//双缓冲刷新用到的变量Image offScreenImage = null;// 声明一个TetrixPiece对象TetrixPiece newPiece = null;TetrixPiece curPiece = null;    // 设定文本字体Font mf = new Font("TimesRoman", Font.ITALIC, 18);public void launcher() {// 出现位置this.setLocation(x,y);// 大小this.setSize(WIDTH, HEIGHT);// 启动线程前先生成一个TetrixPiece实例curPiece = new TetrixPiece(this);newPiece = new TetrixPiece(this);//启动刷新线程new Thread(new paintThread()).start();// 可见性this.setVisible(true);// 窗口标题this.setTitle("Tetris Game");// 不可调整this.setResizable(false);// 布局管理this.setLayout(null);// 背景颜色this.setBackground(new Color(240,255,240));// 添加窗口监听器this.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent e) {System.exit(0);}});// 清空窗格this.clearBoard();// 添加按键事件监控this.addKeyListener(new keyMonitor());}// 屏幕双缓冲避免屏闪public void update(Graphics g) {// 在内存中开辟一个与当前窗口大小一致的空间if(offScreenImage == null) {offScreenImage = this.createImage(WIDTH, HEIGHT);}//建立Graphics对象,把要绘制的对象存放在分配好的内存空间Graphics gOffScreen = offScreenImage.getGraphics();Color c = gOffScreen.getColor();//设定内存对象背景颜色gOffScreen.setColor(new Color(240,255,240));gOffScreen.fillRect(0, 0, WIDTH, HEIGHT);gOffScreen.setColor(c);//绘制窗口到内存对象中
        paint(gOffScreen);//将内存对象一次性绘制到当前窗口,消除屏闪g.drawImage(offScreenImage, 0, 0, null);}// 画出一个指定颜色和位置的小方块public void drawSquare(Graphics g, int x, int y, int Shape) {g.setColor(TetrixPiece.colorArr[Shape]);Graphics2D g2 = (Graphics2D)g;g2.setStroke(new BasicStroke(3.0f));g2.drawRect(x, y , TetrixPiece.SIZE-5, TetrixPiece.SIZE-5);g.fillRect(x + 4, y  + 4, TetrixPiece.SIZE - 12, TetrixPiece.SIZE - 12);}@Overridepublic void paint(Graphics g) {Color c = g.getColor();// 设定红色画笔画框
        g.setColor(Color.MAGENTA);g.drawRect(CORRECT_X - 2 , CORRECT_Y, RECT_WIDTH, RECT_HEIGHT);// 设定文本颜色g.setColor(new Color(70,130,180));g.setFont(mf);g.drawString("Score : "+score, 260,200);g.drawString("Level : "+level, 260,240);g.drawString("Pause :  'p'", 260, 280);g.drawString("Continue :  'c'", 260, 320);g.drawString("Quit :  'q'", 260, 360);// 重新设回原来的颜色
        g.setColor(c);curPiece.draw(g);//curPiece.changeStatus();
        newPiece.drawNewPiece(g);// 因定时器产生的重绘向下走一格,若只是旋转不应下降故此处移除//if(!curPiece.stoped)//    curPiece.drop();// 重画已下落的方块for (int i = 0; i < GRID_HEIGHT; ++i) {for (int j = 0; j < GRID_WIDTH; ++j) {int shape = board[j + (GRID_HEIGHT - i - 1) * GRID_WIDTH];if (shape != TetrixPiece.NoShape) drawSquare(g, CORRECT_X + j * TetrixPiece.SIZE,CORRECT_Y + i * TetrixPiece.SIZE, shape);}}// 为防止消行时最后下落块没有及时重绘,此句放到最后
        curPiece.changeStatus();}// 刷新类private class paintThread implements Runnable {@Overridepublic void run() {while(true) {repaint();if(!curPiece.stoped && !isPaused)     curPiece.drop();//触底后再生成一个Shape实例if(curPiece.stoped && isStarted && !isPaused) {curPiece = newPiece;// 如果当前Shape实例不能移动则停止游戏if(!curPiece.tryMove(curPiece.gridX, curPiece.gridY))isStarted = false;newPiece = new TetrixPiece(TetrixBoard.this);}try{//向下键是否被按下if(!curPiece.speedup) {Thread.sleep(1000/(level + 1));} elseThread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}}}}// 按键事件内部类private class keyMonitor extends KeyAdapter {@Overridepublic void keyPressed(KeyEvent e) {curPiece.keyPressed(e);}@Overridepublic void keyReleased(KeyEvent e) {curPiece.keyReleased(e);}}// 窗格清空public void clearBoard(){for (int i = 0; i < 220; ++i)board[i] = TetrixPiece.NoShape;}// 检测是否可以消行public void removeFullLines(){int numFullLines = 0;// 是否可以消行for (int i = GRID_HEIGHT - 1; i >= 0; --i) {boolean lineIsFull = true;for (int j = 0; j < GRID_WIDTH; ++j) {if (board[j + i * GRID_WIDTH] == TetrixPiece.NoShape) {lineIsFull = false;break;}}// 可以消行则更新方块位置纪录数组if (lineIsFull) {++numFullLines;for (int k = i; k < GRID_HEIGHT - 1; ++k) {for (int j = 0; j < GRID_WIDTH; ++j)board[j + k * GRID_WIDTH] = board[j + (k + 1) * GRID_WIDTH];}for (int j = 0; j < GRID_WIDTH; ++j)board[j + (GRID_HEIGHT - 1) * GRID_WIDTH] = TetrixPiece.NoShape;}}// 消行后更新成绩if (numFullLines > 0) {numLinesRemoved += numFullLines;score += 10 * numFullLines;//isWaitingAfterLine = true;
            curPiece.setShape(TetrixPiece.NoShape);}}public static void main(String[] args) {new TetrixBoard().launcher();}
}

转载于:https://www.cnblogs.com/yangjd/p/10123251.html

俄罗斯方块的设计与实现相关推荐

  1. 基于.NET的俄罗斯方块课程设计

    前言 随着我国物质生活的巨大提高,人们的精神文化需求也不断提升,从温饱中解放出来的人们将会更多地关注娱乐活动.俄罗斯方块游戏就能够很好地满足人们日常简单的娱乐需求.俄罗斯方块游戏风靡于90年代,是现在 ...

  2. 俄罗斯android课程设计,基于Android的俄罗斯方块的设计与实现毕业设计报告.docx...

    PAGE \* MERGEFORMAT 24湖南商学院 <移动互联网应用开发> 课程设计报告 题 目 基于Android的俄罗斯方块的设计与实现 姓 名:学 号:专 业:班 级:指导教师: ...

  3. java毕业设计——基于Java+Java ME的无线网络移动端的俄罗斯方块游戏设计与实现(毕业论文+程序源码)——俄罗斯方块游戏

    基于Java+Java ME的无线网络移动端的俄罗斯方块游戏设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于Java+Java ME的无线网络移动端的俄罗斯方块游戏设计与实现,文章末尾附有 ...

  4. 基于Python的俄罗斯方块游戏设计与实现 报告+项目源码

    资源下载地址:https://download.csdn.net/download/sheziqiong/85630943 资源下载地址:https://download.csdn.net/downl ...

  5. java俄罗斯方块设计报告,俄罗斯方块课程设计报告

    <俄罗斯方块课程设计报告>由会员分享,可在线阅读,更多相关<俄罗斯方块课程设计报告(26页珍藏版)>请在人人文库网上搜索. 1.一.系统概述1.1现状分析在个人电脑日益普及的今 ...

  6. 基于android环境的俄罗斯方块,基于Android的俄罗斯方块的设计和实现完整版.doc

    TOC \o "1-3" \h \z \u 摘要Ⅰ AbstractⅡ 一 引言1 二 Android平台介绍2 2.1 平台背景概述2 2.2 系统概述2 2.3 Android ...

  7. linux俄罗斯方块课程报告,C俄罗斯方块课程设计报告书.doc

    C俄罗斯方块课程设计报告书 大学 C++面向对象课程设计报告 院(系): 计算机工程学院 专业: 学生姓名: 班级:_______ 学号:201007206 题目: 俄罗斯方块 起迄日期: _2012 ...

  8. java俄罗斯方块ppt_基于Java俄罗斯方块游戏设计与开发PPT.ppt

    基于Java俄罗斯方块游戏设计与开发PPT 基于Java的俄罗斯方块游戏的设计与实现 答 辩 人:xxx 学 号:201012120201 指导老师:xxx副教授 专 业:网络工程 学 院:信息科学与 ...

  9. python下俄罗斯方块的游戏设计_[源码和文档分享]基于Python的PyGame的俄罗斯方块游戏设计与实现...

    摘 要 近年来,随着游戏产业的突飞猛进,游戏玩家的技术也是与日俱增,当你看见游戏高手完美的表演时,你是否想过我也能达到那种水平,本程序用Python语言编写俄罗斯方块,左侧显示正在运行的游戏,右边显示 ...

  10. 俄罗斯方块的设计思路

    前段时间帮人写了个俄罗斯方块的Demo,今天有时间分享下设计思路. 分析: 游戏中会出现7种形状,每种形状在游戏中都能够旋转,形成新的形状.每种形状都是由方形的色块组成的. 数据类: Shape:形状 ...

最新文章

  1. hdu 1213 How Many Tables ([kuangbin带你飞]专题五 并查集)
  2. 关于c++类中的指针成员问题
  3. ArcEngine 图层标注 (根据字段、角度)
  4. how to become a very good candidate at the investment bank?
  5. vagrant 简单使用
  6. sqserver对比oracle的区别,oracle和sqlserver比较
  7. FortiAnalyzer-VM 安装使用
  8. Linux-- 查看文件 more与其它
  9. 2019年税收分类编码_通过分析112,654个编码测试,我们了解了2019年开发人员的招聘趋势...
  10. Node.js:POST请求、文件上传
  11. linux模拟http请求命令
  12. 传输线模型(分布参数模型)
  13. [从头学数学] 第203节 坐标系与参数方程
  14. LWN:怕不怕编译器优化让你的代码彻底乱套?
  15. mips和sparc交叉编译工具链网址
  16. 2.15范冰增长黑客读书笔记
  17. 手把手教你ECSHOP去版权与标志
  18. sublime text3--js智能提示插件以及其他常用插件
  19. 沃尔玛的产品知识图谱
  20. YC1090货车驱动桥的结构设计(有cad图)

热门文章

  1. oruxmaps离线地图下载(制作离线地图包)(全国任意地方的离线地图制作)
  2. 敢问出路在何方?——给资深程序员的一封推荐信
  3. java中如何实现qq登录与微博登录,如何从零开始对接第三方登录(Java版):QQ登录和微博登录(2)...
  4. 瑞芯微RK3568开发板深度评测
  5. 1.1 python图像的坐标变换-平移变换
  6. 链表之节点插入、删除节点、遍历打印、遍历释放,static 全局变量
  7. 摩托罗拉GP68对讲机官方说明书下载,包含使用说明压音表和电路结构等
  8. html5豌豆上的公主,安徒生童话《豌豆上的公主》主要内容
  9. ubuntu镜像快速下载
  10. php需要javascript,可以做程序化的php,想做javascript,需要先做oop php吗?