- python/
- Python 游戏人工智能在一边强大地工作,而在另一边则变得哑巴
Python 游戏人工智能在一边强大地工作,而在另一边则变得哑巴
Python 游戏人工智能在一边强大地工作,而在另一边则变得哑巴,python,pygame,artificial-intelligence,tic-tac-toe,minimax,Python,Pygame,Artificial Intelligence,Tic Tac Toe,Minimax,我正在尝试用PyGame和MiniMax算法在Python中制作一个Tic-Tac-Toe游戏。当第一次有机会扮演“X”时,AI的表现非常出色,但当没有第一次有机会扮演“O”时,AI会变得愚蠢到足以帮助用户获胜。我想我知道问题是什么,但是改变它会扰乱整个程序,而不是按照给定的docstring。
我已经创建了两个python文件——一个用于GUI runner.py,另一个用于游戏背后的逻辑和AI tictactoe.py
这就是游戏背后的逻辑:
为函数“deepcopy”导入模块“copy”,
我正在尝试用PyGame和MiniMax算法在Python中制作一个Tic-Tac-Toe游戏。当第一次有机会扮演“X”时,AI的表现非常出色,但当没有第一次有机会扮演“O”时,AI会变得愚蠢到足以帮助用户获胜。我想我知道问题是什么,但是改变它会扰乱整个程序,而不是按照给定的docstring。
我已经创建了两个python文件——一个用于GUI runner.py,另一个用于游戏背后的逻辑和AI tictactoe.py
这就是游戏背后的逻辑:
为函数“deepcopy”导入模块“copy”,以深度复制
原始可变对象,用于从突变中保存对象
导入副本
X='X'
O='O'
空=无
def初始_状态:
返回板的开始状态
返回[
[空,空,空],
[空,空,空],
[空,空,空]
]
def显示板,自动打印=错误:
将板嵌套列表显示为
用于电路板可视化的3x3矩阵
可视电路板=
对于板中的行:
对于行中的playr:
如果playr为None:
playr=''
playr+=''
可视板+=播放器
可视电路板+='\n'
如果自动打印:
印刷电路板
返回视盘
def播放板:
返回棋盘上下一回合的玩家
全局X,O
函数每次调用的初始值
X_计数=0
O_计数=0
对于板中的行:
对于行中的playr:
如果playr==X:
X_计数+=1
elif playr==O:
O_计数+=1
`总是先开始
如果O_计数最佳分数:
最佳分数=分数
最佳行动
返回最佳行动
GUI代码文件:
为GUI导入模块“PyGame”
导入pygame
导入系统
导入时间
从与导入模块相同的文件夹导入模块'tictactoe'
这个文件用于游戏AI的逻辑
将Tictatcoe作为ttt导入
pygame.init
尺寸=宽度,高度=600,400
颜色
黑色=0,0,0
白色=255,255,255
screen=pygame.display.set\u modesize
mediumFont=pygame.font.font'OpenSans-Regular.ttf',24
largeFont=pygame.font.font'OpenSans-Regular.ttf',40
moveFont=pygame.font.font'OpenSans-Regular.ttf',60
用户=无
线路板=ttt.初始状态
ai_turn=错误
尽管如此:
对于pygame.event.get中的事件:
如果event.type==pygame.QUIT:
系统出口
屏幕。黑色
让用户选择一个播放器。
如果用户为无:
抽签标题
title=largeFont。呈现“玩井字游戏”,真,白色
titleRect=title.get\u rect
titleRect.center=圆宽/2,50
萤幕、闪电、标题等
绘图按钮
playXButton=pygame.Rectroundwidth/8,roundheight/2,roundwidth/4,50
playX=mediumFont。渲染“按X播放”,真,黑色
playXRect=playX.get\u rect
playXRect.center=playXButton.center
pygame.draw.rectscreen,白色,playXButton
screen.blitplayX,playXRect
playOButton=pygame.Rect5*roundwidth/8,roundheight/2,roundwidth/4,50
playO=mediumFont。渲染“按O播放”,真,黑色
playORect=playO.get\u rect
playORect.center=playOButton.center
pygame.draw.rectscreen,白色,playOButton
screen.blitplay,playORect
检查按钮是否已单击
单击,u,u=pygame.mouse.get\u按
如果单击==1:
mouse=pygame.mouse.get\u pos
时间是0.5
如果playXButton.collidepointmouse:
user=ttt.X
elif playOButton.collidepointmouse:
用户=ttt.O
其他:
画游戏板
瓷砖尺寸=80
瓷砖原点=宽度/2-1.5*瓷砖尺寸,
高度/2-1.5*瓷砖尺寸
瓷砖=[]
对于范围3中的i:
行=[]
对于范围3中的j:
rect=pygame.rect
圆形平铺原点[0]+j*平铺尺寸,
圆形瓷砖原点[1]+i*瓷砖尺寸,
圆形瓷砖尺寸,圆形瓷砖尺寸
pygame.draw.rectscreen,白色,矩形,3
如果板[i][j]!=ttt.EMPTY:
move=moveFont.renderboard[i][j],真,白色
moveRect=move.get\u rect
moveRect.center=rect.center
screen.blitmove,moveRect
行.appendrect
瓦片.appendrow
游戏结束=ttt终端板
player=ttt.playboard
显示标题
如果游戏结束:
赢家=ttt.Winnboard
如果没有获胜者:
title=f‘比赛结束:平局。’
其他:
title=f'游戏结束:{胜者}获胜。'
elif user==玩家:
title=f'Play as{user}'
其他:
title=f'AI thinking…'
title=largeFont.rendertitle,真,白色
titleRect=title.get\u rect
titleRect.center=圆宽/2,30
萤幕、闪电、标题等
检查AI移动
如果用户!=玩家而非游戏结束:
如果你转身:
时间是0.5
移动=ttt.minimaxboard
线路板=ttt.resultboard,移动
ai_turn=错误
其他:
真的吗
检查是否有用户移动
单击,u,u=pygame.mouse.get\u按
如果单击==1且用户==玩家且未结束游戏:
mouse=pygame.mouse.get\u pos
对于范围3中的i:
对于范围3中的j:
如果电路板[i][j]==ttt.EMPTY且平铺[i][j]。鼠标:
board=ttt.resultboard,i,j
如果游戏结束:
againButton=pygame.rectrondwidth/3,roundheight-65,roundwidth/3,50
再次=中等字体。呈现“再次播放”,真,黑色
againRect=再次。获取正确
againRect.center=againButton.center
pygame.draw.rectscreen,白色,againButton
screen.blitagain,再次引用
单击,u,u=pygame.mouse.get\u按
如果单击==1:
mouse=pygame.mouse.get\u pos
如果再次单击Button.collidepointmouse:
时间是0.2
用户=无
线路板=ttt.初始状态
ai_turn=错误
pygame.display.flip
以下是给出这些问题的组织给出的答案的旁注:
不得更改任何函数中的参数数量或参数本身。
遵循所有函数中编写的docstring
可以定义新的功能
如你所愿
请让我知道是否有任何错误/错误导致AI在作为“O”播放时变哑。我相信这个bug在实用程序中,但我不能更改代码,因为它不允许写在docstring中
谢谢大家!
编辑:问题几乎解决了,但人工智能有时会变得愚蠢,比如不试图用相反的符号阻止用户的移动,等等
best_score = -float('inf') # Least possible score
你需要根据你计算移动的玩家的不同来改变这一点。我认为正因为如此,消极的玩家选择了随机/第一个看似合理的举动
我已经实现了2次minimax和相关的启发式方法,并且总是发现使用negamax方法效果最好,因为你不需要担心何时根据玩家应用max和min。我想我更新了minimaxEdit中for循环中的best_分数值:非常感谢!!!我不明白你先说了什么,所以评论。但现在我想我意识到了你说的话,这真的帮了我大忙!现在AI不再像以前那样第一次有机会就装傻了。再次,非常感谢!!!编辑2:人工智能有时又变傻了。像这次一样,它不是用一个O来阻止用户的三个连续,而是通过将O放在不需要的地方来播放。请将其减少并增强到预期值。显示中间结果与预期结果的偏差。这篇文章表明,您已经确定整个显示框架是EPR问题的一个固有部分——我对此深表怀疑。