`
Chris_bing
  • 浏览: 6394 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
社区版块
存档分类
最新评论

代码重构-以贪吃蛇为示例(四)-继续封装

阅读更多

题外话:

本人第一次写技术文章,希望寻求鼓励啊,发了四篇了一个评论还都没有,真心凉


/* -------------------------------------------------正文分隔条--------------------------------------------- */


上一节我们已经将Snake从原来的类中抽离出来,现在我们继续研究庞大的GamePanel类,继续封装其他的内容。

现在有这样一个需求:我需要提供不同大小,不同样式的地图,可能还有一些阻挡物,然后根据需要选择地图。

单单只靠GamePanel是做不到的,我们需要单独的地图类,也就是GameMap。

按照上一节的思路,下面是GameMap接口和一个简单的实现类SimpleGameMap类。


package snakes;

import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;

/**
 * 贪吃蛇地图
 * 
 * @author Chris
 * 
 */
public interface GameMap
{

	/**
	 * 绘制地图
	 * 
	 * @param g
	 *            画布
	 */
	public void draw(Graphics g);

	/**
	 * 获得地图高度
	 * 
	 * @return
	 */
	public int getHeight();

	/**
	 * 获取一个点在地图上的位置,用作制作无边界地图
	 * 
	 * @param p
	 * @return 返回一个点在地图上的位置,如果没有对应地址则返回 null
	 */
	public Point getPointOnMap(Point p);

	/**
	 * 获得地图尺寸
	 * 
	 * @return
	 */
	public Dimension getSize();

	/**
	 * 获得地图宽度
	 * 
	 * @return
	 */
	public int getWidth();

	/**
	 * 判断输入点是否会装到地图墙壁
	 * 
	 * @param p
	 * @return
	 */
	public boolean isAgainstWall(Point p);

	/**
	 * 从地图上获取一个可行(不撞墙)的点,而且要保证此点沿着<code> direction </code>方向连续
	 * <code> needLength </code>个(算上本身)点也不撞墙
	 * 
	 * @param direction
	 * @param needLength
	 * @return
	 */
	public Point getAvailablePoint(Direction direction, int needLength);

	/**
	 * 从地图上获取一个可行(不撞墙)的点
	 * 
	 * @return
	 */
	public Point getAvailablePoint();
}

 

package snakes;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Point;
import java.util.Random;

public class SimpleGameMap implements GameMap
{
	private static final Random random = new Random();
	private GamePanel panel;

	/**
	 * 地图横向包含的单元格数
	 */
	private int width;

	/**
	 * 地图纵向包含的单元格数
	 */
	private int height;

	public SimpleGameMap (GamePanel panel, int width, int height)
	{
		this.panel = panel;
		this.width = width;
		this.height = height;
	}

	@Override
	public void draw(Graphics g)
	{
		int sellSize = panel.getSellSize();
		g.setColor(new Color(0x555555));
		for (int i = 0; i < width; i++)
		{
			for (int j = 0; j < height; ++j)
			{
				g.drawRect(i * sellSize, j * sellSize, sellSize, sellSize);
			}
		}
	}

	@Override
	public int getHeight()
	{
		return height;
	}

	@Override
	public Point getPointOnMap(Point p)
	{
		if (!isAgainstWall(p))
			return new Point(p);
		return null;
	}

	@Override
	public Dimension getSize()
	{
		return new Dimension(width, height);
	}

	@Override
	public int getWidth()
	{
		return width;
	}

	@Override
	public boolean isAgainstWall(Point p)
	{
		return !(p.x >= 0 && p.x < width && p.y >= 0 && p.y < height);
	}

	@Override
	public Point getAvailablePoint(Direction direction, int needLength)
	{
		int x = 0, y = 0;
		switch (direction)
		{
			case UP:
				x = random.nextInt(width);
				y = random.nextInt(height - needLength) + needLength;
				break;
			case DOWN:
				x = random.nextInt(width);
				y = random.nextInt(height - needLength);
				break;
			case LEFT:
				x = random.nextInt(width - needLength) + needLength;
				y = random.nextInt(height);
				break;
			case RIGHT:
				x = random.nextInt(width - needLength);
				y = random.nextInt(height);
				break;
		}
		return new Point(x, y);
	}

	@Override
	public Point getAvailablePoint()
	{
		return new Point(random.nextInt(width), random.nextInt(height));
	}
}
 

 

另外根据需要,为Direction添加了获取反方向的方法,还修改了Snake的部分逻辑。Direction比较简单,有兴趣的可以查看附件。以下是Snake修改的部分。

 


	/**
	 * 贪吃蛇长度
	 */
	private volatile int length = 3;



	public Snake (GamePanel panel, int length)
	{
		this.length = length;
		this.panel = panel;
		initDirection();
		initList();
	}

	/**
	 * 初始化蛇链表
	 */
	private void initList()
	{
		snakeList = new LinkedList<Point>();

		Point p = panel.getGameMap().getAvailablePoint(direction.getOpposite(), length);
		snakeList.add(p);
		for (int i = 0; i < length - 1; ++i)
		{
			p = getDirection().getPreviousPoint(p);
			snakeList.add(p);
		}
	}

	
	/**
	 * 移动贪吃蛇,包括吃虫
	 */
	public void move()
	{
		snakeList.addFirst(getDirection().getNextPoint(snakeList.getFirst()));
		if (isAgainstTarget())
		{
			++length;
			panel.resetTarget();
			panel.increaseScore();
			panel.increaseSpeed();
		}
		else
		{
			snakeList.removeLast();
		}
	}

	



下节预告:分数管理ScoreManager和速度管理SpeedManager

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics