俄罗斯方块笔记

一.通过分析游戏界面,抽象出几种类型:

1.Cell(格子类)

2.Tetromino(四格方块类):七种组合的父类

根据父类,定义七种子类:T、I、O、J、L、S、Z

3.Tetris(主类)   extends   JPanel

提供静态属性,加载静态资源


Cell

属性:row(行号),col(列号),Image(图片)

方法:softDrop();       //下落

          moveLeft();      //向左移动

          moveRight();    //向右移动


Tetromino

方法:softDrop();       //下落

          moveLeft();      //向左移动

          moveRight();    //向右移动

          randomOne();  //随机生成四格方块

Tetris

方法:paint(Graphics g);//绘制方法

          paintWall(g);         //绘制墙

          piantCurrentOne(g);//绘制正在下落的四格方块

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


将七个子类封装到Tetromino,初始化四格方块的初始位置

以“L”型为例

初始位置:cell[0]=(0,4);

                 cell[1]=(0,3);

                 cell[2]=(0,5);

                 cell[3]=(1,3);




二.类的实现:

cell类:

package com.tetris;

import java.awt.image.BufferedImage;
/*俄罗斯方块的最小单位:方格
 * 特征(属性):
 * row--行号
 * col--列号
 * image--对应的图片
 * 
 * 行为(方法):
 * left()
 * right()
 * down()
 */
public class Cell {
	private int row;
	private int col;
	private BufferedImage image;
	public Cell () {}
	public Cell(int row, int col, BufferedImage image) {
		super();
		this.row = row;
		this.col = col;
		this.image = image;
	}
	public int getRow() {
		return row;
	}
	public void setRow(int row) {
		this.row = row;
	}
	public int getCol() {
		return col;
	}
	public void setCol(int col) {
		this.col = col;
	}
	public BufferedImage getImage() {
		return image;
	}
	public void setImage(BufferedImage image) {
		this.image = image;
	}
	@Override
	public String toString() {
		return "("+ row + ","+ col + ")";
	}
	/**向左移动*/
    public void left() {
    	col--;
	}
    /**向右移动*/
    public void right() {
    	col++;
    }
    /**向下移动*/
    public void drop() {
    	row++;
    }

Tetromino类:

package com.tetris;

import java.util.Arrays;

/*
 * 四格方块
 * 属性:
 * ------cells----四个方块
 * 行为:
 *      moveLeft()
 *      moveRight()
 *      softDrop()
 */
public class Tetromino {
	protected Cell[] cells=new Cell[4];
	public void moveLeft() {
		for(int i=0;i<cells.length;i++) {
			Cell cell=cells[i];
			cell.left();
		}
	}
	public void moveRight() {
		for(Cell c:cells) {
			c.right();
			}
		}
	public void softDrop() {
			for(Cell c:cells) {
				c.drop();
				}
		}
	@Override
	public String toString() {
		return "["+ Arrays.toString(cells) + "]";
	}
	/**随机生成一个四格方块*/
	public static Tetromino randomOne() {
		Tetromino t=null;
		int num=(int)(Math.random()*7);
		switch(num) {
		case 0:t=new T();break;
		case 1:t=new O();break;
		case 2:t=new I();break;
		case 3:t=new J();break;
		case 4:t=new L();break;
		case 5:t=new S();break;
		case 6:t=new Z();break;
		}
		return t;
		
	}
	
	
	
}

Tetris类:

        /**属性:正在下落的四格方块*/
	private Tetromino currentOne=Tetromino.randomOne();
	/**属性:将要下落的四格方块*/
	private Tetromino nextOne=Tetromino.randomOne();
	/**属性:墙 20行10列的表格  宽度为26*/
	private Cell[][] wall=new Cell[20][10];

三.绘制俄罗斯方块图形

加载静态资源:

private static final int CELL_SIZE=26;
    public static  BufferedImage T;
	public static  BufferedImage I;
	public static  BufferedImage O;
	public static  BufferedImage L;
	public static  BufferedImage S;
	public static  BufferedImage Z;
	public static  BufferedImage J;
	public static  BufferedImage Background;
	static {
		try {
			/*getResource(String url)
			 * url:加载图片的路径
			 * 相对位置是同包下
			 */
			T=ImageIO.read(Tetris.class.getResource("T.png"));
			O=ImageIO.read(Tetris.class.getResource("O.png"));
			I=ImageIO.read(Tetris.class.getResource("I.png"));
			J=ImageIO.read(Tetris.class.getResource("J.png"));
			S=ImageIO.read(Tetris.class.getResource("S.png"));
			L=ImageIO.read(Tetris.class.getResource("L.png"));
			Z=ImageIO.read(Tetris.class.getResource("Z.png"));
			Background=ImageIO.read(Tetris.class.getResource("tetris.png"));
		}catch(Exception e) {
			e.printStackTrace();
		}
	}

生成游戏界面:

public void paint(Graphics g) {
		//绘制背景
		/*
		 * g:画笔
		 * g.drawImage(image,x,y,null)
		 * image:绘制的图片
		 * x:开始绘制的横坐标
		 * y:开始绘制的纵坐标
		 */
		g.drawImage(Background, 0, 0, null);
		//平移坐标轴
		g.translate(15, 15);
		//绘制墙
		paintWall(g);
		//绘制正在下落的四格方块
		piantCurrentOne(g);
		//绘制下一个四格方块
		paintNextOne(g);
		
	}
	
	
	
	
	
