Conway's Game of Life in PowerShell using WPF. Slow but seemingly functional (let me know if there are any bugs). Game pauses when mouse is hovering over board. Beware of line breaks caused by "blogger."
#SCRIPT
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName PresentationFramework
Add-Type -AssemblyName PresentationCore
$Window = [System.Windows.Window]@{Width=450;Height=450}
$Global:GX_Size = 25
$Global:GY_Size = 25
$Life_Canvas = [System.Windows.Controls.Canvas]@{Background="#CCEEFF"};$Window.AddChild($Life_Canvas)
Function Compare-Boards ($Board1, $Board2){
$Keys = $Board1.Keys
foreach($Key in $Keys){
$B1_Val = $Board1.$Key
$B2_Val = $Board2.$Key
if($B1_Val -ne $B2_Val){
Write-Host -ForegroundColor Green -Object "$B1_Val != $B2_Val"
}
else{
Write-Host -ForegroundColor Red -Object "$B1_Val = $B2_Val"
}
}
}
Function Draw-Cell($Parent,$CellWidth=20,$CellHeight=20,$State=1,$X, $Y, $Board){
<#States
1: Any live cell with fewer than two live neighbours dies, as if caused by under-population.
2: Any live cell with more than three live neighbours dies, as if by overcrowding.
3: Any live cell with two or three live neighbours lives on to the next generation.
4: Any dead cell with exactly three live neighbours becomes a live cell, as if by reproduction.
#>
$CellPXWidth = $Parent.ActualWidth / ($CellWidth+1)
$CellPXHeight = $Parent.ActualHeight / ($CellHeight+1)
if([bool]$State){[System.Windows.Media.Brush]$BG = "Green"}else{[System.Windows.Media.Brush]$BG="Black"}
$NewCell = [System.Windows.Shapes.Rectangle]@{Width=$CellPXWidth;Height=$CellPXHeight;Name="X$X`_Y$Y";Margin="$($X*$CellPXWidth),$($Y*$CellPXHeight)";HorizontalAlignment="Left";VerticalAlignment="Top";Fill=$BG;Stroke="#FF333333"}
$Click_Change = {
if([System.Windows.Input.Mouse]::LeftButton -ne "Pressed"){}
else{
$Board = $Global:Current_State
$Name = $This.Name
if($Board.$Name -eq 1){$Board.$Name = 0; $This.Fill = "Black"}
else{$Board.$Name = 1;$This.Fill = "Green"}
}
}
$NewCell.add_MouseEnter($Click_Change)
$NewCell.add_MouseDown($Click_Change)
$Parent.AddChild($NewCell)
}
Function Get-Tile($x, $y, $Board){
if($x -lt 0){$x = $Board.Width}
if($y -lt 0){$y = $Board.Height}
if($x -gt $Board.Width){$x = 0}
if($y -gt $Board.Height){$y = 0}
$CoordString = "X$x`_Y$y"
return @{Coord=$CoordString;Value=$Board.$CoordString}
}
Function Get-Neighbors ($xPos = 10, $yPos = 10, $Board){
$LiveCount = 0
$CheckedList = @()
for($x = -1; $x -le 1; $x++){
for($y = -1; $y -le 1; $y++){
#Skip if self
if($x -eq 0 -and $y -eq 0){continue}
$TileData = Get-Tile -x ($xPos + $x) -y ($yPos + $y) -Board $Board
#Skip if already checked; clipping purposes
if($CheckedList -contains $TileData.Coord){continue}
$CheckedList += $TileData.Coord
$LiveCount += $TileData.Value
}
}
return $LiveCount
}
Function Draw-Board ($X_Size=20, $Y_Size=20, $Current_State){
$Next_State = @{Width=$X_Size;Height=$Y_Size;GUID=[guid]::NewGuid().Guid}
for($x = 0; $x -le $X_Size; $x++){
for($y = 0; $y -le $Y_Size; $y++){
$Coord = "X$x`_Y$y"
$Count = Get-Neighbors -xPos $x -yPos $y -Board $Current_State
#Write-Host $Count -ForegroundColor Cyan
if($Current_State.$Coord -eq 1){
#Write-Host "Die" -ForegroundColor Red
if($Count -lt 2){$Next_State.$Coord = 0}
if($Count -eq 2 -or $Count -eq 3){$Next_State.$Coord = 1}
if($Count -gt 3){$Next_State.$Coord = 0}
}
elseif($Current_State.$Coord -eq 0){
if($Count -eq 3){
#Write-Host "Born" -ForegroundColor Cyan
$Next_State.$Coord = 1
}
else{$Next_State.$Coord = 0}
}
}
}
return $Next_State
}
#Initialize board
$Current_State = @{Width=$Global:GX_Size;Height=$Global:GY_Size;GUID=[guid]::NewGuid().Guid}
for($x = 0; $x -le $Global:GX_Size; $x++){
for($y = 0; $y -le $Global:GY_Size; $y++){
#$Current_State."X$x`_Y$y" = (Get-Random @(1,0))
$Current_State."X$x`_Y$y" = 0
}
}
#Write-Host $Current_State.GUID -ForegroundColor Cyan
#Write-Host -ForegroundColor Cyan "Initializing board"
for($ix = 0; $ix -le $Global:GX_Size;$ix++){
for($iy = 0; $iy -le $Global:GY_Size; $iy++){
$Coord = "X$ix`_Y$iy"
Draw-Cell -Parent $Life_Canvas -CellWidth $Global:GX_Size -CellHeight $Global:GY_Size -State $Current_State.$Coord -X $ix -Y $iy -Board $Current_State
}
}
$Global:Generation = 0
$GameLoop = {
Write-Host ($Global:Generation++) -ForegroundColor Cyan
# Write-Host -ForegroundColor Cyan "Running Game Loop"
$Next_State = Draw-Board -X_Size $Global:GX_Size -Y_Size $Global:GY_Size -Current_State $global:Current_State
$Life_Canvas.Children.Clear()
#Write-Host -ForegroundColor Cyan "$($Next_State.X2_Y4)"
for($ix = 0; $ix -le $Global:GX_Size;$ix++){
for($iy = 0; $iy -le $Global:GY_Size; $iy++){
$Coord = "X$ix`_Y$iy"
Draw-Cell -Parent $Life_Canvas -CellWidth $Global:GX_Size -CellHeight $Global:GY_Size -State $Next_State.$Coord -X $ix -Y $iy -Board $Next_State
}
}
$global:Current_State = $Next_State
#Write-Host $Current_State.GUID -ForegroundColor Cyan
}
$Refresher ={
$global:timer = new-object System.Windows.Threading.DispatcherTimer
$global:timer.Interval = [TimeSpan]"0:0:1"
$global:timer.Add_Tick($GameLoop)
$global:timer.Start()
}
$Window.add_Loaded($Refresher)
$Window.add_MouseEnter({$global:Timer.Stop()})
$Window.add_MouseLeave({$global:Timer.Start()})
$Window.ShowDialog()