首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >科特林国际象棋游戏

科特林国际象棋游戏
EN

Code Review用户
提问于 2021-04-21 15:18:25
回答 1查看 549关注 0票数 2

我用Kotlin编写了以下Chess逻辑,并正在寻找反馈,以使代码更简洁,并遵循良好的软件设计原则。我试着坚持面向对象的设计。

一些注意事项:

·为了简单起见,我忽略了“铸人”(Castling)和“粉笔”(En Pessant)等特殊动作。

·我将最后一个when分支放入一个单独的when语句中,这样正交和对角线的皇后移动就可以加起来。

·要重置游戏,需要初始化一个新的ChessGame对象。这样的reset方法会更好吗?

代码语言:javascript
代码运行次数:0
运行
复制
fun resetGame() {
    positionsArray = getStartingPositions()
    currentPlayer = Player.White
    removedPiecesList = mutableListOf()
}

守则本身:

代码语言:javascript
代码运行次数:0
运行
复制
class ChessGame {

    var currentPlayer: Player = Player.White

    private var playingFieldArray = getStartingPositions()
    val playingField: Array<Array<Piece>> = playingFieldArray

    private fun getStartingPositions() = arrayOf<Array<Piece>>(
        arrayOf(
            Piece.Black.Rook1,
            Piece.Black.Knight1,
            Piece.Black.Bishop1,
            Piece.Black.Queen,
            Piece.Black.King,
            Piece.Black.Bishop2,
            Piece.Black.Knight2,
            Piece.Black.Rook2
        ),
        arrayOf(
            Piece.Black.Pawn1,
            Piece.Black.Pawn2,
            Piece.Black.Pawn3,
            Piece.Black.Pawn4,
            Piece.Black.Pawn5,
            Piece.Black.Pawn6,
            Piece.Black.Pawn7,
            Piece.Black.Pawn8
        ),
        arrayOf(
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty
        ),
        arrayOf(
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty
        ),
        arrayOf(
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty
        ),
        arrayOf(
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty,
            Piece.Empty
        ),
        arrayOf(
            Piece.White.Pawn1,
            Piece.White.Pawn2,
            Piece.White.Pawn3,
            Piece.White.Pawn4,
            Piece.White.Pawn5,
            Piece.White.Pawn6,
            Piece.White.Pawn6,
            Piece.White.Pawn8
        ),
        arrayOf(
            Piece.White.Rook1,
            Piece.White.Knight1,
            Piece.White.Bishop1,
            Piece.White.Queen,
            Piece.White.King,
            Piece.White.Bishop2,
            Piece.White.Knight2,
            Piece.White.Rook2
        ),
    )

    private var removedPiecesList = mutableListOf<Piece>()
    val removedPieces: List<Piece> = removedPiecesList

