首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >包装检查器

包装检查器
EN

Code Review用户
提问于 2016-12-27 21:15:27
回答 1查看 189关注 0票数 2

我的Checker系列中的下一篇文章: F#库的F#包装器,以使从C#代码中调用这些方法更加简洁。

GeneralTypes.cs

代码语言:javascript
复制
public enum Player
{
    White, Black
}

public enum PieceType
{
    Checker,
    King
}

public static class Extensions
{
    public static Player Convert(this Checkers.Types.Player value) =>
        Equals(value, Checkers.Types.Player.Black) ? Player.Black : Player.White;

    public static Checkers.Types.Player ConvertBack(this Player value) =>
        value == Player.Black ? Checkers.Types.Player.Black : Checkers.Types.Player.White;

    public static PieceType Convert(this Checkers.Types.PieceType value) =>
        Equals(value, Checkers.Types.PieceType.Checker) ? PieceType.Checker : PieceType.King;

    public static Checkers.Types.PieceType ConvertBack(this PieceType value) =>
        value == PieceType.Checker ? Checkers.Types.PieceType.Checker : Checkers.Types.PieceType.King;

    public static Piece Convert(this FSharpOption<Checkers.Piece.Piece> piece)
    {
        if (Equals(piece, Checkers.Piece.whiteChecker))
        {
            return Piece.WhiteChecker;
        }
        if (Equals(piece, Checkers.Piece.whiteKing))
        {
            return Piece.WhiteKing;
        }
        if (Equals(piece, Checkers.Piece.blackChecker))
        {
            return Piece.BlackChecker;
        }
        if (Equals(piece, Checkers.Piece.blackKing))
        {
            return Piece.BlackKing;
        }

        return null;
    }

    public static FSharpOption<Checkers.Piece.Piece> ConvertBack(this Piece piece)
    {
        if (Equals(piece, Piece.WhiteChecker))
        {
            return Checkers.Piece.whiteChecker;
        }
        if (Equals(piece, Piece.WhiteKing))
        {
            return Checkers.Piece.whiteKing;
        }
        if (Equals(piece, Piece.BlackChecker))
        {
            return Checkers.Piece.blackChecker;
        }
        if (Equals(piece, Piece.BlackKing))
        {
            return Checkers.Piece.blackKing;
        }

        return null;
    }
}

Coord.cs

代码语言:javascript
复制
public class Coord
{
    public int Row { get; }
    public int Column { get; }

    public Coord(int row, int column)
    {
        Row = row;
        Column = column;
    }

    public static Coord operator +(Coord coord1, Coord cooord2)
    {
        return new Coord(coord1.Row + cooord2.Row, coord1.Column + cooord2.Column);
    }

    public static implicit operator Coord(Checkers.Types.Coord coord)
    {
        return new Coord(coord.Row, coord.Column);
    }

    public static implicit operator Checkers.Types.Coord(Coord coord)
    {
        return new Checkers.Types.Coord(coord.Row, coord.Column);
    }

    public static implicit operator Coord(FSharpOption<Checkers.Types.Coord> coord)
    {
        return Equals(coord, FSharpOption<Checkers.Types.Coord>.None)
            ? null
            : new Coord(coord.Value.Row, coord.Value.Column);
    }

    public static implicit operator FSharpOption<Checkers.Types.Coord>(Coord coord)
    {
        return coord == null
            ? FSharpOption<Checkers.Types.Coord>.None
            : FSharpOption<Checkers.Types.Coord>.Some(new Checkers.Types.Coord(coord.Row, coord.Column));
    }
}

Piece.cs

代码语言:javascript
复制
public class Piece
{
    public Player Player { get; }
    public PieceType PieceType { get; }

    public Piece(Player player, PieceType pieceType)
    {
        Player = player;
        PieceType = pieceType;
    }

    public static Piece WhiteChecker =>
        new Piece(Player.White, PieceType.Checker);

    public static Piece WhiteKing =>
        new Piece(Player.White, PieceType.King);

    public static Piece BlackChecker =>
        new Piece(Player.Black, PieceType.Checker);

    public static Piece BlackKing =>
        new Piece(Player.Black, PieceType.King);

    public override bool Equals(object obj)
    {
        if (obj == null || typeof(Piece) != obj.GetType())
        {
            return false;
        }

        var value = (Piece)obj;
        return Player.Equals(value.Player) &&
               PieceType.Equals(value.PieceType);
    }

    public override int GetHashCode() => Player.GetHashCode() ^ PieceType.GetHashCode();
}

Board.cs

代码语言:javascript
复制
public class Board
{
    public List<List<Piece>> GameBoard { get; }

    public Board(IEnumerable<IEnumerable<FSharpOption<Checkers.Piece.Piece>>> board)
    {
        GameBoard = board.Select(row => row.Select(piece => piece.Convert()).ToList()).ToList();
    }

    public Board() : this(Checkers.Board.defaultBoard) { }

