https://ocw.mit.edu/courses/electrical-engineering-and-computer-science/6-001-structure-and-interpretation-of-computer-programs-spring-2005/index.htm

https://github.com/DeathKing/Learning-SICP

https://mitpress.mit.edu/sites/default/files/sicp/index.html

https://www.bilibili.com/video/BV1Xx41117tr?from=search&seid=14983483066585274454

https://mitpress.mit.edu/sites/default/files/sicp/psets/index.html

scheme.exe file.scm

https://doraemonzzz.com/2020/11/29/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%A8%8B%E5%BA%8F%E7%9A%84%E6%9E%84%E9%80%A0%E5%92%8C%E8%A7%A3%E9%87%8A(SICP)%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/

## 游戏规则说明

• 两个人抽值为1~10的牌，最后比较谁手里的牌之和大，如果牌之和大于21，则失败；
• 每个会给对手看一张牌（为第一次抽到的牌，整局保持不变）；
• 每人设计自己策略；

$scheme.exe ps2tw1.scm Chez Scheme Version 9.5.4 Copyright 1984-2020 Cisco Systems, Inc. Opponent up card 8 Your Total: 9 Hit? y Opponent up card 8 Your Total: 14 Hit? y Opponent up card 8 Your Total: 18 Hit? y Opponent up card 9 Your Total: 11 Hit? y Opponent up card 9 Your Total: 21 Hit? n ## Problem 2 代码： (define (stop-at value) (lambda (your-hand opponent-up-card) (if (< (hand-total your-hand) value) #t #f))) (twenty-one hit? (stop-at 16)) 运行结果： $ scheme.exe ps2tw1.scm
Chez Scheme Version 9.5.4

Opponent up card
8

9

Hit?
y

Opponent up card
8

14

Hit?
y

Opponent up card
8

18

Hit?
n

## Problem 3

(define (test-strategy player-strategy house-strategy n)
(define (display-res player-win)
(newline)
(display "player win ")
(display player-win)
(display " in ")
(display n)
(display " games!"))
(define (iter num player-win)
(cond ((= n num) (display-res player-win))
(else (iter (+ num 1) (+ player-win (twenty-one player-strategy house-strategy))))))
(iter 0 0))

(test-strategy (stop-at 16) (stop-at 15) 100)

$scheme.exe ps2tw1.scm Chez Scheme Version 9.5.4 Copyright 1984-2020 Cisco Systems, Inc. player win 44 in 100 games! ## Problem 4 代码： (define (watch-player strategy) (lambda (your-hand opponent-up-card) (newline) (princ "Opponent up card ") (princ opponent-up-card) (newline) (princ "Your Total: ") (princ (hand-total your-hand)) (newline) (strategy your-hand opponent-up-card))) (test-strategy (watch-player (stop-at 16)) (watch-player (stop-at 15)) 1) (test-strategy (stop-at 16) (stop-at 15) 1) 实验结果： $ scheme.exe ps2tw1.scm
Chez Scheme Version 9.5.4

Opponent up card
8

9

Opponent up card
8

14

9

8

Opponent up card
9

11

Opponent up card
9

21

player win 0 in 1 games!
player win 1 in 1 games!

## Problem 5

