简体   繁体   中英

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

I'm creating a chess game, I already created the rook's and the bishop's and I'm about to start creating the queen piece. The problem is that the queen combines the moves of the rook's and the bishop's, so I don't want to write repetitive code and instead just use the 2 classes for the rook's and the bishop's and they're methods into the queen one.

Here's the bishop class

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

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

The rook class is basically the same but with different implementation of the GetValidTurns()

Every single piece in my project inherits the Figure abstract class which contains info that every piece is using the only difference is in the GetValidTurns method so we leave that for the derived class to implement.

That's the queen 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
    }
}

You could perhaps come at this a different way.

Have an abstract base class that defines a move:

public abstract class Move
{
    // Whatever
}

And then derive different moves from that, for example:

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

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

public sealed class KnightsMove : Move
{
}

public sealed class KingsMove : Move
{
}

Then you can combine the different moves using composition:

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()};
}

Your Move class might be declared as follows:

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

where Position is another class defined to hold information about a position on the board (which may be as simple as just X, Y coords), and Board is a class which holds information about where all the pieces are on the board.

Then an implementation of PossibleMoves() would return an enumeration of all the possible moves for that type starting from the given position and with the board in the given state.

You can create a new class or interface for your valid turns to encapsulate them and make it easy to reuse.

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);
    }
}

Also the code in your original classes should be replaced by your new ValidTurn classes.

Edit:

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
    }
}

You could maybe consider put all your validation logic into the ValidTurn(TurnValidation).

If you're a beginner why not put some simple methods in your base class Figure that adds moves to your point list?

    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);

    }
}

Then your derived classes could just re-use those methods inside their respective GetValidTurns building the list of moves to return.

Editorial: Even if you're a beginner I recommend getting away from the Tuple here and creating a simple "point" class or struct. It will make your code much more readable, even for yourself.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM