以学习C#,XAML,尤其是MVVM的目标我就开始编程的扫雷游戏。 我做了第一个版本,而不MVVM部分,在那里我创建并添加与C#代码的按钮,而不是通过MVVM方式XAML做的。 现在,我尝试在MVVM模式应用到游戏中。
余由自己的用户控制其包含表示雷区部分的按钮。 这种控制也有一个视图模型和一个模型类来存储一些状态数据和处理某些命令。 在测试项目中,我创建自己的那些用户控件的4,尽量把他们在按钮的2个按钮形成的2方形网格。 在后面的代码,该按钮被放置在一个ObservableCollection对象。 我认为在这个对象的按钮列和索引,如:
Button1
Button2
Button3
Button4
但在演示文稿中网格我想要显示像按钮
Button1 | Button2
--------+--------
Button3 | Button4
现在的问题是:我怎么做动态地? 因为在我的测试项目我4次按键测试,但在项目中,我想用这个,按钮的数量可以根据玩家选择游戏的难度是不同的。
和第二个问题是我怎么能弄清楚什么是neigbhours一个按钮。 因此,如果电网是4 5含20层的按钮。 并且例如我挑选按钮8我怎样才能达到这些邻居按钮所列的按钮时,其具有作为相邻的按钮号2,3,4,7,9,12,13和14?
我希望我的问题是不够清楚。
先感谢您!
您可以使用显示您的收藏ItemsControl中有它的ItemsPanel
设置为一个Grid
或UniformGrid
。 我有一些ItemsControl
例子在这里 ,可以帮助你,因为我不觉得MDSN的例子,非常有帮助。
一个UniformGrid
将是最简单的,如果你可以绑定你Rows
和Columns
的属性在你的属性ViewModel
,然而,需要所有的细胞是相同的大小,我不记得,如果属性Rows
和Columns
是参加DependencyProperties结合系统或没有。
<ItemsControl ItemsSource="{Binding MyCollection}">
<!-- ItemsPanelTemplate -->
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<UniformGrid Columns="{Binding ColumnCount}"
Rows="{Binding RowCount}" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
如果这不适合你,你可以使用一个Grid
作为ItemsPanel
并设置Grid.Row
和Grid.Column
在绑定ItemContainerStyle
。
这就要求你对你的每一个细胞对象的属性中ObservableCollection
说什么行/列细胞是,但我怀疑你会需要这些反正确定像在点击命令相邻单元格的事情。
此外,还有以行/列数绑定在你没有内置的方式Grid
,所以我倾向于使用一些自定义的附加属性 ,将动态地构建网格的RowDefinitions
和ColumnDefinitions
基础上限值。
所以,你最终的结果,如果您使用的是网格可能会是这个样子:
<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;
}
最近,我解决了扫雷游戏的逻辑,为一种软件开发大赛。 我认为他在比赛中的主要问题是寻找周围的项目相邻煤矿和相邻的空单元格。 在这两种情况下,我们必须考虑到,最多每个小区(项目)可以通过八个项目(单元)包围。 如果我们考虑一个4x4网格(基体)由X定义的小区C,Y坐标,将通过下面的细胞包围:
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
关闭我的头顶:
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不大于例如按钮的数量越大。),但是这很容易完成。