第4講 If文の学習
第14話 児玉さんの順位付け
ソース例
Public Class Form1

   Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

     '変数の宣言
     Dim i As Integer, j As Integer

     '45行追加
     For i = 1 To 45
       DataGridView1.Rows.Add()
     Next

     '1行目に列見出しを入れる。
     DataGridView1(0, 0).Value = "番号 "
     DataGridView1(1, 0).Value = "国語 "
     DataGridView1(2, 0).Value = "社会 "
     DataGridView1(3, 0).Value = "数学 "
     DataGridView1(4, 0).Value = "理科 "
     DataGridView1(5, 0).Value = "英語 "
     DataGridView1(6, 0).Value = "合計 "
     DataGridView1(7, 0).Value = "平均 "
     DataGridView1(8, 0).Value = "最高点"
     DataGridView1(9, 0).Value = "最低点"
     DataGridView1(10, 0).Value = "合否 "
     DataGridView1(11, 0).Value = "講評 "

     '41行から44行 行見出し
     DataGridView1(0, 41).Value = "合計 "
     DataGridView1(0, 42).Value = "平均 "
     DataGridView1(0, 43).Value = "最高点"
     DataGridView1(0, 44).Value = "最低点"


     '出席番号とランダムデータの発生
     For i = 1 To 40
       DataGridView1(0, i).Value = i
       For j = 1 To 5
         DataGridView1(j, i).Value = Int(101 * Rnd())
       Next
     Next

     '各生徒の5教科合計・平均・合否・講評の算出と表示
     For i = 1 To 40
       '合計・平均の算出
       w = 0
       For j = 1 To 5
         w = w + DataGridView1(j, i).Value
       Next
       '合計・平均の表示
       DataGridView1(6, i).Value = w
       DataGridView1(7, i).Value = w / 5
       '合否の表示
       If w >= 250 Then
         DataGridView1(10, i).Value = "合格"
       Else
         DataGridView1(10, i).Value = "不合格"
       End If
       '講評の表示
       If w >= 350 Then
         DataGridView1(11, i).Value = "上位合格です。"
       Else
         If w >= 280 Then
           DataGridView1(11, i).Value = "余裕で合格です。"
         Else
           If w >= 250 Then
             DataGridView1(11, i).Value = "ぎりぎり合格です。"
           Else
             If w >= 230 Then
                DataGridView1(11, i).Value = "合格まで後一歩。"
             Else
                DataGridView1(11, i).Value = "よく勉強して再挑戦!"
             End If
           End If
         End If
       End If
     Next

     '教科合計・平均の算出と表示
     For i = 1 To 5
       '合計・平均の算出
       w = 0
       For j = 1 To 40
         w = w + DataGridView1(i, j).Value
       Next
       '合計・平均の表示
       DataGridView1(i, 41).Value = w
       DataGridView1(i, 42).Value = w / 40
     Next

      '各生徒の最高点・最低点の算出と表示
     Dim max As Integer, min As Integer
     For i = 1 To 40
       max = 0
       min = 100
       For j = 1 To 5
         If DataGridView1(j, i).Value > max Then max = DataGridView1(j, i).Value
         If DataGridView1(j, i).Value < min Then min = DataGridView1(j, i).Value
       Next
       DataGridView1(8, i).Value = max
       DataGridView1(9, i).Value = min
     Next

     '各教科の最高点と最低点の算出と表示
     For i = 1 To 5
       max = 0
       min = 100
       For j = 1 To 40
         If DataGridView1(i, j).Value > max Then max = DataGridView1(i, j).Value
         If DataGridView1(i, j).Value < min Then min = DataGridView1(i, j).Value
       Next
       DataGridView1(i, 43).Value = max
       DataGridView1(i, 44).Value = min
     Next

    '順位
    Dim jun As Integer, k As Integer
    For j = 7 To 46
      jun = 40 '仮の順位
      For k = 7 To 46
        If j <> k Then
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
            jun = jun - 1
          End If
        End If
      Next
      DataGridView1(j, 12).Value = jun
    Next

   End Sub

End Class
実行例
入門
初心者基礎
(合計と順位だけを抜き出した。)

解説
私が考えた順位付けは
      '並び替え
     Dim w1 As String, bn As Integer
     For i = 40 To 2 Step -1
       min = 500
       For j = 1 To i
         If DataGridView1(6, j).Value <= min Then
           min = DataGridView1(6, j).Value
           bn = j
         End If
       Next
       For j = 0 To 12
         w1 = DataGridView1(j, bn).Value
         DataGridView1(j, bn).Value = DataGridView1(j, i).Value
         DataGridView1(j, i).Value = w1
       Next
     Next

     '順位付け
     For i = 1 To 40
       DataGridView1(11, i).Value = i
     Next
     For i = 2 To 40
       If DataGridView1(6, i - 1).Value = DataGridView1(6, i).Value Then DataGridView1(11, i).Value = DataGridView1(11, i - 1).Value
     Next

     '出席番号順並び替え
     For i = 40 To 2 Step -1
       max = 0
       For j = 1 To i
         If DataGridView1(0, j).Value > max Then
           max = DataGridView1(0, j).Value
           bn = j
         End If
       Next
       For j = 0 To 12
         w1 = DataGridView1(j, bn).Value
         DataGridView1(j, bn).Value = DataGridView1(j, i).Value
         DataGridView1(j, i).Value = w1
       Next
     Next
