五子棋落子游戏

题目要求:

假设已有15*15的五子棋棋盘(0-14),黑白子对下,现要求能够实现落子接口:

1)落子成功时,如果当前颜色的棋子胜利(有5子连成一条线),黑子胜利返回2,白子胜利返回3,没有人胜利时,返回落子成功1;

2)黑白子顺序混乱、或者重复落子等异常返回-1;


分析:

1、需要实现保存所下所有棋子的数据;

2、在1前提下,能够判定所下棋子是否有5个子在一条直线上(2条直线、2条对角线),即实现胜利的判定算法;

3、需要保存黑子、白子落子的顺序,处理落子失败等异常;


感觉5子的直线判定算法应该是其中比较麻烦的,我的初步想法是黑子或者白子落子后,遍历其所有下过的棋子,分别遍历2条直线和2条对角线上的棋子是否有5个;

如判定水平线上是否有5子成线:

1)取一点A,判断其右边的点是否在下过的棋子中,是就把水平线上棋子的统计数量加1,继续向右遍历;

2)如果棋子的统计数量加等于5则返回胜利;否则如果右边已经没有下一点在所下棋子中,同时统计数量小于5,则从A点向左遍历,统计继续累加,等于5时返回胜利;

其它三个方向类似;


仔细想想发现没必要遍历每个点,只对最后落的子B进行如上遍历即可。因为如果存在5个点,不与B相邻且是相邻节点,且在一条直线上,那么在B棋子落下之前就已经胜利了;

算法就说这么多;


说说面向对象设计思路:

1、定义1个棋盘类,保存棋盘大小,可对棋子做是否越界判定;

2、定义棋手类,能够保存所下棋子的位置,并在落子后,判定最后的落子是否能够与其它位置的棋子形成5子一线;

3、定义棋子枚举,规定是黑子还是白子,被棋手类引用;

4、定义位置类,点坐标;

5、定义游戏类:拥有一个棋盘和2个棋手,定义了落子参数的入口。


这个问题比较简单:

直接上代码

/**
 * 
 * 类名称:ChessConstants 类描述: 创建人:dobuy
 * 
 */
public interface ChessConstants
{
	/**
	 * 落子成功
	 */
	int SUCCESS = 1;

	/**
	 * 落子失败:顺序不对、位置非法、指定棋手非法
	 */
	int FAIL = -1;

	/**
	 * 黑子赢
	 */
	int BLACK_WIN = 2;

	/**
	 * 白子赢
	 */
	int WHITE_WIN = 3;

	/**
	 * 黑子
	 */
	int BLACK = 0;

	/**
	 * 白子
	 */
	int WHITE = 1;

	/**
	 * 错误的棋手编号
	 */
	int ERROR = -1;

	/**
	 * 赢时一条线上的棋子数量
	 */
	int WIN_OF_LINE_CHESSES = 5;

	int DEFAULT_TURN = -2;
}

/**
 * 棋盘(棋子的地图)
 * 
 * @author dobuy
 * @time 2013-5-12
 */
public class Chessboard
{
	/**
	 * 棋盘的最小边界点(原点)
	 */
	private Position origonPosition;

	/**
	 * 棋盘的最大边界点
	 */
	private Position edgePosition;

	public Chessboard()
	{
		this.origonPosition = new Position(0, 0);
		this.edgePosition = new Position(14, 14);
	}

	/**
	 * 当前位置在棋盘中是否越界
	 * 
	 * @return
	 */
	public boolean isOverEdge(Position currentPosition)
	{
		if (currentPosition.getX() < getOrigonPosition().getX()
				|| currentPosition.getY() < getOrigonPosition().getY()
				|| currentPosition.getX() > getEdgePosition().getX()
				|| currentPosition.getY() > getEdgePosition().getY())
		{
			return true;
		}
		return false;
	}

	private Position getEdgePosition()
	{
		return edgePosition;
	}

	private Position getOrigonPosition()
	{
		return origonPosition;
	}
}
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 
 * 类名称:ChessPlayer 类描述: 棋手 创建人:dobuy
 * 
 */
public class ChessPlayer
{
	/**
	 * 棋子的类型:黑棋/白棋
	 */
	private ChessmanType chessmanType;

	/**
	 * 已经落的棋子位置
	 */
	private List<Position> chessmans;

	/**
	 * 棋子连成一条线(相邻2点)的偏移量, 只列了正方向,如:向下、向右、向右下、右上, 另4个方向通过Position的reversal()方法来表达
	 */
	private List<Position> offsets = Arrays.asList(new Position(0, 1),
			new Position(1, 0), new Position(1, 1), new Position(1, -1));

	public ChessPlayer(ChessmanType type)
	{
		this.chessmanType = type;
		this.chessmans = new ArrayList<Position>();
	}

	public ChessmanType getChessmanType()
	{
		return chessmanType;
	}

	public void addChessman(Position chessman)
	{
		getChessmans().add(chessman);
	}

	public boolean contains(Position chessman)
	{
		return getChessmans().contains(chessman);
	}

	public void clear()
	{
		getChessmans().clear();
	}

