HiveBrain v1.2.0
Get Started
← Back to all entries
patternMinor

Blackjack in Haskell

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
haskellblackjackstackoverflow

Problem

This is my first attempt at creating a game in Haskell, and I would greatly appreciate some feedback.

Here is Main.hs:

module Main where

import Deck

import Data.List
import System.Random
import Control.Monad.State

-- |'main' is the entry point for the program. This function will bind a
-- random number generator and pass it into a new 'Game' state. Finally, it will
-- evaluate the 'gameLoop'.
main :: IO ()
main = do
  stdGen  GameS IO (Action)

-- |'gameLoop' will repeatedly evaluate an iteration of the game. It updates the
-- game state based on the actions of the player and the dealer, and then
-- determines if the game is over.
gameLoop :: GameS IO ()
gameLoop = do
  curr  [Card] -> Bool
won playerH dealerH = playerScore > dealerScore
  where playerScore = score playerH
        dealerScore = score dealerH

score :: [Card] -> Int
score h 
  | bust h    = 0
  | otherwise = best h

bust :: [Card] -> Bool
bust = and . map (( Bool
twentyOne = any ((==) 21) . possiblePoints

best :: [Card] -> Int
best = maximum . filter ((>=) 21) . possiblePoints

showDealer :: [Card] -> String
showDealer hand = "[" ++ (show $ head hand) ++ "," ++ (intersperse ',' hidden) ++ "]"
  where n = length $ tail hand
        hidden = replicate n '?'

mkGame :: StdGen -> Strategy -> Game
mkGame g strat = Game
  { deck = d' 
  , playerHand = playerH
  , playerAction = Hit
  , dealerHand = dealerH
  , dealerAction = Hit
  , dealerStrategy = strat }
  where d = execState shuffle $ mkDeck g
        ((playerH, dealerH), d') = runState deal $ d

deal :: DeckS ([Card], [Card])
deal = do
  mine    Strategy
hitSometimes threshold _ = do
  curr  threshold
    then return Hit
    else return Stay


Here is Deck.hs:

```
module Deck
( Card
, possiblePoints
, Deck
, DeckS
, cards
, gen
, mkDeck
, draw
, shuffle
, takeRandomCard
, takeCardAt ) where

import System.Random
import Control.Monad.State

-- |The 'Card' data type represents the possible playing card ranks.
dat

Solution

I am not a Haskell programmer but I can't help suggest an improvement for possiblePoints. That much repetition hurt my eyes. :)

-- first factor out the mapping from a card to its value(s)
possibleValues :: Card -> [Int]
possibleValues card
    | card == Ace = [1, 11]
    | card `elem` [Jack,Queen,King] = [10]
    | otherwise = fromEnum card

possiblePoints :: [Card] -> [Int]
possiblePoints hand = nub $ map sum $ mapM possibleValues hand

Code Snippets

-- first factor out the mapping from a card to its value(s)
possibleValues :: Card -> [Int]
possibleValues card
    | card == Ace = [1, 11]
    | card `elem` [Jack,Queen,King] = [10]
    | otherwise = fromEnum card


possiblePoints :: [Card] -> [Int]
possiblePoints hand = nub $ map sum $ mapM possibleValues hand

Context

StackExchange Code Review Q#46809, answer score: 8

Revisions (0)

No revisions yet.