2011-02-22 4 views
5

Я реализую игру, подобную шашки, и мне нужна последовательность, которая перечисляет все легальные шаги для данной конфигурации.Создание составного итератора в F #

У меня есть следующие функции, непосредственно переведенный с 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; 
    } 

Это работает, но это неудобно, и не совсем «F # путь», не говоря уже у меня есть подозрение, что то, что я Делать здесь не оптимально.

Что бы я хотел, это «сгладить это» во что-то, что использует комбинацию «итерации по всем ячейкам», «перебирать все допустимые ходы из этой ячейки».

А вот функции я надеюсь объединить:

let AllCells = 
    seq { 
     for y=0 to BOARDSIZE-1 do 
      for x=0 to BOARDSIZE-1 do 
       yield (x,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; 
    } 

я собираюсь пощадить вас подробности моих различных попыток заставить его работать, потому что ни один из них не был успешным. Но, чтобы сделать длинную историю коротким, лучшее, что я мог придумать, - это итератор, который возвращает seq с каждым выходом, а не сглаженной версией, которую я ищу, которая вернет простой MoveStruct.

У кого-нибудь есть хорошая идея, как объединить AllCells и LegalMovesAround (x, y)?

С уважением, Aleks

ответ

1

Вы должны быть в состоянии объединить их так, как они есть, и затем сглаживаются, что-то вроде этого:

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

Это не может быть лучшим решением точки зрения производительности, хотя.

EDIT: Фиксированный образец кода в соответствии с Томашем комментарий

+0

Остерегайтесь смешения ленивых последовательностей и побочных эффектов! Если плата мутирована, важно иметь четкое представление о том, когда оценивается вся последовательность. Вызов Seq.distinct выглядит опасным. – Joh

+0

Не обращайте внимания на мой комментарий выше, Seq.distinct будет вызываться перед спусканием дерева движений. – Joh

+1

Это не печатает проверку. Я думаю, 'legalMovesAround' должен быть аргументом' Seq.collect'. –

3

Вы можете использовать выход! в новом выражении последовательности:

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

Вы знаете о yield!?

что-то вроде

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

Это решение также работает, за исключением того, что возвращает последовательность с каждым выходом, в то время как я предпочитаю, чтобы он возвращал MoveStruct. Вызывающему абоненту не нужно знать о деталях реализации. – user627943

+0

Нет, это дает MoveStruct. Попробуй. – Brian

+0

Правда, да. Работает как магия. – user627943

Смежные вопросы