Files
fzu-product/4.人工智能/4.3.1.2项目:Tic-Tac-Toe井字棋.md
2023-07-02 00:42:55 +08:00

5.3 KiB
Raw Blame History

项目Tic-Tac-Toe 井字棋

我们为你提供了一个简单有趣的项目,帮助你进行知识巩固,请认真阅读文档内容。

如果你卡住了,请记得回来阅读文档,或请求身边人的帮助。

::: tip 📥 本节附件下载 :::

pip3 install -r requirements.txt

理解

  • 这个项目有两个主要文件:runner.pytictactoe.pytictactoe.py 包含了玩游戏和做出最佳动作的所有逻辑。runner.py 已经为你实现,它包含了运行游戏图形界面的所有代码。一旦你完成了 tictactoe.py 中所有必需的功能,你就可以运行 python runner.py 来对抗你的人工智能了!
  • 让我们打开 tictactoe.py 来了解所提供的内容。首先我们定义了三个变量X、O 和 EMPTY以表示游戏的可能移动。
  • 函数 initial_state 返回游戏的启动状态。对于这个问题,我们选择将游戏状态表示为三个列表的列表(表示棋盘的三行),其中每个内部列表包含三个值,即 X、O 或 EMPTY。以下是我们留给你实现的功能

说明

  • 实现 player, actions, result, winner, terminal, utility, 以及 minimax.

    • player 函数应该以棋盘状态作为输入并返回轮到哪个玩家X 或 O

      • 在初始游戏状态下X 获得第一步。随后,玩家交替进行每一个动作。
      • 如果提供结束棋盘状态作为输入(即游戏已经结束),则任何返回值都是可接受的。
    • actions 函数应该返回一组在给定的棋盘状态上可以采取的所有可能的操作。

      • 每个动作都应该表示为元组 (ij),其中 i 对应于移动的行0、1 或 2j 对应于行中的哪个单元格对应于移动(也是 0、1、或 2
      • 可能的移动是棋盘上任何没有 X 或 O 的单元格。
      • 如果提供结束棋盘状态作为输入,则任何返回值都是可接受的。
    • result 函数以一个棋盘状态和一个动作作为输入,并且应该返回一个新的棋盘状态,而不修改原始棋盘。

      • 如果 action 函数接受了一个无效的动作,你的程序应该raise an exception.
      • 返回的棋盘状态应该是从原始输入棋盘,并让轮到它的玩家在输入动作指示的单元格处移动所产生的棋盘。
      • 重要的是,原始棋盘应该保持不变:因为 Minimax 最终需要在计算过程中考虑许多不同的棋盘状态。这意味着简单地更新棋盘上的单元格本身并不是 result 函数的正确实现。在做出任何更改之前,你可能需要先对棋盘状态进行deep copy
    • winner 函数应该接受一个棋盘作为输入,如果游戏结束,则返回游戏的获胜者。

      • 如果 X 玩家赢得了游戏,函数应该返回 X。如果 O 玩家赢得了比赛,函数应该返回 O。
      • 一个人可以通过水平、垂直或对角连续三次移动赢得比赛。
      • 你可以认为最多会有一个赢家(也就是说,没有一个棋盘会同时有两个玩家连着三个,因为这将是一个无效的棋盘状态)。
      • 如果游戏没有赢家(要么是因为游戏正在进行,要么是因为比赛以平局结束),函数应该返回 None
    • terminal 函数应该接受一个棋盘作为输入,并返回一个布尔值,指示游戏是否结束。

      • 如果游戏结束,要么是因为有人赢得了游戏,要么是由于所有单元格都已填充而没有人获胜,则函数应返回 True
      • 否则,如果游戏仍在进行中,则函数应返回 False
    • utility 函数应接受结束棋盘状态作为输入,并输出该棋盘的分数。

      • 如果 X 赢得了比赛,则分数为 1。如果 O 赢得了比赛,则分数为-1。如果比赛以平局结束则分数为 0。
      • 你可以假设只有当 terminal(board) 为 True 时,才会在棋盘上调用 utility
    • minimax 函数应该以一个棋盘作为输入,并返回玩家在该棋盘上移动的最佳移动。

      • 返回的移动应该是最佳动作 (ij),这是棋盘上允许的动作之一。如果多次移动都是同样最佳的,那么这些移动中的任何一次都是可以接受的。
      • 如果该棋盘是结束棋盘状态,则 minimax 函数应返回 None
    • 对于所有接受棋盘作为输入的函数,你可以假设它是一个有效的棋盘(即,它是包含三行的列表,每行都有三个值 X、O 或 EMPTY。你不应该修改所提供的函数声明每个函数的参数的顺序或数量。、

    • 一旦所有功能都得到了正确的实现,你就应该能够运行 python runner.py 并与你的人工智能进行比赛。而且,由于井字棋是双方最佳比赛的平局,你永远不应该能够击败人工智能(尽管如果你打得不好,它可能会打败你!)

提示

  • 如果你想在不同的 Python 文件中测试你的函数,你可以用类似于 from tictactoe import initial_state 的代码来导入它们。
  • 欢迎在 tictactoe.py 中添加其他辅助函数,前提是它们的名称不会与模块中已有的函数或变量名称冲突。
  • alpha-beta 剪枝是可选的,这可能会让你的人工智能运行更高效!