Reputation: 151
I am new to Racket, and am trying to write a Mastermind game for my Programming Languages class. I have completed the code and it runs too. In the code below 'solution' is a list of 4 randomly generated colors. I wanted to ask how can I modify my 'constructSolution' function so I can run a loop/recursion instead of writing set! 4 different times. I tried modifying the constructSolution function like this:
(define i 0)
(define (constructSolution)
(cond
((if (< i 4)
(set! solution (append solution (list (random-color))))
(set! i (+ i 1))))
(else #f))
)
But it didn't work. Ideally the user will enter the length of the list and the function will check '(if (< i length))' instead of '(if (< i 4))'. Any help would be appreciated. Here is the code I have:
#lang racket
(require racket/gui/base)
(define solution1 '(yellow red black blue))
(define solution '())
(define blackPegs 0)
(define totalPegs 0)
(define whitePegs 0)
(define countPegs 0)
(define numBlackPegs 0)
(define guessText "")
(define displayGuess "Guess ")
(define displayScore "Black Pegs = ")
(define displaySolution "Solution: ")
(define numGuess 1)
(define f (new frame% [label "Mastermind"]
[width 300]
[height 500]
[alignment '(center center)]))
(send f show #t)
(define c (new editor-canvas% [parent f]))
(define t (new text%))
(send c set-editor t)
(send t insert "Welcome to Mastermind!\n\n")
(define (constructSolution)
(set! solution (append solution (list (random-color))))
(set! solution (append solution (list (random-color))))
(set! solution (append solution (list (random-color))))
(set! solution (append solution (list (random-color))))
)
(define (random-color)
(choose '(red blue green yellow orange purple black)))
(define (choose xs)
(list-ref xs (random (length xs))))
(define (alist->string alst)
(string-join (map symbol->string alst) " "))
(constructSolution)
(set! displaySolution (string-append displaySolution (alist->string solution)))
(send t insert displaySolution)
(send t insert "\n\n")
(define (try guess)
(compareBlackPegs guess solution blackPegs)
(printf "(~a, " numBlackPegs)
(compareWhitePegs guess solution)
(printf "~a) ~n" whitePegs)
(set! guessText (alist->string guess))
(set! totalPegs 0)
(set! displayGuess (string-append displayGuess (number->string numGuess)))
(set! displayGuess (string-append displayGuess ": "))
(set! displayGuess (string-append displayGuess guessText))
(set! displayGuess (string-append displayGuess "\n"))
(send t insert displayGuess)
(set! displayGuess "Guess ")
(set! displayScore (string-append displayScore (number->string numBlackPegs)))
(set! displayScore (string-append displayScore ", White Pegs = "))
(set! displayScore (string-append displayScore (number->string whitePegs)))
(set! displayScore (string-append displayScore "\n\n"))
(send t insert displayScore)
(set! displayScore "Black Pegs = ")
(set! numGuess (+ numGuess 1))
)
(define (compareBlackPegs guess solution blackPegs)
(if (null? guess) (set! numBlackPegs blackPegs)
(if (equal? (car guess) (car solution)) (compareBlackPegs (cdr guess) (cdr solution) (+ blackPegs 1))
(compareBlackPegs (cdr guess) (cdr solution) blackPegs)))
)
(define (compareWhitePegs guess solution)
(cond ((null? solution)
(set! whitePegs (- totalPegs numBlackPegs)))
;(printf "~a) ~n" totalPegs))
(else
(let ((a (count (car solution) guess countPegs))
(b (count (car solution) solution countPegs)))
(if (equal? (< a b) #t) (set! totalPegs (+ totalPegs a))
(set! totalPegs (+ totalPegs b))))
(compareWhitePegs guess (cdr solution))))
)
(define (count x alist countPegs)
(if (null? alist) countPegs
(if (equal? x (car alist)) (count x (cdr alist) (+ countPegs 1))
(count x (cdr alist) countPegs)))
)
(try '(red red red red))
(try '(red yellow yellow yellow))
(try '(yellow red green green))
(try '(yellow red blue blue))
(try '(yellow red blue white))
(try '(yellow red black blue))
(send t insert "\nGoodbye!\n")
Upvotes: 0
Views: 1381
Reputation: 236004
Please avoid using set!
for implementing a loop in Scheme, that's not the way to go - use recursion or the built-in looping constructs. If you want to repeat a function call a fixed number of times (say, 4) here's an example of how to do it using explicit recursion:
(define (repeat f n)
(cond ((zero? n) 'done)
(else (f)
(repeat f (sub1 n)))))
The above will call f
a given number of times. If necessary modify it to pass additional parameters to f
. For example:
(repeat (lambda () (display 'xo)) 4)
=> xoxoxoxo
'done
Upvotes: 0