python 井字棋 ALPHA-BETA剪枝算法和暴力算法 具体代码

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 井字棋 ALPHA-BETA剪枝算法和暴力算法 具体代码相关的知识,希望对你有一定的参考价值。

参考技术A #!/usr/bin/env python
'''Tic tac toe in python, Minimax with alpha-beta pruning.'''
import sys
import random
import getopt

# Board: array of 9 int, positionally numbered like this:
# 0 1 2
# 3 4 5
# 6 7 8

# Well-known board positions
WINNING_TRIADS = ((0, 1, 2), (3, 4, 5), (6, 7, 8), (0, 3, 6), (1, 4, 7),
(2, 5, 8), (0, 4, 8), (2, 4, 6))
PRINTING_TRIADS = ((0, 1, 2), (3, 4, 5), (6, 7, 8))
# The order in which slots get checked for absence of a player's token:
SLOTS = (0, 1, 2, 3, 4, 5, 6, 7, 8)

# Internal-use values. Chosen so that the "winner" of a finished
# game has an appropriate value, as X minimizes and O maximizes
# the board's value (function board_valuation() defines "value")
# Internally, the computer always plays Os, even though the markers[]
# array can change based on -r command line flag.
X_token = -1
Open_token = 0
O_token = 1

# Strings for output: player's markers, phrase for end-of-game
MARKERS = ['_', 'O', 'X']
END_PHRASE = ('draw', 'win', 'loss')

HUMAN = 1
COMPUTER = 0

def board_valuation(board, player, next_player, alpha, beta):
'''Dynamic and static evaluation of board position.'''
# Static evaluation - value for next_player
wnnr = winner(board)
if wnnr != Open_token:
# Not a draw or a move left: someone won
return wnnr
elif not legal_move_left(board):
# Draw - no moves left
return 0 # Cat
# If flow-of-control gets here, no winner yet, not a draw.
# Check all legal moves for "player"
for move in SLOTS:
if board[move] == Open_token:
board[move] = player
val = board_valuation(board, next_player, player, alpha, beta)
board[move] = Open_token
if player == O_token: # Maximizing player
if val > alpha:
alpha = val
if alpha >= beta:
return beta
else: # X_token player, minimizing
if val < beta:
beta = val
if beta <= alpha:
return alpha
if player == O_token:
retval = alpha
else:
retval = beta
return retval

def print_board(board):
'''Print the board in human-readable format.
Called with current board (array of 9 ints).
'''
for row in PRINTING_TRIADS:
for hole in row:
print MARKERS[board[hole]],
print

def legal_move_left(board):
''' Returns True if a legal move remains, False if not. '''
for slot in SLOTS:
if board[slot] == Open_token:
return True
return False

def winner(board):
''' Returns -1 if X wins, 1 if O wins, 0 for a cat game,
0 for an unfinished game.
Returns the first "win" it finds, so check after each move.
Note that clever choices of X_token, O_token, Open_token
make this work better.
'''
for triad in WINNING_TRIADS:
triad_sum = board[triad[0]] + board[triad[1]] + board[triad[2]]
if triad_sum == 3 or triad_sum == -3:
return board[triad[0]] # Take advantage of "_token" values
return 0

def determine_move(board):
''' Determine Os next move. Check that a legal move remains before calling.
Randomly picks a single move from any group of moves with the same value.
'''
best_val = -2 # 1 less than min of O_token, X_token
my_moves = []
for move in SLOTS:
if board[move] == Open_token:
board[move] = O_token
val = board_valuation(board, X_token, O_token, -2, 2)
board[move] = Open_token
print "My move", move, "causes a", END_PHRASE[val]
if val > best_val:
best_val = val
my_moves = [move]
if val == best_val:
my_moves.append(move)
return random.choice(my_moves)

def recv_human_move(board):
''' Encapsulate human's input reception and validation.
Call with current board configuration. Returns
an int of value 0..8, the Human's move.
'''
looping = True
while looping:
try:
inp = input("Your move: ")
yrmv = int(inp)
if 0 <= yrmv <= 8:
if board[yrmv] == Open_token:
looping = False
else:
print "Spot already filled."
else:
print "Bad move, no donut."

except EOFError:
print
sys.exit(0)
except NameError:
print "Not 0-9, try again."
except SyntaxError:
print "Not 0-9, try again."

if looping:
print_board(board)

return yrmv

