为了学习C#,XAML,特别是MVVM,我开始编写扫雷游戏。我制作的第一个版本没有MVVM部分,我用C#代码创建和添加了按钮,而不是通过MVVM的方式在XAML中完成。现在我尝试将MVVM模式应用到游戏中。
我制作了一个自己的用户控件,其中包含一个代表雷区部件的按钮。该控件还具有一个ViewModel和一个模型类,用于存储一些状态数据和处理一些命令。在一个测试项目中,我创建了4个这样的用户控件,并尝试将它们放在一个网格中,其中的按钮形成一个2 x 2按钮的正方形。在后面的代码中,按钮被放在一个ObservableCollection对象中。我假设在这个对象中,按钮的列表和索引如下:
Button1
Button2
Button3
Button4但在表示网格中,我希望按钮显示如下
Button1 | Button2
--------+--------
Button3 | Button4问题是:我如何动态地做到这一点?因为在我的测试项目中,我使用4个按钮进行测试,但在我想使用的项目中,按钮的数量可以根据玩家所选择的游戏的难度而有所不同。
第二个问题是,我如何才能计算出按钮的邻时。因此,如果网格是4x5,包含20个按钮。例如,我选择了按钮8,它有编号为2、3、4、7、9、12、13和14的相邻按钮。当这些按钮列出时,我如何才能到达这些相邻按钮?
我希望我的问题足够清楚。
提前谢谢你!
发布于 2012-11-27 23:57:55
您可以使用将ItemsPanel设置为Grid或UniformGrid的ItemsControl来显示您的集合。我有一些ItemsControl示例here可能会对您有所帮助,因为我觉得MDSN的示例不是很有帮助。
如果可以将Rows和Columns属性绑定到ViewModel中的属性,那么创建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,并在ItemContainerStyle中设置Grid.Row和Grid.Column绑定。
这将要求您在ObservableCollection中的每个单元格对象上都有属性来说明该单元格所在的行/列,但我怀疑您无论如何都需要这些属性来确定单击命令中的相邻单元格之类的内容。
此外,没有内置的方法来绑定Grid中的行数/列数,因此我倾向于使用一些custom attached properties,它们将基于绑定值动态构建网格的RowDefinitions和ColumnDefinitions。
因此,如果您使用的是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;
}发布于 2015-06-25 01:37:20
最近,我解决了扫雷游戏的逻辑,这是一种软件开发竞赛。我认为他的游戏的主要问题是寻找相邻的地雷和项目周围的相邻空格。在这两种情况下,我们都必须考虑每个单元格(项)最多可以被八个项(单元格)包围。如果我们考虑一个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元素或组件“锁住”。
你可以在这里下载我的项目:
发布于 2012-11-27 23:30:59
在我的脑海中:
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不大于按钮的数量),但这很容易做到。
https://stackoverflow.com/questions/13587311
复制相似问题