第6講 If文(分岐)を理解しよう

第11話 1次元のFor文で2次元ループをする方法による列部分の改良

c
1次元のFor文で2次元ループをする方法による改良例
Private Sub CommandButton1_Click()
  Dim w As Byte, i As Byte, h As Byte
 
Dim s As Byte, a As Byte, k As Byte '最初から使うので中程から移動
  h = 1
  w = 0
 
k = Int(6 * (6 * 6 + 1) / 2) '毎回計算させないようにするための変更
 
For i = 0 To 35
    a = i Mod 6
    s = Int(i / 6)
    w = w + Cells(7 + a, 1 + s)
    If a = 5 Then
      If h = 1 Then If w <> k Then h = 0
      Cells(13, 1 + s) = w
      w = 0
    End If
  Next

  w = 0
  For i = 0 To 5
    w = w + Cells(7, 1 + i)
  Next
  If h = 1 Then If w <>
k Then h = 0 '毎回計算させないようにするための変更
       ・
       ・
       ・

 
Dim v As Long, x As Long '毎回計算させないようにするための変更
  v = 1
 
x = CLng(1) * CLng(2) * CLng(3) * CLng(4) * CLng(5) * CLng(6) * CLng(7) * CLng(8) * CLng(9) '毎回計算させないようにするため
  For i = 0 To 8
    v = v * CLng(Cells(7 + i, 9))
  Next
  If v =
x Then Cells(16, 9) = "○" Else Cells(16, 9) = "×" '毎回計算させないようにするための変更
       ・
       ・
       ・
End Sub
Private Sub CommandButton2_Click()
  Range("A13:F16").Select
  Selection.ClearContents
  Range("G7:G12,I16:v19,R7:R15").Select
  Selection.ClearContents
  Range("A1").Select
End Sub

参考ファイル

解説
  Dim s As Byte, a As Byte, k As Byte '最初から使うので中程から移動
1次元のFor文で2次元ループをする方法にするために
aとsを使うので、2行目に移動しました。
中程のものは削除しておかないと、
同じ宣言を2回することになりエラーするので気をつけてください。
 
k = Int(6 * (6 * 6 + 1) / 2) '毎回計算させないようにするための変更

は前回までのものは毎回Int(6 * (6 * 6 + 1) / 2)を計算させていて、
明らかに無駄な計算をさせていましたので導入しました。
数独自動生成ソフト(アプリ)の計算量は膨大ですから、
できるだけ無駄をさせないようにして、
処理速度を上げるように努めなければなりません。
1回だけ計算させ、それを変数に入れておいて再利用するようにしたわけです。
  If h = 1 Then If w <> k Then h = 0 '毎回計算させないようにするための変更
が再利用の部分です。
  If h = 1 Then If w <>
Int(6 * (6 * 6 + 1) / 2) Then h = 0
からの変更です。
以降もすべて変更してあります。
変更は手作業で行ったのではなく、
一括置換で行いました。
  Dim v As Long, x As Long '毎回計算させないようにするための変更
  x = CLng(1) * CLng(2) * CLng(3) * CLng(4) * CLng(5) * CLng(6) * CLng(7) * CLng(8) * CLng(9) '毎回計算させないようにするため
  If v = x Then Cells(16, 9) = "○" Else Cells(16, 9) = "×" '毎回計算させないようにするための変更

についても同様です。
CLng(1) * CLng(2) * CLng(3) * CLng(4) * CLng(5) * CLng(6) * CLng(7) * CLng(8) * CLng(9)
の計算が1回で済むようにしてあります。
さて、
  h = 1
  w = 0
  k = Int(6 * (6 * 6 + 1) / 2) '毎回計算させないようにするための変更
  For i = 0 To 35
    a = i Mod 6
    s = Int(i / 6)
    w = w + Cells(7 + a, 1 + s)
    If a = 5 Then
      If h = 1 Then If w <> k Then h = 0
      Cells(13, 1 + s) = w
      w = 0
    End If
  Next

メインの部分を解説しましょう。
iが0から35までというのは、
36回のループ処理ということです。
最後が35なので35回と勘違いしがちですが、
0から始まっていますので36回なのです。
なぜ36回でしょうか。
1列あたり6行あり、全部で6列あるので
6×6=36
です。
wを0戻すタイミングが問題です。
wを適切なタイミングで0に戻さないと、
すべて積算されていってしまいます。
戻すタイミングは、a = 5のときであり、
しかもCells(13, 1 + s) = wで表示を行った後です。
頭が混乱しますね。
難解ですので、トレースをしてみたいと思いますが、
ファイルがかなり大きくなったので次話で行います。

トレースを読まなくても理解できた方は、
今回の列部分の改良を参考にして、
是非とも行部分の改良に取り込まれてください。



10話へ 第12話へ


トップ

初心者のためのc++ vc++ c言語 入門 基礎から応用までへ
初心者のための excel 2007 2010 2013 vba マクロ 入門 基礎から応用まで
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ
vb講義トップへ
VB講義基礎へ
専門用語なしのC++入門へ
専門用語なしのJava入門へ
専門用語なしのVBA入門

数独のページ
魔方陣のページ
数学研究室に戻る
本サイトトップへ