#lang racket (require math/array) (require dyoo-while-loop) (define (ask-question prompt) (let loop() (display (string-append prompt "? ")) (flush-output) (define response (string-trim (read-line))) (if (non-empty-string? response) (string-upcase response) (begin (displayln "PLEASE ANSWER THE QUESTION.") (loop))))) (define (ask-for-int prompt) (let loop() (display (string-append prompt ": ")) (flush-output) (define response (string-trim (read-line))) (if (regexp-match? #px"^-?[0-9]+$" response) (string->number response) (begin (display "YOU DID NOT ENTER AN INTEGER.") (loop))))) (define (ask-to-play-again) (let loop() (define response (ask-question "DO YOU WANT TO PLAY AGAIN")) (cond [(or (string=? response "YES") (string=? response "Y")) #t] [(or (string=? response "NO") (string=? response "N")) #f] [else (displayln "PLEASE ANSWER \"YES\" OR \"NO\"") (loop)]))) (define (ask-to-see-the-rules) (let loop() (define response (ask-question "DO YOU WANT TO SEE THE RULES")) (cond [(or (string=? response "YES") (string=? response "Y")) #t] [(or (string=? response "NO") (string=? response "N")) #f] [else (displayln "PLEASE ANSWER \"YES\" OR \"NO\"") (loop)]))) (define (generate-random-number minimum maximum show) (define generated-number (+ minimum (random (+ 1 (- maximum minimum))))) (when show (displayln generated-number)) generated-number) (define (ask-for-guess attempt) (let loop() (define guess (ask-for-int (string-append "GUESS #" (number->string attempt)))) (cond [(< guess 0) (displayln "PLEASE GUESS A NON-NEGATIVE NUMBER.") (loop)] [(or (< guess 100) (> guess 999)) (displayln "PLEASE GUESS A NUMBER BETWEEN 100 AND 999.") (loop)] [else guess]))) (define (display-rules) (displayln "I WILL THINK OF A THREE-DIGIT NUMBER. YOU WILL TRY TO") (displayln "GUESS MY NUMBER AND I WILL GIVE YOU CLUES AS FOLLOWS:") (displayln " PICO - ONE DIGIT CORRECT BUT IN THE WRONG POSITION") (displayln " FERMI - ONE DIGIT CORRECT AND IN THE RIGHT POSITION") (displayln " BAGELS - NO DIGITS ARE CORRECT") (displayln "") (displayln "YOU GET TWENTY TRIES BEFORE YOU LOSE.") (displayln "")) (define (display-game-over arrayIn) (define number (make-int-from-array arrayIn)) (displayln "OH WELL, THAT'S TWENTY GUESSES.") (displayln "MY NUMBER WAS " (number->string number) ".")) (define (make-int-from-array arrayIn) (+ (* (vector-ref arrayIn 0) 100) (* (vector-ref arrayIn 1) 10) (vector-ref arrayIn 2))) (define (make-array-from-int valIn) (define retArray (vector 0 0 0)) (vector-set! retArray 0 (floor(/ valIn 100))) (vector-set! retArray 1 (floor(/ (- valIn (* (vector-ref retArray 0) 100)) 10))) (vector-set! retArray 2 (- valIn (+ (* (vector-ref retArray 0) 100) (* (vector-ref retArray 1) 10)))) retArray) (define (create-the-number) (define digits (vector 0 0 0)) (vector-set! digits 0 (generate-random-number 1 9 #f)) (let loop() (define num (generate-random-number 0 9 #f)) (if (= num (vector-ref digits 0)) (loop) (vector-set! digits 1 num))) (let loop() (define num (generate-random-number 0 9 #f)) (if (or (= num (vector-ref digits 0)) (= num (vector-ref digits 1))) (loop) (vector-set! digits 2 num))) digits) (define (check-guess guess digits) (let* ((temp (make-array-from-int guess)) (vals (vector 0 0 0))) (for ([i (in-range 3)]) (when (= (vector-ref temp i) (vector-ref digits i)) (vector-set! vals i 1))) (if (= (make-int-from-array vals) 111) #t (begin (when (= (vector-ref temp 0) (vector-ref digits 1)) (vector-set! vals 0 2)) (when (= (vector-ref temp 0) (vector-ref digits 2)) (vector-set! vals 0 2)) (when (= (vector-ref temp 1) (vector-ref digits 0)) (vector-set! vals 1 2)) (when (= (vector-ref temp 1) (vector-ref digits 2)) (vector-set! vals 1 2)) (when (= (vector-ref temp 2) (vector-ref digits 0)) (vector-set! vals 2 2)) (when (= (vector-ref temp 2) (vector-ref digits 1)) (vector-set! vals 2 2)) (if (= (make-int-from-array vals) 0) (displayln "BAGELS") (begin (for ([i (in-range 3)]) (cond [(= (vector-ref vals i) 1) (display "FERMI ")] [(= (vector-ref vals i) 2) (display "PICO ")])) (displayln " "))) #f)))) (define (main) (displayln "*** BAGELS : LISP ***") (define score 0) (define running #t) (when (ask-to-see-the-rules) (display-rules)) (while running (define gameover 0) (define attempt 1) (define digits (create-the-number)) (displayln "OK, I HAVE A NUMBER IN MIND.") (while (= gameover 0) (define guess (ask-for-guess attempt)) (if (check-guess guess digits) (begin (displayln "YOU GOT IT!!!") (set! score(+ score 1)) (set! gameover 1)) (begin (set! attempt(+ attempt 1)) (when (> attempt 20) (begin (display-game-over digits) (set! gameover 1)))))) (set! running (ask-to-play-again))) (display "A ") (display score) (displayln " POINT BAGELS BUFF!") (displayln "HOPE YOU HAD FUN. BYE!")) (main)