Back in February Jon Harrop published an implementation of John Conway’s Game of Life in 32 lines of F# using WPF. I’ve managed to increase Jon’s example to a massive 50 lines but at the same time get it running in Silverlight. If you have Silverlight 4 installed you can click in the box below to kick start life.
Jon’s original code for calculating life:
module Game =
let count (a: _ [,]) x y =
let m, n = a.GetLength 0, a.GetLength 1
let mutable c = 0
for x in x-1..x+1 do
for y in y-1..y+1 do
if x>=0 && x<m && y>=0 && y<n && a.[x, y] then
c <- c + 1
if a.[x, y] then c-1 else c
let rule (a: _ [,]) x y =
match a.[x, y], count a x y with
| true, (2 | 3) | false, 3 -> true
| _ -> false
The Silverlight Control, containing a WriteableBitmap updated from an F# Async Workflow:
type GameControl(n) as control =
inherit System.Windows.Controls.UserControl()
let game =
let rand = System.Random()
Array2D.init n n (fun _ _ -> rand.Next 2 = 0) |> ref
let update _ = Game.rule !game |> Array2D.init n n
let bitmap = System.Windows.Media.Imaging.WriteableBitmap(n,n)
do control.Content <- System.Windows.Controls.Image(Source=bitmap)
let render () =
let pixels = bitmap.Pixels
let black, white = 0xff000000, 0xffffffff
for x in 0..n-1 do
for y in 0..n-1 do
pixels.[x+y*n] <-
if (!game).[x, y] then white else black
do for i = 1 to 3 do game:= update() done; render ()
do async {
use handle = new System.Threading.AutoResetEvent(false)
do! control.MouseLeftButtonUp |> Async.AwaitEvent |> Async.Ignore
do! Async.SwitchToThreadPool ()
while true do
game := update ()
bitmap.Dispatcher.BeginInvoke(fun _ ->
render()
bitmap.Invalidate()
handle.Set() |> ignore
) |> ignore
do! Async.AwaitWaitHandle handle |> Async.Ignore
handle.Reset() |> ignore
} |> Async.StartImmediate
Application startup:
type App() as app =
inherit System.Windows.Application()
do app.Startup.Add(fun _ -> app.RootVisual <- GameControl(256))
Resources:
Source code: GameOfLife.zip (2.38 kb)