You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

236 lines
7.5 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# -*- coding:utf-8 -*-
import copy # 注意对象的深拷贝和浅拷贝的使用!!!
class GameNode:
'''博弈树结点数据结构
成员变量:
map - list[[]] 二维列表,三子棋盘状态
val - int 该棋盘状态对执x棋子的评估值1表示胜利-1表示失败0表示平局
deepID - int 博弈树的层次深度根节点deepID=0
parent - GameNode父结点
children - list[GameNode] 子结点列表
'''
def __init__(self, map, val=0, deepID=0, parent=None, children=[]):
self.map = map
self.val = val
self.deepID = deepID
self.parent = parent
self.children = children
class GameTree:
'''博弈树结点数据结构
成员变量:
root - GameNode 博弈树根结点
成员函数:
buildTree - 创建博弈树
'''
def __init__(self, root):
self.root = root # GameNode 博弈树根结点
def buildTree(self, root):
'''递归法创建博弈树
参数:
root - GameNode 初始为博弈树根结点
'''
#请在这里补充代码,完成本关任务
#********** Begin **********#
##创建root的子节点
###fuc用来调用判断是否最终状态的函数
mm=MinMax(False)
if mm.isTerminal(root):
root.val=mm.get_value(root)
return
##递归遍历创造新的节点
l=root.map
val=0
for i in range(3):
for j in range(3):
if l[i][j]=='x' or l[i][j]=='o':
continue
newL=copy.deepcopy(l)
newL[i][j]='o' if root.deepID%2>0 else 'x'
newNode=GameNode(map=newL,parent=root,deepID=(root.deepID+1),children=[],val=0)
root.children.append(newNode)
self.buildTree(newNode)
if root.deepID%2>0:
root.val=mm.min_value(root)
else:
root.val=mm.max_value(root)
#********** End **********#
class MinMax:
'''博弈树结点数据结构
成员变量:
game_tree - GameTree 博弈树
成员函数:
minmax - 极大极小值算法,计算最优行动
max_val - 计算最大值
min_val - 计算最小值
get_val - 计算某棋盘状态中执x棋子的评估值1表示胜利-1表示失败0表示平局
isTerminal - 判断某状态是否为最终状态:无空闲棋可走
'''
def __init__(self, game_tree):
self.game_tree = game_tree # GameTree 博弈树
def minmax(self, node):
'''极大极小值算法,计算最优行动
参数:
node - GameNode 博弈树结点
返回值:
clf - list[map] 最优行动即x棋子的下一个棋盘状态GameNode.map
其中map - list[[]] 二维列表,三子棋盘状态
'''
#请在这里补充代码,完成本关任务
#********** Begin **********#
val=node.val
result=[]
if val>0:
for i in node.children:
if i.val==val:
result.append(i.map)
return result
#********** End **********#
def max_value(self, node):
'''计算最大值
参数:
node - GameNode 博弈树结点
返回值:
clf - int 子结点中的最大的评估值
'''
#请在这里补充代码,完成本关任务
#********** Begin **********#
l=node.children
max=-1
for i in node.children:
max=i.val if i.val>max else max
return max
#********** End **********#
def min_value(self, node):
'''计算最小值
参数:
node - GameNode 博弈树结点
返回值:
clf - int 子结点中的最小的评估值
'''
#请在这里补充代码,完成本关任务
#********** Begin **********#
l=node.children
min=1
for i in node.children:
min=i.val if i.val<min else min
return min
#********** End **********#
def get_value(self, node):
'''计算某棋盘状态中执x棋子的评估值1表示胜利-1表示失败0表示平局
参数:
node - GameNode 博弈树结点
返回值:
clf - int 执x棋子的评估值1表示胜利-1表示失败0表示平局
'''
#请在这里补充代码,完成本关任务
#********** Begin **********#
l=node.map
isEndI=1
isEndJ=1
##判断行列上是否存在直线
for i in range(3):
isEndI=0 if l[i][0]=='_' else 1
isEndJ=0 if l[0][i]=='_' else 1
for j in range(3):
if l[i][j]=='_' or (isEndI>0 and l[i][j]!=l[i][0]):
isEndI=0
if l[j][i]=='_' or (isEndJ>0 and l[j][i]!=l[0][i]):
isEndJ=0
if isEndI+isEndJ<1:
break
if isEndI>0:
return 1 if l[i][0]=='x' else -1
if isEndJ>0:
return 1 if l[0][i]=='x' else -1
##判断斜线上是否存在直线
isEndR=0 if l[0][0]=='_' else 1
isEndL=0 if l[2][0]=='_' else 1
for i in range(3):
if l[i][i]=='_' or (isEndR>0 and l[i][i]!=l[0][0]):
isEndR=0
if l[2-i][i]=='_' or (isEndL>0 and l[2-i][i]!=l[2][0]):
isEndL=0
if isEndR+isEndL<0:
break
if isEndR>0:
return 1 if l[0][0]=='x' else -1
if isEndL>0:
return 1 if l[2][0]=='x' else -1
return 0
#********** End **********#
def isTerminal(self, node):
'''判断某状态是否为最终状态:无空闲棋可走(无子结点)
参数:
node - GameNode 博弈树结点
返回值:
clf - bool 是最终状态返回True否则返回False
'''
#请在这里补充代码,完成本关任务
#********** Begin **********#
l=node.map
##判断是否还有空位
isFull=1
for i in range(3):
for j in range(3):
if l[i][j]=='_':
isFull=0
break
if isFull==0:
break
if isFull>0:
return True
isEndI=1
isEndJ=1
##判断行列上是否存在直线
for i in range(3):
isEndI=1
isEndJ=1
for j in range(3):
if l[i][j]=='_' or (isEndI>0 and l[i][j]!=l[i][0]):
isEndI=0
if l[j][i]=='_' or (isEndJ>0 and l[j][i]!=l[0][i]):
isEndJ=0
if isEndI+isEndJ<1:
break
if isEndI+isEndJ>0:
return True
##判断斜线上是否存在直线
isEndR=1
isEndL=1
for i in range(3):
if l[i][i]=='_' or (isEndR>0 and l[i][i]!=l[0][0]):
isEndR=0
if l[2-i][i]=='_' or (isEndL>0 and l[2-i][i]!=l[0][2]):
isEndL=0
if isEndR+isEndL<0:
break
if isEndR+isEndL>1:
return True
return False
#********** End **********#