首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >用Excel实现2048游戏

用Excel实现2048游戏
EN

Code Review用户
提问于 2021-03-05 23:51:01
回答 2查看 756关注 0票数 4

我正在尝试在Excel中实现游戏2048

第2、4、6和8行中的每个真/假布尔值用于确定第1、3、5和7行中每个单元格的数据是否为0。

实验实现

代码语言:javascript
运行
复制
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
代码语言:javascript
运行
复制
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
代码语言:javascript
运行
复制
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
代码语言:javascript
运行
复制
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
代码语言:javascript
运行
复制
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
代码语言:javascript
运行
复制
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

欢迎所有建议。

EN

回答 2

Code Review用户

回答已采纳

发布于 2021-03-06 15:46:28

一些快速反馈,因为我认为您可以做一些小的更改,以真正提高您的代码的可读性。如果你决定做其中一些,你可以发布一个新的问题与更新的代码,以获得一些更有针对性的评论.

变量

Dim loop_num Dim loop_num2 Dim rand_number(2)‘等。

尽管没有明确要求,但是VBA中的变量可以有类型,就像在强类型语言(如c++ )中一样。在代码中包括类型有两个好处:

  • 提高性能,因为类型化变量工作速度更快,占用的内存更少。
  • 也许更重要的是,它有助于记录代码;如果我们知道loop_num是整数,或者rand_num是浮点,那么我们可以假设它们可能用于什么目的。这使得阅读、维护和改进代码更加容易。

所以更喜欢:

代码语言:javascript
运行
复制
Dim loop_num As Long
Dim loop_num2 As Long
Dim rand_number(2) As Single

当我们这样做的时候,这些变量的名字不是很有描述性,是吗?当然,loop_num告诉我它可能是for-循环中递增的变量,但是我已经通过查看就可以看到这一点了!更好的方法是使用描述性名称,使代码能够自我记录并易于跟踪。我真的不知道所有这些变量是用来做什么的,因为我现在关注的是一般的问题,但是也许是这样的:

代码语言:javascript
运行
复制
Dim worksheetRow As Long
Dim iterationPassNumber As Long

...would更好。

另外,在几个地方,您不声明变量;除了不能声明类型之外,如果不强制执行变量声明,就会允许输入错误( loop_counter vs loop_cuonter )。在模块顶部(S)添加Option Explicit,以强制执行变量声明,并帮助您获取键入的内容。

幻数

您的代码包含了许多神奇的数字--字面值并不意味着孤立的任何东西,但在代码中有一些特殊的含义。

代码语言:javascript
运行
复制
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)‘* ...

为什么??

添加注释来解释为什么您的代码正在做它正在做的事情,或者更好的是将这些数字重命名为常量:

代码语言:javascript
运行
复制
Const randomNumberScalingFactor As Long = 4 'or 4 + SomeMagicNumber - AnotherMagicNumber

..。然后(例如)

代码语言:javascript
运行
复制
randomColumnIndexInSheet = Int(ColumnCount * Rnd + ColumnOffset))

干法

不要重复自己;MergeUp/DownMergeLeft/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结尾,如果下一个

可能会变成这样:

代码语言:javascript
运行
复制
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...

叫像

代码语言:javascript
运行
复制
'move left:
 MoveSidewaysWithMapping "A","B","C","D"

'move right
 MoveSidewaysWithMapping "D","C","B","A"

你知道这个主意(p.s。Call关键字就像在Call rand_num中一样过时了,您不再需要它了,消除IMO是很好的,因为它会让您的大脑处理过多的杂乱。

重复使用代码是很有价值的,因为它意味着如果您更改了逻辑,您只需要在一个地方更改它,从而减少错误的发生。此外,需要处理的代码减少可能会使代码更容易为审阅者和维护人员解释(在6个月内完成),只要缩短不会降低可读性(在本例中,我认为不会)。

无论如何,这是第一次,如果您希望获得更多关于您的技术和算法的反馈,那么我建议尽可能使用上述一些技术整理您的代码,并发布一个后续问题。

希望这会有所帮助,如果你需要澄清的话,请告诉我(PS,我不确定这其中有多少对你来说是新的,因为我看到你已经在CR上问了很多问题了,这是相当普遍的/基本的建议,但我理解如果你只是在尝试一种新的语言,你可以花大部分时间尝试工作,而忘记一些重要的文体基础!)

票数 5
EN

Code Review用户

发布于 2021-03-27 19:03:30

辅助变量和单元格

应该使用辅助变量和单元格来更好地描述我们的代码。单元格公式使过程复杂化。它们迫使您处理合并和合并,而不是向左合并和向右合并。使用一个简单的4x4矩阵代替。

使用4x4矩阵将允许您将数据加载到数组中,在内存中处理数据,并覆盖原始数据。这不仅更有效,而且将数据模型与数据视图分离开来。无论游戏板是从单元格A1还是从Z100开始,您都可以应用相同的逻辑。

使用完全限定引用

将单元格引用限定为工作表是一种最佳做法。这使得调试和重用代码变得更加容易。

下面是如何设置硼砂来使用一个4x4矩阵:

代码语言:javascript
运行
复制
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正确声明的那样,您应该尝试避免重复代码。我建议将枚举值传递到主子例程中,并让它处理数据。

在这个主要过程中,我将有两个嵌套循环。枚举将用于确定循环的开始值、结束值和步骤值。

代码语言:javascript
运行
复制
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
票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/256784

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档