2011-02-22 15 views
5

Estoy implementando un juego tipo damas, y necesito una secuencia que enumere todos los movimientos legales para una configuración dada.Creando un iterador compuesto en F #

Tengo la siguiente función, traducido directamente de C#:

seq { 
    for y1 = 0 to BOARDSIZE-1 do 
     for x1 = 0 to BOARDSIZE-1 do 
      for dy = -2 to 2 do 
       for dx = -2 to 2 do 
        let x2 = x1 + dx; 
        let y2 = y1 + dy; 
        let currentMove = new MoveStruct(x1, y1, x2, y2); 
        if (currentMove.SomeCondition = true) then 
          yield currentMove; 
    } 

Funciona, pero es difícil, y no es la "F # camino", y mucho menos tengo la sospecha de que lo que yo Estoy haciendo aquí no es el rendimiento óptimo.

Lo que me gustaría es "aplanar esto" en algo que utiliza una combinación de "iterar sobre todas las celdas", "iterar sobre todos los movimientos válidos desde esta celda".

Y aquí son las funciones que estoy con la esperanza de combinar:

let AllCells = 
    seq { 
     for y=0 to BOARDSIZE-1 do 
      for x=0 to BOARDSIZE-1 do 
       yield (x,y); 
    }; 

Y

let LegalMovesAround(x1,y1) = 
    seq { 
     if board.[x1, y1] = WHITE then 
     for dy = -2 to 2 do 
      for dx = -2 to 2 do 
       let x2 = x1 + dx; 
       let y2 = y1 + dy; 
       let currentMove = new MoveStruct(x1, y1, x2, y2); 
       if (currentMove.DetermineMoveType <> MoveType.ILLEGAL 
        && board.[x2, y2] = NONE) then 
         yield currentMove; 
    } 

Voy a ahorraré los detalles de mis diversos intentos de hacer que funcione, porque ninguno de ellos tuvo éxito. Pero para abreviar la larga historia, lo mejor que pude llegar es un iterador que devuelve un seq con cada rendimiento, en lugar de la versión aplanada que estoy buscando, que devolvería un simple MoveStruct.

¿Alguien tiene una buena idea de cómo combinar AllCells y LegalMovesAround (x, y)?

Saludos, Aleks

Respuesta

1

Usted debe ser capaz de combinarlos de la manera que son y luego aplanar, algo como esto:

let validMoves = 
    AllCells 
    |> Seq.collect LegalMovesAround 
    |> Seq.distinct 

puede no ser la mejor solución en cuanto al rendimiento, aunque.

EDIT: Fijo código de la muestra según el comentario Tomas

+0

Cuidado con mezclar secuencias perezosos y los efectos secundarios! Si la placa está mutada, es importante tener una idea clara de cuándo se evalúa toda la secuencia. Llamar a Seq.distinct parece peligroso aquí. – Joh

+0

No importa mi comentario anterior, se llamaría a Seq.distinct antes de bajar al árbol de movimientos. – Joh

+1

Esto no escribe verificación. Supongo que 'legalMovesAround' debería ser argumento de' Seq.collect'. –

3

Usted podría utilizar el rendimiento! en una nueva expresión de secuencia:

let allLegalMoves = seq { 
    for cell in AllCells do 
    yield! LegalMovesAround cell 
} 
3

¿Sabe usted de yield!?

algo así como

seq { 
    for x,y in Allcells do 
     yield! LMA(x,y) 
} 
+0

Esta solución también funciona, excepto que devuelve una secuencia con cada rendimiento, mientras que yo prefiero devolver un MoveStruct. La persona que llama no debería necesitar conocer los detalles de la implementación. – user627943

+0

No, produce un MoveStruct. Intentalo. – Brian

+0

Es verdad, lo hace. Funciona como magia – user627943

Cuestiones relacionadas