Creating a compound iterator in F#
-
03-12-2019 - |
문제
I'm implementing a checkers-like game, and I need a sequence that enumerates all legal moves for a given configuration.
I've got the following function, directly translated from 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;
}
It works, but it's awkward, and not quite the "F# way", let alone I have a sneaking suspicion that what I'm doing here is not performance optimal.
What I would like is to "flatten this out" into something that uses a combination of "iterate over all cells", "iterate over all valid moves from this cell".
And here are the functions I'm hoping to combine:
let AllCells =
seq {
for y=0 to BOARDSIZE-1 do
for x=0 to BOARDSIZE-1 do
yield (x,y);
};
AND
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;
}
I'm going to spare you the details of my various attempts to make it work, because none of them were successful. But to make the long story short, the best I could come up with is an iterator that returns a seq with each yield, instead of the flattened version I'm looking for, which would return a simple MoveStruct.
Anyone have a good idea how to combine AllCells, and LegalMovesAround(x,y)?
Regards, Aleks
해결책
You should be able to combine them the way they are and then flatten, something like this:
let validMoves =
AllCells
|> Seq.collect LegalMovesAround
|> Seq.distinct
It may not be the best solution performance-wise though.
EDIT: Fixed sample code as per Tomas comment
다른 팁
You could use yield! in a new sequence expression:
let allLegalMoves = seq {
for cell in AllCells do
yield! LegalMovesAround cell
}
Are you aware of yield!
?
something like
seq {
for x,y in Allcells do
yield! LMA(x,y)
}