Phillip Trelford's Array

POKE 36879,255

Tic-tac-toe

Thanks to a recent article by Cameron Taggart it is now possible to Create F# Silverlight Apps from Visual Studio 2010 Shell. This means that you now don’t need to use a C# project to build the XAP file; which previously outside of VS2010 Pro meant resorting to building the XAP with Visual Web Developer 2010 Express and F# libraries in the VS2010 shell. The only issue I’ve found with this solution is that it is not possible to directly add new files to the F# application project, but you can easily add existing files.

From his example I've created a small reference Silverlight solution with a Tic-tac-toe theme:

  • TicTacToe: the Silverlight application
  • Game: a Silverlight library with some game logic
  • TicTacToe.Test: a Silverlight Unit Test project for testing game logic

If you have Silverlight 4 installed you should see a Tic-tac-toe board that you can mark:

The Silverlight Unit Test project contains a small Behavioural Driven Development (BDD) example to test winning positions using TickSpec:

Feature: Winning positions

Scenario: Winning positions
    Given a board layout:
        | 1   | 2   | 3   |
        | <O> | <O> | <X> |
        | <O> |     |     |
        | <X> |     | <X> |
    When a player marks <X> at <row> <col>
    Then <X> wins
    
Examples:
    | row    | col    | 
    | middle | right  |
    | middle | middle |
    | bottom | middle |

Examples:
    | X | O |
    | X | O |
    | O | X |

 

The example above shows that TickSpec will execute all combinations for multiple examples blocks. This makes it possible to also run the tests with X’s swapped for O’s:

image

The steps in the scenario are mapped to attributed F# tick methods:

let [<Given>] ``a board layout:`` (table:Table) =
    table.Rows |> Seq.iteri (fun y row -> 
        row |> Seq.iteri (fun x value -> board.[x,y] <- parseMark value)
    )
   
let [<When>] ``a player marks (X|O) at (top|middle|bottom) (left|middle|right)``
        (mark:string,Row row,Col col) =
    board.[col,row] <- parseMark mark

let [<Then>] ``(X|O) wins`` (mark:string) =
    Game.mark <- parseMark mark |> Option.get
    let line = winningLine()
    Assert.IsTrue(line.IsSome)

With the column and row positions parsed with F# Active Patterns:

let (|Col|) = function 
    | "left" -> 0 | "middle" -> 1 | "right" -> 2
    | s -> invalidCast s

let (|Row|) = function 
    | "top" -> 0 | "middle" -> 1 | "bottom" -> 2 
    | s -> invalidCast s

 

If you are interested in learning more about BDD & TickSpec there is a free F#unctional Londoners Meetup Group evening event on Wed 24th Nov 2010 at Skills Matter:

Teaser for Tomas Petricek’s talk on his Agent’s:

References:

Source code: TicTacToe.zip (334.65 kb)

Pingbacks and trackbacks (5)+

Comments are closed