井字游戏的 checkDraw 函数 - python [英] checkDraw function for Tic Tac Toe - python
问题描述
我已经编写了一个有效的井字游戏程序,但我一直在思考如何编写 chekDraw 函数(检查游戏是否有平局).所有其他功能都在工作,我可以玩游戏.我的想法是 for in range 循环将遍历板索引,计算 x 和 o 直到整个板已满.在主要方面,我有一个条件,如果它不是赢(checkWin),那么它就是平局.我一直盯着这个这么久,我希望我的代码有新的眼光.任何见解/建议将不胜感激!
I have written a Tic Tac Toe program that is working, but I am stuck on how to go about writing the chekDraw function (checking the game for a tie). All other functions are working, and I can play the game. My thought is that a for in range loop will go through the board indices, counting the x's and o's until the whole board is full. In main, I have the condition that if it is not a win (checkWin) then it is a tie. I have been staring at this so for so long, I would love fresh eyes on my code. Any insight/advice would be appreciated!
特别是 checkDraw 发生的事情是什么 - 如果棋盘已满且没有赢家,游戏会不断要求移动,但此时的任何移动都是非法的,因为所有位置都已被占用(来自 getMove 函数的验证).
specifically what is happening with checkDraw is nothing- if the board is full and no winner, the game continually asks for a move, but any move at that point is illegal because all spots are taken (validation from getMove function).
# display instructions
def displayInstructions():
print()
print("This is a game of Tic-Tac-Toe. You will select an empty location")
print("and enter its index to select a move. The first player will be X")
print("and the second player will be O.")
print()
# display current state
# pass in board
# does not return anything
def showBoard(board):
for i in range(len(board)):
print("[" + str(board[i]) + "]", end="")
if i == 2 or i == 5 or i == 8:
print(end="\n")
# pass in board
# return updated board
# must validate move (in range, unoccupied square)
def getMove(board, player):
validMove = False
while not validMove:
move = input("{0}, what is your move: ".format(player))
position = int(move) - 1 # cast input as an integer, and puts player move in correct index
# in range
if position < 0 or position > 8:
print("That is an illegal move.")
# unoccupied square
if board[position] == "X" or board[position] == "O":
print("That is an illegal move.")
else:
# if valid move, put player on board
board[position] = player
return board
def checkWin(board, player):
if (board[0] == player and board[1] == player and board[2] == player) or \
(board[3] == player and board[4] == player and board[5] == player) or \
(board[6] == player and board[7] == player and board[8] == player) or \
(board[0] == player and board[3] == player and board[6] == player) or \
(board[1] == player and board[4] == player and board[7] == player) or \
(board[2] == player and board[5] == player and board[8] == player) or \
(board[0] == player and board[4] == player and board[8] == player) or \
(board[2] == player and board[4] == player and board[6] == player):
return True
else:
return False
def checkDraw(board, player):
count = 0
for i in range(len(board)):
if board[i] == player:
# if board[i] == "X" or board[i) == "O"
count += 1
if count == len(board):
return True
def main():
# Repeat play loop
playGame = True
while playGame:
# output instructions
displayInstructions()
# initialize board
board = [1, 2, 3, 4, 5, 6, 7, 8, 9]
print(len(board))
# initialize first player to X
player = "X"
# play until win or draw
while not checkWin(board, player) or checkDraw(board, player):
showBoard(board)
getMove(board, player)
checkWin(board, player)
checkDraw(board, player)
# if the game is in play (not a win or draw)
if not checkWin(board, player) or checkDraw(board, player):
# swap player
if player == "X":
player = "O"
else:
player = "X"
# if win
if checkWin(board, player):
showBoard(board)
print("{0} wins.".format(player))
playGame = False
# if draw
elif checkDraw(board, player):
showBoard(board)
print("It's a draw")
playGame = False
# Ask if want to play another game
playAgain = input("Would you like to play again? (y/n): ").lower()
if playAgain == "y":
main()
else:
print("Goodbye.")
if __name__ == "__main__":
main()
推荐答案
代替这些长系列的和/或,您应该构建一个形成线段(线)的板位置列表,并将其用作间接获取所有模式在板上:
instead of these long series of and/or, you should build a list of board positions that form segments (lines) and use it as indirection to get all patterns on the board:
例如:
segments = [ (0,1,2),(3,4,5),(6,7,8),(0,3,6),(1,4,7),(2,5,8),(0,4,8),(2,4,6) ]
boardMarks = [ c if c in "XO" else "." for c in board ]
patterns = [ "".join(sorted(boardMarks[i] for i in s)) for s in segments ]
playerWins = (player*3) in patterns
xWins = "XXX" in patterns
oWins = "OOO" in patterns
draw = not xWins and not oWins and "." not in boardMarks
或者,如果您想更具预测性并在没有更多可以获胜的动作时尽早宣布平局:
or, if you want to be more predictive and call out a draw early when there are no more moves that can win:
draw = not any(canWin in patterns for canWin in ("...","..X","..O",".XX",".OO"))
因为图案是排序的,所以只有5种组合代表一条可赢线
如果你想让电脑玩,你可以使用这个自动播放"功能,根据最小最大评分系统选择一个位置:
If you want to make the computer play, you can use this 'autoPlay' function to select a position based on a mini-max rating system:
skill = 4 # 1 to 4 (novice to master)
def rating(position,player,board,level=skill+5):
if board[position] in "XO" or not level: return 0
newBoard = board[:position]+[player]+board[position+1:]
isWin = player*3 in ( "".join(newBoard[i] for i in s) for s in segments )
if isWin: return 3**level * 2
nextRatings = [rating(p,"XO"[player=="X"],newBoard,level-1) for p in range(9)]
return 3**level - max(nextRatings,key=abs)
from random import sample
def autoPlay(board,player):
return max(sample(range(9),9),key=lambda p:rating(p,player,board))
示例使用:
position = autoPlay(board,player)
print("computer plays ",player," at position ",position+1)
board[position] = player
这篇关于井字游戏的 checkDraw 函数 - python的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!