2013-05-25 1 views
2

Я пытаюсь сделать игру жизни Conway в C# с XAML. Окно позволяет пользователю указывать количество строк и столбцов моего 2D-массива ячеек с помощью ползунка. Когда моя Единая сетка - идеальный квадрат (10x10, 20x20 или даже 16x16), симуляции работают без проблем. Однако, когда пользователь пытается указать прямоугольную равномерную сетку (13x14, 15x26, 24x14), ячейки выбрасываются разностью (т. Е. В сетке 33x27, разность = 6, поэтому ячейка идет соответствующим образом вверх, но отбрасывается (слева/справа) на разницу). Я сузился, что это происходит только на оси х; клетки никогда не отбрасываются по оси y. ВОПРОС: Почему мой массив отбрасывает мою ось x? С этим что-то не так?Game of Life 2D-карты не выстраиваются в линию

Насколько я могу судить, все должно работать нормально. Я создал журнал для проверки размеров моих 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); 
    } 
+0

Hi Carlos. Кстати, я недавно [задал вопрос] (http://stackoverflow.com/questions/16642461/brushes-white-slows-graphics-demo-down) о демо-версии жизни в C#/XAML/WPF. Полный код опубликован, вам интересно узнать о другом подходе. – dharmatech

+1

Несколько снимков экрана помогут здесь много. – RBarryYoung

+0

Попробуйте изменить значения строк/столбцов для 'uniGridOfCells':' unigridOfCells.Rows = column; 'и' unigridOfCells.Columns = row; '. Это классический случай, когда логика x/y путается (скриншот был бы хорош, как сказал RBarryYoung) - является ли это всей проблемой или нет, вы в настоящее время добавляете первый столбец в первую очередь, который заполняет первую строку (и doesn ' t вполне подходит) в Единой сетке (она заполняется сверху, затем на следующий ряд и т. д.) – VisualMelon

ответ

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, и наоборот.

К счастью, исправление прост: переключите порядок колец i и j в setCellsOnGrid. Сделайте петлю j внешним контуром, а петля i - внутренним контуром.

Кстати, ваш метод blockSpace не появляется использовать i и j цикла переменные - это просто тот же метод вызывается codeColumn * codeRow раз. Это намеренно?

+0

Спасибо, что, так много. Это фиксировало это. Я не понимал, что устанавливаю свои клетки сверху вниз. Я слишком долго смотрел на это, думая, что моя логика в том, чтобы жить соседями была неправа, буквально отлаживала ее шаг за шагом. Еще раз большое спасибо, я очень благодарен. Кроме того, я не мог опубликовать фотографию, потому что это был мой первый пост. Но спасибо вам большое. – Carlos

+0

Кроме того, метод blockpace был методом отладки, который я собирался использовать, чтобы увидеть позицию ячейки, которую я нажал относительно массива 2d, но я не закончил ее после реализации Array.IndexOf не поддерживает 2D-массивы. – Carlos