康威的《生命游戏》2D阵列没有对齐

本文关键字:阵列 2D 对齐 游戏 生命游戏 生命 康威 | 更新日期: 2023-09-27 18:15:14

我正在尝试用XAML在c#中制作康威的生活游戏。该窗口允许用户使用滑块指定二维单元格数组的行数和列数。当我的统一网格是一个完美的正方形(10x10, 20x20,甚至16x16),模拟工作没有问题。然而,当用户尝试指定一个矩形均匀网格(13x14, 15x26, 24x14)时,单元格会被差值抛出(即在33x27的网格中,差值= 6,因此单元格会适当地向上移动,但会被差值抛出(左/右))。我缩小了范围,这只发生在x轴上;单元格永远不会偏离y轴。问题:为什么我的数组偏离了x轴?有什么问题吗?

据我所知,一切都应该很好。我设置了一个日志来检查我的二维数组和均匀网格的尺寸。我不确定哪里出了问题,我已经盯着调试了好几天了。我已经无计可施了。请帮忙,我希望有什么是我没有抓住的。

代码传奇: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);
    }

康威的《生命游戏》2D阵列没有对齐

问题是您创建单元格的顺序与UniformGrid排列其子单元格的顺序不同。

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

对于方形网格,网格第一列中的单元格绘制在UniformGrid的第一行中,对于其他列和行也是如此。但是,对于非正方形网格,行长度不等于列长度,因此网格完全不合适。

例如,用3 ×

1 4 7
2 5 8
3 6 9

但是,控件按以下顺序添加到UniformGrid(假设您没有设置FlowDirection="Right"):

1 2 3
4 5 6
7 8 9

For, For 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中交换ij循环的顺序。使j环为外环,i环为内环。

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