课程咨询 :18357109557 QQ:3163902815

杭州达内T计划

  • 我的俄罗斯方块项目总结

    发布:杭州达内      来源:达内培训      时间:2015-07-27

  • 获奖学员:陈启壮

    所获奖项:三等奖

    内容

    俄罗斯方块一共三个类中间用等号隔开

    软件的开发过程

    1 明确业务需求

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

    ...

    2 业务分析

    找到有哪些业务对象,和图片的分析

    tetris(俄罗斯方块)

    |-- score 累计分数

    |-- lines 销毁的行数

    |-- Wall(墙 20行x10列)

    |-- 20row(行)

    |--10 col cell(列)

    |-- tetromino(4格方块,有7种形态)

    |-- 4 cell

    |--nextOne 下一个准备下落的方块

    |-- 4 cell

    3 数据模型,一切业务对象转换为数字表示

    场地按照行列划分为20x10格子

    格子有属性row,col,color

    4 类 设计

    Tetris

    |-- int score

    |-- int lines

    |-- Cell[20][10] wall

    |-- Tetromino tetromino

    | |--Cell[4] cells

    |-- row

    |-- col

    |-- color

    5 算法设计,就是如何利用数据的计算实现软件的功能

    4格方块的初始形态: I S Z J L T O

    就在初始数据的数值状态设计

    四格方块的下落计算:就是将每个格子的row+1

    就是将下落的业务功能,转换为数字计算实现

    左右移动

    下落流程控制:控制方块下落与墙之间的控制关系

    1 合理的文字流程描述

    2 分析文字描述中的功能(动作)为方法

    3 用流程控制语句连接方法实现功能

    4 严格测试结果!TestCase

    左右移动流程控制

    分数计算

    界面的绘制

    键盘事件控制

    旋转流程控制

    加速下降流程控制

    开始流程控制(Timer)

    暂停流程控制

    继续流程控制

    结束流程控制

    首先是Cell类,最基本的类包含3个私有属性和get,set方法,重写Object类的toString输出方法,并规定格子所具有的3个移动功能

    package com.tarena.tetris;

    //包:小写英文字母,域名倒写.项目名

    /**

    * 最小的格子

    */

    public class Cell{

    private int row;

    private int col;

    private int color;

    public Cell(int row, int col, int color) {

    super();

    this.row = row;

    this.col = col;

    this.color = color;

    }

    public int getCol() {

    return col;

    }

    public void setCol(int col) {

    this.col = col;

    }

    public int getColor() {

    return color;

    }

    public void setColor(int color) {

    this.color = color;

    }

    public int getRow() {

    return row;

    }

    public void setRow(int row) {

    this.row = row;

    }

    public void left(){

    col--;

    }

    public void right(){

    col++;

    }

    public void drop(){

    row++;

    }

    public String toString(){

    return row+","+col;

    }

    }

    ===============================================================

    package com.tarena.tetris;

    import java.util.Arrays;

    import java.util.Timer;

    import java.util.TimerTask;

    import javax.swing.JPanel;//是能够显示的矩形面板区域

    import javax.swing.JFrame;//窗口框

    import javax.swing.border.LineBorder;//实现边框

    import java.awt.Color;

    import java.awt.Font;

    import java.awt.Graphics;

    import java.awt.event.KeyAdapter;

    import java.awt.event.KeyListener;

    import java.awt.event.KeyEvent;

    /*

    * 俄罗斯方块类

    * 俄罗斯方块 扩展了(extends)系统的显示面板,增加了墙和

    * 正在下落的方块

    * */

    public class Tetris extends JPanel{

    public static final int ROWS = 20;

    public static final int COLS= 10;

    /*代表方块下落着陆的墙*/

    private Cell[][] wall = new Cell[ROWS][COLS];

    /*是正在下落的方块*/

    private Tetromino tetromino;

    /*下一个进入的方块*/

    private Tetromino nextOne;

    private static int score;

    private int lines;

    Timer timer;

    private boolean gameOver = false;

    private boolean pause = false;//暂停

    private static final int[] SCORE_LEVEL={0,1,4,10,100};

    private static final Graphics Graphics = null;

    /*销毁(destory)满行*/ // 0 1 2 3 4

    /*在Tetris中添加方法,检查游戏是否结束*/

    public void rotateRightAction(){

    tetromino.rotateRight();

    if(outOfBounds()||coincide()){

    tetromino.rotateLeft();

    }

    }

    public void rotateLeftAction(){

    tetromino.rotateLeft();

    if(outOfBounds()||coincide()){

    tetromino.rotateRight();

    }

    }

    /*在Tetris中添加方法,检查游戏是否结束*/

    private boolean gameOver(){

    gameOver = wall[0][4]!=null;

    return gameOver;

    }

    /*在Tetris中添加方法*/

    public void hardDropAction(){

    while(canDrop()){

    tetromino.softDrop();

    }

    tetrominoLandToWall();

    destroy();

    if(gameOver()){

    gameOverAction();

    }

    nextTetromino();

    }

    public void destroy(){

    int lines = 0;//统计本次销毁的行数

    for(int row = 0 ;row

    Cell[] line = wall[row];

    if(fullCell(line)){

    clearLine(row,wall);

    lines++;//每消除一行就累计加1

    }

    }

    score += SCORE_LEVEL[lines];

    this.lines +=lines;

    }

    public static void clearLine(int row,Cell[][] wall ){

    for(int i=row;i>1;i--){

    System.arraycopy(wall[i-1],0,wall[i],0,wall[i].length);

    }

    Arrays.fill(wall[0],null);

    }

    public static boolean fullCell(Cell []line){

    for(int col = 0;col

    if(line[col]==null) {

    return false;//找到空格子,这行没有满

    }

    }

    return true;

    }

    public String toString(){//显示全部的墙

    String str = "";

    for(int row = 0;row

    Cell[] line = wall[row];

    for(int col = 0;col

    Cell cell = line[col];

    if(tetromino.contains (row,col)){

    str +=row+","+col+" ";

    }else{

    str = str + cell + " ";

    }

    }

    str +="\n";

    }

    return str;

    }

    /*4格方块下降流程

    * 方块移动到区域最下方或是着地到其他方块上无法移动时,

    * 就会固定到该处,而新的方法快出现在区域上方开始下落。

    * 如果能下降就继续下降,

    * 否则就着陆到墙上,并且生成(随机)下一个方块

    * */

    public void softDropAction(){

    if(canDrop()){//如果能下降

    tetromino.softDrop();//方块继续下降

    }else{

    tetrominoLandToWall();//着陆到墙上

    destroy();//

    if(gameOver()){

    gameOverAction();

    }

    nextTetromino();//生产(随机)下一个方块

    }

    }

    private void startGameAction(){

    gameOver = false;

    pause = false;

    score = 0;

    lines = 0;

    emptyWall();

    nextTetromino();

    repaint();

    timer = new Timer();

    timer.schedule(new TimerTask(){

    public void run(){

    softDropAction();

    repaint();

    }

    }, 500, 500);

    }

    private void emptyWall() {

    for(int row=0;row

    Arrays.fill(wall[row],null);

    }

    }

    /*清理游戏结束现场,如:停止定时器等*/

    private void gameOverAction() {

    timer.cancel();//停止定时器

    }

    /*检查 方块 是否能够继续下落:到底最低部,或者墙上

    * 的下方有方块,返回false不能下降,返回true可以下降

    * */

    public boolean canDrop(){

    //检查到底部

    Cell[] cells = tetromino.getCells();

    for(Cell cell:cells){

    if(cell.getRow()==ROWS-1){

    return false;

    }

    }

    //检查墙上下方是否有方块

    for(Cell cell:cells){

    int row = cell.getRow();

    int col = cell.getCol();

    Cell block = wall[row+1][col];

    if(block!=null){

    return false;

    }

    }

    return true;

    }

    /*方块“着陆”到墙上,

    * 取出每个小cell

    * 找到cell的行号row和列号col

    * 将cell放置到wall[row][col]位置上

    * */

    public void tetrominoLandToWall(){

    Cell[] cells = tetromino.getCells();

    for(Cell cell:cells){

    int row = cell.getRow();

    int col = cell.getCol();

    wall[row][col] = cell;

    }

    }

    /*生产(随机)下一个方块

    * 1 下一个变为当前的

    * 2 随机产生下一个

    * */

    public void nextTetromino(){

    if(nextOne==null){//第一次nextOne是null时候先生产一个

    nextOne = Tetromino.randomTetromino();

    }

    tetromino = nextOne;//下一个变为当前的

    nextOne = Tetromino.randomTetromino();//随机产生下一个

    if(tetromino==null){//处理第一次使用时候下一个是null

    tetromino=Tetromino.randomTetromino();

    }

    }

    /*以格子为单位左右移动方块

    * 1)如果遇到左右边界就不能移动了

    * 2)如果与墙上的格子相撞就不能移动了

    * 变通为:

    * 1)先将方块左移动,

    * 2)检查(移动结果是否出界),或者(重合)

    * 3)如果检查失败,就右移的回来

    *

    * */

    public void moveLeftAction(){

    tetromino.moveLeft();

    if(outOfBounds() || coincide()){

    tetromino.moveRight();

    }

    }

    private boolean outOfBounds() {

    Cell[] cells = tetromino.getCells();

    for (int i = 0; i < cells.length; i++) {

    Cell cell = cells[i];

    int row = cell.getRow();

    int col = cell.getCol();

    if(row == ROWS||col<0||col>=COLS){

    return true;

    }

    }

    return false;

    }

    private boolean coincide() {

    Cell[] cells = tetromino.getCells();

    for (int i = 0; i < cells.length; i++) {

    Cell cell = cells[i];

    int row = cell.getRow();

    int col = cell.getCol();

    if(row >0&&row0

    &&wall[row][col]!=null){

    return true;//重合

    }

    }

    return false;

    }

    public void moveRightAction(){

    tetromino.moveRight();

    if(outOfBounds() || coincide()){

    tetromino.moveLeft();

    }

    }

    public static final int CELL_SIZE = 25;

    /*在Tetris.java中添加main方法 作为软件的启动方法*/

    public static void main(String []args){

    JFrame frame = new JFrame("俄罗斯方块");

    int wigth =(COLS+8)*CELL_SIZE +100;

    int height =ROWS*CELL_SIZE +100;

    frame.setSize(wigth,height);

    frame.setLocationRelativeTo(null);//居中

    frame.setDefaultCloseOperation(

    JFrame.EXIT_ON_CLOSE);//设置关闭窗口就关闭软件

    frame.setLayout(null);//取消默认布局,取消自动充满

    Tetris panel = new Tetris();

    panel.setLocation(45,25);

    panel.setSize((COLS+8)*CELL_SIZE,ROWS*CELL_SIZE);

    panel.setBorder(new LineBorder(Color.black));

    frame.add(panel);//窗口中添加面板

    frame.setVisible(true);//显示窗口时候调用paint()

    panel.action();

    }

    /*动作方法,这里是让软件开始动作,*/

    public void action(){

    //wall[18][2] = new Cell(18,2,0xff0000);

    startGameAction();

    //重绘方法->尽快调用paint()

    //startGameAction();

    //this 是当前Tetris面板

    this.requestFocus();//为当前面板请求获得输入焦点

    //this对象就获得了输入焦点,以后任何的

    //键盘输入(包括左右方向键)目标就是这个面板对象了!

    //addKeyLIstener添加键盘监听,监听那些按键输入了

    this.addKeyListener(new KeyAdapter(){

    public void keyPressed(KeyEvent e) {

    int key = e.getKeyCode();//key按键

    if(gameOver){

    if(key==KeyEvent.VK_S){

    startGameAction();//启动游戏开始流程

    }

    return;

    }

    if(pause){

    if(key==KeyEvent.VK_C){

    continueAction();

    }return;

    }

    //System.out.println("Type:"+e.getKeyCode());

    switch(key){

    case KeyEvent.VK_RIGHT :moveRightAction();break;

    case KeyEvent.VK_LEFT :moveLeftAction();break;

    case KeyEvent.VK_DOWN :softDropAction();break;

    case KeyEvent.VK_UP :rotateRightAction();break;

    case KeyEvent.VK_SPACE :hardDropAction();break;

    case KeyEvent.VK_P :pasueAction();break;

    }

    //按键->方块移动方法->改变方块数据->repaint()

    //->尽快调用paint()->利用新数据绘制

    repaint();

    }

    private void continueAction() {

    pause = false;

    timer = new Timer();

    timer.schedule(new TimerTask(){

    public void run(){

    softDropAction();

    repaint();

    }

    }, 500, 500);

    }

    private void pasueAction() {

    pause = true;

    timer.cancel();

    }

    });

    }

    //JPanel 类利用paint(涂画)方法绘制界面

    //子类重写paint方法可以修改绘图逻辑

    public static final int BORDER_COLOR = 0x667799;

    public static final int BG_COLOR = 0xC3D5EA;

    public static final int FONT_COLOR = 0;

    public void paint(Graphics g) {

    //g 代表绑定在当前面板上的画笔

    //利用画笔在当前 面板上 绘制了一串字符!

    paintBackground(g);//填充背景

    paintWall(g);//绘制墙

    paintTetromino(g);//绘制当前方块

    paintNextOne(g);//绘制下一个方块

    paintScore(g);//绘制分数

    paintTetrisBorder(g);//绘制边线

    }

    private void paintScore(Graphics g) {

    int x = 12 * CELL_SIZE;

    int y = 5 * CELL_SIZE;

    Font font = new Font(getFont().getName(),Font.BOLD,25);

    String str = "分数: "+score;

    g.setColor(new Color(FONT_COLOR));

    g.setFont(font);

    g.drawString(str, x, y);

    y+=2*CELL_SIZE;

    str = "行数: "+lines;

    g.drawString(str, x, y);

    if(gameOver){

    str = "(T_T)![s]再来!";

    y+=2*CELL_SIZE;

    g.drawString(str, x, y);

    }

    if(pause){

    str = "[c]继续!";

    y+=2*CELL_SIZE;

    g.drawString(str, x, y);

    }else{

    str = "[p]暂停!";

    y+=2*CELL_SIZE;

    g.drawString(str, x, y);

    }

    }

    private void paintNextOne(Graphics g) {

    if(nextOne==null)//如果没有4格方块就返回,不绘制

    return;

    for (Cell cell : nextOne.getCells()) {

    int row = cell.getRow()+1;

    int col = cell.getCol()+9;

    int x = col*CELL_SIZE;

    int y = row*CELL_SIZE;

    g.setColor(new Color(cell.getColor()));

    g.fillRect(x, y, CELL_SIZE, CELL_SIZE);

    g.setColor(new Color(BORDER_COLOR));

    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);

    }

    }

    private void paintTetromino(Graphics g) {

    if(tetromino==null)//如果没有4格方块就返回,不绘制

    return;

    for (Cell cell : tetromino.getCells()) {

    int row = cell.getRow();

    int col = cell.getCol();

    int x = col*CELL_SIZE;

    int y = row*CELL_SIZE;

    g.setColor(new Color(cell.getColor()));

    g.fillRect(x, y, CELL_SIZE, CELL_SIZE);

    g.setColor(new Color(BORDER_COLOR));

    g.drawRect(x, y, CELL_SIZE, CELL_SIZE);

    }

    }

    private void paintWall(Graphics g) {

    for (int row = 0; row

    for (int col = 0; col < COLS; col++) {

    Cell cell = wall[row][col];

    int x = col*CELL_SIZE;

    int y = row*CELL_SIZE;

    if(cell == null){

    //g.setColor(new Color(BORDER_COLOR));

    // g.drawRect(x, y,

    // CELL_SIZE, CELL_SIZE);

    }else{

    g.setColor(new Color(cell.getColor()));

    g.fillRect(x, y,

    CELL_SIZE, CELL_SIZE);

    g.setColor(new Color(BORDER_COLOR));

    g.drawRect(col*CELL_SIZE, row*CELL_SIZE,

    CELL_SIZE, CELL_SIZE);

    }

    }

    }

    }

    private void paintBackground(Graphics g) {

    g.setColor(new Color(BG_COLOR));

    g.fillRect(0, 0, getWidth(), getHeight());

    }

    private void paintTetrisBorder(Graphics g) {

    g.setColor(new Color(BORDER_COLOR));

    g.drawRect(0, 0, CELL_SIZE*COLS, CELL_SIZE*ROWS-1);

    g.drawRect(CELL_SIZE*COLS,0,

    CELL_SIZE*8-1, CELL_SIZE*ROWS-1);

    }

    }

    ===============================================================

    package com.tarena.tetris;

    import java.util.Arrays;

    import java.util.Random;

    /*

    * 四格方块类,有7种子类:I T S Z J L O

    * */

    public abstract class Tetromino {

    public static final int I_COLOR =0xff6600;

    public static final int T_COLOR =0xffff00;

    public static final int S_COLOR =0x66ccff;

    public static final int Z_COLOR =0x00ff00;

    public static final int J_COLOR =0x0000ff;

    public static final int L_COLOR =0xcc00ff;

    public static final int O_COLOR =0xff0000;

    protected Cell[] cells = new Cell[4];

    /*四格方块的下落,是四个格子一起下落*/

    public void softDrop(){

    for(int i = 0;i

    cells[i].drop();

    }

    }

    /*向左移动一步*/

    public void moveLeft(){

    for(int i = 0;i

    Cell cell = cells[i];//引用赋值

    cell.left();

    }

    }

    public void moveRight(){

    //增强for循环,是传统数组迭代的“简化版本”,

    //也称为foreach循环(foreach迭代)(java 5以后)

    for(Cell cell:cells){//底层实现就是经典迭代

    cell.right();

    }

    }

    public Cell[] getCells() {

    return cells;

    }

    protected Offset[] states;//旋转的状态

    protected class Offset{

    int row0,col0;

    int row1,col1;

    int row2,col2;

    int row3,col3;

    public Offset(int row0, int col0, int row1,

    int col1, int row2, int col2,

    int row3, int col3){

    this.row0 = row0;

    this.col0 = col0;

    this.row1 = row1;

    this.col1 = col1;

    this.row2 = row2;

    this.col2 = col2;

    this.row3 = row3;

    this.col3 = col3;

    }

    }

    private int index = 10000-1;

    /*向右转*/

    public void rotateRight(){

    index++;

    Offset offset = states[index%states.length];

    Cell axis = cells[0];//找到轴(axis)的位置

    cells[0].setRow(offset.row0+axis.getRow());

    cells[0].setCol(offset.col0+axis.getCol());

    cells[1].setRow(offset.row1+axis.getRow());

    cells[1].setCol(offset.col1+axis.getCol());

    cells[2].setRow(offset.row2+axis.getRow());

    cells[2].setCol(offset.col2+axis.getCol());

    cells[3].setRow(offset.row3+axis.getRow());

    cells[3].setCol(offset.col3+axis.getCol());

    }

    public void rotateLeft(){

    index--;

    Offset offset = states[index%states.length];

    Cell axis = cells[0];//找到轴(axis)的位置

    cells[0].setRow(offset.row0+axis.getRow());

    cells[0].setCol(offset.col0+axis.getCol());

    cells[1].setRow(offset.row1+axis.getRow());

    cells[1].setCol(offset.col1+axis.getCol());

    cells[2].setRow(offset.row2+axis.getRow());

    cells[2].setCol(offset.col2+axis.getCol());

    cells[3].setRow(offset.row3+axis.getRow());

    cells[3].setCol(offset.col3+axis.getCol());

    }

    /*随机生成一个具体方法*/

    public static Tetromino randomTetromino() {

    Random random = new Random();

    int type = random.nextInt(7);//0~6

    switch(type){

    case 0:return new I();

    case 1:return new T();

    case 2:return new S();

    case 3:return new J();

    case 4:return new Z();

    case 5:return new L();

    case 6:return new O();

    }

    return null;

    }

    public String toString(){

    return Arrays.toString(cells);

    }

    public boolean contains(int row, int col) {

    for(int i =0;i

    Cell cell = cells[i];

    if(cell.getRow()==row && cell.getCol()==col){

    return true;

    }

    }

    return false;

    }

    }

    class I extends Tetromino{

    public I(){

    cells[0] = new Cell(0,4,I_COLOR);

    cells[1] = new Cell(0,3,I_COLOR);

    cells[2] = new Cell(0,5,I_COLOR);

    cells[3] = new Cell(0,6,I_COLOR);

    states = new Offset[]{

    new Offset(0,0,-1,0,1,0,2,0),

    new Offset(0,0,0,-1,0,1,0,2),

    };

    }

    }

    class T extends Tetromino{

    public T(){

    cells[0] = new Cell(0,4,T_COLOR);

    cells[1] = new Cell(0,3,T_COLOR);

    cells[2] = new Cell(0,5,T_COLOR);

    cells[3] = new Cell(1,4,T_COLOR);

    states = new Offset[]{

    new Offset(0,0,1,0,-1,0,0,1),

    new Offset(0,0,0,-1,0,1,1,0),

    new Offset(0,0,1,0,-1,0,0,-1),

    new Offset(0,0,0,1,0,-1,-1,0),

    };

    }

    }

    class S extends Tetromino{

    public S(){

    cells[0] = new Cell(0,4,S_COLOR);

    cells[1] = new Cell(0,5,S_COLOR);

    cells[2] = new Cell(1,3,S_COLOR);

    cells[3] = new Cell(1,4,S_COLOR);

    states = new Offset[]{

    new Offset(0,0,-1,0,1,1,0,1),

    new Offset(0,0,0,1,1,-1,1,0),

    };

    }

    }

    class Z extends Tetromino{

    public Z(){

    cells[0] = new Cell(0,4,Z_COLOR);

    cells[1] = new Cell(0,3,Z_COLOR);

    cells[2] = new Cell(1,4,Z_COLOR);

    cells[3] = new Cell(1,5,Z_COLOR);

    states = new Offset[]{

    new Offset(0,0,-1,1,0,1,1,0),

    new Offset(0,0,-1,-1,-1,0,0,1),

    };

    }

    }

    class J extends Tetromino{

    public J(){

    cells[0] = new Cell(0,4,J_COLOR);

    cells[1] = new Cell(0,3,J_COLOR);

    cells[2] = new Cell(0,5,J_COLOR);

    cells[3] = new Cell(1,5,J_COLOR);

    states = new Offset[]{

    new Offset(0,0,-1,0,1,0,1,-1),

    new Offset(0,0,0,1,0,-1,-1,-1),

    new Offset(0,0,1,0,-1,0,-1,1),

    new Offset(0,0,0,-1,0,1,1,1),

    };

    }

    }

    class L extends Tetromino{

    public L(){

    cells[0] = new Cell(0,4,L_COLOR);

    cells[1] = new Cell(0,3,L_COLOR);

    cells[2] = new Cell(0,5,L_COLOR);

    cells[3] = new Cell(1,3,L_COLOR);

    states = new Offset[]{

    new Offset(0,0,-1,0,1,0,-1,-1),

    new Offset(0,0,0,1,0,-1,-1,1),

    new Offset(0,0,1,0,-1,0,1,1),

    new Offset(0,0,0,-1,0,1,1,-1),

    };

    }

    }

    class O extends Tetromino{

    public O(){

    cells[0] = new Cell(0,4,O_COLOR);

    cells[1] = new Cell(0,5,O_COLOR);

    cells[2] = new Cell(1,4,O_COLOR);

    cells[3] = new Cell(1,5,O_COLOR);

    states = new Offset[]{

    new Offset(0,0,0,1,1,0,1,1),

    new Offset(0,0,0,1,1,0,1,1),

    };

    }

    }

上一篇:在达内,我们都很拼!

下一篇:努力不一定成功,但放弃肯定失败

最新开班日期  |  更多

Android--零基础全日制

Android--零基础全日制

开班日期:7月31

Android--零基础周末班

Android--零基础周末班

开班日期:7月31

Android--优质全日制班

Android--优质全日制班

开班日期:7月31

Android--优质周末班

Android--优质周末班

开班日期:7月31

  • 地址:杭州市西湖区文三路259号昌地火炬大厦1号楼14层
  • 课程培训电话:18357109557 QQ:3163902815     全国服务监督电话:400-111-8989
  • 服务邮箱 tousu@tedu.cn
  • 2002-2018 达内时代科技集团有限公司 版权所有 京ICP证8000853号-56