def usage(progname):
'''Call with name of program, to explain its usage.'''
print progname + ": Tic Tac Toe in python"
print "Usage:", progname, "[-h] [-c] [-r] [-x] [-X]"
print "Flags:"
print "-x, -X: print this usage message, then exit."
print "-h: human goes first (default)"
print "-c: computer goes first"
print "-r: computer is X, human is O"
print "The computer O and the human plays X by default."

def main():
'''Call without arguments from __main__ context.'''
try:
opts, args = getopt.getopt(sys.argv[1:], "chrxX",
["human", "computer", "help"])
except getopt.GetoptError:
# print help information and exit:
usage(sys.argv[0])
sys.exit(2)

next_move = HUMAN # Human goes first by default

for opt, arg in opts:
if opt == "-h":
next_move = HUMAN
if opt == "-c":
next_move = COMPUTER
if opt == "-r":
MARKERS[-1] = 'O'
MARKERS[1] = 'X'
if opt in ("-x", "-X", "--help"):
usage(sys.argv[0])
sys.exit(1)

# Initial state of board: all open spots.
board = [Open_token, Open_token, Open_token, Open_token, Open_token,
Open_token, Open_token, Open_token, Open_token]

# State machine to decide who goes next, and when the game ends.
# This allows letting computer or human go first.
while legal_move_left(board) and winner(board) == Open_token:
print
print_board(board)

if next_move == HUMAN and legal_move_left(board):
humanmv = recv_human_move(board)
board[humanmv] = X_token
next_move = COMPUTER

if next_move == COMPUTER and legal_move_left(board):
mymv = determine_move(board)
print "I choose", mymv
board[mymv] = O_token
next_move = HUMAN

print_board(board)
# Final board state/winner and congratulatory output.
try:
# "You won" should never appear on output: the program
# should always at least draw.
print ["Cat got the game", "I won", "You won"][winner(board)]
except IndexError:
print "Really bad error, winner is", winner(board)

sys.exit(0)
#-------
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
print
sys.exit(1)本回答被提问者采纳

python井字棋算法及代码

