用 Python 构建你的井字游戏
本文将引导你使用 Python 编写一个简单的井字游戏。这个过程能帮助你掌握游戏逻辑的构建,并了解代码结构。
游戏是人们娱乐的重要方式之一。我们可以在网络、移动设备、电脑等各种平台上找到各种类型的游戏。这次,我们不制作复杂的大型游戏,而是用 Python 创建一个命令行(CLI)版本的井字游戏。
如果你还不熟悉井字游戏,可以点击这里进行了解。即使你不熟悉游戏规则,也不必担心,我们将在文章中详细介绍。
井字游戏简介
本教程分为三个部分。第一部分将讲解井字游戏的基本规则。第二部分将介绍帮助我们构建游戏逻辑的算法。最后,我们将看到结构化的代码及其详细解释。
如果你已经熟悉井字游戏,可以直接跳过第一部分。
现在,让我们开始第一部分吧。
如何玩井字游戏
井字游戏需要两名玩家参与,每名玩家使用不同的标志。通常使用的标志是 “X” 和 “O”。游戏在一个包含 9 个格子的棋盘上进行。
下面是井字棋盘的示意图:
井字游戏棋盘
游戏规则如下:
- 首先,一名玩家在一个空的格子上放置自己的标志。
- 然后,另一名玩家在另一个空的格子上放置自己的标志。
- 玩家的目标是将自己的标志连成一行、一列或一条对角线。
- 游戏将持续进行,直到一名玩家获胜,或者所有格子都被填满但无人获胜(平局)。
让我们看一些游戏实例:
在上面的例子中,玩家 “X” 赢得了比赛。所有的 “X” 标志都沿对角线排列。因此,该玩家获胜。
总共有 8 种获胜的排列方式。让我们看看这 8 种排列方式:
最后,如果棋盘被填满,但没有出现任何获胜排列,则游戏为平局。现在你应该已经了解如何玩井字游戏了。
现在你可以去这里亲自体验一下,完全理解游戏规则。如果你已经理解了,那么让我们进入下一部分。
游戏算法
接下来,我们将讨论编写游戏代码的算法。这个算法可以帮助你用任何编程语言编写游戏。让我们看看它是如何实现的。
- 创建一个二维数组来表示棋盘,并将每个元素初始化为空。
- 你可以使用任何符号表示空。这里,我们使用连字符 ‘-’。
- 编写一个函数来检查棋盘是否被填满。
- 遍历棋盘,如果发现任何一个格子为空,则返回 `false`,否则返回 `true`。
- 编写一个函数来检查玩家是否获胜。
- 我们需要检查上一节中讨论的所有获胜可能性。
- 检查所有行、列和两条对角线。
- 编写一个函数来显示棋盘,因为在用户玩游戏时,我们会多次向用户展示棋盘。
- 编写一个函数来启动游戏。
- 随机选择一位玩家先行。
- 进入一个无限循环,当游戏结束(无论是获胜还是平局)时跳出循环。
- 向用户展示棋盘,提示用户选择下一步行动的格子。
- 要求用户输入行号和列号。
- 用相应玩家的标志更新格子。
- 检查当前玩家是否获胜。
- 如果当前玩家获胜,则打印获胜消息,并跳出无限循环。
- 接下来,检查棋盘是否被填满。
- 如果棋盘已满,则打印平局消息,并跳出无限循环。
- 最后,向用户展示最终的棋盘状态。
你可能已经对游戏流程有了大概的了解。如果你没有完全理解,也不必担心,看完代码你会更加清晰。
现在让我们进入代码部分。我假设你的电脑上已经安装了 Python,可以尝试运行代码。
代码实现
请仔细阅读下面的代码:
import random class TicTacToe: def __init__(self): self.board = [] def create_board(self): for i in range(3): row = [] for j in range(3): row.append('-') self.board.append(row) def get_random_first_player(self): return random.randint(0, 1) def fix_spot(self, row, col, player): self.board[row][col] = player def is_player_win(self, player): win = None n = len(self.board) # checking rows for i in range(n): win = True for j in range(n): if self.board[i][j] != player: win = False break if win: return win # checking columns for i in range(n): win = True for j in range(n): if self.board[j][i] != player: win = False break if win: return win # checking diagonals win = True for i in range(n): if self.board[i][i] != player: win = False break if win: return win win = True for i in range(n): if self.board[i][n - 1 - i] != player: win = False break if win: return win return False for row in self.board: for item in row: if item == '-': return False return True def is_board_filled(self): for row in self.board: for item in row: if item == '-': return False return True def swap_player_turn(self, player): return 'X' if player == 'O' else 'O' def show_board(self): for row in self.board: for item in row: print(item, end=" ") print() def start(self): self.create_board() player="X" if self.get_random_first_player() == 1 else 'O' while True: print(f"Player {player} turn") self.show_board() # taking user input row, col = list( map(int, input("Enter row and column numbers to fix spot: ").split())) print() # fixing the spot self.fix_spot(row - 1, col - 1, player) # checking whether current player is won or not if self.is_player_win(player): print(f"Player {player} wins the game!") break # checking whether the game is draw or not if self.is_board_filled(): print("Match Draw!") break # swapping the turn player = self.swap_player_turn(player) # showing the final view of board print() self.show_board() # starting the game tic_tac_toe = TicTacToe() tic_tac_toe.start()
下面是代码的运行示例输出:
$ python tic_tac_toe.py Player X turn - - - - - - - - - Enter row and column numbers to fix spot: 1 1 Player O turn X - - - - - - - - Enter row and column numbers to fix spot: 2 1 Player X turn X - - O - - - - - Enter row and column numbers to fix spot: 1 2 Player O turn X X - O - - - - - Enter row and column numbers to fix spot: 1 3 Player X turn X X O O - - - - - Enter row and column numbers to fix spot: 2 2 Player O turn X X O O X - - - - Enter row and column numbers to fix spot: 3 3 Player X turn X X O O X - - - O Enter row and column numbers to fix spot: 3 2 Player X wins the game! X X O O X - - X O
帮助你理解代码结构的一些要点:
- 我们使用一个类来组织所有的方法,这样可以方便地在其他代码中重用。
- 我们将每个任务都定义为独立的函数,即使任务很小。这有助于代码的维护。
- 如果我们想更新游戏,上述两种方法可以帮助我们轻松完成更新。
你可以根据自己的喜好调整代码结构。代码结构并不受限制。
总结
恭喜! 你已经成功地从头开始创建了一个井字游戏。虽然这不是我们每天玩的视觉游戏,但它可以帮助你掌握游戏逻辑,并保持代码的结构清晰。可以尝试使用类似的思路来创建其他有趣的游戏。也许你能找到一些儿时的经典游戏。
编码愉快!👩💻
接下来,你可以探索如何使用 Python 的 `unittest` 模块创建猜数字游戏和单元测试。
喜欢这篇文章吗?分享给你的朋友吧!