update
many chore
This commit is contained in:
@@ -1,8 +1,9 @@
|
||||
# 项目:扫雷,骑士与流氓问题
|
||||
|
||||
我们为你提供了两个简单有趣的项目,帮助你进行知识巩固,请认真阅读文档内容。
|
||||
::: warning 😋 我们为你提供了两个简单有趣的项目,帮助你进行知识巩固,请认真阅读文档内容。
|
||||
|
||||
如果你卡住了,请记得回来阅读文档,或请求身边人的帮助。
|
||||
:::
|
||||
|
||||
::: tip 📥
|
||||
本节附件下载 <Download url="https://cdn.xyxsw.site/code/2-Projects.zip"/>
|
||||
@@ -10,9 +11,9 @@
|
||||
|
||||
`pip3 install -r requirements.txt`
|
||||
|
||||
# 骑士与流氓问题
|
||||
## 骑士与流氓问题
|
||||
|
||||
## 背景
|
||||
### 背景
|
||||
|
||||
- 在 1978 年,逻辑学家雷蒙德·斯穆里安(Raymond Smullyan)出版了《这本书叫什么名字?》,这是一本逻辑难题的书。在书中的谜题中,有一类谜题被斯穆里安称为“骑士与流氓”谜题。
|
||||
- 在骑士与流氓谜题中,给出了以下信息:每个角色要么是骑士,要么是流氓。骑士总是会说实话:如果骑士陈述了一句话,那么这句话就是真的。相反,流氓总是说谎:如果流氓陈述了一个句子,那么这个句子就是假的。
|
||||
@@ -21,15 +22,15 @@
|
||||
- 从逻辑上讲,我们可以推断,如果 A 是骑士,那么这句话一定是真的。但我们知道这句话不可能是真的,因为 A 不可能既是骑士又是流氓——我们知道每个角色要么是骑士,要么是流氓,不会出现是流氓的骑士或是骑士的流氓。所以,我们可以得出结论,A 一定是流氓。
|
||||
- 那个谜题比较简单。随着更多的字符和更多的句子,谜题可以变得更加棘手!你在这个问题中的任务是确定如何使用命题逻辑来表示这些谜题,这样一个运行模型检查算法的人工智能可以为我们解决这些谜题。
|
||||
|
||||
## 理解
|
||||
### 理解
|
||||
|
||||
- 看一下 `logic.py`,你可能还记得讲义的内容。无需了解此文件中的所有内容,但请注意,此文件为不同类型的逻辑连接词定义了多个类。这些类可以相互组合,所以表达式 `And(Not(A), Or(B, C))` 代表逻辑语句:命题 A 是不正确的,同时,命题 B 或者命题 C 是正确的。(这里的“或”是同或,不是异或)
|
||||
- 回想一下 `logic.py`,它还包含一个 函数 `model_check` 。`model_check` 输入知识库和查询结论。知识库是一个逻辑命题:如果知道多个逻辑语句,则可以将它们连接在一个表达式中。 递归考虑所有可能的模型,如果知识库推理蕴含查询结论,则返回 `True`,否则返回 `False`。
|
||||
- 回想一下 `logic.py`,它还包含一个 函数 `model_check` 。`model_check` 输入知识库和查询结论。知识库是一个逻辑命题:如果知道多个逻辑语句,则可以将它们连接在一个表达式中。递归考虑所有可能的模型,如果知识库推理蕴含查询结论,则返回 `True`,否则返回 `False`。
|
||||
- 现在,看看 `puzzle.py`,在顶部,我们定义了六个命题符号。例如,`AKnight` 表示“A 是骑士”的命题,`AKnave` 而表示“A 是流氓”的句子。我们也为字符 B 和 C 定义了类似的命题符号。
|
||||
- 接下来是四个不同的知识库 `knowledge0`, `knowledge1`, `knowledge2`, and `knowledge3`,它们将分别包含推断即将到来的谜题 0、1、2 和 3 的解决方案所需的知识。请注意,目前,这些知识库中的每一个都是空的。这就是你进来的地方!
|
||||
- 这个 `puzzle.py` 的 `main` 函数在所有谜题上循环,并使用模型检查来计算,给定谜题的知识,无论每个角色是骑士还是无赖,打印出模型检查算法能够得出的任何结论。
|
||||
|
||||
## 明确
|
||||
### 明确
|
||||
|
||||
- 将知识添加到知识库 `knowledge0`, `knowledge1`, `knowledge2`, 和 `knowledge3` 中,以解决以下难题。
|
||||
|
||||
@@ -62,7 +63,7 @@ C 说:“A 是骑士。”
|
||||
- 上述每个谜题中,每个角色要么是骑士,要么是流氓。骑士说的每一句话都是真的,流氓说的每一句话都是假的。
|
||||
- 一旦你完成了一个问题的知识库,你应该能够运行 `python puzzle.py` 来查看谜题的解决方案。
|
||||
|
||||
## 提示
|
||||
### 提示
|
||||
|
||||
- 对于每个知识库,你可能想要编码两种不同类型的信息:(1)关于问题本身结构的信息(即骑士与流氓谜题定义中给出的信息),以及(2)关于角色实际说了什么的信息。
|
||||
- 考虑一下,如果一个句子是由一个角色说出的,这意味着什么。在什么条件下这句话是真的?在什么条件下这个句子是假的?你如何将其表达为一个合乎逻辑的句子?
|
||||
@@ -71,15 +72,15 @@ C 说:“A 是骑士。”
|
||||
- 例如,对于谜题 0,设置 `knowledge0=AKnave` 将产生正确的输出,因为通过我们自己的推理,我们知道 A 一定是一个无赖。但这样做违背了这个问题的精神:目标是让你的人工智能为你做推理。
|
||||
- 您不需要(也不应该)修改 `logic.py` 来完成这个问题。
|
||||
|
||||
# 扫雷
|
||||
## 扫雷
|
||||
|
||||
写一个 AI 来玩扫雷游戏。
|
||||
|
||||

