2013-05-25 51 views
2

我試圖用XAML在C#中製作康威的生命遊戲。該窗口允許用戶使用滑塊指定我2D單元格數組的行數和列數。當我的統一網格是一個完美的正方形(10x10,20x20,甚至16x16)時,模擬工作沒有問題。然而,當用戶試圖指定一個矩形的均勻網格時(13x14,15x26,24x14),單元格會被差異拋出(即在一個33x27的網格中,差值= 6,因此單元格會適當地向上移動,但是會被丟棄(左/右)的差異)。我已經縮小了,這隻發生在x軸上;細胞永遠不會在y軸上拋出。 問題:爲什麼我的數組拋出我的x軸?它有什麼問題嗎?康威的生命遊戲2D陣列不排隊

據我所知,一切都應該正常工作。我建立了一個日誌來檢查我的2D陣列和我的統一網格的尺寸。我不確定什麼是錯誤的,我一直在盯着DAYS進行調試。我在我的智慧結束。請幫助,我希望有一些我根本沒有抓住。代碼說明: 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

嗨卡洛斯。巧合的是,我最近[問了一個問題](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所說的那樣) - 不管這是否是全部問題,您現在首先添加第一列,填滿第一行(並且不會「 (非常適合)在統一網格中(它沿頂部填充,然後填充到下一行等等) – 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繪製爲相鄰,反之亦然細胞。

幸運的是,修復很簡單:在setCellsOnGrid中切換ij循環的順序。使j循環爲外循環,i循環爲內循環。

順便說一句,你blockSpace方法不會出現使用ij循環變量 - 它只是調用同一方法codeColumn * codeRow倍。這是故意的嗎?

+0

非常感謝,非常感謝。這固定了它。我沒有意識到我正在設置我的細胞從上到下。我盯着這個太久,認爲我的生活鄰居的邏輯是錯誤的,從字面上逐步調試它。再次,非常感謝,我非常感謝。此外,我無法發佈圖片,因爲這是我的第一篇文章。但非常感謝。 – Carlos

+0

此外,塊空間方法是一個調試方法,我將用它來查看相對於2d數組單元的位置,但是在實現Array.IndexOf不支持2D數組後,我沒有完成它。 – Carlos