    fun getAvailableMoves(x: Int, y: Int): List<Pair<Int, Int>> {
        if (playingFieldArray[x][y] is Piece.White && currentPlayer == Player.Black ||
            playingFieldArray[x][y] is Piece.Black && currentPlayer == Player.White ||
            isGameOver()
        ) {
            return emptyList()
        }

        val availableMoves = mutableListOf<Pair<Int, Int>>()

        fun isValidPosition(x: Int, y: Int) = x in 0..7 && y in 0..7 && !tileHasPieceOfCurrentPlayer(x, y)

        when (playingFieldArray[x][y]) {
            Piece.Black.Rook1, Piece.Black.Rook2, Piece.White.Rook1, Piece.White.Rook2, Piece.Black.Queen, Piece.White.Queen -> {
                var toXUp = x - 1
                val toYUp = y
                while (isValidPosition(toXUp, toYUp)
                    && !tileHasPieceOfCurrentPlayer(toXUp, toYUp)
                ) {
                    availableMoves.add(Pair(toXUp, toYUp))
                    if (tileHasPieceOfOpponent(toXUp, toYUp)) break
                    toXUp--
                }
                var toXDown = x + 1
                val toYDown = y
                while (isValidPosition(toXDown, toYDown)
                    && !tileHasPieceOfCurrentPlayer(toXDown, toYDown)
                ) {
                    availableMoves.add(Pair(toXDown, toYDown))
                    if (tileHasPieceOfOpponent(toXDown, toYDown)) break
                    toXDown++
                }
                val toXLeft = x
                var toYLeft = y - 1
                while (isValidPosition(toXLeft, toYLeft)
                    && !tileHasPieceOfCurrentPlayer(toXLeft, toYLeft)
                ) {
                    availableMoves.add(Pair(toXLeft, toYLeft))
                    if (tileHasPieceOfOpponent(toXLeft, toYLeft)) break
                    toYLeft--
                }
                val toXRight = x
                var toYRight = y + 1
                while (isValidPosition(toXRight, toYRight)
                    && !tileHasPieceOfCurrentPlayer(toXRight, toYRight)
                ) {
                    availableMoves.add(Pair(toXRight, toYRight))
                    if (tileHasPieceOfOpponent(toXRight, toYRight)) break
                    toYRight++
                }
            }
            Piece.Black.Knight1, Piece.Black.Knight2, Piece.White.Knight1, Piece.White.Knight2 -> {
                val toXUpLeft = x - 2
                val toYUpLeft = y - 1
                if (isValidPosition(toXUpLeft, toYUpLeft)) {
                    availableMoves.add(Pair(toXUpLeft, toYUpLeft))
                }
                val toXUpRight = x - 2
                val toYUpRight = y + 1
                if (isValidPosition(toXUpRight, toYUpRight)) {
                    availableMoves.add(Pair(toXUpRight, toYUpRight))
                }
                val toXDownLeft = x + 2
                val toYDownLeft = y - 1
                if (isValidPosition(toXDownLeft, toYDownLeft)) {
                    availableMoves.add(Pair(toXDownLeft, toYDownLeft))
                }
                val toXDownRight = x + 2
                val toYDownRight = y + 1
                if (isValidPosition(toXDownRight, toYDownRight)) {
                    availableMoves.add(Pair(toXDownRight, toYDownRight))
                }
                val toXLeftUp = x - 1
                val toYLeftUp = y - 2
                if (isValidPosition(toXLeftUp, toYLeftUp)) {
                    availableMoves.add(Pair(toXLeftUp, toYLeftUp))
                }
                val toXRightUp = x - 1
                val toYRightUp = y + 2
                if (isValidPosition(toXRightUp, toYRightUp)) {
                    availableMoves.add(Pair(toXRightUp, toYRightUp))
                }
                val toXLeftDown = x + 1
                val toYLeftDown = y - 2
                if (isValidPosition(toXLeftDown, toYLeftDown)) {
                    availableMoves.add(Pair(toXLeftDown, toYLeftDown))
                }
                val toXRightDown = x + 1
                val toYRightDown = y + 2
                if (isValidPosition(toXRightDown, toYRightDown)) {
                    availableMoves.add(Pair(toXRightDown, toYRightDown))
                }
            }
            Piece.Black.King, Piece.White.King -> {
                val toXUp = x - 1
                val toYUp = y
                if (isValidPosition(toXUp, toYUp)) {
                    availableMoves.add(Pair(toXUp, toYUp))
                }
                val toXDown = x + 1
                val toYDown = y
                if (isValidPosition(toXDown, toYDown)) {
                    availableMoves.add(Pair(toXDown, toYDown))
                }
                val toXLeft = x
                val toYLeft = y - 1
                if (isValidPosition(toXLeft, toYLeft)) {
                    availableMoves.add(Pair(toXLeft, toYLeft))
                }
                val toXRight = x
                val toYRight = y + 1
                if (isValidPosition(toXRight, toYRight)) {
                    availableMoves.add(Pair(toXRight, toYRight))
                }
                val toXUpLeft = x - 1
                val toYUpLeft = y - 1
                if (isValidPosition(toXUpLeft, toYUpLeft)) {
                    availableMoves.add(Pair(toXUpLeft, toYUpLeft))
                }
                val toXUpRight = x - 1
                val toYUpRight = y + 1
                if (isValidPosition(toXUpRight, toYUpRight)) {
                    availableMoves.add(Pair(toXUpRight, toYUpRight))
                }
                val toXDownLeft = x + 1
                val toYDownLeft = y - 1
                if (isValidPosition(toXDownLeft, toYDownLeft)) {
                    availableMoves.add(Pair(toXDownLeft, toYDownLeft))
                }
                val toXDownRight = x + 1
                val toYDownRight = y + 1
                if (isValidPosition(toXDownRight, toYDownRight)) {
                    availableMoves.add(Pair(toXDownRight, toYDownRight))
                }
            }
            Piece.Black.Pawn1, Piece.Black.Pawn2, Piece.Black.Pawn3, Piece.Black.Pawn4, Piece.Black.Pawn5, Piece.Black.Pawn6, Piece.Black.Pawn7, Piece.Black.Pawn8 -> {
                val toXDown = x + 1
                val toY1Down = y
                if (isValidPosition(toXDown, toY1Down) && !tileHasPieceOfOpponent(toXDown, toY1Down)) {
                    availableMoves.add(Pair(toXDown, toY1Down))
                }
                val toXDownRight = x + 1
                val toYDownRight = y + 1
                if (isValidPosition(toXDownRight, toYDownRight)
                    && tileHasPieceOfOpponent(toXDownRight, toYDownRight)
                ) {
                    availableMoves.add(Pair(toXDownRight, toYDownRight))
                }
                val toXDownLeft = x + 1
                val toYDownLeft = y - 1
                if (isValidPosition(toXDownLeft, toYDownLeft)
                    && tileHasPieceOfOpponent(toXDownLeft, toYDownLeft)
                ) {
                    availableMoves.add(Pair(toXDownLeft, toYDownLeft))
                }
            }
            Piece.White.Pawn1, Piece.White.Pawn2, Piece.White.Pawn3, Piece.White.Pawn4, Piece.White.Pawn5, Piece.White.Pawn6, Piece.White.Pawn7, Piece.White.Pawn8 -> {
                val toXUp = x - 1
                val toYUp = y
                if (isValidPosition(toXUp, toYUp) && !tileHasPieceOfOpponent(toXUp, toYUp)) {
                    availableMoves.add(Pair(toXUp, toYUp))
                }
                val toXUpRight = x - 1
                val toYUpRight = y + 1
                if (isValidPosition(toXUpRight, toYUpRight) && tileHasPieceOfOpponent(toXUpRight, toYUpRight)) {
                    availableMoves.add(Pair(toXUpRight, toYUpRight))
                }
                val toXUpLeft = x - 1
                val toYUpLeft = y - 1
                if (isValidPosition(toXUpLeft, toYUpLeft) && tileHasPieceOfOpponent(toXUpLeft, toYUpLeft)) {
                    availableMoves.add(Pair(toXUpLeft, toYUpLeft))
                }
            }
        }
        when (playingFieldArray[x][y]) {
            Piece.Black.Bishop1, Piece.Black.Bishop2, Piece.White.Bishop1, Piece.White.Bishop2, Piece.Black.Queen, Piece.White.Queen -> {
                var toXUpLeft = x - 1
                var toYUpLeft = y - 1
                while (isValidPosition(toXUpLeft, toYUpLeft)
                    && !tileHasPieceOfCurrentPlayer(toXUpLeft, toYUpLeft)
                ) {
                    availableMoves.add(Pair(toXUpLeft, toYUpLeft))
                    if (tileHasPieceOfOpponent(toXUpLeft, toYUpLeft)) break
                    toXUpLeft--
                    toYUpLeft--
                }
                var toXUpRight = x - 1
                var toYUpRight = y + 1
                while (isValidPosition(toXUpRight, toYUpRight)
                    && !tileHasPieceOfCurrentPlayer(toXUpRight, toYUpRight)
                ) {
                    availableMoves.add(Pair(toXUpRight, toYUpRight))
                    if (tileHasPieceOfOpponent(toXUpRight, toYUpRight)) break
                    toXUpRight--
                    toYUpRight++
                }
                var toXDownLeft = x + 1
                var toYDownLeft = y - 1
                while (isValidPosition(toXDownLeft, toYDownLeft)
                    && !tileHasPieceOfCurrentPlayer(toXDownLeft, toYDownLeft)
                ) {
                    availableMoves.add(Pair(toXDownLeft, toYDownLeft))
                    if (tileHasPieceOfOpponent(toXDownLeft, toYDownLeft)) break
                    toXDownLeft++
                    toYDownLeft--
                }
                var toXDownRight = x + 1
                var toYDownRight = y + 1
                while (isValidPosition(toXDownRight, toYDownRight)
                    && !tileHasPieceOfCurrentPlayer(toXDownRight, toYDownRight)
                ) {
                    availableMoves.add(Pair(toXDownRight, toYDownRight))
                    if (tileHasPieceOfOpponent(toXDownRight, toYDownRight)) break
                    toXDownRight++
                    toYDownRight++
                }
            }
        }
        return availableMoves
    }

