五子棋落子游戏 您所在的位置:网站首页 五子棋编程思路 五子棋落子游戏

五子棋落子游戏

2023-09-05 08:09| 来源: 网络整理| 查看: 265

题目要求:

假设已有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 chessmans; /** * 棋子连成一条线(相邻2点)的偏移量, 只列了正方向,如:向下、向右、向右下、右上, 另4个方向通过Position的reversal()方法来表达 */ private List 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(); } 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 getChessmans() { return chessmans; } private List 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); } }



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有