Search code examples
f#2048

Making a "2048 solitaire game" with F#: creating the functions for the implementation file (.fs file)


I am tasked with creating a version of the 2048 game. This version is on a 3x3 field, and uses colors (instead of numbers). The functions that I will need have already been given to me. Among these, I have to make a filter function, which I am having trouble figuring out how to implement. The filter function is defined as shown below with some examples which make perfect sense to me.

type pos = int*int // A 2 - dimensional vector in board - coordinats (not pixels)
type value = Red | Green | Blue | Yellow | Black // piece values
type piece = value*pos //
type state = piece list // the board is a set of randomly organized pieces

val filter: k: int -> s: state -> state

// return the list of pieces on a column k on board s, e.g. ,
// > filter 0 [( Blue , (1 , 0)); (Red , (0 , 0))];;
// val it: state = [( Blue , (1 , 0)); (Red , (0 , 0))]
// > filter 1 [( Blue , (1 , 0)); (Red , (0 , 0))];;
// val it: state = []

My thoughts are:

  • To use some kind of pattern matching, specific to this case of a 3x3 board, with k columns being {0, 1, 2}
let filter (k: int) (s: state) : state =
 match k with
  | 0 -> 
  | 1 -> 
  | 2 -> 

Solution

  • As the state is a List<piece> I would use List.filter. Within the filter predicate you can "deconstruct" the state and verify whether k equals column:

    let filter (k: int) (s: state) : state = 
      s |> List.filter(fun (pieceValue, (row, column)) -> k = column)
    

    Note that we can also ignore unused values by using _.

    let filter (k: int) (s: state) : state = 
      s |> List.filter(fun (_, (_, column)) -> k = column)
    

    We can also remove all the explicit types in these functions as they are inferred automatically by the F# compiler.

    let filter k s = 
      s |> List.filter(fun (_, (_, column)) -> k = column) 
    

    And to make it even shorter we can even remove the explicit pipe of s into List.filter:

    let filter k = List.filter (fun (_, (_, column)) -> k = column) 
    

    Now you can see that the filter for you game state is nothing more than a List.filter with a specific predicate.

    Also, I know the functions you have to implement are given, but still consider renaming this function to something like column and k to c or col :).

    /// The `piece`s in the given column `col`.
    let column col = List.filter (fun (_, (_, column)) -> col = column)