    fun movePiece(fromX: Int, fromY: Int, toX: Int, toY: Int) {
        if (getAvailableMoves(fromX, fromY).contains(Pair(toX, toY))) {
            if (tileHasPieceOfOpponent(toX, toY)) {
                removedPiecesList.add(playingField[toX][toY])
            }
            playingFieldArray[toX][toY] = playingFieldArray[fromX][fromY]
            playingFieldArray[fromX][fromY] = Piece.Empty
        } else {
            throw IllegalArgumentException("Invalid move coordinates")
        }
        currentPlayer = if (currentPlayer == Player.White) Player.Black else Player.White
    }

    fun tileHasPieceOfCurrentPlayer(x: Int, y: Int) = when (currentPlayer) {
        Player.Black -> {
            playingField[x][y] is Piece.Black
        }
        Player.White -> {
            playingField[x][y] is Piece.White
        }
    }

    private fun tileHasPieceOfOpponent(x: Int, y: Int) = when (currentPlayer) {
        Player.Black -> {
            playingField[x][y] is Piece.White
        }
        Player.White -> {
            playingField[x][y] is Piece.Black
        }
    }

    fun isGameOver() =
        removedPieces.contains(Piece.White.King) || removedPieces.contains(Piece.Black.King)

    sealed class Piece {
        sealed class White : Piece() {
            object Pawn1 : White()
            object Pawn2 : White()
            object Pawn3 : White()
            object Pawn4 : White()
            object Pawn5 : White()
            object Pawn6 : White()
            object Pawn7 : White()
            object Pawn8 : White()
            object Rook1 : White()
            object Knight1 : White()
            object Bishop1 : White()
            object Queen : White()
            object King : White()
            object Bishop2 : White()
            object Knight2 : White()
            object Rook2 : White()
        }

