我正在尝试用XAML在C#中制作Conway的生活游戏。该窗口允许用户使用滑块指定我的2D单元数组的行数和列数。当我的均匀网格是一个完美的正方形(10x10,20x20,甚至16x16)时,模拟工作没有问题。但是,当用户尝试指定矩形均匀网格(13x14,15x26,24x14)时,单元格将被差异抛出(即,在33x27网格中,差异= 6,因此单元格适当向上,但因差异而被抛出(左/右))。我已经缩小了范围,这只发生在x轴上;单元格永远不会在y轴上被抛出。问题是:为什么我的数组偏离了x轴?有什么问题吗?
据我所知,一切都应该很好。我设置了一个日志来检查我的2D数组和均匀网格的尺寸。我不确定哪里出了问题,我已经盯着调试了好几天了。我无计可施了。请帮帮忙,我希望有什么是我根本没有注意到的。
代码图例: unigridOfCells是XAML中的一个统一网格。slideWidth/slideHeight是滑块。此外,我还使用了一个来自我的资源的转换器,它将我的isAlive属性转换为一个SolidColorBrush。
private Cell[,] cells;
private Cell[,] nextGenCells;
private int codeColumn, codeRow, difference, secondDiff;
public MainWindow()
{
InitializeComponent();
unigridOfCells.Height = 500;
unigridOfCells.Width = 500;
setCellsOnGrid(10, 10);
}
//Sets all the cells on the grid, as well as setting the number of columns and rows to be reset for all arrays in the application
public void setCellsOnGrid(int column, int row)
{
unigridOfCells.Rows = row;
unigridOfCells.Columns = column;
codeColumn = column;
codeRow = row;
time = new Timer(3000);
cells = new Cell[codeColumn, codeRow];
nextGenCells = new Cell[codeColumn, codeRow];
for (int i = 0; i < codeColumn; i++)
{
for (int j = 0; j < codeRow; j++)
{
cells[i, j] = new Cell();
Rectangle block = new Rectangle();
block.Height = 10;
block.Width = 10;
block.DataContext = cells[i, j];
block.MouseLeftButtonDown += cells[i, j].ParentClicked;
//block.MouseLeftButtonDown += blockSpace;
Binding b = new Binding();
b.Source = cells[i, j];
b.Path = new PropertyPath("isAlive");
b.Converter = (BoolColorConverter)Application.Current.FindResource("cellLifeSwitch");
block.SetBinding(Rectangle.FillProperty, b);
unigridOfCells.Children.Add(block);
}
}
}
public void blockSpace(object sender, MouseButtonEventArgs e)
{
int spot = 0;
int pick = 0;
for (int i = 0; i < codeColumn; i++)
{
for (int j = 0; j < codeRow; j++)
{
spot = unigridOfCells.Children.IndexOf((Rectangle)sender);
}
}
MessageBox.Show("" + spot + " : " + pick);
}
//Updates the cells. This is where the rules are applied and the isAlive property is changed (if it is).
public void updateCells()
{
for (int n = 0; n < codeColumn; n++)
{
for (int m = 0; m < codeRow; m++)
{
nextGenCells[n, m] = new Cell();
bool living = cells[n, m].isAlive;
int count = GetLivingNeighbors(n, m);
bool result = false;
if (living && count < 2)
{
result = false;
}
if (living && (count == 2 || count == 3))
{
result = true;
}
if (living && count > 3)
{
result = false;
}
if (!living && count == 3)
{
result = true;
}
nextGenCells[n, m].isAlive = result;
}
}
setNextGenCells();
}
//Resets all the cells in a time step
public void setNextGenCells()
{
for (int f = 0; f < codeColumn; f++)
{
for (int k = 0; k < codeRow; k++)
{
cells[f, k].isAlive = nextGenCells[f, k].isAlive;
}
}
}
//Checks adjacent cells to the cell in the position that was passed in
public int GetLivingNeighbors(int x, int y)
{
int count = 0;
// Check cell on the right.
if (x != codeColumn - 1)
if (cells[x + 1, y].isAlive)
count++;
// Check cell on the bottom right.
if (x != codeColumn - 1 && y != codeRow - 1)
if (cells[x + 1, y + 1].isAlive)
count++;
// Check cell on the bottom.
if (y != codeRow - 1)
if (cells[x, y + 1].isAlive)
count++;
// Check cell on the bottom left.
if (x != 0 && y != codeRow - 1)
if (cells[x - 1, y + 1].isAlive)
count++;
// Check cell on the left.
if (x != 0)
if (cells[x - 1, y].isAlive)
count++;
// Check cell on the top left.
if (x != 0 && y != 0)
if (cells[x - 1, y - 1].isAlive)
count++;
// Check cell on the top.
if (y != 0)
if (cells[x, y - 1].isAlive)
count++;
// Check cell on the top right.
if (x != codeColumn - 1 && y != 0)
if (cells[x + 1, y - 1].isAlive)
count++;
return count;
}
//Fires when the next generation button is clicked. Simply makes the board go through the algorithm
private void nextGenerationClick(object sender, RoutedEventArgs e)
{
updateCells();
}
//Fired when the "Reset Grid" button is pressed, resets EVERYTHING with the new values from the sliders
private void resetGrid(object sender, RoutedEventArgs e)
{
MessageBox.Show("First Slide (width) value: " + slideWidth.Value + "\nSecond Slide (length) value: " + slideHeight.Value + "\nDifference: " + (codeColumn - codeRow) + "\nColumns: " + unigridOfCells.Columns + " \nRows: " + unigridOfCells.Rows + "\nChildren count: " + unigridOfCells.Children.Count + " \nLengths: "
+ "\n\tOf 1D of cells: " + cells.GetLength(0) + "\n\tOf 1D of nextGenCells: " + nextGenCells.GetLength(0) + "\n\tUniform Grid Columns: " + unigridOfCells.Columns + " \nWidths: "
+ "\n\tOf 2D of cells: " + cells.GetLength(1) + "\n\tOf 2D of nextGenCells: " + nextGenCells.GetLength(1) + "\n\tUniform Grid Rows: " + unigridOfCells.Rows);
unigridOfCells.Children.Clear();
setCellsOnGrid((int)slideWidth.Value, (int)slideHeight.Value);
}发布于 2013-05-26 03:39:38
问题是您创建单元格的顺序与UniformGrid排列其子级的顺序不同。
在您的setCellsOnGrid方法中,从上到下创建单元格,然后从左到右创建单元格,而UniformGrid按照从左到右再从上到下的顺序排列其子级。
对于方形网格,网格第一列中的单元格绘制在UniformGrid的第一行中,对于其他列和行也是如此。但是,对于非正方形网格,行的长度不等于列的长度,因此网格完全不在合适的位置。
例如,对于3×3栅格,循环按以下顺序运行:
1 4 7
2 5 8
3 6 9但是,控件将按以下顺序添加到UniformGrid中(假设您尚未设置FlowDirection="Right"):
1 2 3
4 5 6
7 8 9对于,对于3×4网格,您的循环按如下顺序运行
1 5 9
2 6 10
3 7 11
4 8 12但是这些控件会按如下顺序添加到UniformGrid中
1 2 3
4 5 6
7 8 9
10 11 12这意味着在cells数组中相邻的单元格可能不会在UniformGrid中绘制为相邻,反之亦然。
幸运的是,修复方法很简单:在setCellsOnGrid中交换i和j循环的顺序。将j循环设置为外部循环,将i循环设置为内部循环。
顺便说一句,您的blockSpace方法似乎没有使用i和j循环变量-它只是调用相同的方法codeColumn * codeRow次。这是故意的吗?
https://stackoverflow.com/questions/16752584
复制相似问题