/collects/tests/unstable/temp-c/ttt.rkt

http://github.com/gmarceau/PLT · Racket · 180 lines · 155 code · 17 blank · 8 comment · 12 complexity · 20ba8ed6bd0dd8e122c81e91a2e49264 MD5 · raw file

  1. #lang racket/base
  2. (require racket/contract
  3. racket/match
  4. tests/eli-tester)
  5. ; A space is #f, 'X, or 'O
  6. (define space/c
  7. (or/c false/c 'X 'O))
  8. ; A board is a (hasheq (hasheq space space space) x 3 )
  9. (define posn/c
  10. (or/c 0 1 2))
  11. (define board/c
  12. (hash/c posn/c
  13. (hash/c posn/c
  14. space/c
  15. #:immutable #t)
  16. #:immutable #t))
  17. (define empty-board
  18. (hasheq 0 (hasheq 0 #f 1 #f 2 #f)
  19. 1 (hasheq 0 #f 1 #f 2 #f)
  20. 2 (hasheq 0 #f 1 #f 2 #f)))
  21. (define winning-o-board/col
  22. (hasheq 0 (hasheq 0 'O 1 #f 2 #f)
  23. 1 (hasheq 0 'O 1 #f 2 #f)
  24. 2 (hasheq 0 'O 1 #f 2 #f)))
  25. (define winning-x-board/row
  26. (hasheq 0 (hasheq 0 'O 1 #f 2 #f)
  27. 1 (hasheq 0 'X 1 'X 2 'X)
  28. 2 (hasheq 0 'O 1 #f 2 #f)))
  29. (define winning-x-board/left
  30. (hasheq 0 (hasheq 0 'X 1 #f 2 #f)
  31. 1 (hasheq 0 'O 1 'X 2 'X)
  32. 2 (hasheq 0 'O 1 #f 2 'X)))
  33. (define winning-o-board/right
  34. (hasheq 0 (hasheq 0 'X 1 #f 2 'O)
  35. 1 (hasheq 0 'O 1 'O 2 'X)
  36. 2 (hasheq 0 'O 1 #f 2 'X)))
  37. (define (board-ref b r c)
  38. (hash-ref (hash-ref b r) c))
  39. (test
  40. (board-ref empty-board 0 0) => #f
  41. (board-ref winning-o-board/right 1 2) => 'X)
  42. (define equal?*
  43. (match-lambda*
  44. [(list) #t]
  45. [(list e) e]
  46. [(list* e1 e2 es)
  47. (and (equal? e1 e2)
  48. (apply equal?* e2 es))]))
  49. (test
  50. (equal?*)
  51. (equal?* 1)
  52. (equal?* 1 1)
  53. (equal?* 1 1 1)
  54. (equal?* 1 1 1 2) => #f)
  55. (define (winning-board? b)
  56. (or
  57. ; Cols
  58. (for/or ([c (in-range 3)])
  59. (equal?*
  60. (board-ref b 0 c)
  61. (board-ref b 1 c)
  62. (board-ref b 2 c)))
  63. ; Rows
  64. (for/or ([r (in-range 3)])
  65. (equal?*
  66. (board-ref b r 0)
  67. (board-ref b r 1)
  68. (board-ref b r 2)))
  69. ; Left diagonal
  70. (equal?* (board-ref b 0 0)
  71. (board-ref b 1 1)
  72. (board-ref b 2 2))
  73. ; Right diagonal
  74. (equal?* (board-ref b 0 2)
  75. (board-ref b 1 1)
  76. (board-ref b 2 0))))
  77. (test
  78. (winning-board? empty-board) => #f
  79. (winning-board? winning-o-board/col) => 'O
  80. (winning-board? winning-x-board/row) => 'X
  81. (winning-board? winning-x-board/left) => 'X
  82. (winning-board? winning-o-board/right) => 'O)
  83. (define (board-set b r c m)
  84. #;(printf "b[~a][~a] = ~a\n" r c m)
  85. (hash-update b r (Îť (r) (hash-set r c m))))
  86. (test
  87. (board-set
  88. (board-set
  89. (board-set empty-board
  90. 0 0 'O)
  91. 1 0 'O)
  92. 2 0 'O)
  93. =>
  94. winning-o-board/col)
  95. (define (full-board? b)
  96. (for/and ([r (in-range 3)]
  97. [c (in-range 3)])
  98. (board-ref b r c)))
  99. (test
  100. (full-board?
  101. (for/fold ([b empty-board])
  102. ([r (in-range 3)]
  103. [c (in-range 3)])
  104. (board-set b r c 'X))))
  105. (define (tic-tac-toe o-player x-player)
  106. (let loop ([board empty-board]
  107. [os-turn? #t
  108. #;(zero? (random 2))])
  109. (cond
  110. [(winning-board? board)
  111. => (Îť (winner)
  112. (printf "~a wins!\n" winner))]
  113. [(full-board? board)
  114. (printf "Stalemate!\n")]
  115. [else
  116. (loop
  117. ((if os-turn?
  118. o-player
  119. x-player)
  120. board board-ref board-set)
  121. (not os-turn?))])))
  122. (require unstable/match
  123. unstable/temp-c/dsl)
  124. (provide
  125. (rename-out [tic-tac-toe
  126. tic-tac-toe:raw]))
  127. (provide/contract
  128. [tic-tac-toe
  129. (with-monitor
  130. (label 'game
  131. (-> (label 'turn
  132. (-> board/c
  133. (board/c posn/c posn/c . -> . space/c)
  134. (label 'board-set
  135. (board/c posn/c posn/c
  136. (and space/c (not/c false/c))
  137. . -> . board/c))
  138. board/c))
  139. (label 'turn
  140. (-> board/c
  141. (board/c posn/c posn/c . -> . space/c)
  142. (label 'board-set
  143. (board/c posn/c posn/c
  144. (and space/c (not/c false/c))
  145. . -> . board/c))
  146. board/c))
  147. void))
  148. (complement
  149. (union
  150. ; A board set hits something that was hit before
  151. (seq (star _)
  152. (call 'game _ _)
  153. (star _)
  154. (dseq (call 'board-set _ r c _)
  155. (seq (star (not (ret 'game _)))
  156. (call 'board-set _ (== r) (== c) _))))
  157. ; A player takes two turns
  158. (seq (star _)
  159. (call 'turn _ _ _)
  160. (? monitor:proj?)
  161. (call 'board-set _ _ _ _)
  162. (ret 'board-set _)
  163. (call 'board-set _ _ _ _)))))])