首页>代码>java swing开发的俄罗斯方块游戏,包含完整代码+详细注释>/ItcastTetris1.02_final/src/cn/itcast/tetris/entities/Ground.java
                
                package cn.itcast.tetris.entities;
import java.awt.Color;
import java.awt.Graphics;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import cn.itcast.tetris.listener.GroundListener;
import cn.itcast.tetris.util.Global;
/**
 * 可以叫做地形, 或地面<BR>
 * 维护障碍物的信息<BR>
 * 可以使用提供的 addObstacle(int, int) 和 addStubbornObstacle(int ,int) 方法添加障碍物。<BR>
 * <BR>
 * 可以通过setObstacleColor(), setStubbornObstacleColor() 或
 * setGriddingColor()方法更改障碍物或网格的颜色<BR>
 * 通过setDrawGridding() 方法设置是否画空白(网格)<BR>
 * 用 setColorfulSupport() 方法设置是否支持彩色显示<BR>
 * <BR>
 * 覆盖 drawObstacle(Graphics, int, int, int, int) 方法可以改变障碍物的显示方式<BR>
 * 覆盖 drawStubbornObstacle(Graphics, int, int, int, int) 方法可以改变不可消除的障碍物的显示方式<BR>
 * <BR>
 * 
 */
public class Ground {
	/**
	 * 监听器
	 */
	protected Set<GroundListener> listeners = new HashSet<GroundListener>();
	/**
	 * 容器
	 */
	protected UnitType[][] obstacles = new UnitType[Global.WIDTH][Global.HEIGHT];
	/**
	 * 不可消除的障碍物的颜色
	 */
	protected Color stubbornObstacleColor = UnitType.STUBBORN_OBSTACLE
			.getColor();
	/**
	 * 默认的网格颜色
	 */
	public static final Color DEFAULT_GRIDDING_COLOR = Color.LIGHT_GRAY;
	/**
	 * 网格的颜色
	 */
	protected Color griddingColor = DEFAULT_GRIDDING_COLOR;
	public static final Color DEFAULT_OBSTACLE_COLOR = UnitType.OBSTACLE
			.getColor();
	/**
	 * 障碍物的颜色
	 */
	protected Color obstacleColor = DEFAULT_OBSTACLE_COLOR;
	public static final Color DEFAULT_FULL_LINE_COLOR = Color.DARK_GRAY;
	/**
	 * 满行的颜色
	 */
	protected Color fullLineColor = DEFAULT_FULL_LINE_COLOR;
	/**
	 * 是否画网格 的开关
	 */
	protected boolean drawGridding;
	/**
	 * 是否支持彩色石头
	 */
	protected boolean colorfulSupport;
	/**
	 * 是否还能接受石头
	 */
	protected boolean full;
	protected Random random = new Random();
	public Ground() {
		init();
	}
	/**
	 * 初始化,将会调用clear() 方法<BR>
	 * 
	 */
	public void init() {
		clear();
		full = false;
	}
	/**
	 * 清空容器
	 */
	public void clear() {
		/**
		 * 初始化数组
		 */
		for (int x = 0; x < Global.WIDTH; x++)
			for (int y = 0; y < Global.HEIGHT; y++)
				obstacles[x][y] = UnitType.BLANK.clone();
	}
	/**
	 * 随机生成一个不可消除的障碍物, 这个随机的坐标的y 坐标不小于5
	 */
	public void genernateAStubbornStochasticObstacle() {
		Random random = new Random();
		if (Global.HEIGHT < 5)
			return;
		int y = random.nextInt(5) + Global.HEIGHT - 5;
		int x = random.nextInt(Global.WIDTH);
		addStubbornObstacle(x, y);
	}
	/**
	 * 在指定的范围内随机生成一些障碍物<BR>
	 * 产生的区域行是1 - lineNum
	 * 
	 * @param amount
	 *            要生成的数量
	 * @param lineNum
	 *            行号, 从1开始
	 */
	public void generateSomeStochasticObstacle(int amount, int lineNum) {
		if (lineNum < 1)
			return;
		if (lineNum > Global.HEIGHT)
			lineNum = Global.HEIGHT;
		for (int i = 0; i < amount; i++) {
			int x = random.nextInt(Global.WIDTH);
			int y = random.nextInt(lineNum) + Global.HEIGHT - lineNum;
			obstacles[x][y] = UnitType.OBSTACLE.clone();
			obstacles[x][y].setColor(Global.getRandomColor());
		}
	}
	/**
	 * 把指定的图形变成石头<BR>
	 * 然后将会调用 deleteFullLine() 方法扫描并删除满行
	 * 
	 * @param shape
	 */
	public void accept(Shape shape) {
		/**
		 * 把图形对应的坐标变成石头
		 */
		int left = shape.getLeft();
		int top = shape.getTop();
		for (int x = 0; x < 4; x++)
			for (int y = 0; y < 4; y++)
				if (left + x < Global.WIDTH && top + y < Global.HEIGHT) {
					if (shape.isMember(x, y, false))
						/**
						 * 如果超出上边界了, 就是放满了
						 */
						if (top + y < 0) {
							full = true;
							for (GroundListener l : listeners)
								l.groundIsFull(this);
						} else {
							/**
							 * 先变成障碍物
							 */
							obstacles[left + x][top + y]
									.cloneProperties(UnitType.OBSTACLE);
							obstacles[left + x][top + y]
									.setColor(colorfulSupport ? shape
											.getColor() : obstacleColor);
						}
				}
		/**
		 * 扫描并删除满行
		 */
		deleteFullLine();
	}
	/**
	 * 扫描并删除满行<BR>
	 * 将调用 deleteLine(int) 方法删除满行
	 */
	public void deleteFullLine() {
		/**
		 * 这次一共消了几行
		 */
		int deletedLineCount = 0;
		/**
		 * 从最后一行开始, 一直到第一行
		 */
		for (int y = Global.HEIGHT - 1; y >= 0; y--) {
			boolean isFull = true;
			for (int x = 0; x < Global.WIDTH; x++) {
				if (obstacles[x][y].equals(UnitType.BLANK))
					isFull = false;
			}
			/**
			 * 如果当前行满了
			 */
			if (isFull) {
				/**
				 * 删除满(当前)行并且当前扫描行号加 1
				 */
				deleteLine(y++);
				deletedLineCount++;
			}
		}
		/**
		 * 如果消行了, 则触发消行事件
		 */
		if (deletedLineCount > 0)
			for (GroundListener l : listeners)
				l.fullLineDeleted(this, deletedLineCount);
	}
	/**
	 * 删除指定的行(这一行上面所有的石头整体下移一行)
	 * 
	 * @param lineNum
	 */
	public void deleteLine(int lineNum) {
		/**
		 * 触发将要消行事件
		 */
		for (GroundListener l : listeners)
			l.beforeDeleteFullLine(this, lineNum);
		for (int y = lineNum; y > 0; y--)
			for (int x = 0; x < Global.WIDTH; x++)
				if (!obstacles[x][y].equals(UnitType.STUBBORN_OBSTACLE))
					if (obstacles[x][y - 1].equals(UnitType.STUBBORN_OBSTACLE)) {
						obstacles[x][y].cloneProperties(UnitType.BLANK);
						obstacles[x][y].setColor(this.griddingColor);
					} else
						obstacles[x][y].cloneProperties(obstacles[x][y - 1]);
		/**
		 * 第一行变成空白
		 */
		for (int x = 0; x < Global.WIDTH; x++)
			if (!obstacles[x][0].equals(UnitType.STUBBORN_OBSTACLE))
				obstacles[x][0] = UnitType.BLANK.clone();
	}
	/**
	 * 容器是否放满了(是否还能接受图形)<BR>
	 * 
	 * @return
	 */
	public boolean isFull() {
		return full;
	}
	/**
	 * 根据图形的动作,判断是否会碰到障碍物或不可消除的障碍物, 或是否会超出边界,
	 * 
	 * @param shape
	 * @param action
	 *            图形将要做的动作
	 * @return 图形是否可以做这个动作
	 */
	public synchronized boolean isMoveable(Shape shape, int action) {
		int left = shape.getLeft();
		int top = shape.getTop();
		/**
		 * 根据动作,得到最新信息
		 */
		switch (action) {
		case Shape.UP:
			top--;
			break;
		case Shape.DOWN:
			top++;
			break;
		case Shape.LEFT:
			left--;
			break;
		case Shape.RIGHT:
			left++;
			break;
		}
		if (top < 0 - shape.getHeight()) {
			return false;
		}
		for (int x = 0; x < 4; x++)
			for (int y = 0; y < 4; y++)
				/**
				 * 如果这个位置超出边界又是图形的一部分
				 */
				if ((left + x < 0 || left + x >= Global.WIDTH || top + y >= Global.HEIGHT)
						&& shape.isMember(x, y, action == Shape.ROTATE))
					return false;
				else if (top + y < 0)
					continue;
				else {
					/**
					 * 或者位置不是空白(是障碍物或不可消除的障碍物)又是图形的一部分
					 */
					if (shape.isMember(x, y, action == Shape.ROTATE))
						if (!obstacles[left + x][top + y]
								.equals(UnitType.BLANK))
							return false;
				}
		return true;
	}
	/**
	 * 改变指定行的颜色,(可以做为消行前的效果)
	 * 
	 * @param lineNum
	 */
	public void changeFullLineColor(int lineNum) {
		for (int x = 0; x < Global.WIDTH; x++)
			obstacles[x][lineNum].setColor(fullLineColor);
	}
	/**
	 * 在指定的位置添加一个障碍物
	 * 
	 * @param x
	 *            x 格子坐标
	 * @param y
	 *            y 格子坐标
	 */
	public void addObstacle(int x, int y) {
		if (x < 0 || x >= Global.WIDTH || y < 0 || y >= Global.HEIGHT)
			throw new RuntimeException("这个位置超出了显示区域 (x:" + x + "  y:" + y + ")");
		obstacles[x][y].cloneProperties(UnitType.OBSTACLE);
	}
	/**
	 * 在指定的位置添加一块不可消除的障碍物
	 * 
	 * @param x
	 *            x 格子坐标
	 * @param y
	 *            y 格子坐标
	 */
	public void addStubbornObstacle(int x, int y) {
		if (x < 0 || x >= Global.WIDTH || y < 0 || y >= Global.HEIGHT)
			throw new RuntimeException("这个位置超出了显示区域 (x:" + x + "  y:" + y + ")");
		obstacles[x][y].cloneProperties(UnitType.STUBBORN_OBSTACLE);
	}
	/**
	 * 显示, 将调用 drawGridding(Graphics, int, int, int, int),
	 * drawObstacle(Graphics, int, int, int, int)和
	 * drawStubbornObstacle(Graphics, int, int, int, int) 方法
	 * 
	 * @param g
	 */
	public void drawMe(Graphics g) {
		for (int x = 0; x < Global.WIDTH; x++)
			for (int y = 0; y < Global.HEIGHT; y++) {
				/**
				 * 画空白/网格(如果允许)
				 */
				if (drawGridding && obstacles[x][y].equals(UnitType.BLANK)) {
					g.setColor(griddingColor);
					drawGridding(g, x * Global.CELL_WIDTH, y
							* Global.CELL_HEIGHT, Global.CELL_WIDTH,
							Global.CELL_HEIGHT);
				}
				/**
				 * 画不可消除的障碍物
				 */
				else if (obstacles[x][y].equals(UnitType.STUBBORN_OBSTACLE)) {
					g.setColor(stubbornObstacleColor);
					drawStubbornObstacle(g, x * Global.CELL_WIDTH, y
							* Global.CELL_HEIGHT, Global.CELL_WIDTH,
							Global.CELL_HEIGHT);
				}
				/**
				 * 画障碍物
				 */
				else if (obstacles[x][y].equals(UnitType.OBSTACLE)) {
					g.setColor(obstacles[x][y].getColor());
					drawObstacle(g, x * Global.CELL_WIDTH, y
							* Global.CELL_HEIGHT, Global.CELL_WIDTH,
							Global.CELL_HEIGHT);
				}
			}
	}
	/**
	 * 
	 * 画一个空白的方法(网格), 可以覆盖这个方法改变空白(网格)的显示
	 * 
	 * @param g
	 * @param x
	 *            像素坐标 x
	 * @param y
	 *            像素坐标 y
	 * @param width
	 *            宽度(单位:像素)
	 * @param height
	 *            高度(单位:像素)
	 */
	public void drawGridding(Graphics g, int x, int y, int width, int height) {
		g.drawRect(x, y, width, height);
	}
	/**
	 * 
	 * 画一个不可消除的障碍物的方法, 可以覆盖这个方法改变不可消除的障碍物的显示
	 * 
	 * @param g
	 * @param x
	 *            像素坐标 x
	 * @param y
	 *            像素坐标 y
	 * @param width
	 *            宽度(单位:像素)
	 * @param height
	 *            高度(单位:像素)
	 */
	public void drawStubbornObstacle(Graphics g, int x, int y, int width,
			int height) {
		g.fill3DRect(x, y, width, height, true);
	}
	/**
	 * 
	 * 画一个障碍物的方法, 可以覆盖这个方法改变障碍物的显示
	 * 
	 * @param g
	 * @param x
	 *            像素坐标 x
	 * @param y
	 *            像素坐标 y
	 * @param width
	 *            宽度(单位:像素)
	 * @param height
	 *            高度(单位:像素)
	 */
	public void drawObstacle(Graphics g, int x, int y, int width, int height) {
		g.fill3DRect(x, y, width, height, true);
	}
	/**
	 * 得到不可消除的障碍物的颜色
	 * 
	 * @return
	 */
	public Color getStubbornObstacleColor() {
		return stubbornObstacleColor;
	}
	/**
	 * 设置不可消除的障碍物的颜色
	 * 
	 * @param stubbornObstacleColor
	 */
	public void setStubbornObstacleColor(Color stubbornObstacleColor) {
		this.stubbornObstacleColor = stubbornObstacleColor;
	}
	/**
	 * 得到网格的颜色
	 * 
	 * @return
	 */
	public Color getGriddingColor() {
		return griddingColor;
	}
	/**
	 * 设置网格的颜色
	 * 
	 * @param griddingColor
	 */
	public void setGriddingColor(Color griddingColor) {
		this.griddingColor = griddingColor;
	}
	/**
	 * 得到障碍物的颜色
	 * 
	 * @return
	 */
	public Color getObstacleColor() {
		return obstacleColor;
	}
	/**
	 * 设置障碍物的颜色
	 * 
	 * @param obstacleColor
	 */
	public void setObstacleColor(Color obstacleColor) {
		this.obstacleColor = obstacleColor;
	}
	/**
	 * 得到满行的颜色
	 * 
	 * @return
	 */
	public Color getFullLineColor() {
		return fullLineColor;
	}
	/**
	 * 设置满行的颜色
	 * 
	 * @param fullLineColor
	 */
	public void setFullLineColor(Color fullLineColor) {
		this.fullLineColor = fullLineColor;
	}
	/**
	 * 是否画网格
	 * 
	 * @return
	 */
	public boolean isDrawGridding() {
		return drawGridding;
	}
	/**
	 * 设置是否画网格
	 * 
	 * @param drawGridding
	 */
	public void setDrawGridding(boolean drawGridding) {
		this.drawGridding = drawGridding;
	}
	/**
	 * 是否支持彩色显示
	 * 
	 * @return
	 */
	public boolean isColorfulSupport() {
		return colorfulSupport;
	}
	/**
	 * 设置是否支持彩色显示
	 * 
	 * @param colorfulSupport
	 */
	public void setColorfulSupport(boolean colorfulSupport) {
		this.colorfulSupport = colorfulSupport;
	}
	/**
	 * 添加监听器, 可添加多个
	 * 
	 * @param l
	 */
	public void addGroundListener(GroundListener l) {
		if (l != null)
			this.listeners.add(l);
	}
	/**
	 * 移除监听器
	 * 
	 * @param l
	 */
	public void removeGroundListener(GroundListener l) {
		if (l != null)
			this.listeners.remove(l);
	}
	/**
	 * 指定位置是否是不可除的障碍物
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean isStubbornObstacle(int x, int y) {
		if (x >= 0 && x < Global.WIDTH && y >= 0 && y < Global.HEIGHT)
			return obstacles[x][y].equals(UnitType.STUBBORN_OBSTACLE);
		else
			throw new RuntimeException("这个坐标超出了显示区域: (x:" + x + " y:" + y + ")");
	}
	/**
	 * 指定位置是否是障碍物
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean isObstacle(int x, int y) {
		if (x >= 0 && x < Global.WIDTH && y >= 0 && y < Global.HEIGHT)
			return obstacles[x][y].equals(UnitType.OBSTACLE);
		else
			throw new RuntimeException("这个坐标超出了显示区域: (x:" + x + " y:" + y + ")");
	}
	/**
	 * 指定位置是否是空白
	 * 
	 * @param x
	 * @param y
	 * @return
	 */
	public boolean isBlank(int x, int y) {
		if (x >= 0 && x < Global.WIDTH && y >= 0 && y < Global.HEIGHT)
			return obstacles[x][y].equals(UnitType.BLANK);
		else
			throw new RuntimeException("这个坐标超出了显示区域: (x:" + x + " y:" + y + ")");
	}
}
 最近下载更多
