我正在使用Realm of Racket书中给出的存根作为基础,为一个打勾的游戏构建AI。到目前为止,一切都进展顺利。但是,当我尝试在树的根上运行minimax
函数时,它会返回一个可以通过运行它获得的最低可能值的列表(以任一播放器作为谓词)。
这是函数的代码转储:
(define (minimax tree player depth)
(define (generate-score tree player depth)
(define won (winner (ttt-tree-board tree)))
(if (<= depth 0) 0
(+ (cond
[(equal? won player) 1]
[(false? won) 0]
[else -1])
(apply +
(for/list ([t (ttt-tree-moves tree)])
(generate-score (second t) player (sub1 depth)))))))
(for/list ([t (ttt-tree-moves tree)])
(generate-score (second t) player depth)))
这只是我的minimax
函数,因为不需要显示其他任何函数(winner
除外)。这是winner
:
(define (winner board)
(or
(ormap (lambda (row) (if (all-equal? row) (first row) #f)) board) ; Horizontal
(ormap (lambda (i) (if ; Vertical
(all-equal? (map (lambda (j) (list-ref (list-ref board j) i)) (stream->list (in-range (length board)))))
(list-ref (first board) i) #f))
(stream->list (in-range (length board))))
(if ; Diagonal
(all-equal? (map (lambda (i) (list-ref (list-ref board i) i)) (stream->list (in-range (length board)))))
(first (first board)) #f)
(if ; Diagonal cont.
(all-equal? (map (lambda (i) (list-ref (reverse (list-ref board i)) i)) (stream->list (in-range (length board)))))
(last (first board)) #f)))
(这有点草率,所以如果有人想让它缩短,请告诉我你的建议)
ttt-tree
结构遵循以下模式:
(ttt-tree board moves)
其中board
是与刻度线板对应的2D数组(格式为'((X - O) (O X -) (- X O))
),moves
是可以进行的可能移动的列表从该节点开始,每个节点都是一个包含两个元素的列表:更改的位置和构成下一个节点的ttt-tree
。因此,如果(second t)
为t
(list-ref (ttt-tree-moves #<ttt-tree>) x)
会引用下一个节点
我最初的想法是cond
可能存在一些错误,但我使用的是equal?
而不是eq?
,所以我看不出这会是一个什么问题。另一种可能性是我正在定义winner
错误,但我已经多次测试过,所以我不知道会出现什么问题。请帮忙!
答案 0 :(得分:1)
事实证明问题在于,在winner
函数中,我从未检查过获胜者是否为"-"
,空格。因此,在大多数情况下会触发,激活else子句并导致得分为-1。