(define (louis your-hand opponent-up-card)
(cond ((< (hand-total your-hand) 12) #t)
((> (hand-total your-hand) 16) #f)
((and (= (hand-total your-hand) 12) (< opponent-up-card 4)) #t)
((and (= (hand-total your-hand) 16) (= opponent-up-card 10)) #f)
((> opponent-up-card 6) #t)
(else #f)))

(test-strategy louis (stop-at 15) 100)
(test-strategy louis (stop-at 16) 100)
(test-strategy louis (stop-at 17) 100)

$scheme.exe ps2tw1.scm Chez Scheme Version 9.5.4 Copyright 1984-2020 Cisco Systems, Inc. player win 39 in 100 games! player win 44 in 100 games! player win 46 in 100 games! ## Problem 6 代码： (define (both s1 s2) (lambda (your-hand opponent-up-card) (and (s1 your-hand opponent-up-card) (s2 your-hand opponent-up-card)))) (test-strategy (both louis (stop-at 19)) (stop-at 18) 100) 实验结果： $ scheme.exe ps2tw1.scm
Chez Scheme Version 9.5.4

player win 37 in 100 games!

## Tutorial exercise 1

;;; Scheme code for Twenty-One Simulator [PS2 Fall '90]

(define (twenty-one player-strategy house-strategy)
(let ((house-initial-hand (make-new-hand (deal))))
(let ((player-hand
(play-hand player-strategy
(make-new-hand (deal))
(hand-up-card house-initial-hand))))
(if (> (hand-total player-hand) 21)
0                                ; bust'': player loses
(let ((house-hand
(play-hand house-strategy
house-initial-hand
(hand-up-card player-hand))))
(cond ((> (hand-total house-hand) 21)
1)                      ; bust'': house loses
((> (hand-total player-hand)
(hand-total house-hand))
1)                      ; house loses
(else 0)))))))           ; player loses

; (total ((v1 s1) (v2 s2)))

(define (card value suit)
(list value suit))

(define (card-value card)
(car card))

(define (card-suit card)

(define (deal)
(card (+ 1 (random 10)) (+ 1 (random 4))))

(define (make-new-hand first-card)
(make-hand (list first-card) (card-value first-card)))

(define (make-hand up-card total)
(list total up-card))

(define (hand-up-card hand)

(define (hand-total hand)
(car hand))

(define (hand-cards hand)

(define (play-hand strategy my-hand opponent-up-card)
(cond ((> (hand-total my-hand) 21) my-hand) ; I lose... give up
((strategy my-hand opponent-up-card) ; hit?
(play-hand strategy
opponent-up-card))
(else my-hand)))                ; stay

; append new-card
; (newline)
; (display hand)
(make-hand (append (cadr hand) (list new-card))
(+ (card-value new-card) (hand-total hand))))

(define (hit? your-hand opponent-up-card)
(newline)
(princ "Opponent up card ")
(princ opponent-up-card)
(newline)
(princ (hand-total your-hand))
(newline)
(princ (hand-cards your-hand))
(newline)
(princ "Hit? ")
(user-says-y?))

(define (princ cmd)
(display cmd)
(newline))

(twenty-one hit? hit?)

\$ scheme.exe tu_e1.scm
Chez Scheme Version 9.5.4

Opponent up card
(9 4)

4
Opponent up card
(9 4)

14

((4 3) (10 1))

Hit?
y

Opponent up card
(9 4)

17

((4 3) (10 1) (3 1))

Hit?
y

## Tutorial exercise 2

### a

; a
(define (fresh-deck)
(let ((n 10))
(define (iter i res)
(if (= i 0)
res
(iter (- i 1)
(append (list i i i i) res))))
(iter n '())))

(display (fresh-deck))

(define (fresh-deck-change)
(let ((n 10))
(define (iter i d res)
(cond ((= i 0) res)
((<= i n) (iter (- i 1) (- d 1) (append (list d d d d) res)))
(else (iter (- i 1) d (append (list d d d d) res)))))
(iter (+ n 3) n '())))

(display (fresh-deck-change))

(1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 10 10 10 10)

(1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 5 5 5 5 6 6 6 6 7 7 7 7 8 8 8 8 9 9 9 9 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10 10)

### b

; b
(define (length arr)
(define (iter arr l)
(if (eq? arr '())
l
(iter (cdr arr) (+ l 1))))
(iter arr 0))

; arr[:i], arr[i:]
(define (get-arr arr i)
(define (iter j a1 a2)
(if (= j 0)
(list a1 a2)
(iter (- j 1) (append a1 (list (car a2))) (cdr a2))))
(iter i '() arr))

(define a (list 1 2 3))

(get-arr a 1)

(define (shuffle arr)
(let ((n (length arr)))
; n // 2
(let ((m (quotient n 2)))
(let ((arrs (get-arr arr m)))
(let ((a1 (car arrs))
(define (iter arr1 arr2 res flag)
(cond ((eq? arr1 '()) (append res arr2))
((eq? arr2 '()) (append res arr1))
((eq? flag 0) (iter (cdr arr1) arr2 (append res (list (car arr1))) 1))
(else (iter arr1 (cdr arr2) (append res (list (car arr2))) 0))))
(iter a1 a2 '() 0))))))

(shuffle (list 1 2 3 4 5 6))

((1) (2 3))

(1 4 2 5 3 6)

### c

; c
(define (random-shuffle arr)
(let ((n (length arr)))
(let ((m (quotient n 2)))
(let ((arrs (get-arr arr m)))
(let ((a1 (car arrs))
(define (get-random-num)
(+ 1 (random 5)))
(define (iter arr1 arr2 res num flag)
(let ((m (get-random-num)))
(cond ((eq? arr1 '()) (append res arr2))
((eq? arr2 '()) (append res arr1))
((> num 0)
(if (eq? flag 0)
(iter (cdr arr1) arr2 (append res (list (car arr1))) (- num 1) 0)
(iter arr1 (cdr arr2) (append res (list (car arr2))) (- num 1) 1)))
(else (iter arr1 arr2 res m (- 1 flag))))))
(iter a1 a2 '() 0 1))))))

(random-shuffle (list 1 2 3 4 5 6 7 8 9 10 11 12))

(1 2 3 4 9 10 5 6 11 12 13 14 15 7 8 16)

### d

; d
(define (get-deck player-hand-and-deck)

(define (get-player-hand player-hand-and-deck)
(car player-hand-and-deck))

(define (twenty-one player-strategy house-strategy)
(let ((deck (new-deck)))
(let ((house-initial-hand (make-new-hand (deal deck))))
(let ((player-hand-and-deck
(play-hand player-strategy
(make-new-hand (deal (cdr deck)))
(hand-up-card house-initial-hand)
(cddr deck))))
(let ((player-deck (get-deck player-hand-and-deck))
(player-hand (get-player-hand player-hand-and-deck)))
; 如果牌没了
(cond ((eq? player-deck '()) (random-res))
(else
(if (> (hand-total player-hand) 21)
0                                ; bust'': player loses
(let ((house-hand-and-deck
(play-hand house-strategy
house-initial-hand
(hand-up-card player-hand)
player-deck)))
(let ((house-deck (get-deck house-hand-and-deck))
(house-hand (get-player-hand house-hand-and-deck)))
(cond ((> (hand-total house-hand) 21)
1)                      ; bust'': house loses
((> (hand-total player-hand)
(hand-total house-hand))
1)                      ; house loses
(else 0))))))))))))       ; player loses

(define (play-hand strategy my-hand opponent-up-card deck)
(cond ((eq? deck '()) (list my-hand deck))
((> (hand-total my-hand) 21) (list my-hand deck)) ; I lose... give up
((strategy my-hand opponent-up-card) ; hit?
(play-hand strategy
opponent-up-card
(cdr deck)))
(else (list my-hand deck))))                ; stay

(define (new-deck)
(let ((deck (fresh-deck-change))
(n 10))
(define (shuffle-iter i res)
(if (= i 0)
res
(shuffle-iter (- i 1) (random-shuffle res))))
(shuffle-iter n deck)))

(define (random-res)
(random 2))

(define (deal deck)
(car deck))

(define (make-new-hand first-card)
(make-hand first-card first-card))

(define (make-hand up-card total)
(cons up-card total))

(define (hand-up-card hand)
(car hand))

(define (hand-total hand)
(cdr hand))

(make-hand (hand-up-card hand)
(+ new-card (hand-total hand))))

(define (hit? your-hand opponent-up-card)
(newline)
(princ "Opponent up card ")
(princ opponent-up-card)
(newline)
(princ (hand-total your-hand))
(newline)
(princ "Hit? ")
(user-says-y?))

(define (princ cmd)
(display cmd)
(newline))

(define (stop-at value)
(lambda (your-hand opponent-up-card)
(if (< (hand-total your-hand) value)
#t
#f)))

(define (test-strategy player-strategy house-strategy n)
(define (display-res player-win)
(newline)
(display "player win ")
(display player-win)
(display " in ")
(display n)
(display " games!"))
(define (iter num player-win)
(cond ((= n num) (display-res player-win))
(else (iter (+ num 1) (+ player-win (twenty-one player-strategy house-strategy))))))
(iter 0 0))

(test-strategy (stop-at 16) (stop-at 15) 100)

player win 51 in 100 games!