如何组合源自 1 个碱基的 2 类 中的 2 种方法?

How to combine 2 methods from 2 classes derived from 1 base?

我正在创建一个国际象棋游戏,我已经创建了车和象,我即将开始创建皇后棋子。问题是女王结合了车和象的移动,所以我不想写重复的代码,而是只使用 2 classes 来代表车和象,它们是方法女王一号。

这里是主教 class

public class OficerPiece : Figure
{
    public OficerPiece(FigureDefinition definition) : base(definition)
    {
    }

    protected override List<Tuple<int, int>> GetValidTurns()
    {
        //here i set the valid moves
    }
}

新车 class 基本相同,但 GetValidTurns()

的实现不同

我项目中的每个片段都继承了 Figure 摘要 class,其中包含每个片段都在使用的信息,唯一的区别在于 GetValidTurns 方法,因此我们将其留给导出 class 实现。

那是女王class

public class Kralica : Figure
{
    public Kralica(FigureDefinition definition) : base(definition)
    {
    }

    protected override List<Tuple<int, int>> GetValidTurns()
    {
        //here i want to combine the 2 methods GetValidTurns from the bishop class and the rook class
    }
}

你或许可以换一种方式。

有一个定义移动的抽象基础class:

public abstract class Move
{
    // Whatever
}

然后从中推导出不同的走法,例如:

public sealed class Diagonal : Move // Bishop, Queen
{
}

public sealed class Orthongonal : Move // Rook, Queen
{
}

public sealed class KnightsMove : Move
{
}

public sealed class KingsMove : Move
{
}

然后你可以使用组合来组合不同的动作:

public class Kralica : Figure
{
    public Kralica(FigureDefinition definition) : base(definition)
    {
    }

    protected override List<Move> GetValidTurns()
    {
        return moves;
    }

    readonly List<Move> moves = new List<Move> {new Diagonal(), new Orthongonal()};
}

您的 Move class 可能声明如下:

public abstract class Move
{
    public abstract IEnumerable<Position> PossibleMoves(Position start, Board board);
}

其中 Position 是另一个 class 定义来保存有关板上位置的信息(可能只是 X、Y 坐标一样简单),而 Board 是一个class 包含有关棋盘上所有棋子位置的信息。

然后 PossibleMoves() 的实现将 return 从给定位置开始并且棋盘处于给定状态的该类型的所有可能移动的枚举。

您可以为您的有效回合创建一个新的 class 或接口来封装它们并使其易于重用。

public interface ValidTurn
{
    List<Tuple<int, int>> GetValidTurns();
}

public class StraightSlide : ValidTurn
{
    public List<Tuple<int, int>> GetValidTurns()
    {
         // ... valid rook turns here
    }
}

public class DiagonalSlide : ValidTurn
{
    public List<Tuple<int, int>> GetValidTurns()
    {
         // ... valid bishops turns here
    }
}

public class Kralica : Figure
{
    public Kralica(FigureDefinition definition) : base(definition)
    {
    }

    protected override List<Tuple<int, int>> GetValidTurns()
    {
        var straight = new StraightSlide();
        var diagonal = new DiagonalSlide();

        return straight.Concat(diagonal);
    }
}

您原始 classes 中的代码也应替换为新的 ValidTurn classes。

编辑:

public class StraightSlide : ValidTurn
{
    private Figure figure;
    public StraightSlide(Figure figure)
    {
        this.figure = figure;
    }

    public List<Tuple<int, int>> GetValidTurns()
    {
         figure.YourMethodToCall();
         // ... valid rook turns here
    }
}

您可以考虑将所有验证逻辑放入 ValidTurn(TurnValidation)。

如果您是初学者,为什么不在您的基础中添加一些简单的方法class 将移动添加到您的点列表中的图形?

    public class Kralica : Figure
    {
        protected Tuple<int, int> Position {get; set;}

        public Kralica(FigureDefinition definition) : base(definition)
        {
        }

        protected override List<Tuple<int, int>> GetValidTurns()
        {
            //here i want to combine the 2 methods GetValidTurns from the bishop class and the rook class
        }

        protected void AddDiagonalMoves(List<Tuple<int, int>> moves)
        {
            diagonalMoves = new List<Tuple<int, int>>();

            // calculate diagonal moves from my piece position which should be a member property here

            moves.AddRange(diagonalMoves);
        }
    }


public class Kralica : Figure
{
    public Kralica(FigureDefinition definition) : base(definition)
    {
    }

    protected override List<Tuple<int, int>> GetValidTurns()
    {
        var movesThisTurn = new List<Tuple<int, int>>(); 
        //here i want to combine the 2 methods GetValidTurns from the bishop class and the rook class
        base.AddDiagonalMoves(movesThisTurn);
        base.AddLinearMoves(movesThisTurn);

    }
}

然后您派生的 classes 可以在各自的 GetValidTurns 中重复使用这些方法来构建移动列表 return。

社论:即使您是初学者,我也建议您远离此处的元组并创建一个简单的 "point" class 或结构。它将使您的代码更具可读性,甚至对您自己也是如此。