[1.1] 自分が今行いたい事は何か
個人でのゲーム制作に用いるのを目的としています
複数存在するキャラクターと、マップ上に複数存在するポイントの距離差を、
kyori[j]という二次元配列を用いて、求めました。(iがキャラクター、jがポイントとしています)
次に、其々のキャラクター別に、求めた距離差から、最短距離(最小値)、最長距離(最大値)を、
関数(返り値int型)を用いて算出したいと思いました。
そこで、まずは一次元配列を引数にして、同様に最大値、最小値を求める関数(上記のプレイヤーが単数になったもの)を作りました。
そちらは成功しました、しかし、二次元配列を引数とするとどうも勝手が分かりません。
さまざまなサイトを巡り、情報を収集し、実装可能なレベルで実装しましたが、うまくいかない。
よって、ここでは、二次元配列を引数とし、最小値、あるいは最大値を返す関数を作りたい。
しかし、分からないので(詳細は後記)ご教授願いたい。
というのが質問の主旨となります。
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
実際のプログラムを記述します。
//キャラクター(3人)からマップに存在するポイント(10点)との距離差をキャラクターごとに求め
//その最短距離(最小値)と最長距離(最大値)を返す関数を作成するサンプルソース
#include <stdio.h> //出力用
#include <math.h> //距離差算出用(sqrt,pow)
//マクロ
#define CHARA_MAX 3 //キャラクター数
#define POINT_MAX 10 //ポイント数
#define MIN 0 //最小値
#define MAX 1 //最大値
//関数プロトタイプ宣言
void Init(void); //初期化
//今回問題とする関数--------------------------------------------------------------------------
int MostValue2(int Target[][10], int Rotate1, int Rotate2, int pattern);
//--------------------------------------------------------------------------------------------------
//構造体
typedef struct
{
int x, y;
}CHARA;
CHARA chara[CHARA_MAX]; //キャラクター
CHARA point[POINT_MAX]; //ポイント
//メイン(void main(void)の略でmain() )----------------------------------------------------------------------------
main()
{
//初期化
Init();
//カウント用
int i, j;
//最小値、最大値、それ以外の値を出力する用
int min[CHARA_MAX], max[CHARA_MAX];
//距離差(二次元配列を用いる)
int kyori[CHARA_MAX][POINT_MAX];
//charaとpointの(双方複数存在する)距離差を求めている。---------------------------
for (i = 0; i < CHARA_MAX; i++)
{
for (j = 0; j < POINT_MAX; j++)
{
kyori[i][j] = sqrt(pow((chara[i].x - point[j].x), 2.0) + pow((chara[i].y - point[j].y), 2.0));
}
}
//--------------------------------------------------------------------------------
for (i = 0; i < CHARA_MAX; i++)
{
//最小値をminに入れる
min[i] = MostValue2(kyori, CHARA_MAX, POINT_MAX, MIN);
//最大値をmaxに入れる
max[i] = MostValue2(kyori, CHARA_MAX, POINT_MAX, MAX);
}
//〓結果出力〓---------------------------------------------------------------------
//キャラクター1の場合
printf("%d,%d,%d\n", min[0], max[0]);
//キャラクター2の場合
printf("%d,%d,%d\n", min[1], max[1]);
//キャラクター3の場合
printf("%d,%d,%d\n", min[2], max[2]);
//---------------------------------------------------------------------------------
}
//最小値、最大値を返す関数本体-------------------------------------------------------------------------------------
//◆Target[][] → 算出元、今回の場合,kyori[CHARA_MAX][POINT_MAX]、
//◆Rotate1,2 → 繰り返し回数、今回の場合CHARA_MAX,POINT_MAX
//◆pattern → MINなら最小値、MAXなら最大値、それ以外なら-999を返す(値が返らない可能性があるというエラー防止用)
int MostValue2(int Target[][10], int Rotate1, int Rotate2, int pattern)
{
//カウント用
int i, j;
//最小、最大値算出用。キャラクターごとの最小値を求めたい為、配列にしている。
int min[Rotate1];
int max[Rotate1];
//初期化。始めの配列の添え字(0)と比較していくため、0に初期化している。
for (i = 0; i < Rotate1; i++)
{
min[i] = Target[i][0];
max[i] = Target[i][0];
}
switch (pattern)
{
//最小値を返す
case MIN:
for (i = 0; i < Rotate1; i++)
{
for (j = 0; j < Rotate2; j++)
{
if (Target[i][j] < min[i])
{
min[i] = Target[i][j];
}
}
//ポイントとの比較を終えたら、そのキャラクタの場合の最小値を返す
return min[i];
}
break;
//最大値を返す
case MAX:
for (i = 0; i < Rotate1; i++)
{
for (j = 0; j < Rotate2; j++)
{
if (Target[i][j] > max[i])
{
max[i] = Target[i][j];
}
}
//ポイントとの比較を終えたら、そのキャラクタの場合の最大値を返す
return max[i];
}
break;
//それ以外なら-999を返す
default:
return -999;
}
}
//初期化-----------------------------------------------------------------------------------------------
void Init()
{
int i;
for (i = 0; i < POINT_MAX; i++)
{
chara[i].x = 530 + (i * 30);
chara[i].y = 30;
}
point[0].x = 160;
point[0].y = 250;
point[1].x = 50;
point[1].y = 250;
point[2].x = 160;
point[2].y = 120;
point[3].x = 290;
point[3].y = 80;
point[4].x = 450;
point[4].y = 80;
point[5].x = 290;
point[5].y = 300;
point[6].x = 450;
point[6].y = 300;
point[7].x = 570;
point[7].y = 300;
point[8].x = 570;
point[8].y = 100;
point[9].x = 50;
point[9].y = 420;
point[10].x = 160;
point[10].y = 420;
}
//補足。◆一次元配列の最小値、最大値を返す関数(原文ではコメントアウトしてある)---------------------------------------------
int MostValue(int *Target, int Rotate, int pattern)
{
int i;
int min = Target[0];
int max = Target[0];
switch (pattern)
{
//最小値を返す
case 0:
for (i = 0; i < Rotate; i++)
{
if (Target[i] < min)
{
min = Target[i];
}
}
return min;
break;
//最大値を返す
case 1:
for (i = 0; i < Rotate; i++)
{
if (Target[i] > max)
{
max = Target[i];
}
}
return max;
break;
default:
return -999;
}
}
まず、二次元配列[][]に格納されているデータの最小値、最大値を求めたい為、
関数の引数には当然ながら如何なる数字が入ってもそれに対応した答えを返してきてほしい。
なので17行目、90行目の「10」のように固定された数字は入れたくない。今回はエラー防止のために入れた。
int Rotate2といれてみたが
例)int MostValue2(int Target[][int Rotate2], int Rotate1, int pattern)
]が型の前にありません。などというコンパイルエラーが出る↑
何もいればければ
例)int MostValue2(int Target[][], int Rotate1,int Rotate2, int pattern)
'Target' 添え字がありません。というコンパイルエラーが出る↑
調べてみると、二次元配列の列(横)の添え字は、指定しないといけないとのことだったので
今回) int MostValue2(int Target[][10], int Rotate1,int Rotate2, int pattern)
とすることで解決を図った。しかし意図していたものではない。
更に、95,96行目で
int min[Rotate1];
int max[Rotate1];
といった風に宣言しているが、これも、サイズが不明です。というコンパイルエラーが出る。
引数を、配列の添え字に当てはめる行為は間違っているようなのです。
[1.4] 今何がわからないのか、知りたいのか
上記のエラーがでる理由。
まず、二次元配列を引数とし、更にそのサイズは決まっていない(引数によって定める)場合の方法。
そして、一次元配列での最大値、最小値を求めるプログラム(ソース内に記載)との違い。
その改善法、あるいは考え方が知りたいです。
[2] 環境
[2.1] OS : Windows, Linux等々
windows8.1
[2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々
VS2013 x86 Native Tools コマンドプロンプト
[3] その他
・どの程度C言語を理解しているか
C言語を学び始めて3か月です。
二次元配列は、csvファイル(stdio.hのFILE構造体関係)によるマップの構築にしか用いたことがなく、
今回のように関数の引数として用いるというのは初めてです。
ポインタ。に関してですが、今回一次元配列バージョンの最大値、最小値算出関数の中で
「配列の先頭の値を渡す」という認識で用いています。
これは自分で調べ、取り入れたものですので、「ポインタ」というものが何か。ほかにどのような用途があるのか
その全貌を理解しているわけではありません。