两个相关继承层次结构的OOAD(游戏组件)

时间:2015-04-13 13:30:08

标签: c# inheritance interface abstract-class class-hierarchy

我正在进行一些OO分析来计算游戏组件之间的关系,以便我可以设计类。 我最终会进入C#。

要求

我的游戏将包括:

件:块,卡,计数器

地方:网格,堆栈

可能放置件:

  • 块可以放在网格上(需要网格,x,y)
  • 卡片可放置在堆叠上(需要堆叠,位置)
  • 计数器可以放在网格上(需要网格,x,y)
  • 计数器也可以放在堆栈顶部(需要堆叠,位置)

分析

  1. 作为接口(IPiece)或抽象类(Piece)的片段。 (哪个最好?)
  2. Block,Card&计数器作为IP的子实体或子类的实现。
  3. 作为界面(IPlace)或抽象类(Place)放置。 (哪个最好?)
  4. Grid&堆叠为IPlace的实现或Place的子类。
  5. 然后我感到困惑......

    每一件都有地方所以那里有关系。 这是一对一的关系,因为每件作品必须只有一个地方。

    但是我如何确保Block只能在网格上进行,只能在堆栈上使用卡片和在任何一个上使用计数器?

    提前感谢您的帮助。

2 个答案:

答案 0 :(得分:3)

  

但是我如何确保Block只能在网格上进行,只能在堆栈上使用卡片和在任何一个上使用计数器?

您可以利用泛型和generic type constraints在编译时强制执行这些规则

public interface IPiece<TPlace> where TPlace : IPlace
{
    TPlace Place { get; }

    void PlaceOn(TPlace place);
}

public class Block : IPiece<Grid>
{
    private Grid _place;

    public Grid Place
    {
        get { return _place; }
    }

    public void PlaceOn(Grid place)
    {
        _place = place;
    }
}

答案 1 :(得分:0)

通常声称您应该favor composition over inheritance。考虑到这一点,我一直在尝试这个想法,这就是我提出的:

class Grid
{ }

class Stack
{ }

abstract class Location
{
    private Location() {}

    public class GridLocation : Location
    {
        public Grid Grid { get; set; }

        public int X { get; set; }

        public int Y { get; set; }
    }

    public class StackLocation : Location
    {
        public Stack Stack { get; set; }

        public int Position { get; set; }
    }
}

abstract class Visual
{

}

class Block
{
    public Visual Visual { get; set; }

    public Location.GridLocation Location { get; set; }
}

class Card
{
    public Visual Visual { get; set; }

    public Location.StackLocation Location { get; set; }
}

class Counter
{
    public Visual Visual { get; set; }

    public Location Location { get; set; }
}

class Game
{
    public IEnumerable<Block> Blocks { get; set; }

    public IEnumerable<Card> Cards { get; set; }

    public IEnumerable<Counter> Counters { get; set; }

    public IEnumerable<Tuple<Location.StackLocation, Visual>> StackVisuals
    {
        get
        {
            var cardVisuals =
                Cards.Select (c => Tuple.Create(c.Location, c.Visual));

            var counterVisuals =
                Counters.Select (c => Tuple.Create(c.Location, c.Visual))
                .OfType<Tuple<Location.StackLocation, Visual>>();

            return cardVisuals.Concat(counterVisuals).OrderBy (v => v.Item1.Position);
        }
    }

    public IEnumerable<Tuple<Location.GridLocation, Visual>> GridVisuals
    {
        get
        {
            var blockVisuals =
                Blocks.Select (b => Tuple.Create(b.Location, b.Visual));

            var counterVisuals =
                Counters.Select (c => Tuple.Create(c.Location, c.Visual))
                .OfType<Tuple<Location.GridLocation, Visual>>();

            return blockVisuals.Concat(counterVisuals).OrderBy (v => new { v.Item1.X, v.Item1.Y });
        }
    }
}

我在示例中使用了占位符Visual类,以显示在需要时如何统一具有特定位置类型的实体(例如StackVisualsGridVisuals)。