4

我正在对 Elm 进行独立研究,我觉得我正在重新学习编程!作为一个学习语言的项目,我试图让一个简单的二十一点开始并运行,但一旦我开始,我意识到我仍然没有掌握多少。我已经从牌组中抽牌并将它们添加到列表中:

import Random
import Mouse
import Array

--Build the deck
faces = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
suits = ['H', 'D', 'C', 'S']

allCards faces suits =
  case suits of
    x :: xs -> family faces x ++ allCards faces xs
    _ -> []

family faces suit =
  case faces of
    x :: xs -> (,) x suit :: family xs suit
    _ -> []

deck = allCards faces suits

rand : Signal Int
rand = Random.range 0 (length deck-1) Mouse.clicks 

pickCard n = head <| drop n deck
nextCard = lift pickCard rand

yourHand = foldp (::) [] nextCard

main = lift asText yourHand

我的问题主要是关于如何继续。查看已完成的 Elm 项目会有所帮助,但作为初学者,我很难解析其中的许多项目。任何方向都有帮助!

  1. 我遇到的第一个问题是试图弄清楚如何在卡片被抽出后从牌堆中移除,使用类似dropCard deck card = filter (\card /= nextCard) deck从列表中过滤掉抽出的卡片。但我对 Elm 的理解是,每次信号变化时,程序都会重新评估,这意味着每次抽牌时都会重新创建完整的牌组。我也需要foldp原来的甲板吗?

  2. 在函数式编程中从一个列表中删除一个元素并将其添加到另一个列表中的正确方法是什么?函数组合,例如toHand . dropCard card?

  3. 为了添加卡面以确定输赢,我不确定如何从列表中获取整数值。我试着做fst (head deck),但我得到了类型错误,可能是因为甲板本身就是某种信号。有什么我没看到的吗?

也就是说,到目前为止,我真的很喜欢 Elm!

4

1 回答 1

7

问题

  1. 对于简单的程序,考虑信号的最简单方法是考虑程序中哪些类型的东西可以改变。在你的情况下,这将是甲板和手。然后你把这些东西拿来做一个数据结构来存储它们。然后,您foldp对整个数据结构进行了处理,因此您不仅可以跟踪手牌,还可以跟踪牌组。
  2. 您可以编写一个接受列表和索引的函数,并返回列表中该索引处的项目以及删除该项目的列表。然后你将项目添加到另一个列表中,你就完成了。
  3. fst (head deck)应该管用。lift也许您在尝试时忘记在定义中删除main

示例代码

-- This first part is your code:
import Random
import Mouse
import Array

--Build the deck
faces = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
suits = ['H', 'D', 'C', 'S']

allCards faces suits =
  case suits of
    x :: xs -> family faces x ++ allCards faces xs
    _ -> []

family faces suit =
  case faces of
    x :: xs -> (,) x suit :: family xs suit
    _ -> []

-- Here come my additions/changes:
-- Naming some types for clarity
type Card = (Int,Char)
type ProgramState = { deck : [Card], hand : [Card] }

getFromList : Int -> [a] -> (a,[a])
getFromList index list =
  let prefix = take index list
      (item :: postfix) = drop index list
  in (item, prefix ++ postfix)

startState : ProgramState
startState = { deck = allCards faces suits, hand = [] }

rand : Signal Float
rand = Random.float Mouse.clicks 

rFloatToInt : Float -> Int -> Int -> Int
rFloatToInt rnd lo hi = round ((rnd + toFloat lo) * toFloat hi)

pickCard : Float -> ProgramState -> ProgramState
pickCard rnd {deck,hand} = 
  let index = rFloatToInt rnd 0 (length deck - 1)
      (item, newDeck) = getFromList index deck
  in { deck = newDeck, hand = item :: hand }

programState : Signal ProgramState
programState = foldp pickCard startState rand

main : Signal Element
main = lift asText programState

如果有任何不清楚的地方,请告诉我。

于 2014-10-08T18:02:57.757 回答