	/**
	 * 判断是否有五子连成线,只需判断以最后下的棋子为中心的2条对接线和2条直线即可
	 * 
	 */
	public boolean isWin()
	{
		if (getChessmans().isEmpty())
		{
			return false;
		}

		Position currentPosition = getLastChessman();

		int lineOfChesses = 0;
		Position nextPosition = null;
		boolean hasReversal = false;

		// 依次遍历2条直线上和2条对角线上的点,遍历每条直线时,当正向找不到时,开始反向找
		for (Position offset : getOffsets())
		{
			lineOfChesses = 1;
			nextPosition = currentPosition.offset(offset);

			// 是否反向找过了
			hasReversal = false;
			while ((contains(nextPosition) || !hasReversal))
			{
				// 不包含这个点时,说明正向直线上已经找不到下一个点了,开始反向找,下一个指向正向的第一个点
				if (!contains(nextPosition))
				{
					hasReversal = true;
					nextPosition = currentPosition;
					offset = offset.reversal();
				}
				else
				{
					lineOfChesses++;
				}

				if (ChessConstants.WIN_OF_LINE_CHESSES == lineOfChesses)
				{
					return true;
				}

				nextPosition = nextPosition.offset(offset);
			}
		}
		return false;
	}

	/**
	 * 获取最近下的棋子位置
	 * 
	 */
	private Position getLastChessman()
	{
		int size = getChessmans().size();
		return getChessmans().get(size - 1);
	}

	private List<Position> getChessmans()
	{
		return chessmans;
	}

	private List<Position> getOffsets()
	{
		return offsets;
	}
}
public enum ChessmanType
{
	BLACK(ChessConstants.BLACK), WHITE(ChessConstants.WHITE), ERROR(
			ChessConstants.ERROR);

	private int type;

	private ChessmanType(int type)
	{
		this.type = type;
	}

	public int getChessmanType()
	{
		return this.type;
	}

	/**
	 * 查找指定的棋手,找不到返回错误信息
	 * 
	 */
	public static ChessmanType getChessmanTypeByNo(int playerNo)
	{
		ChessmanType[] types = ChessmanType.values();
		for (ChessmanType chessmanType : types)
		{
			if (chessmanType.getChessmanType() == playerNo)
			{
				return chessmanType;
			}
		}
		return ERROR;
	}
}
/**
 * 坐标位置对象
 * 
 * @author dobuy
 * @time 2013-5-12
 */
public class Position
{
	private int x;

	private int y;

	public Position(int x, int y)
	{
		super();
		this.x = x;
		this.y = y;
	}

	/**
	 * 获取偏移后的位置
	 * 
	 * @param offset 偏移量
	 * @return
	 */
	public Position offset(Position offset)
	{
		return new Position(getX() + offset.getX(), getY() + offset.getY());
	}

	/**
	 * 偏移量的X,Y坐标取反
	 * 
	 * @return
	 */
	public Position reversal()
	{
		return new Position(-getX(), -getY());
	}

	public int getX()
	{
		return x;
	}

	public void setX(int x)
	{
		this.x = x;
	}

	public int getY()
	{
		return y;
	}

	public void setY(int y)
	{
		this.y = y;
	}

	@Override
	public int hashCode()
	{
		final int prime = 31;
		int result = 1;
		result = prime * result + x;
		result = prime * result + y;
		return result;
	}

	@Override
	public boolean equals(Object obj)
	{
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Position other = (Position) obj;
		if (x != other.x)
			return false;
		if (y != other.y)
			return false;
		return true;
	}

	@Override
	public String toString()
	{
		return "Position [x=" + x + ", y=" + y + "]";
	}
}
/**
 * 
 * 类名称:ChessGame 类描述: 创建人:dobuy
 * 
 */
public class ChessGame
{
	private Chessboard chessboard;

	private ChessPlayer player1;

	private ChessPlayer player2;

	private int turnNo = ChessConstants.DEFAULT_TURN;

	public ChessGame()
	{
		chessboard = new Chessboard();
		player1 = new ChessPlayer(ChessmanType.BLACK);
		player2 = new ChessPlayer(ChessmanType.WHITE);
	}

	/**
	 * 启动游戏: 每次落一子,如果棋子位置在棋盘上,且落子顺序正常(黑子白子交替下), 则添加棋子到棋盘上,如果没人赢,返回落子成功;
	 * 如果当前黑子/白子赢了,则返回黑子/白子赢的编号(非棋手的编号)
	 * 
	 * @param playerNo:玩家序号:黑子棋手/白子棋手
	 * @param position 落子位置
	 * 
	 */
	public int startGame(int playerNo, int[] position)
	{
		ChessmanType chessmanType = ChessmanType.getChessmanTypeByNo(playerNo);

		if (ChessmanType.ERROR == chessmanType)
		{
			return ChessConstants.FAIL;
		}

		// 位置非法:参数非法、重复落子、棋子位置越界
		if (isIllegalPosition(position))
		{
			return ChessConstants.FAIL;
		}

		if (getTurnNo() == ChessConstants.DEFAULT_TURN)
		{
			setTurnNo(chessmanType.getChessmanType());
		}
		// 不是第一次落子时,判断上一次落子的下一个选手的序号是否和输入相同
		else
		{
			if ((getTurnNo() + 1) % 2 != playerNo)
			{
				return ChessConstants.FAIL;
			}
			setTurnNo(playerNo);
		}

		ChessPlayer currentPlayer = getCurrentChessPlayer(chessmanType);

		currentPlayer.addChessman(new Position(position[0], position[1]));

		if (currentPlayer.isWin())
		{
			reset();
			return playerNo == ChessConstants.BLACK ? ChessConstants.BLACK_WIN
					: ChessConstants.WHITE_WIN;
		}

		return ChessConstants.SUCCESS;
	}

