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 を除くすべての数字が既にテーブルにある場合、未使用の数字を 1 つ取得するには、平均で 100 回の推測が必要になります。範囲が 1 の場合-40000 (200x200)、最後のセルを埋めるのに 40000 回の推測が必要です。)

したがって、すでに使用されている数字のリストを保持する代わりに、どのように効果的に調べて、既に使用されている数字を「クロスオフ」し、新しいセルごとに正確に 1 つの「推測」でデータを入力できるかを考えてください。

これを実装する方法の 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 に答える