井字棋(Tic-Tac-Toe)的棋盘只有 3×3,规则简单到一句话:谁先连成一线谁赢。但把它写成程序,你要处理输入校验、轮流切换、胜负判定、平局检测——这些正是所有棋类游戏(乃至更复杂的博弈 AI)的公共骨架。认真做完,你对"状态机"的理解会深一层。
玩法介绍
棋盘 9 个格子按 0~8 编号。两名玩家(X 和 O)轮流输入格子编号落子,不能落在已有棋子的位置;任意一方在横、竖、斜方向连成 3 个即获胜;9 格下满仍无人连成一线则平局。本教程做"人机对战":玩家执 X,电脑(随机落子)执 O。
第 1 步:棋盘表示与打印
用长度为 9 的列表 board 表示棋盘,空位是空格字符串,落子后存 "X" 或 "O"。打印时按 3 个一行输出,加上分隔线,看起来就像真正的棋盘。
board = [" "] * 9
def show():
for row in range(3):
line = board[row * 3 : row * 3 + 3]
print(" | ".join(line))
if row < 2:
print("---------")
show()
第 2 步:玩家落子与合法性校验
玩家输入 0~8 的编号,需要校验两条规则:编号在范围内、该格为空。不满足就提示并重新输入。
while True:
text = input("轮到 X,请选择格子(0-8): ")
if not text.isdigit():
print("请输入数字!")
continue
pos = int(text)
if pos < 0 or pos > 8:
print("编号要在 0 到 8 之间!")
continue
if board[pos] != " ":
print("这个格子已经有棋子了!")
continue
board[pos] = "X"
break
第 3 步:胜负判定
3×3 一共只有 8 种赢法:3 行 + 3 列 + 2 条对角线。把所有赢法写成常量列表,逐个检查是否被同一方占满。这种"穷举所有可能"的思路,在状态空间小时是最简单可靠的。
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], # 两条对角线
]
def winner():
for a, b, c in LINES:
if board[a] == board[b] == board[c] != " ":
return board[a] # 返回 'X' 或 'O'
return None
board[a] == board[b] == board[c] != " " 是 Python 特有的链式比较:三个值相等且不等于空格。连写比 and 拼接更简洁,也不容易漏括号。
第 4 步:电脑随机落子
先收集所有空格,用 random.choice 随机选一个。这个 AI 很"笨",但足以让游戏完整跑起来;想让电脑变聪明,请看文末的改进方向。
import random
empty = [i for i in range(9) if board[i] == " "]
move = random.choice(empty)
board[move] = "O"
print(f"电脑落在了 {move} 号格子")
第 5 步:主循环与平局判断
用 while 循环轮流走棋,每步后检查胜负;所有格子下满且无人获胜就是平局。完整版代码:
import random
board = [" "] * 9
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]]
def show():
for row in range(3):
print(" | ".join(board[row*3:row*3+3]))
if row < 2:
print("---------")
def winner():
for a, b, c in LINES:
if board[a] == board[b] == board[c] != " ":
return board[a]
return None
def player_move():
while True:
text = input("轮到 X,请选择格子(0-8): ")
if not text.isdigit():
print("请输入数字!")
continue
pos = int(text)
if pos < 0 or pos > 8 or board[pos] != " ":
print("无效位置,重新选!")
continue
board[pos] = "X"
return
while True:
show()
player_move()
if winner():
print(f"\n{winner()} 获胜!")
break
if " " not in board:
print("\n平局!")
break
empty = [i for i in range(9) if board[i] == " "]
board[random.choice(empty)] = "O"
show()
第 6 步:完整代码与运行
第 5 步的代码就是完整版,保存为 tictactoe.py,运行 python3 tictactoe.py 与电脑对战。想和朋友一起玩,把电脑落子的两行换成"让 O 玩家输入"即可变成双人模式——这个改动也顺便帮你理解了"程序结构服务于游戏规则"。
💡 改进方向:①让电脑优先堵住玩家的必胜线(检查对手差一格连成三线的情况),难度立刻上一个台阶;②用 minimax 回溯算法让电脑永不输;③支持"再来一局"并记录总比分;④把棋盘扩展成 4×4 甚至 5×5,练习用循环动态生成赢法列表。