	public void paintNextOne(Graphics g) {
		//获取NextOne对象的四个元素
		Cell[] cells=nextOne.cells;
		for(Cell c:cells) {
			//获取行号和列号
			int row=c.getRow();
			int col=c.getCol();
			//横坐标
			int x=col*CELL_SIZE+260;
			//纵坐标
			int y=row*CELL_SIZE+26;
			g.drawImage(c.getImage(),x,y,null);
		}
	}
	
	
	/**绘制正在下落的四格方块
	 * 取出数组的元素
	 * 绘制元素的图片
	 * 横坐标x:
	 * 纵坐标y:
	 * */
	public void piantCurrentOne(Graphics g){
		Cell[] cells=currentOne.cells;
		for(Cell c:cells) {
			int x=c.getCol()*CELL_SIZE;
			int y=c.getRow()*CELL_SIZE;
			g.drawImage(c.getImage(),x,y,null);
		}
	}
	/**
	 * 墙是20行10列的表格
	 * 是个二维数组
	 * 应该使用双层循环
	 * 绘制正方形
	 * */
	public void paintWall(Graphics a) {
		//外层循环控制行数
		for(int i=0;i<20;i++) {
			//内层循环控制列数
			for(int j=0;j<10;j++) {
				int x=j*CELL_SIZE;
				int y=i*CELL_SIZE;
				Cell cell=wall[i][j];
				if(cell==null) {
					a.drawRect(x, y, CELL_SIZE, CELL_SIZE);
				}else {
					a.drawImage(cell.getImage(),x,y,null);
				}
			}
		}
	}

添加动态效果和接收键盘指令并响应的能力:

public void start()  {
		//开启键盘监听事件
		KeyListener l=new KeyAdapter() {
			/**
			 * keyPressed()是键盘按钮按下去调用的方法
			 */
			public void keyPressed(KeyEvent e) {
				//获取一下按键的代号
				int code=e.getKeyCode();
				switch(code) {
				case KeyEvent.VK_DOWN:
					softDropAction();break;
				case KeyEvent.VK_LEFT:
					moveLeftAction();break;
				case KeyEvent.VK_RIGHT:
					moveRightAction();break;
				}
				repaint();
			}

		};
		//面板添加监听事件对象
		this.addKeyListener(l);
		//面板对象设置成焦点
		this.requestFocus();
		
		while(true) {			
			try {
				/**
				 * 当程序运行到此,会进入睡眠状态
				 * 睡眠时间为300毫秒
				 * 300毫秒后,会自动执行后续代码
				 */
				Thread.sleep(300);
			} catch (InterruptedException e) {				
				e.printStackTrace();
			}
			
			if(canDrop()) {
				currentOne.softDrop();
			}else {
				landToWall();
				//将下一个下落的四格方块赋值给正在下落的变量
				currentOne=nextOne;
				nextOne=Tetromino.randomOne();
			}
			/**
			 * 下落之后,进行重新绘制,才会看到下落后的方块
			 * repaint方法 也是JPanel类中提供的
			 * 此方法中调用了paint方法
			 */
			repaint();
		}
	}
		
	 //使用向下键控制向下的行为
	public void softDropAction() {
		if(canDrop()) {
			currentOne.softDrop();
		}else {
			landToWall();
			currentOne=nextOne;
			nextOne=Tetromino.randomOne();
		}
	}

	 //使用LEFT控制向左的行为
	public void moveLeftAction() {
		currentOne.moveLeft();
		if(outOfBounds()||coincide()) {
			currentOne.moveRight();
		}
	}
	//使用向右键控制向右的行为
	protected void moveRightAction() {
		currentOne.moveRight();
		if(outOfBounds()||coincide()) {
			currentOne.moveLeft();
		}
	}
	
	
		private boolean coincide() {
			Cell[] cells=currentOne.cells;
			for(Cell c:cells) {
				int row=c.getRow();
				int col=c.getCol();
				if(wall[row][col]!=null) {
					return true;
				}
			}
		return false;
	}
		private boolean outOfBounds() {
			Cell[] cells=currentOne.cells;
			for(Cell c:cells) {
				int col=c.getCol();
				if(col<0||col>9) {
					return true;
				}
			}
		return false;
	}

		public boolean canDrop() {
		Cell[] cells=currentOne.cells;
		for(Cell c:cells) {
			//获取每个元素的行号
			/**
			 * 判断:
			 * 只要有一个元素的下一行有方块
			 * 或只要有一个元素到底就不能下落
			 */
			int row=c.getRow();
			int col=c.getCol();
			
			if(row==19) {
				return false;
			}
			if(wall[row+1][col]!=null) {
				return false;
			}
			
		}
		return true;
	}
	/**
	 * 当不能下落时,将四格方块嵌入到墙中
	 * 也就是储存到二维数组中相应的位置上
	 */
	public void landToWall() {
		Cell[] cells=currentOne.cells;
		for(Cell c:cells) {
			//获取最终的行号和列号
			int row=c.getRow();
			int col=c.getCol();
			wall[row][col]=c;
		}
	}











评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值