第17講 関数の再帰的呼び出しによる3次・4次魔方陣ソフトの改良
第8話 ソフトに乱数を組み込む

さらに、ソフトを高速化するために乱数を組み込みます。
乱数の組み込むにはプログラム冒頭で、ファイルstdlib.hをインクルードしておく必要があります。
#pragma once
int n;
int a[10][10];
int x[100],y[100];
int s;
namespace My3次・4次魔方陣作成改良版 {
         ・
         ・
         ・
        void f(char g){
          if(s==10)return;
          int i,j,k,h,wa,;
          array<String^>^ w=gcnew array<String^>(16);
          for(i=0;i<n*n;i++){
            a[y[g]][x[g]]=i+1;
              ・
              ・
              ・
          if(h==1){
            if(g<n*n-1){
              f(g+1);
            }
            else{
              for(j=0;j<n;j++){
                for(k=0;k<n;k++){
                  w[k]=(a[j][k]).ToString();
                }
                dataGridView1->Rows->Add(w);
              }
              for(j=0;j<16;j++)w[j]=L"";
              dataGridView1->Rows->Add(w);
              s++;
              if(s==10)return;
            }
          }
             ・
             ・
             ・
を次のように変更しましょう。
#pragma once
#include<stdlib.h>
int n;
int a[10][10];
int x[100],y[100];
int s;
namespace My3次・4次魔方陣作成改良版 {
         ・
         ・
         ・
        void f(char g){
          if(s==100)return;
          int i,j,k,h,wa,kk,kkk;
          array<String^>^ w=gcnew array<String^>(16);
          rand();
          rand();
          kk=rand()%(n*n);

          for(i=0;i<n*n;i++){
            kkk=(kk+i)%(n*n);
            a[y[g]][x[g]]=kkk+1;
              ・
              ・
              ・
          if(h==1){
            if(g<n*n-1){
              f(g+1);
            }
            else{
              for(j=0;j<n;j++){
                for(k=0;k<n;k++){
                  w[k]=(a[j][k]).ToString();
                }
                dataGridView1->Rows->Add(w);
              }
              for(j=0;j<16;j++)w[j]=L"";
              dataGridView1->Rows->Add(w);
              s++;
              if(s==100)return;
            }
          }
             ・
             ・
             ・
ピンクは追加部分、からの変更部分。

私の使用パソコンで乱数を組み込む前は、5次魔方陣では100個作るに203秒かかりましたが、
乱数を組み込むと31秒に圧縮されました。約7倍化に成功しました。

尚、
           rand();
          rand();

は乱数のから打ちです。このから打ちを2回入れると約7倍になりました。
皆さんもから打ちの回数を増やしたり減らしたりして実験してみて下さい。
私はから打ち5回までで実験を打ちきってしまいましが、
もっと速い場合もきっと見つかるでしょう。

kk=rand()%(n*n);kkk=(kk+i)%(n*n);について説明しましょう。
rand()は10万以下ぐらい(正確には知りませんので曖昧な表現になっています。申し訳ありません。)の整数をランダムに発生させるものです。
a%bはaをbで割ったときの余りを求める計算です。(n×n)とは魔方陣のセル数です。
5次魔方陣なら5×5=25です。
つまり、kk=rand()%(n*n);は整数を25で割った余りということになり、25未満の整数をランダムに発生させることになります。

次のkkk=(kk+i)%(n*n);は始まりを0と固定するのではなく、25未満のランダムな整数にするためのものです。
例えば、kk=12であったとすると、kkkは次のように動いていきます。
12,13,14,15,16,17,18,19,20,21,22,23,24,0,1,2,3,4,5,6,7,8,9,10,11
したがって、a[y[g]][x[g]]=kkk+1;は
13,14,15,16,17,18,19,20,21,22,23,24,25,1,2,3,4,5,6,7,8,9,10,11,12
と動いていくことになります。

始まりは変わりますが、結局25通りのすべての場合を網羅していることが分かります。

仕上がりは

のように自然なものになります。
乱数が入っていない場合と比較して下さい。

さて、このような改良を加えても6次魔方陣にはまったく歯が立ちません。
さらなる改良が必要になります。

第17講第7話 第18講第1話へ

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