と長ったらしいコードになるのに対して、児玉さんの方式だと
    '順位
    Dim jun As Integer, k As Integer
    For j = 7 To 46
      jun = 40
      For k = 7 To 46
        If j <> k Then
          If DataGridView1(j, 7).Value >
= DataGridView1(k, 7).Value Then
            jun = jun - 1
          End If
        End If
      Next
      DataGridView1(j, 12).Value = jun
    Next

ですんでしまいます。
明らかに、児玉さんの方法の方が優れています。
私のやり方は、
並び替え→順位付け→同点者の処理→再び並び替え
という迂路を経てはじめて順位付けができるのに対して、
ストレートに順位付けをしています。
児玉さんの方ではストレートにできているだけでなく、
同点者の処理が必要ありません。
40人について、同じ条件でランク付けをしているので、
同点なら必然的に同じ順位になるからです。

データ数が40だと多すぎですから、
データ数を5として、
28,32,19,32,58
でトレースしてみましょう。
この場合コードは
    '順位
    Dim jun As Integer, k As Integer
    For j = 7 To 11
      jun = 5
      For k = 7 To 11
        If j <> k Then
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
            jun = jun - 1
          End If
        End If
      Next
      DataGridView1(j, 12).Value = jun
    Next

となります。
        If j <> k Then
がありますから、各データは自分以外のデータと比較されます。
つまり、
(28,32,19,32,58)
28は、32,19,32,58と
32は、28,19,32,58と
19は、28,32,32,58と
32は、28,32,19,58と
58は、28,32,19,32と比較されるわけです。
順に追っていきましょう。
j = 7 場合
 k = 7 のときは
        
If 7 <> k Then
  から比較されません。
 k = 8 のときは
 (28,32,19,32,58)
        
If 7 <> k Then
  が満たされ28は32と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たしませんから、
            jun = jun - 1

  は実行されずに、jyu = 5
  のままです。
 k = 9 のときは
 (28,32,19,32,58)
        
If 7 <> k Then
  が満たされ28は19と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たしますから、
            jun = jun - 1

  は実行され、jun = 4
  となります。

 k = 10 のときは
 (28,32,19,32,58)
        
If 7 <> k Then
  が満たされ28は32と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たしませんから、
            jun = jun - 1

  は実行されずに、jun = 4
  のままです。

 k = 11 のときは
 (28,32,19,32,58)
        
If 7 <> k Then
  が満たされ28は58と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たしませんから、
            jun = jun - 1

  は実行されずに、jun = 4
  のままです。
 以上を通して、28の順位4位が確定します。
 (28(4),32(2),19(5),32(2),58(1) 

 順位は上の通りですから、正しい順位付けができています。

j = 8 場合
 k = 7 のときは
        
If 8 <> k Then

  (28,32,19,32,58)
        
If 8 <> k Then
  が満たされ32は28と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たしますから、

            jun = jun - 1

  は実行され、jun = 4
  となります。
 k = 8 のときは
 (28,32,19,32,58)
        
If 8 <> k Then
  は満たしませんから比較がされません。

 k = 9 のときは
 (28,32,19,32,58)
        
If 7 <> k Then
  が満たされ32は19と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たし、
            jun = jun - 1

  は実行され、jun = 3
  となります。

 k = 10 のときは
 (28,32,19,32,58)
        
If 8 <> k Then
  が満たされ32は32と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たし、
            jun = jun - 1

  が実行され、jun = 2
  となります。

 k = 11 のときは
 (28,32,19,32,58)
        
If 8 <> k Then
  が満たされ38は58と比較されます。
          If DataGridView1(j, 7).Value >= DataGridView1(k, 7).Value Then
  を満たしませんから、
            jun = jun - 1

  は実行されずに、jun = 2
  のままです。
 以上を通して、32の順位2位が確定します。
 (28(4),32(2),19(5),32(2),58(1) 

 今回も正しい順位付けになっています。

煩雑になりますので、トレースは以上にしますが、
皆さんはトレースを続けて、
児玉さんのコードで正しく順位付けができることを確認してください。
ポイントを繰り返しておきますが、
すべてのデータについて、同じ条件でランク付けをしているので、
同点なら同じ順位になるということです。


児玉さんは、学生時代にこそ卒論でFORTRANを学んでいましたが、
その後50年もプログラムには触れておらず、
ほとんど初学者に使い状態から、
VB・VBA・Javascript等を勉強されているということです。
登山際の登りと下りにかかる時間を予想する現在のソフトが、
下りにおいて精度にかけているので、
より精度の高いソフトの開発を目指されているそうです。
とても素晴らしいことだと思います。



第13話へ 第5講第1話へ

006

VC++講義第1部へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual C++入門基礎講座

数学研究室に戻る