在本文中,我们将介绍使用 Python 语言从零开始创建井字游戏的步骤。
在本文中,我们将介绍使用 Python 语言从零开始创建井字游戏的步骤。
游戏简介
井字游戏是一种双人游戏,在 3×3 正方形网格上进行。每位玩家轮流占据一个单元格,目标是按水平、垂直或对角线模式放置三个标记。一名玩家使用十字 "X "作为标记,另一名玩家则使用无 "O "标记。
步骤 1:井字棋设计
我们将在命令行上玩井字游戏,因此首先要为井字游戏设计一个图案。
如果玩家需要标记某个方格,则必须输入方格中显示的相应数字。假设我们想占据中间的方格,那么我们就在终端输入 5。这个网格可以通过以下方式生成
注意:在python代码中,在一行前添加“#”,代表注释,不会被编译,常作为函数的理解。
# 打印井字的函数
def print_tic_tac_toe(values):
print("\n")
print("\t | |")
print("\t {} | {} | {}".format(values[0], values[1], values[2]))
print('\t_____|_____|_____')
print("\t | |")
print("\t {}| {} | {}".format(values[3], values[4], values[5]))
print('\t_____|_____|_____')
print("\t | |")
print("\t {}| {} | {}".format(values[6], values[7], values[8]))
print("\t | |")
print("\n")
在上面的代码中,函数根据参数值创建井字游戏。这里的参数 values 是一个列表,包含网格中每个单元格的状态。
步骤 2:使用数据结构存储信息
任何游戏的核心都是其背后的游戏机制。由于这是一款相当容易制作的游戏,因此所涉及的机制也很简单。
在任何一瞬间,我们都需要两个关键信息:
- 网格的状态: 我们必须有一个数据结构来存储每个单元格的状态,即它是被占用还是空置。
- 每个棋手的棋步 : 我们必须以某种方式掌握每个棋手过去和现在的棋步,即 "X "和 "O "所占据的位置。
注:这两种信息都可以通过网格的状态来获取,但每次我们需要玩家的位置时,都需要遍历网格。这可以称为时间与空间复杂性的权衡。这是一种节省时间的通用技术。
# 单次井字游戏的函数
def single_game(cur_player):
# 表示井字游戏
values = [' ' for x in range(9)] # 表示井字游戏。
# 存储 X 和 O 所占的位置
player_pos = {'X':[], 'O':[]}
网格的状态由一个字符列表管理,该列表有三种可能的值:
- ’ ’ —— 空格
- ‘X’ —— 玩家 X 占用的单元格
- ‘O’ —— 玩家 O 占用的单元格
每个棋手的棋步都以整数列表的字典形式存储。每个棋手的键分别是 "X "和 “O”。它们对应的列表包含它们所占网格单元的数字。
注:变量 cur_player 存储了当前玩家的移动位置,如 "X "或 “O”。
步骤 3:游戏循环
每个游戏都有某种游戏循环,循环运行直到某个玩家获胜或游戏以平局结束。在井字游戏中,每个循环迭代指的是棋手的一次走棋。
# 一次井字游戏的游戏循环
while True:
print_tic_tac_toe(values)
步骤 4:处理玩家输入
在每次游戏迭代中,玩家都必须输入自己的棋步。
# 尝试 MOVE 输入的异常块
try:
print("Player ", cur_player, " turn. Which box? : ", end="")
move = int(input())
except ValueError:
print("Wrong Input!!! Try Again")
continue
# 对 inout 中的 MOVE 进行正确性检查
if move < 1 or move > 9:
print("Wrong Input!!! Try Again")
continue
# 检查方框是否已被占用
if values[move-1] != ' ':
print("Place already filled. Try again!!")
continue
我们创建了一个 try 块,以防玩家输入了一些非预期值。这样的事件一定不会让游戏停止,因此我们会处理 ValueError 异常,然后继续游戏。
我们需要执行一些合理性检查,比如输入的值是否是有效位置,如果是有效位置,是否已经被占用?
步骤 5:更新信息
根据玩家的输入,我们需要更新信息,以便游戏顺利进行。
# 更新游戏信息
# 更新网格状态
values[move-1] = cur_player
# 更新棋手位置
player_pos[cur_player].append(move)
值列表会根据当前玩家更新所占的单元格。玩家位置会添加当前玩家刚刚占据的位置。
更新值列表并调用 print_tic_tac_toe() 函数后,网格看起来就像这样了:
步骤 6:检查胜负
每走一步棋后,我们都要检查是否有棋手获胜或平局。检查方法如下
功能调用:
# 调用函数检查是否获胜
if check_win(player_pos, cur_player):
print_tic_tac_toe(values)
print("Player ", cur_player, " has won the game!!")
print("\n")
return cur_player
# 调用函数检查平局
if check_draw(player_pos):
print_tic_tac_toe(values)
print("Game Drawn")
print("\n")
return 'D'
如果任何棋手获胜,那么 single_game() 函数将返回当前下棋的棋手。如果棋局平局,则返回 “D”。
代码
# 检查是否有玩家获胜的功能
def check_win(player_pos, cur_player):
# 所有可能的获胜组合
soln = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]]
# 循环检查是否满足任何中奖组合
for x in soln:
if all(y in player_pos[cur_player] for y in x):
# 如果任何获胜组合满足以下条件,则返回 True
return True
# 如果不满足任何组合,则返回 False
return False
# 检查游戏是否平局的函数
def check_draw(player_pos):
if len(player_pos['X']) + len(player_pos['O']) == 9:
return True
return False
check_win():该函数包含所有获胜组合。它所做的就是检查当前玩家的位置是否满足任何获胜组合。如果满足,则返回 True。如果任何组合都不符合,则函数返回 False。
check_draw():平局条件相当简单,因为当所有 "9 "个位置都被占满时,游戏就会平局。
步骤 7:切换当前玩家
由于每个棋手每次只能移动一次,因此每次成功移动后,我们都必须交换当前棋手。
# 切换玩家移动
if cur_player == 'X':
cur_player = 'O'
else:
cur_player = 'X'
就单个游戏而言,这就是我们需要做的。不过,如果玩家想进行多局游戏,本文还介绍了一个记分牌系统,用于跟踪记录。
步骤 8:输入玩家姓名
任何计分板都必须显示每位玩家的姓名。
if __name__ == "__main__":
print("Player 1")
player1 = input("Enter the name : ")
print("\n")
print("Player 2")
player2 = input("Enter the name : ")
print("\n")
步骤 9:存储游戏相关信息
需要存储的信息包括:当前玩家、玩家选择(叉或圈)、可用选项(叉和圈)以及记分牌。
# 存储选择 X 和 O 的玩家
cur_player = player1
# 存储玩家的选择
player_choice = {'X' : "", 'O' : ""}
# 存储选项
options = ['X', 'O']
# 存储记分板
score_board = {player1: 0, player2: 0}
默认情况下,当前玩家是最先输入名字的玩家。
步骤 10:设计记分牌
记分板以字典形式存储,键为玩家姓名,值为胜场数。
# 打印记分牌的功能
def print_scoreboard(score_board):
print("--------------------------------")
print(" SCOREBOARD ")
print("--------------------------------")
players = list(score_board.keys())
print(" ", players[0], " ", score_board[players[0]])
print(" ", players[1], " ", score_board[players[1]])
print("--------------------------------\n")
要显示记分牌,我们需要球员的名字。我们使用 .keys() 函数提取键值,然后将其转换为列表,以便在显示分数时进行索引。
步骤 11:外部游戏循环
我们需要另一个游戏循环来管理多场井字游戏。每场比赛中,当前玩家都要选择自己的标记("X "或 “O”)。选择菜单必须在每次游戏迭代中显示:
# 一系列井字游戏的环路
# 循环运行,直到玩家退出
while True:
# 玩家选择菜单
print("Turn to choose for", cur_player)
print("Enter 1 for X")
print("Enter 2 for O")
print("Enter 3 to Quit")
记分牌和菜单是这样的
步骤 12:处理和分配玩家选择
每次迭代,我们都要处理并存储当前玩家的选择。
# 尝试 CHOICE 输入的异常
try:
choice = int(input())
except ValueError:
print("Wrong Input!!! Try Again\n")
continue
# 玩家选择的条件
if choice == 1:
player_choice['X'] = cur_player
if cur_player == player1:
player_choice['O'] = player2
else:
player_choice['O'] = player1
elif choice == 2:
player_choice['O'] = cur_player
if cur_player == player1:
player_choice['X'] = player2
else:
player_choice['X'] = player1
elif choice == 3:
print("Final Scores")
print_scoreboard(score_board)
break
else:
print("Wrong Choice!!!! Try Again\n")
根据玩家的选择,数据已被存储。这一点非常重要,因为每场比赛结束后,它都会告诉我们哪位选手获胜。
步骤 13:执行匹配
存储完所有必要信息后,就可以执行独立比赛并存储获胜分数了。
# 存储单局井字游戏的获胜者
winner = single_game(options[choice-1])
步骤 14:更新记分牌
每次井字游戏结束后,我们都需要更新记分板。
# 根据胜负更新记分板
if winner != 'D' :
player_won = player_choice[winner]
score_board[player_won] = score_board[player_won] + 1
print_scoreboard(score_board)
如果比赛没有以平局结束,我们将更新记分牌。
步骤 15:切换选择播放器
每个玩家都必须有机会选择自己想要的标记,这是一个宽宏大量的想法。为此,我们要交换 cur_player 中的值。
# 切换选择 X 或 O 的玩家
if cur_player == player1:
cur_player = player2
else:
cur_player = player1
完整的工作代码
# Function to print Tic Tac Toe
def print_tic_tac_toe(values):
print("\n")
print("\t | |")
print("\t {} | {} | {}".format(values[0], values[1], values[2]))
print('\t_____|_____|_____')
print("\t | |")
print("\t {} | {} | {}".format(values[3], values[4], values[5]))
print('\t_____|_____|_____')
print("\t | |")
print("\t {} | {} | {}".format(values[6], values[7], values[8]))
print("\t | |")
print("\n")
# Function to print the score-board
def print_scoreboard(score_board):
print("\t--------------------------------")
print("\t SCOREBOARD ")
print("\t--------------------------------")
players = list(score_board.keys())
print("\t ", players[0], "\t ", score_board[players[0]])
print("\t ", players[1], "\t ", score_board[players[1]])
print("\t--------------------------------\n")
# Function to check if any player has won
def check_win(player_pos, cur_player):
# All possible winning combinations
soln = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [1, 4, 7], [2, 5, 8], [3, 6, 9], [1, 5, 9], [3, 5, 7]]
# Loop to check if any winning combination is satisfied
for x in soln:
if all(y in player_pos[cur_player] for y in x):
# Return True if any winning combination satisfies
return True
# Return False if no combination is satisfied
return False
# Function to check if the game is drawn
def check_draw(player_pos):
if len(player_pos['X']) + len(player_pos['O']) == 9:
return True
return False
# Function for a single game of Tic Tac Toe
def single_game(cur_player):
# Represents the Tic Tac Toe
values = [' ' for x in range(9)]
# Stores the positions occupied by X and O
player_pos = {'X':[], 'O':[]}
# Game Loop for a single game of Tic Tac Toe
while True:
print_tic_tac_toe(values)
# Try exception block for MOVE input
try:
print("Player ", cur_player, " turn. Which box? : ", end="")
move = int(input())
except ValueError:
print("Wrong Input!!! Try Again")
continue
# Sanity check for MOVE inout
if move < 1 or move > 9:
print("Wrong Input!!! Try Again")
continue
# Check if the box is not occupied already
if values[move-1] != ' ':
print("Place already filled. Try again!!")
continue
# Update game information
# Updating grid status
values[move-1] = cur_player
# Updating player positions
player_pos[cur_player].append(move)
# Function call for checking win
if check_win(player_pos, cur_player):
print_tic_tac_toe(values)
print("Player ", cur_player, " has won the game!!")
print("\n")
return cur_player
# Function call for checking draw game
if check_draw(player_pos):
print_tic_tac_toe(values)
print("Game Drawn")
print("\n")
return 'D'
# Switch player moves
if cur_player == 'X':
cur_player = 'O'
else:
cur_player = 'X'
if __name__ == "__main__":
print("Player 1")
player1 = input("Enter the name : ")
print("\n")
print("Player 2")
player2 = input("Enter the name : ")
print("\n")
# Stores the player who chooses X and O
cur_player = player1
# Stores the choice of players
player_choice = {'X' : "", 'O' : ""}
# Stores the options
options = ['X', 'O']
# Stores the scoreboard
score_board = {player1: 0, player2: 0}
print_scoreboard(score_board)
# Game Loop for a series of Tic Tac Toe
# The loop runs until the players quit
while True:
# Player choice Menu
print("Turn to choose for", cur_player)
print("Enter 1 for X")
print("Enter 2 for O")
print("Enter 3 to Quit")
# Try exception for CHOICE input
try:
choice = int(input())
except ValueError:
print("Wrong Input!!! Try Again\n")
continue
# Conditions for player choice
if choice == 1:
player_choice['X'] = cur_player
if cur_player == player1:
player_choice['O'] = player2
else:
player_choice['O'] = player1
elif choice == 2:
player_choice['O'] = cur_player
if cur_player == player1:
player_choice['X'] = player2
else:
player_choice['X'] = player1
elif choice == 3:
print("Final Scores")
print_scoreboard(score_board)
break
else:
print("Wrong Choice!!!! Try Again\n")
# Stores the winner in a single game of Tic Tac Toe
winner = single_game(options[choice-1])
# Edits the scoreboard according to the winner
if winner != 'D' :
player_won = player_choice[winner]
score_board[player_won] = score_board[player_won] + 1
print_scoreboard(score_board)
# Switch player who chooses X or O
if cur_player == player1:
cur_player = player2
else:
cur_player = player1
游戏时间到
创建游戏的所有步骤都已完成。现在是玩游戏的时候了。
Player 1
Enter the name : Luffy
Player 2
Enter the name : Sanji
--------------------------------
SCOREBOARD
--------------------------------
Luffy 0
Sanji 0
--------------------------------
Turn to choose for Luffy
Enter 1 for X
Enter 2 for O
Enter 3 to Quit
1
| |
| |
_____|_____|_____
| |
| |
_____|_____|_____
| |
| |
| |
Player X turn. Which box? : 5
| |
| |
_____|_____|_____
| |
| X |
_____|_____|_____
| |
| |
| |
Player O turn. Which box? : 1
| |
O | |
_____|_____|_____
| |
| X |
_____|_____|_____
| |
| |
| |
Player X turn. Which box? : 9
| |
O | |
_____|_____|_____
| |
| X |
_____|_____|_____
| |
| | X
| |
Player O turn. Which box? : 2
| |
O | O |
_____|_____|_____
| |
| X |
_____|_____|_____
| |
| | X
| |
Player X turn. Which box? : 3
| |
O | O | X
_____|_____|_____
| |
| X |
_____|_____|_____
| |
| | X
| |
Player O turn. Which box? : 7
| |
O | O | X
_____|_____|_____
| |
| X |
_____|_____|_____
| |
O | | X
| |
Player X turn. Which box? : 6
| |
O | O | X
_____|_____|_____
| |
| X | X
_____|_____|_____
| |
O | | X
| |
Player X has won the game!!
--------------------------------
SCOREBOARD
--------------------------------
Luffy 1
Sanji 0
--------------------------------
Turn to choose for Sanji
Enter 1 for X
Enter 2 for O
Enter 3 to Quit
2
| |
| |
_____|_____|_____
| |
| |
_____|_____|_____
| |
| |
| |
Player O turn. Which box? : 5
| |
| |
_____|_____|_____
| |
| O |
_____|_____|_____
| |
| |
| |
Player X turn. Which box? : 3
| |
| | X
_____|_____|_____
| |
| O |
_____|_____|_____
| |
| |
| |
Player O turn. Which box? : 2
| |
| O | X
_____|_____|_____
| |
| O |
_____|_____|_____
| |
| |
| |
Player X turn. Which box? : 8
| |
| O | X
_____|_____|_____
| |
| O |
_____|_____|_____
| |
| X |
| |
Player O turn. Which box? : 1
| |
O | O | X
_____|_____|_____
| |
| O |
_____|_____|_____
| |
| X |
| |
Player X turn. Which box? : 9
| |
O | O | X
_____|_____|_____
| |
| O |
_____|_____|_____
| |
| X | X
| |
Player O turn. Which box? : 6
| |
O | O | X
_____|_____|_____
| |
| O | O
_____|_____|_____
| |
| X | X
| |
Player X turn. Which box? : 7
| |
O | O | X
_____|_____|_____
| |
| O | O
_____|_____|_____
| |
X | X | X
| |
Player X has won the game!!
--------------------------------
SCOREBOARD
--------------------------------
Luffy 2
Sanji 0
--------------------------------
Turn to choose for Luffy
Enter 1 for X
Enter 2 for O
Enter 3 to Quit
3
Final Scores
--------------------------------
SCOREBOARD
--------------------------------
Luffy 2
Sanji 0
--------------------------------
结论
希望这篇文章能给读者带来乐趣和信息。如果对游戏有任何建议,欢迎发表评论。