|
||||
|
||||
## 背景
|
||||
### 背景
|
||||
|
||||
### 扫雷
|
||||
#### 扫雷游戏
|
||||
|
||||
- 扫雷器是一款益智游戏,由一个单元格网格组成,其中一些单元格包含隐藏的“地雷”。点击包含地雷的单元格会引爆地雷,导致用户输掉游戏。单击“安全”单元格(即不包含地雷的单元格)会显示一个数字,指示有多少相邻单元格包含地雷,其中相邻单元格是指从给定单元格向左、向右、向上、向下或对角线一个正方形的单元格。
|
||||
- 例如,在这个 3x3 扫雷游戏中,三个 1 值表示这些单元格中的每个单元格都有一个相邻的单元格,该单元格是地雷。四个 0 值表示这些单元中的每一个都没有相邻的地雷。
|
||||
@@ -89,7 +90,7 @@ C 说:“A 是骑士。”
|
||||
- 给定这些信息,玩家根据逻辑可以得出结论,右下角单元格中一定有地雷,左上角单元格中没有地雷,因为只有在这种情况下,其他单元格上的数字标签才会准确。
|
||||
- 游戏的目标是标记(即识别)每个地雷。在游戏的许多实现中,包括本项目中的实现中,玩家可以通过右键单击单元格(或左键双击,具体取决于计算机)来标记地雷。
|
||||
|
||||
### 命题逻辑
|
||||
#### 命题逻辑
|
||||
|
||||
- 你在这个项目中的目标是建立一个可以玩扫雷游戏的人工智能。回想一下,基于知识的智能主体通过考虑他们的知识库来做出决策,并根据这些知识做出推断。
|
||||
- 我们可以表示人工智能关于扫雷游戏的知识的一种方法是,使每个单元格成为命题变量,如果单元格包含地雷,则为真,否则为假。
|
||||
@@ -100,7 +101,7 @@ C 说:“A 是骑士。”
|
||||
- `Or(A,B,C,D,E,F,G,H)`
|
||||
- 但事实上,我们知道的比这个表达所说的要多。上面的逻辑命题表达了这样一种观点,即这八个变量中至少有一个是真的。但我们可以做一个更有力的陈述:我们知道八个变量中有一个是真的。这给了我们一个命题逻辑命题,如下所示。
|
||||
|
||||
```
|
||||
```txt
|
||||
Or(
|
||||
And(A, Not(B), Not(C), Not(D), Not(E), Not(F), Not(G), Not(H)),
|
||||
And(Not(A), B, Not(C), Not(D), Not(E), Not(F), Not(G), Not(H)),
|
||||
@@ -121,7 +122,7 @@ Or(
|
||||
|
||||
个可能的模型——太多了,计算机无法在任何合理的时间内计算。对于这个问题,我们需要更好地表达知识。
|
||||
|
||||
### 知识表示
|
||||
#### 知识表示
|
||||
|
||||
- 相反,我们将像下面这样表示人工智能知识的每一句话。
|
||||
- `{A, B, C, D, E, F, G, H} = 1`
|
||||
@@ -147,17 +148,17 @@ Or(
|
||||
- 更一般地说,任何时候我们有两个命题满足 `set1=count1` 和 `set2=count2`,其中 `set1` 是 `set2` 的子集,那么我们可以构造新的命题 `set2-set1=count2-count1`。考虑上面的例子,以确保你理解为什么这是真的。
|
||||
- 因此,使用这种表示知识的方法,我们可以编写一个人工智能智能主体,它可以收集有关扫雷的知识,并希望选择它知道安全的单元格!
|
||||
|
||||
## 理解
|
||||
### 理解
|
||||
|
||||
- 这个项目有两个主要文件:`runner.py` 和 `minesweeper.py`。`minesweeper.py` 包含游戏本身和 AI 玩游戏的所有逻辑。`runner.py` 已经为你实现,它包含了运行游戏图形界面的所有代码。一旦你完成了 `minesweeper.py` 中所有必需的功能,你就可以运行 `python runner.py` 来玩扫雷了(或者让你的 AI 为你玩)!
|
||||
- 让我们打开 `minesweeper.py` 来了解提供了什么。这个文件中定义了三个类,`Minesweeper`,负责处理游戏;`Sentence`,表示一个既包含一组 `cell` 又包含一个 `count` 的逻辑命题;以及 `MinesweeperAI`,它处理根据知识做出的推断。
|
||||
- `Minesweeper` 类已经完全实现了。请注意,每个单元格都是一对 `(i,j)`,其中 `i` 是行号(范围从 `0` 到 `height-1`),`j` 是列号(范围从 `0` 到 `width-1`)。
|
||||
- `Minesweeper` 类已经完全实现了。请注意,每个单元格都是一对 `(i,j)`,其中 `i` 是行号 (范围从 `0` 到 `height-1`),`j` 是列号 (范围从 `0` 到 `width-1`)。
|
||||
- `Sentence` 类将用于表示背景中描述的形式的逻辑命题。每个命题中都有一组 `cell`,以及 `count` 表示其中有多少单元格是地雷。该类还包含函数 `known_mines` 和 `known_safes`,用于确定命题中的任何单元格是已知的地雷还是已知的安全单元格。它还包含函数 `mark_mine` 和 `mark_safe`,用于响应有关单元格的新信息来更新命题。
|
||||
- 最后,`MinesweeperAI` 类将实现一个可以玩扫雷的 AI。AI 类跟踪许多值。`self.moves_made` 包含一组已经点击过的所有单元格,因此人工智能知道不要再选择这些单元格。`self.mines` 包含一组已知为地雷的所有单元格。`self.safes` 包含一组已知安全的所有单元格。而 `self.knowledge` 包含了人工智能知道是真的所有命题的列表。
|
||||
- `mark_mine` 函数为 `self.mines` 添加了一个单元格,因此 AI 知道这是一个地雷。它还循环遍历人工智能知识中的所有命题,并通知每个命题该单元格是地雷,这样,如果命题包含有关地雷的信息,它就可以相应地更新自己。`mark_safe` 函数也做同样的事情,只是针对安全单元格。
|
||||
- 剩下的函数 `add_knowledge`、`make_safe_move` 和 `make_random_move` 由你完成!
|
||||
|
||||
## 明确
|
||||
### 明确
|
||||
|
||||
- 完成 `minesweeper.py` 中的 `Sentence` 类和 `MinesweeperAI` 类的实现。
|
||||
- 在 `Sentence` 类中,完成 `known_mines`、`known_safes`、`mark_mine` 和 `mark_safe` 的实现。
|
||||
@@ -194,11 +195,11 @@ Or(
|
||||
- 此举决不能是已知的地雷行动。
|
||||
- 如果无法进行此类移动,则函数应返回 `None`。
|
||||
|
||||
## 提示
|
||||
### 提示
|
||||
|
||||
- 确保你已经彻底阅读了背景部分,以了解知识在这个人工智能中是如何表现的,以及人工智能是如何进行推理的。
|
||||
- 如果对面向对象编程感觉不太舒服,你可能会发现<u>python 关于类</u>的文档很有帮助。
|
||||
- 你可以在<u>python 关于集合</u>的文档中找到一些常见的集合操作。
|
||||
- 如果对面向对象编程感觉不太舒服,你可能会发现[<u>python 关于类</u>](https://docs.python.org/3/tutorial/classes.html)的文档很有帮助。
|
||||
- 你可以在[<u>python 关于集合</u>](https://docs.python.org/3/library/stdtypes.html#set)的文档中找到一些常见的集合操作。
|
||||
- 在 `Sentence` 类中实现 `known_mines` 和 `known_safes` 时,请考虑:在什么情况下,你确信命题的单元格是安全的?在什么情况下,你确定一个命题的单元格是地雷?
|
||||
- `add_knowledge` 做了很多工作,可能是迄今为止你为该项目编写的最长的函数。一步一步地实现此函数的行为可能会有所帮助。
|
||||
- 如果愿意,欢迎您向任何类添加新方法,但不应修改任何现有函数的定义或参数。
|
||||
|
||||
Reference in New Issue
Block a user