最終講 卒業研究と卒業試験
第2話 課題1 順列を2次元に並べる
課題1は前に作った順列作成ソフトを少し改良すれば出来ます。
9次順列を2次元に並べるだけです。
セルの内容 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
セル番号 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
1 | 2 | 3 |
0 | 1 | 2 |
4 | 5 | 6 |
3 | 4 | 5 |
7 | 8 | 9 |
6 | 7 | 8 |
下のコーティングのgはセル番号に対応しています。
順列のときと同じでセルのラベル(すなわちセル番号)であるgとセルに入っている数字(セルの内容)を区別しないと訳がわからなくなります。
ビール瓶で例えれば、『一番搾り』がラベルで、内容が『ビール』でしたね。
セル番号(セルのラベル)と内容(1から9までの行列を構成する数字)を明確に区別して下さい。
上図の右側のiはfor(i=0;i<9;i++)のiに対応し、gはSub f(ByVal g As Integer)のgです。
このgは0から8へと進んでいきます。
1 | 2 | 3 |
0 | 1 | 2 |
4 | 5 | 6 |
3 | 4 | 5 |
7 | 8 | 9 |
6 | 7 | 8 |
次のコーティング例は、この課題だけとしては少し難しいかもしれませんが、
最終的には数独(ナンバープレイス)解答作成が目的ですから、
それとの関連を考えてのことです。
コーティング例
Public Class Form1
'変数の宣言と初期化
Dim a(3, 3) As Integer, x(9) As Integer, y(9) As Integer, s As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
s = 0
DataGridView1.Rows.Clear()
h()
f(0)
DataGridView1.Rows.Add() '1行追加
'見出し表示
DataGridView1(6, 4 * s).Value() = "順"
DataGridView1(7, 4 * s).Value() = "列"
DataGridView1(8, 4 * s).Value() = "方"
DataGridView1(9, 4 * s).Value() = "陣"
DataGridView1(10, 4 * s).Value() = "総"
DataGridView1(11, 4 * s).Value() = "数"
'総数表示
DataGridView1(12, 4 * s).Value() = s
End Sub
Sub h()
For i = 0 To 8
x(i) = i Mod 3
y(i) = Int(i / 3)
Next
End Sub
Sub f(ByVal g As Integer)
If s = 100 Then Exit Sub '計算時間が膨大なので100個で止めている。
Dim h As Integer
For i = 0 To 8
a(y(g), x(g)) = i + 1
h = 1
If g > 0 Then
For j = 0 To g - 1
If a(y(j), x(j)) = a(y(g), x(g)) Then
h = 0
Exit For
End If
Next
End If
If h = 1 Then
If g + 1 < 9 Then
f(g + 1)
Else
For j = 0 To 2
DataGridView1.Rows.Add() '1行追加
For k = 0 To 2
DataGridView1(k, j + 4 * s).Value = a(j, k)
Next
Next
DataGridView1.Rows.Add() '1行追加
s = s + 1 '総数カウント
If s = 100 Then Exit Sub '計算時間が膨大なので100個で止めている。
End If
End If
Next
End Sub
End Class
実行例
解説
Sub h()
For i = 0 To 8
x(i) = i Mod 3
y(i) = Int(i / 3)
Next
End Sub
では座標を計算しています。1次元のデータを2次元に対応させるためのものです。
x(0)=0,x(1)=1,x(2)=2
x(3)=0,x(4)=1,x{5)=2
x(6)=0,x(7)=1,x{8)=2
y(0)=0,y(1)=0,y(2)=0
y(3)=1,y(4)=1,y(5)=1
y(6)=2,y(7)=2,y(8)=3
と対応します。これを使えば1次元データを2次元に配置することが出来るのです。
尚、色対応でお分かりかと思いますが、ここでのiは、Sub f(ByVal g As Integer)のgに対応します。
gはセル番号=セルのラベルです。
今回のプログラミンで眼目部分は、Sub f(ByVal g As Integer)です。
これが自己再帰型で使われています。
If s = 100 Then Exit Sub を入れた理由は、すべて計算させるには時間がかかりすぎますので、
100個目で止めるためです。
If h = 1 Then
If g + 1 < 9 Then
f(g + 1)
Else
For j = 0 To 2
DataGridView1.Rows.Add() '1行追加
For k = 0 To 2
DataGridView1(k, j + 4 * s).Value = a(j, k)
Next
Next
DataGridView1.Rows.Add() '1行追加
s = s + 1 '総数カウント
If s = 100 Then Exit Sub '計算時間が膨大なので100個で止めている。
End If
End If
では、例えば、g=5のときは
1 | 2 | 3 |
4 | 5 | 1 |
* | * | * |
1と他が比べられます。同じものがあるときは、
h=0とすることによって強制的に
If h = 1 Then
If g + 1 < 9 Then
f(g + 1)
Else
For j = 0 To 2
DataGridView1.Rows.Add() '1行追加
For k = 0 To 2
DataGridView1(k, j + 4 * s).Value = a(j, k)
Next
Next
DataGridView1.Rows.Add() '1行追加
s = s + 1 '総数カウント
If s = 100 Then Exit Sub '計算時間が膨大なので100個で止めている。
End If
End If
をスルーさせています。そして、ループが進み
1 | 2 | 3 |
4 | 5 | 6 |
* | * | * |
と問題をクリアさせています。
If g + 1 < 9 Then
f(g + 1)
の部分はg+1が8までしか進められません。
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
セル番号は右図をご覧なればお分かりのように8までしかないからです。
大事な点を繰り返します。
順列のときと同じでセルのラベル(すなわちセル番号)であるgとセルに入っている数字(セルの内容)を明確に区別して下さい。
上図の右側のiはFor i = 0 To 8のiに対応し、gはSub f(ByVal g As Integer)のgです。
0 | 1 | 2 |
3 | 4 | 5 |
6 | 7 | 8 |
セル番号は8でしかありませんので、
g+1が9のときは、
Else
For j = 0 To 2
DataGridView1.Rows.Add() '1行追加
For k = 0 To 2
DataGridView1(k, j + 4 * s).Value = a(j, k)
Next
Next
DataGridView1.Rows.Add() '1行追加
s = s + 1 '総数カウント
If s = 100 Then Exit Sub '計算時間が膨大なので100個で止めている。
End If
が実行されて、出来た方陣がDataGridViewに表示されます。
ここで課題です。現在
と使われない部分が多いので
実行結果が
となるように変更するにはどうしたらよいでしょうか。
VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座
数学研究室に戻る