【发布时间】:2015-07-21 05:17:06
【问题描述】:
我正在尝试使用类似于 Scheme 的中级学生语言制作井字游戏。如果可能,我想使用我定义的数据类型使其工作,但如有必要会更改。在下面的代码中,我创建了一些让我接近我想要的位置的函数:
- potential-moves,列出每一个可能的下一步行动
- game-over?,它告诉我是否有玩家在井字棋盘中选择了中奖号码(空格)
请注意,我设计这款井字游戏的方式是使用“选择 3 个数字(1 到 9 之间)加起来为 15”的方法 - 我愿意改变这一点。
我只是迷路了,不知道下一步该做什么。我想要的是我的主要 minimax 函数返回下一个动作,如果轮到计算机,它将最小化分数,如果轮到玩家,则最大化分数。
(define-struct board [turn compmoves playermoves remaining])
; A Board is a (make-game symbol [List-of Number] [List-of Number] [List-of Number])
; interpretation -> who's turn is it, which spaces have been played by computer,
; which spaces have been played by the player, and
; which spaces remain
;Winning combinations (order doesn't matter,
;and this is reflected in the 'game-over?' function
(define winr1 '(8 1 6))
(define winr2 '(3 5 7))
(define winr3 '(4 9 2))
(define winc1 '(8 3 4))
(define winc2 '(1 5 9))
(define winc3 '(6 7 2))
(define wind1 '(8 5 2))
(define wind2 '(4 5 6))
(define a-win (list winr1 winr1 winr3 winc1 winc2 winc3 wind1 wind2))
(define BOARD0 (make-board 'player '(9 3 1) '(4 8 6) '(2 5 7)))
(define BOARD1 (make-board 'player '(8 6 5 9) '(1 3 7 4 2) '()))
(define BOARD2 (make-board 'player '(4 2 5 8) '(1 9 6) '(3 7)))
;Board -> Number
;evaluates a game tree
;NOT SURE WHAT TO DO HERE
#;(define (minimax board)
(cond
[(game-over? board) (evaluate board)]
[else minimax ?]))
;(check-expect (minimax BOARD1) 0)
;(check-expect (minimax BOARD2) -1)
;Board -> [List-of Board]
;returns a list of potential boards
(define (potential-moves board)
(local (;Number -> [List-of Number]
;takes a referenced nummber in a list
;and adds it to another list
(define (add-move n)
(cond
[(player-turn? board)(cons (list-ref (board-remaining board) n)
(board-playermoves board))]
[else (cons (list-ref (board-remaining board) n)
(board-compmoves board))]))
;Number [List-of Number] -> [List-of Number]
;returns a list without the nth term
(define (extract n xs)
(cond
[(= n 0)(rest xs)]
[else (cons (first xs) (extract (sub1 n) (rest xs)))]))
)
(build-list (length (board-remaining board))
(λ (i) (make-board (next-player (board-turn board))
(if (not (player-turn? board))
(add-move i)
(board-compmoves board))
(if (player-turn? board)
(add-move i)
(board-playermoves board))
(extract i (board-remaining board)))))))
;Symbol -> Symbol
;changes the turn
(define (next-player s)
(if (symbol=? s 'player)
'computer
'player))
(check-expect (next-player 'player) 'computer)
(check-expect (next-player 'computer) 'player)
;Board -> Number
;evaluates the board
(define (evaluate board)
(cond
[(empty? (board-remaining board)) 0]
[(player-turn? board) -1]
[else 1]))
(check-expect (evaluate BOARD1) 0)
(check-expect (evaluate BOARD2) -1)
;Board -> Boolean
;the game is over if
; - there are no more moves remaining,
; - the player has a winning combination, or
; - the computer has a winning combination
(define (game-over? board)
(or (empty? (board-remaining board))
(ormap (λ (win) (in-moves? win (board-compmoves board))) a-win)
(ormap (λ (win) (in-moves? win (board-playermoves board))) a-win)))
(check-expect (game-over? BOARD1) true)
(check-expect (game-over? BOARD2) true)
;[List-of Number] [List-of Number] -> Boolean
;are the values from the first list in the second, in any order?
(define (in-moves? combo moves)
(andmap (λ (number) (member? number moves)) combo))
(check-expect (in-moves? '(4 5 6) '(4 1 8 6 5 3 2)) true)
;Board -> Boolean
;determines if it's the player's turn
(define (player-turn? board)
(symbol=? 'player (board-turn board)))
(check-expect (player-turn? BOARD1) true)
;Board -> Boolean
;determines if it's the computer's turn
(define (computer-turn? board)
(symbol=? 'computer (board-turn board)))
(check-expect (computer-turn? BOARD2) false)
【问题讨论】:
-
当你有一个动作要进行,并且有一个所有可能的动作列表(比如
n动作)时,对于每个动作,进行动作。这会产生n新游戏板。将算法递归地应用到这些板上。继续到一定深度,或者直到游戏结束。你做出的每一个动作都应该有一个效用,这是你给它的分数,表明这个动作有多好。我认为您可能需要阅读 minimax ocf.berkeley.edu/~yosenl/extras/alphabeta/alphabeta.html。 -
目前还不清楚你是如何给棋盘打分的,或者确切地说是“你在问什么”。请提供minimal complete verifiable example 而不是代码转储。
标签: algorithm scheme lisp racket minimax