'''
改编自《python编程快速上手》,原代码仅能实现井字棋棋盘的打印、落子的记录
在此基础上增加了双人与人机对战模式、判断胜负、电脑下棋AI
判断胜负时,联想到三阶幻方各行、列、斜线之和均为15,因此将原棋盘的落子位置转化为用三阶幻方的数字表示,从而轻松地实现胜负地判断
电脑下棋AI采用alpha-beta剪枝法,得到最优策略
感觉写得很凌乱,将来掌握多一点了再回头修改
2019.06
'''
import itertools
import random
def printBoard(board, rounds):
# 打印棋盘
print('\ntop ' + board['top-L'] + '|' + board['top-M'] + '|' + board['top-R'])
print(' -+-+-')
print('mid ' + board['mid-L'] + '|' + board['mid-M'] + '|' + board['mid-R'])
print(' -+-+-')
print('low ' + board['low-L'] + '|' + board['low-M'] + '|' + board['low-R'])
print('\n L M R\n')
if (rounds % 2) == 0:
print('-' * 60)
print(f'ROUND {int(rounds/2)+1}\n')
if rounds == -1:
print('-' * 60)
def chooseMode():
# 选择模式:1.双人;2.人机
mode = input('\nEnter 1 to play with your friend, 2 to play with computer: ')
while mode not in ['1', '2']:
print('\nInvalid input. Do again.')
mode = input('\nEnter 1 to play with your friend, 2 to play with computer: ')
return int(mode)
def choosePieces():
# 选择棋子
player1 = input('\nEnter pieces you(player1) like (X or O): ')
while player1 not in ['X', 'O']:
print('\nInvalid input. Do again.')
player1 = input('\nEnter pieces you(player1) like (X or O): ')
player2 = 'O' if player1 == 'X' else 'X'
return player1, player2
def chooseInitiaties():
# 选择先手方
turn = random.choice(['X', 'O'])
print('\n' + turn + ' goes first!')
return turn
def playerMove(correctInput, turn):
# 记录落子
move = input('Turn for ' + turn + '. Move on which space?(e.g.mid-M): ')
while move not in correctInput: # 检查输入是否正确,或者将要落子的位置是否已经有了棋子
print('\nInvalid input. Do again.')
move = input('\nTurn for ' + turn + '. Move on which space?(e.g.mid-M): ')
correctInput.remove(move)
return move
def board2magic(board):
# 将棋盘位置转换为用三阶幻方同位置上数字表示
tempBoard = board.copy()
magic3 = [4, 9, 2, 3, 5, 7, 8, 1, 6] # 利用三阶幻方各行列及斜线之和均为15,简单地判断是否获胜
j = 0
for i in list(tempBoard.keys()):
tempBoard[str(magic3[j])] = tempBoard.pop(i)
j += 1
return tempBoard
def checkWin_sub(pieces):
# 判断是否获胜的子程序,返回判断结果
comb = list(itertools.combinations(pieces, 3))
isWin = True if 15 in [sum(i) for i in comb] else False
return isWin
def checkWin(board):
# 判断是否有获胜方
tempBoard = board2magic(board)
Xpieces = [int(x[0]) for x in tempBoard.items() if 'X' in x[1]]
Opieces = [int(x[0]) for x in tempBoard.items() if 'O' in x[1]]
Xwin = checkWin_sub(Xpieces)
Owin = checkWin_sub(Opieces)
winner = 'N'
if Xwin == True:
winner = 'X'
elif Owin == True:
winner = 'O'
return winner
def abValuation(board, player1, player2, computerTurn, alpha, beta):
# alpha-beta剪枝法
tempBoard = board.copy()
tempCorrectInput = [x for x in tempBoard.keys() if tempBoard[x] == ' ']
winner = checkWin(tempBoard)
if winner == computerTurn: # 电脑获胜
return 1
elif winner == 'N':
if not tempCorrectInput: # 平局
return 0
else: # 玩家获胜
return -1
for move in tempCorrectInput:
tempBoard[move] = player1
tempVal = abValuation(tempBoard, player2, player1, computerTurn, alpha, beta)
tempBoard[move] = ' '
if player1 == computerTurn: # 当前玩家是电脑,即Max节点
if tempVal > alpha:
alpha = tempVal
if alpha >= beta:
return beta
else: # 当前玩家是Min节点
if tempVal < beta:
beta = tempVal
if beta <= alpha:
return alpha
if player1 == computerTurn:
value = alpha
else:
value = beta
return value
def computerMove(board, turn, correctInput, computerTurn):
# 电脑落子
print("Computer's turn. Computer decides to move on: ", end = '')
best = -2
strategy = []
player1 = computerTurn
player2 = 'O' if player1 == 'X' else 'X'
for possibleMove in correctInput:
board[possibleMove] = player1
val = abValuation(board, player2, player1, computerTurn, -2, 2) #深度优先
board[possibleMove] = ' '
if val > best:
best = val
strategy = [possibleMove]
if val == best:
strategy.append(possibleMove)
move = random.choice(strategy)
correctInput.remove(move)
print(move)
return move
def main():
while True:
theBoard = {'top-L': ' ', 'top-M': ' ', 'top-R': ' ',
'mid-L': ' ', 'mid-M': ' ', 'mid-R': ' ',
'low-L': ' ', 'low-M': ' ', 'low-R': ' '}
correctInput = list(theBoard.keys())
mode = chooseMode()
player1, player2 = choosePieces()
turn = chooseInitiaties()
for rounds in range(9):
printBoard(theBoard, rounds)
if mode == 1:
move = playerMove(correctInput, turn)
else:
if turn == player1:
move = playerMove(correctInput, turn)
else:
move = computerMove(theBoard, turn, correctInput, player2)
theBoard[move] = turn
turn = 'O' if turn == 'X' else 'X'
winner = checkWin(theBoard)
if winner == 'N':
if rounds == 8:
print('\nDraw!')
else:
print("\n'" + winner + "'wins!")
break
printBoard(theBoard, -1)
if input('Enter y to start a new game. Others to quit.') != 'y':
break
if __name__ == '__main__':
main()