Academic Integrity: tutoring, explanations, and feedback — we don’t complete graded work or submit on a student’s behalf.

Conway’s Game of Life THIS MUST BE IN C# AND WPF From http://en.wikipedia.org/wi

ID: 3845194 • Letter: C

Question

Conway’s Game of Life THIS MUST BE IN C# AND WPF

From http://en.wikipedia.org/wiki/Conway%27s_Game_of_Life:

The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square cells, each of which is in one of two possible states, live or dead. Every cell interacts with its eight neighbours, which are the cells that are directly horizontally, vertically, or diagonally adjacent. At each step in time, the following transitions occur:

Any live cell with fewer than two live neighbours dies, as if by needs caused by underpopulation.

Any live cell with more than three live neighbours dies, as if by overcrowding.

Any live cell with two or three live neighbours lives, unchanged, to the next generation.

Any dead cell with exactly three live neighbours becomes a live cell.

The initial pattern constitutes the 'seed' of the system. The first generation is created by applying the above rules simultaneously to every cell in the seed — births and deaths happen simultaneously, and the discrete moment at which this happens is sometimes called a tick. (In other words, each generation is a pure function of the one before.) The rules continue to be applied repeatedly to create further generations.

Requirements:

For this assignment, you will provide a way for a user to define the size of a grid on your window. Each dimension has a minimum of 10 and a maximum of 100. Each grid cell will have some representation (a Button, Label, Canvas or something else) of a single Cell. Initially all the Cells will be dead, but you will provide a way for the user to populate the grid with a random distribution of live Cells. Additionally, if the user clicks the Cell in the UI, it will change the state of the cell from live to dead or vice versa.

You will provide a way for the user to step ahead a single generation, and a way to press “play” that will progress through the generations at a maximum speed of 15 generations per second.

You must create a Cell class that holds at least the information of whether the cell is alive or dead. The Cell’s representation must be data-bound to instances of the Cell class. The representations’ change in appearance must be done by some kind of ValueConverter. Any logic done for the game in your application must be done on the Cell objects, not the on-screen representation.

Rubric:

(30 pt.) Game of Life is implemented with the correct rules, and it functions correctly.

If you want to test your implementation, draw a straight line (horizontal or vertical, not diagonal) with 10 live Cells in a row, then run it. You should see it morph into a repeating pattern. Alternately, you can try any of the patterns documented in the Wikipedia article.

(10 pt.) User can create a grid of any size between 10x10 to 100x100. The grid can be rectangular instead of only square. You may allow the user to create smaller or larger grids, but the program must allow at least these sizes.

(5 pt.) Button to step ahead one generation is correctly implemented.

(15 pt.) Button to “play” is correctly implemented, including speed throttle.

Some people like to let their simulations run at maximum speed. If you’re one of those people, be sure to include some sort of throttle option that the grader can enable so that they can test if you’ve implemented the 15 generations / second requirement.

(10 pt.) Provide a way to populate the grid randomly with living cells.

(10 pt.) Cell representations on the grid use data binding to update themselves.

(10 pt.) Cell representations can be clicked to toggle a cell’s state between alive and dead.

(10 pt.) User interface is easy to use, code is clean and well-documented.

Explanation / Answer

using System;
using System.Text;
using System.Threading;

