Search code examples
racket

Making a deck of cards in Racket


I am trying to use Racket to make a full deck of playing cards for a BlackJack game. However, I have two problems:

  1. When I use the following code

    ;This function creates a list of all the card faces.
    (define faces '(2 3 4 5 6 7 8 9 10 J Q K A))
    ;This function creates a list of all card suits.
    (define suits '(Clubs Diamonds Hearts Spades))
    
    ;make-deck: Creates a new (unshuffled) 52 card deck
    ;     Returns: The deck (a list of cards)
    ;     Parameters: none
    
    (define make-deck
      (letrec ([pair-items (lambda (x y)
                             (cond
                               [(null? x) '()]
                               [(null? y) '()]
                               [(displayln (cons (car x) (cons (car y) (pair-items x (cdr y)))))]
                               ))])                 
        (pair-items faces suits))
      )
    

    I get

    (2 Spades)
    (2 Hearts . #<void>)
    (2 Diamonds . #<void>)
    (2 Clubs . #<void>)
    

    And I do not know what the issue is.

  2. I have no idea how to reset the iterator to pair the next element in the faces function with the whole of the suits function. Do I use let?


Solution

  • The trivial way is to use cartesian-product to generate the list of cards (You can also use for*/list to iterate over your faces and suits lists to get the same effect). Both demonstrated below:

    #lang racket/base
    
    (require racket/list)
    
    ;This function creates a list of all the card faces.
    (define faces '(2 3 4 5 6 7 8 9 10 J Q K A))
    ;This function creates a list of all card suits.
    (define suits '(Clubs Diamonds Hearts Spades))
    
    ; These two variables should be equal?
    (define deck-1 (cartesian-product faces suits))
    (define deck-2 (for*/list ([face (in-list faces)]
                               [suit (in-list suits)])
                     (list face suit)))
    

    A big issue with your code is using (cond ... [(displayln ...)]). displayln always returns a void value, which, since it's not #f, is always going to count as true in a cond. And without a test-body part of that cond-clause, what the true test-expr returns is what the cond evaluates to, so that's what you're getting added to the lists your function is printing (But not returning). You should probably start by splitting the display of data apart from the creation of it.