	private void reset()
	{
		getPlayer1().clear();
		getPlayer2().clear();
		setTurnNo(ChessConstants.DEFAULT_TURN);
	}

	private ChessPlayer getCurrentChessPlayer(ChessmanType chessmanType)
	{
		if (getPlayer1().getChessmanType() == chessmanType)
		{
			return getPlayer1();
		}
		else
		{
			return getPlayer2();
		}
	}

	/**
	 * 判断当前棋子是否合法:包括参数不合法、超越棋盘边界、重复落子
	 * 
	 */
	private boolean isIllegalPosition(int[] position)
	{
		if (null == position || position.length != 2)
		{
			return true;
		}

		Position pos = new Position(position[0], position[1]);

		return isIllegalPosition(pos);
	}

	private boolean isIllegalPosition(Position position)
	{
		// 越界
		if (getChessboard().isOverEdge(position))
		{
			return true;
		}

		// 重复落子
		if (getPlayer1().contains(position) || getPlayer2().contains(position))
		{
			return true;
		}
		return false;
	}

	private Chessboard getChessboard()
	{
		return chessboard;
	}

	private ChessPlayer getPlayer1()
	{
		return player1;
	}

	private ChessPlayer getPlayer2()
	{
		return player2;
	}

	private int getTurnNo()
	{
		return turnNo;
	}

	private void setTurnNo(int turnNo)
	{
		this.turnNo = turnNo;
	}
}

测试类:

import static org.junit.Assert.assertEquals;

import org.junit.Test;

/**
 * 
 * 类名称:ChessGameTest 类描述: 创建人:dobuy
 * 
 */
public class ChessGameTest
{
	private static ChessGame game = new ChessGame();

	/**
	 * 落子成功
	 */
	int SUCCESS = 1;

	/**
	 * 落子失败:顺序不对、位置非法、指定棋手非法
	 */
	int FAIL = -1;

	/**
	 * 黑子赢
	 */
	int BLACK_WIN = 2;

	/**
	 * 白子赢
	 */
	int WHITE_WIN = 3;

	/**
	 * 黑子
	 */
	int BLACK = 0;

	/**
	 * 白子
	 */
	int WHITE = 1;

	/**
	 * CASE1:正常流程
	 */
	@Test
	public void testStartGame1()
	{
		// 2条直线
		assertEquals(game.startGame(BLACK, new int[] { 4, 4 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 5, 3 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 5, 4 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 7, 6 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 6, 4 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 9, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 7, 4 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 2, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 8, 4 }), BLACK_WIN);

		assertEquals(game.startGame(BLACK, new int[] { 4, 4 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 5, 3 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 5 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 7, 6 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 6 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 9, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 7 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 2, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 8 }), BLACK_WIN);

		// 2条对角线
		assertEquals(game.startGame(BLACK, new int[] { 6, 6 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 9, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 7, 7 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 2, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 4 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 5, 3 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 5, 5 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 7, 6 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 8, 8 }), BLACK_WIN);

		assertEquals(game.startGame(BLACK, new int[] { 4, 6 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 9, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 6, 4 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 2, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 7, 3 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 5, 3 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 5, 5 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 8, 9 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 8, 2 }), BLACK_WIN);
	}

	/**
	 * CASE2:参数非法
	 */
	@Test
	public void testStartGame2()
	{
		assertEquals(game.startGame(BLACK, new int[] { 4 }), FAIL);
		assertEquals(game.startGame(BLACK, new int[] { 4, -1 }), FAIL);
		assertEquals(game.startGame(BLACK, new int[] { -1, 4 }), FAIL);
		assertEquals(game.startGame(BLACK, new int[] { 7, 15 }), FAIL);
	}

	/**
	 * CASE3:重复落子、顺序不对
	 */
	@Test
	public void testStartGame3()
	{
		assertEquals(game.startGame(BLACK, new int[] { 4, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 10, 4 }), FAIL);
		assertEquals(game.startGame(WHITE, new int[] { 4, 4 }), FAIL);

		assertEquals(game.startGame(WHITE, new int[] { 5, 3 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 5 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 7, 6 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 6 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 9, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 7 }), SUCCESS);
		assertEquals(game.startGame(WHITE, new int[] { 2, 4 }), SUCCESS);
		assertEquals(game.startGame(BLACK, new int[] { 4, 8 }), BLACK_WIN);
	}
}



猜你喜欢

转载自blog.csdn.net/dobuy/article/details/8937723