为扫雷游戏动态创建游戏板

Cor*_*lis 3 c# xaml mvvm

为了学习 C#、XAML,尤其是 MVVM,我开始编写扫雷游戏。我制作的第一个版本没有 MVVM 部分,我使用 C# 代码创建和添加按钮,而不是通过 MVVM 方式在 XAML 中进行。现在我尝试将 MVVM 模式应用到游戏中。

我制作了一个自己的用户控件,其中包含一个代表雷区部分的按钮。这个控件还有一个 ViewModel 和一个 Model Class 来存储一些状态数据和处理一些命令。在一个测试项目中,我创建了 4 个自己的用户控件,并尝试将它们放在一个网格中,其中按钮形成一个 2 x 2 按钮的正方形。在后面的代码中,按钮被放在一个 ObservableCollection 对象中。我假设在这个对象中,按钮被列出和索引如下:

Button1
Button2
Button3
Button4
Run Code Online (Sandbox Code Playgroud)

但在演示文稿网格中,我希望按钮显示为

Button1 | Button2
--------+--------
Button3 | Button4
Run Code Online (Sandbox Code Playgroud)

问题是:我如何动态地做到这一点?因为在我的测试项目中我测试了 4 个按钮,但是在我想使用它的项目中,按钮的数量可能会根据玩家选择的游戏难度而有所不同。

第二个问题是我如何弄清楚按钮的 neigbhours 是什么。因此,如果网格是包含 20 个按钮的 4 x 5。例如,我选择按钮 8,它的邻居按钮编号为 2、3、4、7、9、12、13 和 14。当按钮被列出时,我怎样才能到达这些邻居按钮?

我希望我的问题足够清楚。

先感谢您!

Rac*_*hel 5

您可以使用显示您的收藏ItemsControl中有它的ItemsPanel集到GridUniformGrid。我这里有一些ItemsControl示例可能对您有所帮助,因为我认为 MDSN 的示例没有太大帮助。

一个UniformGrid是最简单的,如果你可以绑定你RowsColumns属性在你的属性ViewModel,但是需要你所有的细胞是相同的大小,我不记得,如果属性RowsColumns是参与结合系统或不DependencyProperties。

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="{Binding ColumnCount}" 
                         Rows="{Binding RowCount}" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

如果这不适合你,你可以使用GridItemsPanel,并设置Grid.RowGrid.Column绑定的ItemContainerStyle

这将要求您在每个单元格对象上都有属性ObservableCollection来说明该单元格所在的行/列,但是我怀疑您无论如何都需要这些来确定单击命令中的相邻单元格等内容。

此外,没有内置的方法来绑定 . 中的行/列数Grid,因此我倾向于使用一些自定义附加属性,这些属性将动态构建网格RowDefinitionsColumnDefinitions基于绑定值。

因此,如果您使用 Grid,您的最终结果可能如下所示:

<ItemsControl ItemsSource="{Binding Cells}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <!-- This is assuming you use the attached properties linked above -->
            <Grid local:GridHelpers.RowCount="{Binding Height}"
                  local:GridHelpers.ColumnCount="{Binding Width}" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" 
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row" 
                    Value="{Binding RowIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>
Run Code Online (Sandbox Code Playgroud)

模型/视图模型看起来像这样

public class GameViewModel
{
    // These should be full properties w/ property change notification
    // but leaving that out for simplicity right now
    public int Height;
    public int Width;
    public ObservableCollection<CellModel> Cells;
}

public class CellModel
{
    // Same thing, full properties w/ property change notification
    public int ColumnIndex;
    public int RowIndex;
    public bool IsVisible;
    public bool IsMine;
    public int NumberAdjacentMines;
}
Run Code Online (Sandbox Code Playgroud)