private Cell[] GetNeighbours(Cell[,] cells, int x, int y, ref int alive) { Cell[] neighbours = new Cell[8]; if (x < FIELD_WIDTH - 1) neighbours[0] = cells[x + 1, y]; if (y < FIELD_HEIGHT - 1) neighbours[1] = cells[x, y + 1]; if (x > 0) neighbours[2] = cells[x - 1, y]; if (y > 0) neighbours[3] = cells[x, y - 1]; if (x < FIELD_WIDTH - 1 && y < FIELD_HEIGHT - 1) neighbours[4] = cells[x + 1, y + 1]; if (x > 0 && y > 0) neighbours[5] = cells[x - 1, y - 1]; if (x < FIELD_WIDTH - 1 && y > 0) neighbours[6] = cells[x + 1, y - 1]; if (x > 0 && y < FIELD_HEIGHT - 1) neighbours[7] = cells[x - 1, y + 1]; alive = 0; for (int i = 0; i < 8; ++i) if (neighbours[i].IsAlive) alive++; return neighbours; }
// Один шаг игры private void Step() { cells_clone = (Cell[,])cells.Clone(); Point[] search_p; int nalive = 0; // Число активных соседей for (int i = 0; i < FIELD_WIDTH; i++) for (int c = 0; c < FIELD_HEIGHT; c++) { Cell[] neighbours = GetNeighbours(cells_clone, i, c, ref nalive); if (RegularLife) { if (cells_clone[i, c].IsAlive == false && nalive == 3) cells[i, c].IsAlive = true; else if (cells_clone[i, c].IsAlive && nalive != 2 && nalive != 3) cells[i, c].IsAlive = false; } else { // Если клетка имеет некомфортное число соседей if (cells_clone[i, c].IsAlive && nalive != cells_clone[i, c].PreferedNeighboursNumber && nalive != cells_clone[i, c].PreferedNeighboursNumber + 1) { // Координаты окружающих клеток search_p = new Point[] { new Point(i + 1, c), new Point(i - 1, c), new Point(i, c + 1), new Point(i, c - 1), new Point(i + 1, c + 1), new Point(i - 1, c - 1), new Point(i + 1, c - 1), new Point(i - 1, c + 1)}; int calive = 0; bool found = false; // Найдена ли подходщая клетка // Просматриваем всех соседей for (int ch = 0; ch < 8; ++ch) try { // Если любая соседняя клетка имеет допустимое число соседей, перемещаемся в неё if (cells_clone[search_p[ch].X, search_p[ch].Y].IsAlive == false) { Cell[] neigh = GetNeighbours(cells_clone, search_p[ch].X, search_p[ch].Y, ref calive); calive -= 1; // Из соседей убираем текущую клетку if (calive == cells_clone[i, c].PreferedNeighboursNumber || calive == cells_clone[i, c].PreferedNeighboursNumber + 1) { cells[i, c].IsAlive = false; cells[search_p[ch].X, search_p[ch].Y] = cells[i, c]; cells[search_p[ch].X, search_p[ch].Y].IsAlive = true; found = true; break; } } } catch { /* Выход за пределы массива. */ } // Процент смертности int death_percent = (int)deathTrackBar.Value; if (found == false && rnd.Next(0, 101) < death_percent) cells[i, c].IsAlive = false; } else if (cells_clone[i, c].IsAlive == false) { // Процент рождаемости int born_percent = (int)bornTrackBar.Value; if (nalive > 1 && rnd.Next(0, 101) < born_percent) { // Выбираем два несовпадающих соседа int parent1_num = 0, parent2_num = 0; while (neighbours[parent1_num].IsAlive == false) parent1_num = rnd.Next(0, 8); while (neighbours[parent2_num].IsAlive == false || parent1_num == parent2_num) parent2_num = rnd.Next(0, 8); // Шанс мутации bool mutation = rnd.Next(0, 101) <= 5; // Магия (двойное условное выражение) Cell child = new Cell( mutation ? rnd.Next(0, 8) : (rnd.Next(0, 2) == 0) ? neighbours[parent1_num].PreferedNeighboursNumber : neighbours[parent2_num].PreferedNeighboursNumber, true); cells[i, c] = child; } } } } ++countOfSteps; stepCountLabel.Text = countOfSteps.ToString(); }
private void GenerateField(bool init) { for (int i = 0; i < FIELD_WIDTH; i++) for (int c = 0; c < FIELD_HEIGHT; c++) cells[i, c] = new Cell( rnd.Next(0, 8), init ? false : rnd.Next(0, 4) == 0 ? true : false ); }
// Возвращает цвет ячейки в зависимости от её любимого кол-ва соседей private ColorU GetCellColor(Cell c) { switch (c.PreferedNeighboursNumber) { case 0: return new ColorU(Color.DarkBlue); case 1: return ColorU.Blue; case 2: return ColorU.DeepSkyBlue; case 3: return ColorU.Green; case 4: return ColorU.LimeGreen; case 5: return ColorU.Gold; case 6: return ColorU.Orange; case 7: return ColorU.Red; default: return bgColor; } }