        sealed class Black : Piece() {
            object Pawn1 : Black()
            object Pawn2 : Black()
            object Pawn3 : Black()
            object Pawn4 : Black()
            object Pawn5 : Black()
            object Pawn6 : Black()
            object Pawn7 : Black()
            object Pawn8 : Black()
            object Rook1 : Black()
            object Knight1 : Black()
            object Bishop1 : Black()
            object Queen : Black()
            object King : Black()
            object Bishop2 : Black()
            object Knight2 : Black()
            object Rook2 : Black()
        }

        object Empty : Piece()
    }

    enum class Player {
        Black, White
    }
}
```
代码语言:javascript
代码运行次数:0
运行
复制
EN

回答 1

Code Review用户

发布于 2021-04-21 20:02:21

您的设计有几个部分可以改进。

目前有很多重复的代码关于颜色,允许的移动,以及Pawn1,Pawn2,Pawn3等。

Pawn1,Pawn2,Pawn3等真的有什么区别吗?我不这样认为。Piece可以是播放机颜色和列出所有选项的enum class PieceType之间的组合(不对它们编号)。

移动逻辑可以使用List<Point>,其中Pointdata class Point(val x: Int, val y: Int)。对于一个骑士来说,这可能是:

代码语言:javascript
代码运行次数:0
运行
复制
val knightMoves = listOf(
   Point(2, 1), Point(2, -1),
   Point(-1, 2), Point(1, 2),
   Point(-1, -2), Point(1, -2),
   Point(-2, -1), Point(-2, 1)
)

然后遍历这个列表并检查哪些移动是允许的。

代码语言:javascript
代码运行次数:0
运行
复制
for (val move in knightMoves) {
    if (isValidPosition(x + move.x, y + move.y)) {
        availableMoves.add(move)
    }
}

可以做更多的改进,但是.一次做几件事。

票数 5
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/259807

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档