我将使用我的特定用例来描述我的问题,但考虑到可能有其他应用程序需要根据某些默认值创建子类,它应该更广泛适用。这并不意味着“为我做我的功课”问题。
我目前正在开发一款简单的俄罗斯方块游戏,我将我的游戏场定义为一个充满布尔的二维阵列。我在类Grid中执行此操作以添加函数并拆分我的代码。我已经开发了一个功能,可以让我检查是否可以在某个位置添加另一个Grid,以检查是否可以将tetromino移动到某个位置。 (并非两个bool在一个位置都是真的)
由于tetrominos(也是一个网格)有预定义的形状和大小,所以只需要创建一次每个形状,然后我可以将我当前的下降块设置为预定义的tetromino的副本,以便按照我的意愿进行操作。 / p>
现在我知道了两种初始化这些预定义形状的方法:在初始化器中的主要Tetris类中启动它们,我为每个tetromino调用一次Grid(Columns,Rows)并手动将正确的坐标设置为true,或者创建Grid类中的第二个构造函数,它接受一个char(tetromino命名为L,J,S,Z,T,X,I)并使用我已经构建的其他构造函数初始化3x3或4x4网格,然后手动设置正确的再次坐标为真。
这两种方法都会给这些感觉难看的类增加混乱。我希望可以改为使用子类,从技术上讲,tetriminos是特定类型的网格。
现在,我所能找到的子类中的构造函数只能传递给子类构造函数的默认参数或参数,如下所示:
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.
}
}
现在这需要我传递tetromino的尺寸,考虑到这将是预设的,这感觉很奇怪。我更喜欢的是这些内容:
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.
}
}
}
这些方面的内容是否可行?如果是这样,怎么办呢?如果没有,是否有一个干净的替代解决方案,不会混乱我的网格或俄罗斯方块类?我应该做些什么吗?
答案 0 :(得分:0)
我只是使用静态只读字段。 Tetrominos是不可变的,你只需要初始化它们并重复使用它们多次。
另外,我并不十分相信来自Grid
的tetrominos。对我来说,它们在概念上是非常不同的东西;前者是预设的不可变块,后者是动态变化的游戏场。我根本不会把这两个元素混为一谈。我创建了一个特定的Tetromino
类:
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];
}
现在,在您的Tetris
或Grid
课程中,您可以与Tetromino
合作,而不关心他们的真实形象。要生成特定的一个,您只需使用相应的字段; myPlayingGrid.Add(Tetromino.J)