我正在尝试在Excel中实现游戏2048。
第2、4、6和8行中的每个真/假布尔值用于确定第1、3、5和7行中每个单元格的数据是否为0。
Sub MergeUp()
Dim loop_num
Dim loop_num2
For loop_num2 = 1 To 3
For loop_num = 1 To 4
If Cells(6, loop_num) = True Then
Cells(5, loop_num) = Cells(7, loop_num)
Cells(7, loop_num) = 0
End If
If Cells(4, loop_num) = True Then
Cells(3, loop_num) = Cells(5, loop_num)
Cells(5, loop_num) = 0
End If
If Cells(2, loop_num) = True Then
Cells(1, loop_num) = Cells(3, loop_num)
Cells(3, loop_num) = 0
End If
Next
Next
For loop_num = 1 To 4
If Cells(1, loop_num) = Cells(3, loop_num) Then
Cells(1, loop_num) = Cells(1, loop_num) + Cells(3, loop_num)
Cells(9, "C") = Cells(9, "C") + Cells(3, loop_num)
Cells(3, loop_num) = 0
End If
If Cells(3, loop_num) = Cells(5, loop_num) Then
Cells(3, loop_num) = Cells(3, loop_num) + Cells(5, loop_num)
Cells(9, "C") = Cells(9, "C") + Cells(5, loop_num)
Cells(5, loop_num) = 0
End If
If Cells(5, loop_num) = Cells(7, loop_num) Then
Cells(5, loop_num) = Cells(5, loop_num) + Cells(7, loop_num)
Cells(9, "C") = Cells(9, "C") + Cells(7, loop_num)
Cells(7, loop_num) = 0
End If
Next
For loop_num2 = 1 To 3
For loop_num = 1 To 4
If Cells(6, loop_num) = True Then
Cells(5, loop_num) = Cells(7, loop_num)
Cells(7, loop_num) = 0
End If
If Cells(4, loop_num) = True Then
Cells(3, loop_num) = Cells(5, loop_num)
Cells(5, loop_num) = 0
End If
If Cells(2, loop_num) = True Then
Cells(1, loop_num) = Cells(3, loop_num)
Cells(3, loop_num) = 0
End If
Next
Next
Call rand_num
End Sub
Sub MergeDown()
Dim loop_num
Dim loop_num2
For loop_num2 = 1 To 3
For loop_num = 1 To 4
If Cells(4, loop_num) = True Then
Cells(3, loop_num) = Cells(1, loop_num)
Cells(1, loop_num) = 0
End If
If Cells(6, loop_num) = True Then
Cells(5, loop_num) = Cells(3, loop_num)
Cells(3, loop_num) = 0
End If
If Cells(8, loop_num) = True Then
Cells(7, loop_num) = Cells(5, loop_num)
Cells(5, loop_num) = 0
End If
Next
Next
For loop_num = 1 To 4
If Cells(7, loop_num) = Cells(5, loop_num) Then
Cells(7, loop_num) = Cells(7, loop_num) + Cells(5, loop_num)
Cells(9, "C") = Cells(9, "C") + Cells(5, loop_num)
Cells(5, loop_num) = 0
End If
If Cells(5, loop_num) = Cells(3, loop_num) Then
Cells(5, loop_num) = Cells(5, loop_num) + Cells(3, loop_num)
Cells(9, "C") = Cells(9, "C") + Cells(3, loop_num)
Cells(3, loop_num) = 0
End If
If Cells(3, loop_num) = Cells(1, loop_num) Then
Cells(3, loop_num) = Cells(3, loop_num) + Cells(1, loop_num)
Cells(9, "C") = Cells(9, "C") + Cells(1, loop_num)
Cells(1, loop_num) = 0
End If
Next
For loop_num2 = 1 To 3
For loop_num = 1 To 4
If Cells(4, loop_num) = True Then
Cells(3, loop_num) = Cells(1, loop_num)
Cells(1, loop_num) = 0
End If
If Cells(6, loop_num) = True Then
Cells(5, loop_num) = Cells(3, loop_num)
Cells(3, loop_num) = 0
End If
If Cells(8, loop_num) = True Then
Cells(7, loop_num) = Cells(5, loop_num)
Cells(5, loop_num) = 0
End If
Next
Next
Call rand_num
End Sub
Sub MergeLeft()
For loop_num2 = 1 To 3
For loop_num = 1 To 7 Step 2
If Cells(loop_num + 1, "C") = True Then
Cells(loop_num, "C") = Cells(loop_num, "D")
Cells(loop_num, "D") = 0
End If
If Cells(loop_num + 1, "B") = True Then
Cells(loop_num, "B") = Cells(loop_num, "C")
Cells(loop_num, "C") = 0
End If
If Cells(loop_num + 1, "A") = True Then
Cells(loop_num, "A") = Cells(loop_num, "B")
Cells(loop_num, "B") = 0
End If
Next
Next
For loop_num = 1 To 7 Step 2
If Cells(loop_num, "A") = Cells(loop_num, "B") Then
Cells(loop_num, "A") = Cells(loop_num, "A") + Cells(loop_num, "B")
Cells(9, "C") = Cells(9, "C") + Cells(loop_num, "B")
Cells(loop_num, "B") = 0
End If
If Cells(loop_num, "B") = Cells(loop_num, "C") Then
Cells(loop_num, "B") = Cells(loop_num, "B") + Cells(loop_num, "C")
Cells(9, "C") = Cells(9, "C") + Cells(loop_num, "C")
Cells(loop_num, "C") = 0
End If
If Cells(loop_num, "C") = Cells(loop_num, "D") Then
Cells(loop_num, "C") = Cells(loop_num, "C") + Cells(loop_num, "D")
Cells(9, "C") = Cells(9, "C") + Cells(loop_num, "D")
Cells(loop_num, "D") = 0
End If
Next
For loop_num2 = 1 To 3
For loop_num = 1 To 7 Step 2
If Cells(loop_num + 1, "C") = True Then
Cells(loop_num, "C") = Cells(loop_num, "D")
Cells(loop_num, "D") = 0
End If
If Cells(loop_num + 1, "B") = True Then
Cells(loop_num, "B") = Cells(loop_num, "C")
Cells(loop_num, "C") = 0
End If
If Cells(loop_num + 1, "A") = True Then
Cells(loop_num, "A") = Cells(loop_num, "B")
Cells(loop_num, "B") = 0
End If
Next
Next
Call rand_num
End Sub
Sub MergeRight()
For loop_num2 = 1 To 3
For loop_num = 1 To 7 Step 2
If Cells(loop_num + 1, "B") = True Then
Cells(loop_num, "B") = Cells(loop_num, "A")
Cells(loop_num, "A") = 0
End If
If Cells(loop_num + 1, "C") = True Then
Cells(loop_num, "C") = Cells(loop_num, "B")
Cells(loop_num, "B") = 0
End If
If Cells(loop_num + 1, "D") = True Then
Cells(loop_num, "D") = Cells(loop_num, "C")
Cells(loop_num, "C") = 0
End If
Next
Next
For loop_num = 1 To 7 Step 2
If Cells(loop_num, "C") = Cells(loop_num, "D") Then
Cells(loop_num, "D") = Cells(loop_num, "D") + Cells(loop_num, "C")
Cells(9, "C") = Cells(9, "C") + Cells(loop_num, "C")
Cells(loop_num, "C") = 0
End If
If Cells(loop_num, "B") = Cells(loop_num, "C") Then
Cells(loop_num, "C") = Cells(loop_num, "C") + Cells(loop_num, "B")
Cells(9, "C") = Cells(9, "C") + Cells(loop_num, "B")
Cells(loop_num, "B") = 0
End If
If Cells(loop_num, "A") = Cells(loop_num, "B") Then
Cells(loop_num, "B") = Cells(loop_num, "B") + Cells(loop_num, "A")
Cells(9, "C") = Cells(9, "C") + Cells(loop_num, "A")
Cells(loop_num, "A") = 0
End If
Next
For loop_num2 = 1 To 3
For loop_num = 1 To 7 Step 2
If Cells(loop_num + 1, "B") = True Then
Cells(loop_num, "B") = Cells(loop_num, "A")
Cells(loop_num, "A") = 0
End If
If Cells(loop_num + 1, "C") = True Then
Cells(loop_num, "C") = Cells(loop_num, "B")
Cells(loop_num, "B") = 0
End If
If Cells(loop_num + 1, "D") = True Then
Cells(loop_num, "D") = Cells(loop_num, "C")
Cells(loop_num, "C") = 0
End If
Next
Next
Call rand_num
End Sub
Public Sub rand_num()
Dim cell_row(4)
cell_row(1) = 1
cell_row(2) = 3
cell_row(3) = 5
cell_row(4) = 7
Dim rand_number(2)
rand_number(1) = cell_row(Int((4 - 1 + 1) * Rnd + 1))
rand_number(2) = Int((4 - 1 + 1) * Rnd + 1)
While (Cells(rand_number(1) + 1, rand_number(2)) = False)
rand_number(1) = cell_row(Int((4 - 1 + 1) * Rnd + 1))
rand_number(2) = Int((4 - 1 + 1) * Rnd + 1)
Wend
Cells(rand_number(1), rand_number(2)) = Int((2 - 1 + 1) * Rnd + 1)
Randomize [Timer]
End Sub
Sub Clear()
For loop_num = 1 To 4
Cells(1, loop_num) = 0
Cells(3, loop_num) = 0
Cells(5, loop_num) = 0
Cells(7, loop_num) = 0
Next
Cells(9, "C") = 0
Call rand_num
Call rand_num
End Sub
欢迎所有建议。
发布于 2021-03-06 15:46:28
一些快速反馈,因为我认为您可以做一些小的更改,以真正提高您的代码的可读性。如果你决定做其中一些,你可以发布一个新的问题与更新的代码,以获得一些更有针对性的评论.
Dim loop_num Dim loop_num2 Dim rand_number(2)‘等。
尽管没有明确要求,但是VBA中的变量可以有类型,就像在强类型语言(如c++
)中一样。在代码中包括类型有两个好处:
loop_num
是整数,或者rand_num
是浮点,那么我们可以假设它们可能用于什么目的。这使得阅读、维护和改进代码更加容易。所以更喜欢:
Dim loop_num As Long
Dim loop_num2 As Long
Dim rand_number(2) As Single
当我们这样做的时候,这些变量的名字不是很有描述性,是吗?当然,loop_num
告诉我它可能是for-循环中递增的变量,但是我已经通过查看就可以看到这一点了!更好的方法是使用描述性名称,使代码能够自我记录并易于跟踪。我真的不知道所有这些变量是用来做什么的,因为我现在关注的是一般的问题,但是也许是这样的:
Dim worksheetRow As Long
Dim iterationPassNumber As Long
...would更好。
另外,在几个地方,您不声明变量;除了不能声明类型之外,如果不强制执行变量声明,就会允许输入错误( loop_counter
vs loop_cuonter
)。在模块顶部(S)添加Option Explicit
,以强制执行变量声明,并帮助您获取键入的内容。
您的代码包含了许多神奇的数字--字面值并不意味着孤立的任何东西,但在代码中有一些特殊的含义。
Dim cell_row(4)
cell_row(1) = 1 'ok I guess, thanks to a fairly descriptive variable name
cell_row(2) = 3
cell_row(3) = 5
cell_row(4) = 7
Dim rand_number(2) 'um sure, 2 of them why not
rand_number(1) = cell_row(Int((4 - 1 + 1) * Rnd + 1)) 'I'm at a loss... What do these numbers mean?!
rand_number(2) = Int((4 - 1 + 1) * Rnd + 1)
While (Cells(rand_number(1) + 1, rand_number(2)) = False)
rand_number(1) = cell_row(Int((4 - 1 + 1) * Rnd + 1))
rand_number(2) = Int((4 - 1 + 1) * Rnd + 1)
Wend
Cells(rand_number(1), rand_number(2)) = Int((2 - 1 + 1) * Rnd + 1)
想象一下第一次阅读这段代码(就像我现在所做的那样)--您知道这个函数在做什么吗?我看到随机数被放入单元格中,一些循环看起来可能永远不会停止,我不知道这段代码的逻辑应该是什么。我是说
(4-1+ 1)‘* ...
为什么??
添加注释来解释为什么您的代码正在做它正在做的事情,或者更好的是将这些数字重命名为常量:
Const randomNumberScalingFactor As Long = 4 'or 4 + SomeMagicNumber - AnotherMagicNumber
..。然后(例如)
randomColumnIndexInSheet = Int(ColumnCount * Rnd + ColumnOffset))
不要重复自己;MergeUp/Down
和MergeLeft/Right
包含很多重复,但是A,B,C,D
的组合略有不同。最好将这些参数作为单个Sub的参数,这样您就可以重用代码来执行多项任务。
例如:
对于loop_num2 =1至3的loop_num =1至7步骤2,如果单元格(loop_num+ 1,"B") = True然后单元格(loop_num,"B") =单元格(loop_num,"A")单元格(loop_num,"A") =0如果单元格(loop_num+ 1,"C") = True然后单元格(loop_num,"C") =单元格(loop_num,"B")单元(loop_num,"B") =0如果单元格(loop_num+ 1,"D") = True然后单元格(loop_num,"D") =单元格(loop_num,"C")单元(loop_num,"C") =0如果loop_num2 =1至3表示loop_num =1至7步骤2如果单元格(loop_num+ 1,"C") = True然后单元格(loop_num,"C") =单元格(loop_num,"D")单元格(loop_num,"D") =0如果单元格(loop_num+ 1,“B”=真然后单元格(loop_num,"B") =单元格(loop_num,"C")单元(loop_num,"C") =0如果单元格(loop_num+ 1,"A") = True然后单元格(loop_num,"A") =单元格(loop_num,"B")单元格(loop_num,( "B") =0结尾,如果下一个
可能会变成这样:
Sub MoveSidewaysWithMapping(ByVal first As String, ByVal second As String, ByVal third As String, ByVal fourth As String)
'[...]
For loop_num2 = 1 To 3
For loop_num = 1 To 7 Step 2
If Cells(loop_num + 1, third) = True Then
Cells(loop_num, third) = Cells(loop_num, fourth)
Cells(loop_num, fourth) = 0
End If
If Cells(loop_num + 1, second) = True Then
Cells(loop_num, second) = Cells(loop_num, third)
Cells(loop_num, third) = 0
End If
If Cells(loop_num + 1, first) = True Then
Cells(loop_num, first) = Cells(loop_num, second)
Cells(loop_num, second) = 0
End If
Next
Next
'etc...
叫像
'move left:
MoveSidewaysWithMapping "A","B","C","D"
'move right
MoveSidewaysWithMapping "D","C","B","A"
你知道这个主意(p.s。Call
关键字就像在Call rand_num
中一样过时了,您不再需要它了,消除IMO是很好的,因为它会让您的大脑处理过多的杂乱。
重复使用代码是很有价值的,因为它意味着如果您更改了逻辑,您只需要在一个地方更改它,从而减少错误的发生。此外,需要处理的代码减少可能会使代码更容易为审阅者和维护人员解释(在6个月内完成),只要缩短不会降低可读性(在本例中,我认为不会)。
无论如何,这是第一次,如果您希望获得更多关于您的技术和算法的反馈,那么我建议尽可能使用上述一些技术整理您的代码,并发布一个后续问题。
希望这会有所帮助,如果你需要澄清的话,请告诉我(PS,我不确定这其中有多少对你来说是新的,因为我看到你已经在CR上问了很多问题了,这是相当普遍的/基本的建议,但我理解如果你只是在尝试一种新的语言,你可以花大部分时间尝试工作,而忘记一些重要的文体基础!)
发布于 2021-03-27 19:03:30
应该使用辅助变量和单元格来更好地描述我们的代码。单元格公式使过程复杂化。它们迫使您处理合并和合并,而不是向左合并和向右合并。使用一个简单的4x4矩阵代替。
使用4x4矩阵将允许您将数据加载到数组中,在内存中处理数据,并覆盖原始数据。这不仅更有效,而且将数据模型与数据视图分离开来。无论游戏板是从单元格A1还是从Z100开始,您都可以应用相同的逻辑。
将单元格引用限定为工作表是一种最佳做法。这使得调试和重用代码变得更加容易。
下面是如何设置硼砂来使用一个4x4矩阵:
Private Const GameSheetName As String = "2048"
Private Const TopLeftCellAddress As String = "A1"
Private Const ColumnCount As Long = 4
Private Const RowCount As Long = 4
Function GameSheet() As Worksheet
Set GameBoard = ThisWorkbook.Worksheets(GameSheetName)
End Function
Function GameBoard() As Range
Set GameBoard = GameSheet.Range(TopLeftCellAddress).Resize(RowCount, ColumnCount)
End Function
Function Scrore() As Range
Set GameBoard = GameBoard.Offset(RowCount, ColumnCount).Offset(2, 3)
End Function
我可能遗漏了一些东西,但循环不应该减少1,以便可以移动下一个值并可能合并吗?
正如Greedo正确声明的那样,您应该尝试避免重复代码。我建议将枚举值传递到主子例程中,并让它处理数据。
在这个主要过程中,我将有两个嵌套循环。枚举将用于确定循环的开始值、结束值和步骤值。
Private Enum MergeDirection
Left
Right
Up
Down
End Enum
Sub MergeTiles(Direction As MergeDirection)
Dim Data As Variant
Data = GameBoard.Value
Dim a As Long, b As Long
Rem Loop Logic
GameBoard.Value = Data
End Sub
https://codereview.stackexchange.com/questions/256784
复制相似问题