0
Sub FWP()

Dim i As Integer
Dim j As Integer
Dim n As Integer
n = Range("A1").Value

For i = 1 To n
  For j = 1 To n

    If Cells(i + 1, j) = 0 Then
        Cells(i + 1, j).Value = Int(((n ^ 2) - 1 + 1) * Rnd + 1)
    ElseIf Cells(i + 1, j) <> 0 Then
        Cells(i + 1, j).Value = Cells(i + 1, j).Value
    End If
  Next j
Next i

我正在尝试做一个家庭作业问题的一部分,该问题要求在VBA的幻方中填写缺失的空格。它被设置为一个(n x n)包含 n^2 个数字的矩阵;我需要填充的空间由矩阵中的零表示。到目前为止,我有一些代码会检查每个单独的单元格值,如果不为 0,则将单独保留这些值,如果值为 0,它将用 1 和 n^2 之间的随机数替换它们。问题是显然我得到了一些重复的值,这是不允许的,每个数字必须只有 1 个。

如何对其进行编码,以便网格中不会出现重复的数字?我正在尝试添加检查功能以查看它们是否已经在网格中,但不知道该怎么做

谢谢

4

2 回答 2

1

您可以采取很多方法,但@CMArg 说数组或字典是确保您没有重复项的好方法是正确的。

您要避免的是每个单元格填充时间逐渐延长的情况。对于非常小的正方形(例如 10x10)来说这不是问题,但是非常大的正方形会变得丑陋。(如果您的范围是 1-100,并且除了 31 之外的所有数字都已经在表中,那么平均需要很长时间 - 100 次猜测,对吧? - 拉出一个未使用的数字。如果范围是 1 -40000 (200x200),需要 40000 次猜测才能填充最后一个单元格。)

因此,与其保留已使用的数字列表,不如考虑如何有效地检查并“划掉”已使用的数字,以便每个新单元格准确地填充 1 个“猜测”。

这是您可以实现它的一种方法:

类:SingleRandoms

Option Explicit

Private mUnusedValues As Scripting.Dictionary
Private mUsedValues As Scripting.Dictionary

Private Sub Class_Initialize()
  Set mUnusedValues = New Scripting.Dictionary
  Set mUsedValues = New Scripting.Dictionary
End Sub

Public Sub GenerateRange(minimumNumber As Long, maximumNumber As Long)
  Dim i As Long
  With mUnusedValues
    .RemoveAll
    For i = minimumNumber To maximumNumber
      .Add i, i
    Next
  End With
End Sub

Public Function GetRandom() As Long
  Dim i As Long, keyID As Long
  Randomize timer
  With mUnusedValues
    i = .Count
    keyID = Int(Rnd * i)
    GetRandom = .Keys(keyID)
    .Remove GetRandom
  End With
  mUsedValues.Add GetRandom, GetRandom
End Function

Public Property Get AvailableValues() As Scripting.Dictionary
  Set AvailableValues = mUnusedValues
End Property

Public Property Get UsedValues() As Scripting.Dictionary
  Set UsedValues = mUsedValues
End Property

实际使用的类示例:

Public Sub getRandoms()
Dim r As SingleRandoms
Set r = New SingleRandoms
With r
  .GenerateRange 1, 100
  Do Until .AvailableValues.Count = 0
    Debug.Print .GetRandom()
  Loop
End With
End Sub

使用集合实际上比使用字典更节省内存和更快,但是字典更容易验证它正在做它应该做的事情(因为你可以使用.Exists等)。

于 2016-04-22T15:01:03.453 回答
0

没有人会为你做功课。你只会欺骗自己。如果他们这样做,他们会感到羞耻。

我不确定你的老师有多挑剔,但有很多方法可以解决这个问题。

您可以将矩阵的值放入数组中。检查是否存在零值元素,如果不存在,则中断。然后获取您潜在的随机数进行插入。使用 for 循环遍历数组,检查该值的每个元素。如果不存在,请更换零元素。

于 2016-04-22T14:47:30.793 回答