python井字棋ai,python 井字棋(Tic Tac Toe)

说明

用python实现了井字棋,整个框架是本人自己构思的,自认为比较满意。另外,90%+的代码也是本人逐字逐句敲的。

minimax算法还没完全理解,所以参考了这里的代码,并作了修改。

特点

可以选择人人、人机、机人、机机四种对战模式之一

电脑玩家的AI使用了minimax算法,带apha-beta剪枝

电脑玩家在思考时,时时刻刻都有一个“假想敌”。以便使得minimax算法运转起来

代码

作者:hhh5460

时间:2017年6月26日

# 棋盘

class Board(object):

def __init__(self):

#self._board = '-'*9 # 坑!!

self._board = ['-' for _ in range(9)]

self._history = [] # 棋谱

# 按指定动作,放入棋子

def _move(self, action, take):

if self._board[action] == '-':

self._board[action] = take

self._history.append((action, take)) # 加入棋谱

# 撤销动作,拿走棋子

def _unmove(self, action):

self._board[action] = '-'

self._history.pop()

# 棋盘快照

def get_board_snapshot(self):

return self._board[:]

# 取棋盘上的合法走法

def get_legal_actions(self):

actions = []

for i in range(9):

if self._board[i] == '-':

actions.append(i)

return actions

# 判断走法是否合法

def is_legal_action(self, action):

return self._board[action] == '-'

# 终止检测

def teminate(self):

board = self._board

lines = [board[0:3], board[3:6], board[6:9], board[0::3], board[1::3], board[2::3], board[0::4], board[2:7:2]]

if ['X']*3 in lines or ['O']*3 in lines or '-' not in board:

return True

else:

return False

# 胜负检查

def get_winner(self):

board = self._board

lines = [board[0:3], board[3:6], board[6:9], board[0::3], board[1::3], board[2::3], board[0::4], board[2:7:2]]

if ['X']*3 in lines:

return 0

elif ['O']*3 in lines:

return 1

else:

return 2

# 打印棋盘

def print_b(self):

board = self._board

for i in range(len(board)):

print(board[i], end='')

if (i+1)%3 == 0:

print()

# 打印棋谱

def print_history(self):

print(self._history)

# 玩家

class Player(object):

'''

玩家只做两件事:思考、落子

1. 思考 --> 得到走法

2. 落子 --> 执行走法,改变棋盘

'''

def __init__(self, take='X'): # 默认执的棋子为 take = 'X'

self.take=take

def think(self, board):

pass

def move(self, board, action):

board._move(action, self.take)

# 人类玩家

class HumanPlayer(Player):

def __init__(self, take):

super().__init__(take)

def think(self, board):

while True:

action = input('Please input a num in 0-8:')

if len(action)==1 and action in '012345678' and board.is_legal_action(int(action)):

return int(action)

# 电脑玩家

class AIPlayer(Player):

def __init__(self, take):

super().__init__(take)

def think(self, board):

print('AI is thinking ...')

take = ['X','O'][self.take=='X']

player = AIPlayer(take) # 假想敌!!!

_, action = self.minimax(board, player)

#print('OK')

return action

# 极大极小法搜索,α-β剪枝

def minimax(self, board, player, depth=0) :

'''参考:https://stackoverflow.com/questions/44089757/minimax-algorithm-for-tic-tac-toe-python'''

if self.take == "O":

bestVal = -10

else:

bestVal = 10

if board.teminate() :

if board.get_winner() == 0 :

return -10 + depth, None

elif board.get_winner() == 1 :

return 10 - depth, None

elif board.get_winner() == 2 :

return 0, None

for action in board.get_legal_actions() : # 遍历合法走法

board._move(action, self.take)

val, _ = player.minimax(board, self, depth+1) # 切换到 假想敌!!!

board._unmove(action) # 撤销走法,回溯

if self.take == "O" :

if val > bestVal:

bestVal, bestAction = val, action

else :

if val < bestVal:

bestVal, bestAction = val, action

return bestVal, bestAction

# 游戏

class Game(object):

def __init__(self):

self.board = Board()

self.current_player = None

# 生成玩家

def mk_player(self, p, take='X'): # p in [0,1]

if p==0:

return HumanPlayer(take)

else:

return AIPlayer(take)

# 切换玩家

def switch_player(self, player1, player2):

if self.current_player is None:

return player1

else:

return [player1, player2][self.current_player == player1]

# 打印赢家

def print_winner(self, winner): # winner in [0,1,2]

print(['Winner is player1','Winner is player2','Draw'][winner])

# 运行游戏

def run(self):

ps = input("Please select two player's type:\n\t0.Human\n\t1.AI\nSuch as:0 0\n")

p1, p2 = [int(p) for p in ps.split(' ')]

player1, player2 = self.mk_player(p1, 'X'), self.mk_player(p2, 'O') # 先手执X,后手执O

print('\nGame start!\n')

self.board.print_b() # 显示棋盘

while True:

self.current_player = self.switch_player(player1, player2) # 切换当前玩家

action = self.current_player.think(self.board) # 当前玩家对棋盘进行思考后,得到招法

self.current_player.move(self.board, action) # 当前玩家执行招法,改变棋盘

self.board.print_b() # 显示当前棋盘

if self.board.teminate(): # 根据当前棋盘,判断棋局是否终止

winner = self.board.get_winner() # 得到赢家 0,1,2

break

self.print_winner(winner)

print('Game over!')

self.board.print_history()

if __name__ == '__main__':

Game().run()

效果图

下图是人人对战的结果

3a76f35b0004e673562f6b82471fe91e.png

&lbrack;CareerCup&rsqb; 17&period;2 Tic Tac Toe 井字棋游戏

17.2 Design an algorithm to figure out if someone has won a game oftic-tac-toe. 这道题让我们判断玩家是否能赢井字棋游戏, ...

LeetCode 5275&period; 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game

地址 https://www.acwing.com/solution/LeetCode/content/6670/ 题目描述A 和 B 在一个 3 x 3 的网格上玩井字棋. 井字棋游戏的规则如下: ...

python 游戏&lpar;井字棋&rpar;

1. 游戏思路和流程图 实现功能,现实生活中的井字棋玩法 游戏流程图 2. 使用模块和游戏提示 import random def game_info(): print('欢迎来到井字棋游戏') pr ...

POJ 2361 Tic Tac Toe

题目:给定一个3*3的矩阵,是一个井字过三关游戏.开始为X先走,问你这个是不是一个合法的游戏.也就是,现在这种情况,能不能出现.如果有人赢了,那应该立即停止.那么可以知道X的步数和O的步数应该满足x= ...

&lbrack;LeetCode&rsqb; 348&period; Design Tic-Tac-Toe 设计井字棋游戏

Design a Tic-tac-toe game that is played between two players on a n x n grid. You may assume the fol ...

井字棋&lpar;Tic-Tac-Toe&rpar;

井字棋介绍:https://en.wikipedia.org/wiki/Tic-tac-toe 井字棋简单,但是获胜策略却和直觉不同,四角比中间重要性要高,而且先手有很大的获胜概率获胜(先手胜:91, ...

python3 井字棋 GUI - 人机对战、机器对战 (threading、tkinter库)

python3 井字棋 GUI - 人机对战.机器对战 功能 GUI界面 人机对战(可选择机器先走) 机器对战(50局) 流程图 内核 棋盘 [0][1][2] [3][4][5] [6][7][8] ...

&lbrack;LeetCode&rsqb; Design Tic-Tac-Toe 设计井字棋游戏

Design a Tic-tac-toe game that is played between two players on a n x n grid. You may assume the fol ...

随机推荐

ODCA最佳实践翻译:Architecting Cloud-Aware Applications (一)

Architecting Cloud-Aware Applications ** ODCA(Open Data Center Alliance)最佳实践 ** MagicBowen(e.bowen.w ...

H&period;264中NAL、Slice与frame意思及相互关系

H.264中NAL.Slice与frame意思及相互关系 NAL nal_unit_type中的1(非IDR图像的编码条带).2(编码条带数据分割块A).3(编码条带数据分割块B).4(编码条带数据分 ...

c&plus;&plus; 类名和enum时重复时要在类名前加class&colon;&colon;

c++ 类名和enum时重复时要在类名前加class:: 一些不好的习惯都是用小写,但又没有区分开token,看看代码再说,下面的代码是我在测试polymorphism时写的一部分,怎么也查不出,最后 ...

理解python的元类

看了一篇文档,借鉴一下!写下自己对python元类的理解,欢迎各位大神给出意见. 我的理解就是 type用来创建元类,元类用来创建类,类用来创建实例 这样一想,是不是可以认为元类创建类的过程等同于类创 ...

js流程语句

一.跳转语句1.break; 终止整个循环,不再进行判断2.continue; 终止本次循环,接着去判断是否执行下次循环 二.选择(判断)结构1.if 如果               if(条件1) ...

C&num;比较两个由基本数据类型构成的object类型

/// /// 比较查询条件 /// public class ModelExtensions { ///

python之打印日志logging

import logging # 简单打印日志举例 logging.basicConfig(level=logging.DEBUG) # 设置日志级别,WARN logging.warning('Wa ...

8&period;0-uC&sol;OS-III临界段

1.临界段 (临界段代码,也叫临界区,是指那些必须完整连续运行,不可被打断的代码段) 锁调度器,可以执行ISR,开启调度器不可执行ISR: (1).临界段代码,也称作临界域,是一段不可分割的代码. u ...

Luogu 2279 &lbrack;HNOI2003&rsqb;消防局的设立 - 贪心

Description 给定一棵树形图, 建若干个消防站, 消防站能够覆盖到距离不超过2的点, 求最少需要建几个消防站才能覆盖所有点 Solution 从深度最深的点开始, 在它的爷爷节点上建, 每建 ...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值