最近下载更多
                
                微信网友_7556339099734016     LV3
                6月23日
            
            
        
                chy520     LV1
                2024年6月2日
            
            
        
                ClydeSon     LV5
                2023年12月18日
            
            
        
                微信网友_6770780673069056     LV2
                2023年12月9日
            
            
        
                npc也有忧伤     LV3
                2022年3月19日
            
            
        
                guzhiguo0313     LV5
                2022年2月12日
            
            
        
                闫小玥     LV8
                2021年12月22日
            
            
        
                秒速一千米     LV2
                2021年9月4日
            
            
        
                jnagri     LV6
                2021年7月6日
            
            
        
                zhangjian800     LV1
                2021年5月25日
            
            
         最近浏览更多
最近浏览更多
                
                微信网友_7556339099734016     LV3
                6月23日
            
            
        
                dushine     LV3
                4月10日
            
            
        
                luoyanglin     LV2
                2024年9月14日
            
            
        
                2824163870szy    
                2024年7月1日
            
            
                    暂无贡献等级
            
        
                zr20050503     LV2
                2024年6月27日
            
            
        
                hainabian1977     LV2
                2024年6月24日
            
            
        
                bill1234     LV1
                2024年6月23日
            
            
        
                chy520     LV1
                2024年5月29日
            
            
        
                douxing    
                2024年3月5日
            
            
                    暂无贡献等级
            
        
                crapcrap     LV2
                2024年2月1日
            
            
        
 
                 
                