namespace ConwaysGame
{
  
class Program
{
  
private const int DELAY = 50; // initial dealy

// The cell colors.
private const ConsoleColor D_COLOR = ConsoleColor.White; //dead color
private const ConsoleColor L_COLOR = ConsoleColor.Black; //live color

// The color of the cells that are off of the board.
private const ConsoleColor EX_COLOR = ConsoleColor.Gray;

private const char EMPTY_BLOCK_CHAR = ' ';
private const char FULL_BLOCK_CHAR = 'u2588';

// Holds the current state of the board.
private static bool[,] board;

// The dimensions of the board in cells but the choice is yours.
private static int width = 35;
private static int height = 35;

// True if cell rules can loop around edges.
private static bool loopEdges = true;


static void Main(string[] args)
{
// Use initializeRandomBoard for a larger, random board.
initializeDemoBoard();

initializeConsole();

// Run the game until the Escape key is pressed.
while (!Console.KeyAvailable || Console.ReadKey(true).Key != ConsoleKey.Escape) {
Program.drawBoard();
Program.updateBoard();

// Wait for a bit between updates.
Thread.Sleep(DELAY);
}
}

// Sets up the Console.
private static void initializeConsole()
{
Console.BackgroundColor = EX_COLOR;
Console.Clear();

Console.CursorVisible = false;

// Each cell is two characters wide.
// Using an extra row on the bottom to prevent scrolling when drawing the board.
int width = Math.Max(Program.width, 8) * 2 + 1;
int height = Math.Max(Program.height, 8) + 1;
Console.SetWindowSize(width, height);
Console.SetBufferSize(width, height);

Console.BackgroundColor = D_COLOR;
Console.ForegroundColor = L_COLOR;
}

// Creates the initial board with a random state.
private static void initializeRandomBoard()
{
var random = new Random();

Program.board = new bool[Program.width, Program.height];
for (var y = 0; y < Program.height; y++) {
for (var x = 0; x < Program.width; x++) {
// Equal probability of being true or false.
Program.board[x, y] = random.Next(2) == 0;
}
}
}

// Creates a 3x3 board with a blinker.
private static void initializeDemoBoard()
{
Program.width = 3;
Program.height = 3;

Program.loopEdges = false;

Program.board = new bool[3, 3];
Program.board[1, 0] = true;
Program.board[1, 1] = true;
Program.board[1, 2] = true;
}

// Draws the board to the console.
private static void drawBoard()
{
// One Console.Write call is much faster than writing each cell individually.
var builder = new StringBuilder();

for (var y = 0; y < Program.height; y++) {
for (var x = 0; x < Program.width; x++) {
char c = Program.board[x, y] ? FULL_BLOCK_CHAR : EMPTY_BLOCK_CHAR;

// Each cell is two characters wide.
builder.Append(c);
builder.Append(c);
}
builder.Append(' ');
}

// Write the string to the console.
Console.SetCursorPosition(0, 0);
Console.Write (builder.ToString());
}

// Moves the board to the next state based on Conway's rules.
private static void updateBoard()
{
// A temp variable to hold the next state while it's being calculated.
bool[,] newBoard = new bool[Program.width, Program.height];

for (var y = 0; y < Program.height; y++) {
for (var x = 0; x < Program.width; x++) {
var n = countLiveNeighbors(x, y);
var c = Program.board[x, y];

// A live cell dies unless it has exactly 2 or 3 live neighbors.
// A dead cell remains dead unless it has exactly 3 live neighbors.
newBoard[x, y] = c && (n == 2 || n == 3) || !c && n == 3;
}
}

// Set the board to its new state.
Program.board = newBoard;
}

// Returns the number of live neighbors around the cell at position (x,y).
private static int countLiveNeighbors(int x, int y)
{
// The number of live neighbors.
int value = 0;

// This nested loop enumerates the 9 cells in the specified cells neighborhood.
for (var j = -1; j <= 1; j++) {
// If loopEdges is set to false and y+j is off the board, continue.
if (!Program.loopEdges && y + j < 0 || y + j >= Program.height) {
continue;
}

// Loop around the edges if y+j is off the board.
int k = (y + j + Program.height) % Program.height;

for (var i = -1; i <= 1; i++) {
// If loopEdges is set to false and x+i is off the board, continue.
if (!Program.loopEdges && x + i < 0 || x + i >= Program.width) {
continue;
}

// Loop around the edges if x+i is off the board.
int h = (x + i + Program.width) % Program.width;

// Count the neighbor cell at (h,k) if it is alive.
value += Program.board[h, k] ? 1 : 0;
}
}

// Subtract 1 if (x,y) is alive since we counted it as a neighbor.
return value - (Program.board[x, y] ? 1 : 0);
}
}
}