我正在尝试使用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);
    }

最佳答案

问题在于,创建单元格的顺序与UniformGrid排列其子级的顺序不同。

在您的setCellsOnGrid方法中,您将创建从上到下,然后从左到右的单元格,而UniformGrid则按从左到右然后从上到下的顺序排列其子级。

对于方形网格,网格第一列中的单元格绘制在UniformGrid的第一行中,其他列和行也类似。您最终将网格反映在x = y线中。但是,对于非正方形网格,行的长度不等于列的长度,因此该网格完全不合适。

例如,对于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中相邻绘制,反之亦然。

幸运的是,修复很简单:在i中切换jsetCellsOnGrid循环的顺序。使j循环为外循环,而i循环为内循环。

顺便说一句,您的blockSpace方法似乎没有使用ij循环变量-它只是调用同一方法codeColumn * codeRow次。这是故意的吗?

09-17 13:25