3

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

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

Button1
Button2
Button3
Button4

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

Button1 | Button2
--------+--------
Button3 | Button4

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

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

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

先感谢您!

4

3 回答 3

5

您可以使用设置为 a或的ItemsControl来显示您的集合。我这里有一些示例可能会对您有所帮助,因为我认为 MDSN 的示例没有多大帮助。ItemsPanelGridUniformGridItemsControl

如果UniformGrid您可以将您的RowsColumns属性绑定到您ViewModel的.RowsColumns

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="{Binding ColumnCount}" 
                         Rows="{Binding RowCount}" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

如果这对您不起作用,您可以使用 a作为GridtheItemsPanel并在.Grid.RowGrid.ColumnItemContainerStyle

这将要求您在每个单元格对象上都有属性,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>

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

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;
}
于 2012-11-27T15:57:54.900 回答
1

最近我解决了扫雷游戏逻辑,用于一种软件开发竞赛。我认为他的游戏的主要问题是找到相邻的地雷和物品周围的相邻空单元。在这两种情况下,我们都必须考虑最多每个单元格(项目)可以被八个项目(单元格)包围。如果我们考虑一个 4x4 网格(矩阵)一个由 X,Y 坐标定义的单元 C,它将被以下单元包围:

C1 (X-1,Y-1)
C2 (X,Y-1)
C3 (X+1,Y-1)
C4 (X-1,Y)
C5 (X+1,Y)
C6 (X-1,Y+1)
C7 (X,Y+1)
C8 (X+1,Y+1)

换句话说,我们可以通过平移 x 和 y 轴上的一个点来找到一个项目的相邻单元格。我通过将游戏的呈现(前端)与游戏逻辑(后端)分开来开发了一个类集。
通过使用这种策略,您实际上可以在不同的 .Net 环境中使用它:我们不会“锁定”在 UI 元素或组件周围。
你可以在这里下载我的项目:
https ://github.com/alchimya/csharp-minesweeper-sdk

于 2015-06-24T17:37:19.683 回答
-1

在我的头顶上:

List<Button> myButtons = new List<Button>();
Button myFirstButton = new Button(/*make first button*/);
myButtons.Add(myFirstButton);

void addButtonX ()
{//add new button along x axis
    Button tempButt = new Button();        
    Button lastButt = myButtons[myButtons.count - 1];
    tempButt.posX = lastButt.posX + lastButt.sizeX;
    tempButt.posY = lastButt.posY;
    //other code for buttons
    myButtons.Add(tempButt);
}
void addButtonY ()
{//add new button along y axis
    Button tempButt = new Button();
    Button lastButt = myButtons[myButtons.count - 1];
    tempButt.posX = lastButt.posX;
    tempButt.posY = lastButt.posY + lastButt.sizeY;
    //other code for buttons
    myButtons.Add(tempButt);
}

要跟踪周围的按钮,您需要知道网格有多少按钮宽,例如,如果网格有 20 个按钮宽,则按钮将如下所示:

[B-20-1][B-20][B-20+1]
[B-1]   [B]   [B+1]
[B+20-1][B+20][B+20+1]

其中 B = 单击按钮。

当然,您必须检查没有值超出网格(例如,B-20-1 不小于 0,B+20+1 不大于按钮的数量。),但这很容易完毕。

于 2012-11-27T15:30:58.727 回答