请把上面的代码复制或录入到编程窗口中,按F5键运行一下,看看是否能画出同样的迷宫。
如果对这段程序有不明白的地方,建议按F8键单步执行,观看程序的执行流程,可以帮助理解。
04 画参数表迷宫画好后,我们要做的工作是让老鼠动起来。
怎么动呢?假设老鼠在迷宫内某一个单元格中,有上、下、左、右4个方向可以移动。但是,迷宫中有墙,被墙挡住的方向不能移动。
所以,需要让老鼠知道,往哪个方向可以移动,哪个方向不能移动。否则它可能会随意穿墙乱走。
为此,我们建一张表,把迷宫中每个单元格的4个方向都列出来,在有墙的方向写0,没有墙的方向写1。这样,老鼠根据表中的数值是1还是0,就知道这个方向是能走还是不能走。
迷宫一共有9个单元格,每个格有4个方向。所以我们建一张9行4列的表,就可以把所有可能的情况表示出来。这个表称为“动作参数表”。
在人工智能中,直接建表是处理参数最简单的方式。然而,不是所有的应用都可以直接建表的,或者是直接建表的参数过于巨大,不经济。这种情况下,通常用神经网络模型来表达,例如在处理文字、图形、语言等复杂情况时。ChatGPT处理自然语言时,就使用了神经网络技术,其中包含大量的参数。
我们把动作参数表的左上角,放在表格的第4行,第8列,我们定义两个常量代表这两个数字。定义常量的代码如下:
Const 参数表头行 = 4 '动作参数表左上角行号
Const 参数表头列 = 8 '动作参数表左上角列号
这两句代码与之前定义的两个迷宫常量要放在一起,放在整个程序的最上方,如下图:
然后我们创建一个新的过程:画动作参数表,并定义内部使用的局部变量。如下:
Sub 画动作参数表() '画动作参数表(θ)
Dim 迷宫行号 As Integer '迷宫内部行号
Dim 迷宫列号 As Integer '迷宫内部列号
Dim 迷宫编号 As Integer '迷宫位置编号
Dim 参数表行号 As Integer '动作参数表当前行号
Dim 参数表列号 As Integer '动作参数表当前列号
End Sub
接着,在Dim语句下面写“画表头”的语句,如下:
'画动作参数表表头
Cells(参数表头行 - 2, 参数表头列 1).Value = "动作参数表θ(动作表格化)"
Cells(参数表头行 - 2, 参数表头列 - 1) = "迷宫编号/"
Cells(参数表头行 - 1, 参数表头列 - 1) = "移动方向"
Cells(参数表头行 - 1, 参数表头列 0) = "上"
Cells(参数表头行 - 1, 参数表头列 1) = "右"
Cells(参数表头行 - 1, 参数表头列 2) = "下"
Cells(参数表头行 - 1, 参数表头列 3) = "左"
'画动作参数表边框
With Range(Cells(参数表头行, 参数表头列), Cells(参数表头行 8, 参数表头列 3))
.BorderAround LineStyle:=xlContinuous '画参数表四边单线边框
End With
然后,我们向动作参数表中填数据。
方法是从『迷宫编号』为0的单元格开始,一直到第8个迷宫单元格,依次判断该单元格的上、右、下、左四个方向有没有边框。
如果没有边框,代表可以通行,则向对应的参数表中填数字1 。
如果有边框,代表不能通行,则向对应的参数表中填数字0 。
如下图:
实现判断比较的功能需要使用IF分支语句,用法如下:
其中的『条件表达式』通常要比较两个常量或变量的大小,常用的比较运算符有:
比较运算符 | 描述 |
= | 等于:前者的值是否等于后者的值?是则表达式为真。 |
< | 小于:前者的值是否小于后者的值?是则表达式为真。 |
> | 大于:前者的值是否大于后者的值?是则表达式为真。 |
<= | 小于等于:前者的值是否小于等于后者的值?是则表达式为真。 |
>= | 大于等于:前者的值是否大于等于后者的值?是则表达式为真。 |
<> | 不等于:前者的值是否不等于后者的值?是则表达式为真。 |
表达式中也可以使用算数运算符,常用的如下:
算术运算符 | 描述 |
| 加:将两数相加,如a b。 |
- | 减:将两数相减,如a-b。 |
* | 乘:将两数相乘,如a*b。 |
/ | 除:将两数相除,如a/b。 |
^ | 幂:进行幂运算,如a^2表示a的2次方。 |
使用举例:
Sub 测试() '这是一个测试程序
Dim x As Integer '定义一个整型变量x
x = 11 '给x赋值
If x <= 2 * 5 Then '如果x小于等于2乘以5(即10)
Cells(2, 1) = "小" '则在第2行1列单元格中填入“小” 。
Else '其他情况,即x大于10
Cells(2, 1) = "大" '则在第2行1列单元格中填入“大”。
End If 'If语句结束
End Sub
把这段代码复制或录入到编程窗口中,按F5或F8执行一下,看看结果如何。
试着修改 x=7 这句代码,把数字改成7以下的值,看看程序运行结果是否改变?
下面我们看往动作参数表中填写参数的代码:
'向表内填写动作参数
迷宫编号 = 0
For 迷宫行号 = 0 To 2
For 迷宫列号 = 0 To 2
参数表行号 = 参数表头行 迷宫编号
Cells(参数表行号, 参数表头列 - 1) = 迷宫编号 '动作参数表中左侧写迷宫编号
With Cells(迷宫头行 迷宫行号, 迷宫头列 迷宫列号) '指定迷宫某个单元格
'以下检查单元格上方有无边框
If .Borders(xlEdgeTop).LineStyle = -4142 Then '如果上方无边框
Cells(参数表行号, 参数表头列 0) = 1 '动作参数值填1
Else
Cells(参数表行号, 参数表头列 0) = 0 '动作参数值填0
End If
'以下检查单元格右方有无边框
If .Borders(xlEdgeRight).LineStyle = -4142 Then '如果右方无边框
Cells(参数表行号, 参数表头列 1) = 1 '动作参数值填1
Else
Cells(参数表行号, 参数表头列 1) = 0 '动作参数值填0
End If
'以下检查单元格下方有无边框
If .Borders(xlEdgeBottom).LineStyle = -4142 Then '如果下方无边框
Cells(参数表行号, 参数表头列 2) = 1 '动作参数值填1
Else
Cells(参数表行号, 参数表头列 2) = 0 '动作参数值填0
End If
'以下检查单元格左方有无边框
If .Borders(xlEdgeLeft).LineStyle = -4142 Then '如果左方无边框
Cells(参数表行号, 参数表头列 3) = 1 '动作参数值填1
Else
Cells(参数表行号, 参数表头列 3) = 0 '动作参数值填0
End If
End With
迷宫编号 = 迷宫编号 1 '迷宫编号 1
Next 迷宫列号
Next 迷宫行号
程序看起来很长,其实结构很简单。
程序的主体结构依然是两个嵌套在一起的For循环语句,用With语句依次选中迷宫中编号0到8的单元格,然后用4个IF分支语句分别判断该单元格的上、右、下、左四个方向有没有边框。
查手册得知,属性.LineStyle = -4142代表“无边框”。
把以上代码复制或录入到“Sub 画动作参数表()”过程中,完成该过程。
我们把调用“画动作参数表”的语句也加入到“Sub 初始化()”过程中。如下:
Sub 初始化()
Dim 列号 As Integer '把变量 列号 定义为整型
For 列号 = 1 To 20 '列号从1到20循环
Cells(1, 列号) = 列号 '循环体,向指定单元格写入数据
Next 列号 '每循环一次列号加1,大于20后退出循环
Range(Cells(2, 1), Cells(26, 12)).Clear '清空指定矩形区域
画迷宫 '调用“画迷宫()”过程
画动作参数表 '调用“画动作参数表()”过程
End Sub
最后一句是新增的。然后运行“初始化()”过程,结果如下图: