 

(1)多次元配列の考え方
旧来のC言語,C++では,
配列を要素とする配列を多次元配列としており,たとえば,
int A[4][30];
A[3][2] = 87;
と記述することになっていますが,
C#では,他の多くの言語と同様,以下のように自然な表現となっています。
int[,] A = new int[4,30];
A[3,2] = 87;

図2−7 2次元配列
  
(2)数値地図
2次元配列の代表例として,XYのメッシュ番号をインデックスとし
標高値を要素値とする数値地図を挙げることができます。
例えば,以下のようにXY座標をメッシュで分割し,
各マス目に標高値が入るようなデータです。

図2−8 メッシュデータのイメージ
有名な国土地理院の50mメッシュ数値地図は,
約50m(正確には緯度経度で異なる)メッシュの
縦200×横200のマス目に標高値×10の整数値が入っています。
ファイルの形式は提供されているCDに付属する説明書に委ねますが,
大まかにいうと,先頭1行がタイトル及び制御データ,
2行目以降に番号と5桁刻みの標高値が入っています。
順序は,南西から東方向に200個のデータが並び,
これが北方向に並びます。
図2−9 国土地理院50mメッシュ数値地図のデータの順序
国土地理院の数値地図(MEM)ファイルを読み込んで,
色地図として画面に表示するプログラムをProgram
2-12に示します。
プログラムでは,ビットマップ型の変数に描画しておき,
それを描画用オーバライドOnPaintで描画します(注)。
なお,先頭レコードのタイトル,制御データ,
2行目以降の先頭レコード番号等は無視し,
表示に必要な標高データのみ使用しています。
(注)
Onpaintで描画しないと,画面切替え等のタイミングで
フォームの再描画は行われません。
[Program 2−12] 数値地図データの読み込みと色地図表示
コントロールとしてはbutton1(Text:数値地図読込み)と
openFileDialog1を貼り付けます。
(以下は,実行例です)
private double [,] pbJR=new double[201,201];
private string pbA;
private Bitmap image;
// 描画用オーバライド
protected override void OnPaint(PaintEventArgs
e)
{
base.OnPaint(e); e.Graphics.DrawImage(image,0,0);
}
private void 描画()
{
double MX=標高最大(); double MN=標高最小();
double DX=(MX-MN)/255; if(DX<0.000001)
DX=255;
Graphics g=Graphics.FromImage(image);
for(int i=1; i<=200; i++)
for(int j=1; j<=200; j++)
{
int C=(int)((pbJR[201-j,i]-MN)/DX);
Brush brush = new SolidBrush(Color.FromArgb(C,C,C));
g.FillRectangle(brush,j-1,i-1,1,1);
}
}
private double 標高最大( )
{
double MX=pbJR[1,1];
for(int i=1;i<=200;i++)
for(int j=1;j<=200;j++)
if(MX<pbJR[i,j])
MX=pbJR[i,j];
return MX;
}
private double 標高最小( )
{
double MN=pbJR[1,1];
for(int i=1;i<=200;i++)
for(int j=1;j<=200;j++)
if(MN>pbJR[i,j])
MN=pbJR[i,j];
return MN;
}
private void openFileDialog1_FileOk(object
sender,
System.ComponentModel.CancelEventArgs
e)
{
StreamReader DTS;
int ii, pbII;
string FName=openFileDialog1.FileName;
if(FName == "")
return;
DTS=new StreamReader(FName,System.Text.Encoding.Default);
pbA=DTS.ReadLine(); // 制御データの無視
pbII=0;string DT=DTS.ReadLine(); // 1行読込み
while(DT !=null)
{
ii = 5; pbII=pbII+1;
for(int j=1;j<=200;j++) // 5桁ずつ区切って西→東にデータを設定
{
ii = ii + 5;
pbJR[pbII, j] = int.Parse(midStr(DT,
ii, 5));
}
DT=DTS.ReadLine(); // 1行読込み
}
DTS.Close();描画();
this.Invalidate(); // OnPaintを強制的に引き起こす
}
private string midStr(string DT, int ist,int
N)
{
string S="";int
k=ist-1;
for(int i=1 ;i<=N;i++){S
= S + DT[k];
k=k+1;}
return S;
}
private void button1_Click(object
sender,
System.EventArgs e)
{
openFileDialog1.ShowDialog();
}
private void Form1_Load(object
sender, System.EventArgs
e)
{
image =new Bitmap(200,200);
}
|
  
(3)経過日数
多次元配列は,何らかの条件で値が異なるような
表データとして用いられることも多くあります。
ここで示す例は,うるう年と通常年のときの
月の日数の違いを表で表した例です。
[Program 2−13] 経過日数

private int[,] 月日数= new int[,]
{ {31,28,31,30,31,30,31,31,30,31,30,31},
{31,29,31,30,31,30,31,31,30,31,30,31},
};
private int うるう年判定(int
Y)
{
return (Y % 4 ==0 && Y % 100
!=0 || Y % 400 ==0)? 1:0;
}
private int 経過日数(int Y, int M, int D)
{
int i; int 日数=D;
int K= うるう年判定(Y);
for (i=1; i<M; i++) 日数 += 月日数[K,i-1];
return 日数;
}
private void button1_Click(object sender,
System.EventArgs e)
{
int Y=int.Parse(textBox1.Text);
int M=int.Parse(textBox2.Text);
int D=int.Parse(textBox3.Text);
label4.Text=経過日数(Y,M,D).ToString();
}
|
  
1. 基本的なアルゴリズム
2. 基本的なデータ構造
3. 操作を伴うデータ構造
4. 探索
5. 再帰的アルゴリズム
6. ソート
7. 集合
8. 文字列処理
9. 色々なアルゴリズム

上のタイトルをクリックします
|