学员宁嘉欣的高光时刻!
经过近一年的VBA编程学习,学员宁嘉欣从零基础到把我狂虐,不禁深深的被当代大学生的聪明与智慧所折服!
事情的起因是这样的(最后附上学员代码及照片):
2023年7月18日晚上课时,我说:“今天做个2048游戏,在表格内画个4X4的游戏区域,增加两个按钮,一个是开始,一个是上,今天只写上键的代码。” 游戏界面如下图:

我继续说:“我以前写的代码分两部分,一是先做合并,二是再做移动,那么,我们能不能用一步来完成合并和移动这两个动作呢?”
然后我就和学员们一起写起代码来,我虽然做到了一步完成合并和移动这两个动作,但代码有50行之多,且包含非常多的判断。非常的不如意!
此时学员宁嘉欣向我示意,她也完成了代码,当我看到她的代码时,惊出了一身的冷汗,她只用了22行代码就完成了任务,且连随机放置下一数也做好了。代码如下:

我问她:“你能给我讲一下吗?”
她简单给我描述了一下原理,大意如下,她为了省去过多的、烦人的判断,采用了数组与表格的互动方式进行制作,先用数组arr取得游戏区域的数值,再将表格内游戏区域的2-3行内容清空,定义变量endRow用于取表格内游戏区域最后一行的行号。然后判断数组arr的当前位置是否为空,不为空,就将内容放置回表格的相应位置,再判断表格内上下相邻的两个数是否相等,相等则相加,并清空多余的数。
看完她的代码并运行后,基本没有什么错误,我就说,你试试224组合,如下图:

结果出现了错误,原因当然出在取最后一行的行号上。
没想到,她很快就改好了代码,只增加了一个判断和一条语句:
arr(endRow, i) <> 1
arr(endRow, i) = 1
更改后的代码如下:

最后点评一下:
1、因为游戏区域只剩第一行了,所以,内循环为 2 to 4 ,这点非常的好;
2、使用endRow取最后一行的行号的方法是点睛之笔;
附上学员宁嘉欣的全部代码:
Sub UP_Click() '上键
Dim i&, j&, endRow&
arr = Range("a1:d4")
Range("a2:d4").ClearContents
For i = 1 To 4
For j = 2 To 4
endRow = Cells(Rows.Count, i).End(xlUp).Row
If arr(j, i) <> "" Then
If Cells(1, i) = "" Then
Cells(endRow, i) = arr(j, i)
Else
Cells(endRow + 1, i) = arr(j, i)
End If
End If
If Cells(endRow + 1, i) = Cells(endRow, i) And Cells(endRow, i) <> "" And arr(endRow, i) <> 1 Then
Cells(endRow, i) = Cells(endRow, i) + Cells(endRow + 1, i)
Cells(endRow + 1, i) = ""
arr(endRow, i) = 1
End If
Next
Next
Call t
End Sub
Sub t() '随机放置一个2
Dim i&, r&, c&, arr(1 To 16), js&
For i = 0 To 15
r = i \ 4 + 1
c = i Mod 4 + 1
If Cells(r, c) = "" Then
js = js + 1
arr(js) = i + 1
End If
Next
If arr(1) = "" Then
MsgBox "你输了"
Else
i = arr(Rnd * (js - 1) + 1) - 1
r = i \ 4 + 1
c = i Mod 4 + 1
Cells(r, c) = 2
End If
End Sub
Sub kaishi() '开始按钮
Dim i&
Range("a1:d4").ClearContents
For i = 1 To 8
Call t
Next
End Sub
最后附上学员照片:
