2

我正在尝试使用 XAML 在 C# 中制作 Conway 的生命游戏。该窗口允许用户使用滑块指定我的二维单元格数组的行数和列数。当我的统一网格是一个完美的正方形(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);
    }
4

1 回答 1

1

问题是您创建单元格的顺序与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,反之亦然。

幸运的是,解决方法很简单:将iandj循环的顺序切换到setCellsOnGrid. 使j循环为外循环,i循环为内循环。

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

于 2013-05-25T19:39:37.753 回答