    public Piece this[Coord coord] => GameBoard[coord.Row][coord.Column];

    public static implicit operator Board(FSharpList<FSharpList<FSharpOption<Checkers.Piece.Piece>>> value)
    {
        return new Board(value);
    }

    public static implicit operator FSharpList<FSharpList<FSharpOption<Checkers.Piece.Piece>>>(Board value)
    {
        return Checkers.Board.listFromSeq(value.GameBoard.Select(row => row.Select(piece => piece.ConvertBack())));
    }
}

GameController.cs

代码语言:javascript
复制
public class GameController : INotifyPropertyChanged
{
    public GameController(Board board, Player currentPlayer, Coord currentCoord = null)
    {
        Board = board;
        CurrentPlayer = currentPlayer;
        CurrentCoord = currentCoord;
    }

    public Player CurrentPlayer { get; }
    public Coord CurrentCoord { get; }

    private Board _board;
    public Board Board
    {
        get { return _board; }
        set
        {
            Debug.Assert(value.GameBoard != null);
            _board = value;
            OnPropertyChanged();
        }
    }

    public GameController(Checkers.GameController.GameController gameController)
        :this(gameController.Board, gameController.CurrentPlayer.Convert(), gameController.CurrentCoord) { }

    public GameController()
        : this(new Board(), Player.Black) { }

    public GameController Move(Coord startCoord, Coord endCoord) =>
        Checkers.PublicAPI.movePiece(startCoord, endCoord, this);

    public GameController Move(IEnumerable<Coord> moves) =>
        Checkers.PublicAPI.move(moves.Select(item => (Checkers.Types.Coord)item), this);

    public bool IsValidMove(Coord startCoord, Coord endCoord) =>
        Checkers.PublicAPI.isValidMove(startCoord, endCoord, this);

    public IEnumerable<Coord> GetMove(int searchDepth) =>
        Checkers.PublicAPI.getMove(searchDepth, this).Select(coord => (Coord)coord);

    public Player? GetWinningPlayer()
    {
        var player = Checkers.PublicAPI.isWon(this);
        return Equals(player, FSharpOption<Checkers.Types.Player>.None) ? new Player?() : player.Value.Convert();
    }

    public static implicit operator GameController(Checkers.GameController.GameController controller)
    {
        return new GameController(controller);
    }

    public static implicit operator Checkers.GameController.GameController(GameController controller)
    {
        return new Checkers.GameController.GameController(controller.Board, controller.CurrentPlayer.ConvertBack(),
            controller.CurrentCoord);
    }

    public static implicit operator GameController(FSharpOption<Checkers.GameController.GameController> controller)
    {
        return Equals(controller, FSharpOption<Checkers.GameController.GameController>.None)
            ? null
            : new GameController(controller.Value);
    }

    public static implicit operator FSharpOption<Checkers.GameController.GameController>(GameController controller)
    {
        return controller == null
            ? FSharpOption<Checkers.GameController.GameController>.None
            : FSharpOption<Checkers.GameController.GameController>.Some(
                new Checkers.GameController.GameController(controller.Board, controller.CurrentPlayer.ConvertBack(),
                    controller.CurrentCoord));
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) =>
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
EN

回答 1

Code Review用户

回答已采纳

发布于 2016-12-27 21:59:35

Piece.cs

为什么每次检索Piece类的公共静态属性时都需要创建一个新的片段实例并返回它?

我倾向于将它们声明为静态只读字段或静态获取属性,如下所示:

代码语言:javascript
复制
public static Piece WhiteChecker { get; } =
    new Piece(Player.White, PieceType.Checker);

public static Piece WhiteKing { get; } =
    new Piece(Player.White, PieceType.King);

public static Piece BlackChecker { get; } =
    new Piece(Player.Black, PieceType.Checker);

public static Piece BlackKing { get; } =
    new Piece(Player.Black, PieceType.King);

如果类不是用于继承的,可以考虑将它们设置为sealed

在当前的实现中,(假设)以下条件可能返回true对象的Piece对象:

代码语言:javascript
复制
if (obj == null || typeof(Piece) != obj.GetType())

原因:对于从Piece派生的某些类型的对象,obj.GetType()返回不等于Piece的类型。

另一种方法是在考虑继承的情况下比较类型:

代码语言:javascript
复制
if (!typeof(Piece).IsInstanceOfType(obj))

为什么不在IEquatable<Piece>类中实现Piece接口?当您调用Equals方法来比较两个PieceS时,它将消除不必要的装箱:

代码语言:javascript
复制
public class Piece : IEquatable<Piece>
{
    ... 

    public override bool Equals(object obj)
    {
        return Equals(obj as Piece);
    }

    public bool Equals(Piece other)
    {
        return other != null
            && Player.Equals(other.Player)
            && PieceType.Equals(other.PieceType);
    }

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

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

复制
相关文章

相似问题

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