说明

用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()

效果图

下图是人人对战的结果

python 井字棋(Tic Tac Toe)的更多相关文章

  1. [CareerCup] 17.2 Tic Tac Toe 井字棋游戏

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

  2. LeetCode 5275. 找出井字棋的获胜者 Find Winner on a Tic Tac Toe Game

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

  3. Principle of Computing (Python)学习笔记(7) DFS Search + Tic Tac Toe use MiniMax Stratedy

    1. Trees Tree is a recursive structure. 1.1 math nodes https://class.coursera.org/principlescomputin ...

  4. python 游戏(井字棋)

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

  5. POJ 2361 Tic Tac Toe

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

  6. [LeetCode] 348. 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 ...

  7. 井字棋(Tic-Tac-Toe)

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

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

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

  9. [LeetCode] 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 ...

随机推荐

  1. Android网络编程系列之HTTP协议原理总结

    前言 作为搞移动开发的我们,免不了与网络交互打交道.虽然市面上很多开源库都封装的比较到位,我们实现网络访问也轻车熟路.但还是十分有必要简要了解一下其中的原理,以便做到得心应手,也是通往高级开发工程师甚 ...

  2. innodb compressed 表碰到的问题,BUG么?

    innodb compressed 表碰到的问题 (摘自 http://papaisadba.puyu.me/?p=239) compressed innodb 表是MySQL 5.5开始提供的功能, ...

  3. redie config 详解

    # redis 配置文件示例 # 当你需要为某个配置项指定内存大小的时候,必须要带上单位,# 通常的格式就是 1k 5gb 4m 等酱紫:## 1k => 1000 bytes# 1kb =&g ...

  4. Java计算大整数

    import java.util.*; import java.math.*; //BigInteger类型在这个包里 public class Gcc_test { public static vo ...

  5. 【未完成】[Spark SQL_2] 在 IDEA 中编写 Spark SQL 程序

    0. 说明 在 IDEA 中编写 Spark SQL 程序,分别编写 Java 程序 & Scala 程序 1. 编写 Java 程序 待补充 2. 编写 Scala 程序 待补充

  6. 乘风破浪:LeetCode真题_034_Find First and Last Position of Element in Sorted Array

    乘风破浪:LeetCode真题_034_Find First and Last Position of Element in Sorted Array 一.前言 这次我们还是要改造二分搜索,但是想法却 ...

  7. ndroid动态创建按钮并添加事件

    public class MyActivity extends Activity { /** * Called when the activity is first created. */ @Over ...

  8. Oracle 11g AWR 系列五:如何生成 AWR 报告?

    1.生成单实例 AWR 报告: @$ORACLE_HOME/rdbms/admin/awrrpt.sql 2.生成 Oracle RAC AWR 报告: @$ORACLE_HOME/rdbms/adm ...

  9. win10怎么更改切换输入法按键 切换输入法与Win7一样(Ctrl + 空格)

    找到电脑左下角的“开始"图标,用鼠标右键点击它,在弹出的菜单选项里再用鼠标左键点击“设置”来打开Windows设置. 进入“Windows设置”后再点击“设备” 打开“设备”界面后再点击左边 ...

  10. Jmeter函数助手中添加自定义函数

    最近,群里的牛肉面大神有个需求,是将每个post请求的body部分做一个加密操作,其实这个需求不算难,用beanshell引入加密函数的包,然后调用就行了.只是,如果请求多了,每次都要调用一下自己加密 ...