在 C# 中通过子类创建特定 Class 个实例

Creating Specific Class Instances Through a Subclass in C#

我将使用我的特定用例来描述我的问题,但考虑到可能有其他应用程序希望基于某些默认值创建子class,它应该更广泛适用。这不是一个 "do my homework for me" 问题。

我目前正在开发一个简单的俄罗斯方块游戏,我将我的游戏场定义为一个充满布尔值的二维数组。我在 class 网格中执行此操作以添加功能并拆分我的代码。我开发了一个功能,可以让我检查是否可以在特定位置在其顶部添加另一个网格,以检查四联骨牌是否可以移动到特定位置。 (不是一个位置上的两个布尔值都为真)

由于 tetrominos(也是一个网格)有预定义的形状和大小,因此只需创建每个形状一次,然后我可以将我当前的下落块设置为该预定义 tetromino 的副本以按照我的意愿进行操作.

现在我知道了两种初始化这些预定义形状的方法:在主俄罗斯方块中启动它们 class 在初始化程序中,我为每个四联骨牌调用一次 Grid(Columns, Rows) 并手动设置正确的坐标为真,或在 Grid class 中创建第二个构造函数,它接受一个字符(四联骨牌名称 L、J、S、Z、T、X、I)并使用另一个构造函数初始化 3x3 或 4x4 网格我已经构建的,然后再次手动将正确的坐标设置为 true。

这两种方法都会让这些 classes 变得混乱,让人感觉很难看。我希望可以使用 subclass,从技术上讲,tetriminos 是一种 特定类型的网格

现在,据我所知,subclass 中的构造函数只能传递默认参数或提供给 subclass 构造函数的参数,如下所示:

class Grid
{
    bool[,] grid;

    public Grid(int x, int y)
    {
        // Creates grid, fills it with bools.
    }
}

class Block : Grid
{
    public Block(char blockShape, int x, int y) : base(x, y)
    {
        // Add additional logic here.
    }
}

现在这需要我传递四联骨牌的尺寸,考虑到这将是预设的,这感觉很奇怪。我更喜欢的是这些方面的东西:

class Block : Grid
{
    public Block(string blockShape)
    {
        if ("IX".Contains(blockShape))
        {
            this = new Grid(4, 4);
            // Add additional logic here.
        }
        if ("JLSZT".Contains(blockShape))
        {
            this = new Grid(3, 3);
            // Add additional logic here.
        }
    }
}

这方面的事情可能吗?如果可以,怎么办?如果没有,是否有一个干净的替代解决方案不会使我的网格或俄罗斯方块 class 混乱?我应该做点别的吗?

我只会使用静态只读字段。 Tetrominos 是不可变的,您只需将它们初始化一次,并根据需要多次重复使用它们。

此外,我不太相信来自 Grid 的四联骨牌。对我来说,它们在概念上是非常不同的东西;前者是预设的不可变块,后者是动态变化的竞争环境。我根本不会将这两个元素混为一谈。我会创建一个特定的 Tetromino class:

public class Tetromino
{
    public static readonly Tetromino J = new Tetromino(new[,] { { false, false, true }, .... });
    public static readonly Tetromino L = new Terromino(new[,] { { true, false, false } .... });
    //and so on...

    private readonly bool[,] grid;
    private Tetromino(bool[,] shape) //disallow any other Terronimos from being built.
    {
         this.shape = shape;
         Width = shape.GetLength(0);
         Height = shape.GetLength(1);
    }

    public int Height { get; }
    public int Width { get; }
    public bool this[int row, int col] => shape[row, col];
}

现在在您的 TetrisGrid class 中,您可以使用 Tetromino 而不关心它们的实际形状。要生成特定的一个,您只需使用相应的字段即可; myPlayingGrid.Add(Tetromino.J)