I'm doing an independent study on Elm, and I feel like I'm learning to program all over again! As a learn-the-language project, I'm trying to get an easy blackjack up and running, but once I started I realized how much I still don't grasp. I have as far as drawing cards from a deck and adding them to a list:
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
My questions are mostly on how to continue. Looking at completed Elm projects helps a little, but many of them are hard for me to parse as a beginner. Any kind of direction helps!
One of the first problems I had was trying to figure out how to remove cards from the deck once they're drawn, using something like dropCard deck card = filter (\card /= nextCard) deck
to filter out the drawn card from the list. But my understanding of Elm is that every time a signal changes, the program re-evaluates, meaning that the deck is recreated in full every time a card is drawn. Would I need to foldp
the original deck as well?
What's the proper way to remove an element from one list and add it to another in functional programming? Function composition, like toHand . dropCard card
?
For adding card faces to determine winning/losing, I'm not sure how to get the integer value out of the list. I tried doing fst (head deck)
, but I got type errors, probably because deck is itself a signal of some kind. Is there something I'm not seeing?
That said, I've really enjoyed Elm thus far!
foldp
over that whole datastructure, so instead of just keeping track of the hand you also keep track of the deck. fst (head deck)
should work. Perhaps you forgot to remove lift
in the main
definition when you tried it?-- 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
If anything is unclear, let me know.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With