为扫雷游戏动态创建游戏板 [英] Dynamicly create a playboard for Minesweeper game
问题描述
为了学习 C#、XAML,尤其是 MVVM,我开始编写扫雷游戏的程序.我制作的第一个版本没有 MVVM 部分,我使用 C# 代码创建和添加按钮,而不是通过 MVVM 方式在 XAML 中进行.现在我尝试将 MVVM 模式应用到游戏中.
with the objective to learn C#, XAML and especially MVVM I started to program the Minesweeper game. First version I made was without the MVVM part, where I created and added the buttons with C# code instead of doing it in XAML via the MVVM way. Now I try to apply the MVVM pattern into the game.
我制作了一个自己的用户控件,其中包含一个代表雷区部分的按钮.这个控件还有一个 ViewModel 和一个 Model Class 来存储一些状态数据和处理一些命令.在一个测试项目中,我创建了 4 个自己的用户控件,并尝试将它们放在一个网格中,其中按钮形成一个 2 x 2 按钮的正方形.在后面的代码中,按钮被放在一个 ObservableCollection 对象中.我假设在这个对象中按钮被列出和索引如下:
I made an own User Control which contains a button representing a minefield part. This control also has a ViewModel and a Model Class to store some state data and handle some commands. In a test project I create 4 of those own User Controls and try to put them in a grid where the buttons forms a square of 2 by 2 buttons. In the code behind, the buttons are put in an ObservableCollection object. I assume that in this object the buttons are listed and indexed like:
Button1
Button2
Button3
Button4
但在演示文稿网格中我希望按钮显示为
but in the presentation grid I want the buttons to be shown like
Button1 | Button2
--------+--------
Button3 | Button4
问题是:我如何动态地做到这一点?因为在我的测试项目中我测试了 4 个按钮,但是在我想使用它的项目中,按钮的数量可能会根据玩家选择的游戏难度而有所不同.
The question is: how do I do that dynamicly? Cause in my test project I test with 4 buttons, but In the project I want to use this, the amount of buttons can be different depending on the difficulty of the game the player has chosen.
第二个问题是我如何弄清楚按钮的 neigbhours 是什么.因此,如果网格是包含 20 个按钮的 4 x 5.例如,我选择了按钮 8,它的邻居按钮编号为 2、3、4、7、9、12、13 和 14.当按钮被列出时,我怎样才能到达这些邻居按钮?
And a second question is how I can figure out what the neigbhours are of a button. So if the grid is 4 by 5 containing 20 buttons. And for example I pick button 8 which has as neighbour buttons number 2, 3, 4, 7, 9, 12, 13 and 14. How can I reach those neighbour buttons when the buttons are listed?
我希望我的问题足够清楚.
I hope my questions are clear enough.
先谢谢你!
推荐答案
您可以使用 ItemsControl 将它的 ItemsPanel
设置为 Grid
或 UniformGrid
.我有一些 ItemsControl
示例 这里 这可能对您有所帮助,因为我认为 MDSN 的示例没有太大帮助.
You can display your collection using an ItemsControl that has it's ItemsPanel
set to a Grid
or UniformGrid
. I have some ItemsControl
examples here that may help you, as I don't find MDSN's examples very helpful.
UniformGrid
将是最简单的>,但是这要求所有单元格的大小都相同,我不记得属性 Rows
和 Columns
是否是参与绑定系统的 DependencyProperties.
A UniformGrid
would be easiest if you can bind your Rows
and Columns
properties to a property in your ViewModel
, however that requires all your cells be the same size, and I can't remember if the properties Rows
and Columns
are DependencyProperties that participate in the binding system or not.
<ItemsControl ItemsSource="{Binding MyCollection}">
<!-- ItemsPanelTemplate -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding ColumnCount}"
Rows="{Binding RowCount}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
如果这对您不起作用,您可以使用 Grid
作为 ItemsPanel
并设置 Grid.Row
和 ItemContainerStyle
中的 >Grid.Column 绑定.
If this doesn't work for you, you can use a Grid
as the ItemsPanel
and set the Grid.Row
and Grid.Column
bindings in the ItemContainerStyle
.
这将要求您在 ObservableCollection
中的每个单元格对象上都有属性来说明该单元格所在的行/列,但是我怀疑您无论如何都需要这些来确定诸如相邻单击命令中的单元格.
This will require you have properties on each of your cell objects in the ObservableCollection
to say what Row/Column that cell is in, however I suspect you'll need these anyways to determine things like adjacent cells in your click command.
此外,没有内置的方法来绑定Grid
中的行/列数,所以我倾向于使用一些自定义附加属性,将动态构建网格的 RowDefinitions
和 ColumnDefinitions
基于绑定值.
In addition, there's no built-in way to bind the number of Rows/Columns in your Grid
, so I tend to use some custom attached properties that will dynamically build the Grid's RowDefinitions
and ColumnDefinitions
based on a bound value.
因此,如果您使用网格,您的最终结果可能如下所示:
So your end result if you're using a Grid would probably look something like this:
<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>
模型/视图模型看起来像这样
With a Model/ViewModel looking something like this
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;
}
这篇关于为扫雷游戏动态创建游戏板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!