Tic-Tac-Toe
一个简单的井字棋项目,写给那些学了很多语法但不知道下一步该做什么的人。
Board
首先我们需要一个 3 ✖️ 3 的棋盘,可以用一个简单的列表来表示,每个元素就代表一个棋盘格。
py
[
None, None, None,
None, None, None,
None, None, None
]
任务一:实现 new_board()
函数,返回一个空棋盘,也就是一个全为 None
的列表。
py
def new_board():
# 补全它
参考
py
def new_board():
return [None] * 9
Render
为了简化,我们会将棋盘直接 print 到终端内,就像这样:
1 2 3
-------
1 | X O X |
2 | O X O |
3 | |
-------
任务二:实现 print_board(board)
函数,接受棋盘作为参数,然后打印出棋盘。
py
def print_board(board):
# 补全它
提示:print()
函数可以使用 end
参数来指定换行符。
参考
py
def print_board(board):
print(" 1 2 3")
print(" -------")
for row in range(3):
print(f"{row + 1} | ", end="")
for col in range(3):
print(board[row * 3 + col] or " ", end=" ")
print("|")
print(" -------")
Input
任务三:获取玩家输入,范围是 [1, 9],如果输入不符合要求或已经被占用,则提示重新输入。
py
def get_move(board):
# 补全它
参考
py
def get_move(board):
while True:
try:
move = int(input("Enter move (1-9): ")) - 1
if move < 0 or move >= 9:
raise ValueError
if board[move] is not None:
print("This square is already taken, try again.")
continue
return move
except ValueError:
print("Invalid input, try again.")
Move
任务四:实现 make_move(board, move, player)
函数,在对应位置放置玩家的棋子。
py
def make_move(board, move, player):
# 补全它
参考
py
def make_move(board, move, player):
board[move] = player
Winner
任务五:检测有无获胜者,如果有,则返回获胜者,否则返回 None
。
py
def check_winner(board):
lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
]
# 补全它
参考
py
def check_winner(board):
lines = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6],
]
for line in lines:
a, b, c = line
if board[a] and board[a] == board[b] == board[c]:
return board[a]
return None
Draw
任务六:如果没有获胜者,则继续检测棋盘是否已经被占满,如果是,则判定为平局。
py
def check_draw(board):
# 补全它
参考
py
def check_draw(board):
return None not in board
Game Loop
任务七:组合以上函数,实现一个完整的游戏循环。
py
def play_game():
# 初始化棋盘
# 初始化玩家
# 显示棋盘
while True:
# 玩家输入
# 显示输入后的棋盘
# 判定输赢或平局
# 切换玩家
if __name__ == "__main__":
play_game()
参考
py
def play_game():
board = new_board()
player = "X"
print_board(board)
while True:
move = get_move(board)
make_move(board, move, player)
print_board(board)
winner = check_winner(board)
if winner:
print(f"{winner} wins!")
break
if check_draw(board):
print("Draw!")
break
player = "O" if player == "X" else "X"
Random AI
任务八:实现 AI 随机落子的函数,返回一个随机的棋子位置。
py
def get_random_ai_move(board):
# 补全它
参考
py
def get_random_ai_move(board):
available_moves = [i for i in range(9) if board[i] is None]
return random.choice(available_moves)
def play_game():
...
while True:
if player == "X":
move = get_move(board)
else:
move = get_random_ai_move(board)
make_move(board, move, player)
...
Minimax AI
任务十:学习 Minimax 算法来实现 AI 的最佳落子。
py
def get_ai_move(board):
# 补全它
参考
py
def get_ai_move(board):
best_score = float("-inf")
best_move = None
for i in range(len(board)):
if board[i] is None:
board[i] = "O"
score = minimax(board, False)
board[i] = None
if score > best_score:
best_score = score
best_move = i
return best_move
def minimax(board, is_maximizing):
winner = check_winner(board)
if winner == "X":
return -10
elif winner == "O":
return 10
elif check_draw(board):
return 0
if is_maximizing:
best_score = float("-inf")
for i in range(len(board)):
if board[i] is None:
board[i] = "O"
score = minimax(board, False)
board[i] = None
best_score = max(score, best_score)
return best_score
else:
best_score = float("inf")
for i in range(len(board)):
if board[i] is None:
board[i] = "X"
score = minimax(board, True)
board[i] = None
best_score = min(score, best_score)
return best_score