井字棋盘看起来像一个大的井字符号(#),有9 个空格,可以包含X、O 或
关于落子问题
由于只能采用键盘输入,所以需要对棋盘进行坐标表示;
即直接用1-9个9个数字来表示位置,
7|8|9
-+-+-
4|5|6
-+-+-
1|2|3
其索引顺序与数字键盘上的数字键排列一致,下棋时看着数字键下,较为简便。
计算机的算法--寻找最佳落子位置
首先简单的将棋盘划分为三个部分——中心(1),角(4),边(4)。
中心虽然只有一个但却不是最重要的,三个部分落子的优先顺序依次为:角、中心、边。
因此,井字棋的计算机算法计算最佳落子位置的顺序如下:
1 直接落子获胜
2 阻止玩家获胜
3 在角上落子
4 在中心落子
5 在边上落子

游戏流程
1、开始
2、选子 X或者O
3、随机先手
4、轮流下棋
5、是否分出胜负
5.1 分出胜负 跳到6
5.2 未分出胜负 跳到4
6、再来一局
6.1是, 跳到2
6.2否, 退出

游戏代码:
import random

def printBoard(borad):
print(borad[7] + ‘|‘ + borad[8] + ‘|‘ + borad[9])
print(‘-+-+-‘)
print(borad[4] + ‘|‘ + borad[5] + ‘|‘ + borad[6])
print(‘-+-+-‘)
print(borad[1] + ‘|‘ + borad[2] + ‘|‘ + borad[3])

‘‘‘printBoard 定义了棋盘打印输出函数
与数字键盘排列一致‘‘‘

def inputPlayerLetter():
‘‘‘#让玩家选择棋子
返回一个列表,显示玩家和电脑的棋子类型
‘‘‘
letter = ‘‘
while not (letter == ‘X‘ or letter == ‘O‘):
print(‘Do you want to be X or O?‘)
letter = input().upper()

if letter == ‘X‘:
    return [‘X‘, ‘O‘]
else:
    return [‘O‘, ‘X‘]

def whoGoesFirst():
‘‘‘随机先手‘‘‘
if random.randint(0, 1) == 0:
return ‘Computer‘
else:
return ‘Player‘

def playAgain():
‘‘‘再玩一次?‘‘‘
print(‘Do you want to play again?(yes or no)‘)
return input().lower().startswith(‘y‘)

def makeMove(board, letter, move):
‘‘‘落子‘‘‘
board[move] = letter

def isWinner(board, occupy):

判断是否获胜

return ((board[1] == occupy and board[2] == occupy and board[3] == occupy) or
        (board[4] == occupy and board[5] == occupy and board[6] == occupy) or
        (board[7] == occupy and board[8] == occupy and board[9] == occupy) or
        (board[1] == occupy and board[4] == occupy and board[7] == occupy) or
        (board[2] == occupy and board[5] == occupy and board[8] == occupy) or
        (board[3] == occupy and board[6] == occupy and board[9] == occupy) or
        (board[1] == occupy and board[5] == occupy and board[9] == occupy) or
        (board[3] == occupy and board[5] == occupy and board[7] == occupy))

def getBoardCopy(board):

复制一份棋盘给电脑落子使用

depuBoard = []

for i in board:
    depuBoard.append(i)

return depuBoard

def isSpaceFree(board, move):

判断这个位置是否有子,无子返回True

return board[move] == ‘ ‘

def getPlayerMove(board):
move = ‘ ‘
while move not in ‘1 2 3 4 5 6 7 8 9‘.split() or not isSpaceFree(board, int(move)):
print(‘What is your next move?(1-9)‘)
move = input()
return int(move)

def choosePossibleMoverFromList(board, moveList):

随机返回一个可以落子的坐标,若无子可下,则返回None

possibleMoves = []
for i in moveList:
    if isSpaceFree(board, i):
        possibleMoves.append(i)

if len(possibleMoves) != 0:
    return random.choice(possibleMoves)
else:
    return None

def getComputerMove(board, computerLetter):

确定电脑的落子位置

if computerLetter == ‘X‘:
    playerLetter == ‘O‘
else:
    playerLetter == ‘X‘

‘‘‘先判断电脑方能否通过一次落子直接获得游戏胜利‘‘‘
for i in range(1, 10):
    copy = getBoardCopy(board)
    if isSpaceFree(copy, i):
        makeMove(copy, computerLetter, i)
        if isWinner(copy, computerLetter):
            return i

‘‘‘判断玩家下一次落子是否获胜,若能,则再该点落子‘‘‘
for i in range(1, 10):
    copy = getBoardCopy(board)
    if isSpaceFree(copy, i):
        makeMove(copy, playerLetter, i)
        if isWinner(copy, playerLetter):
            return i

‘‘‘若角上能落子,则在角上落子‘‘‘
move = choosePossibleMoverFromList(board, [1, 3, 5, 7])

if move != None:
    return move

‘‘‘若中心能落子,则在中心落子‘‘‘
if isSpaceFree(board, 5):
    return 5

‘‘‘若边上能落子,则在边上落子‘‘‘
return choosePossibleMoverFromList(board, [2, 4, 6, 8])

def isBoardFull(board):
‘‘‘ 如果棋盘满了,返回True‘‘‘
for i in range(1, 10):
if isSpaceFree(board, i):
return False
return True

print(‘Welcome to the TicTacToe game!‘)

while True:

update board

theBoard = [‘ ‘] * 10
playerLetter, computerLetter = inputPlayerLetter()

turn = whoGoesFirst()

print(‘The ‘ + turn + ‘ will go first.‘)

gameIsPlaying = True

while gameIsPlaying:
    if turn == ‘Player‘:
        # 玩家回合
        printBoard(theBoard)
        move = getPlayerMove(theBoard)
        makeMove(theBoard, playerLetter, move)

        if isWinner(theBoard, playerLetter):
            printBoard(theBoard)
            print(‘Wow!!!You win the game!!!‘)
            gameIsPlaying = False
        else:
            if isBoardFull(theBoard):
                printBoard(theBoard)
                print(‘The game is tie‘)
                break
            else:
                turn = ‘Computer‘

    else:
        # 电脑回合
        move = getComputerMove(theBoard, computerLetter)
        makeMove(theBoard, computerLetter, move)

        if isWinner(theBoard, computerLetter):
            printBoard(theBoard)
            print(‘Oh!,The computer win!,You lose.‘)
            gameIsPlaying = False
        else:
            if isBoardFull(theBoard):
                printBoard(theBoard)
                print(‘The game is tie‘)
                break
            else:
                turn = ‘Player‘

if not playAgain():
    break

以上是关于python 井字棋 ALPHA-BETA剪枝算法和暴力算法 具体代码的主要内容,如果未能解决你的问题,请参考以下文章

alpha-beta剪枝算法原理(附代码)

井字棋算法

Alpha-Beta剪枝

如何在使用 minimax 算法实现 2048 AI 代理中应用 alpha-beta 剪枝?

Python小游戏 井字棋(人机对战,玩家对战)

AI五子棋第二篇-运用极大极小值算法书写AI三子棋,可拓展到五子棋(建议收藏)