ランダムダンジョン自動生成に関して

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
namari
記事: 111
登録日時: 12年前

ランダムダンジョン自動生成に関して

#1

投稿記事 by namari » 12年前

ランダムダンジョンを作るために頑張っていたんですが、
おかしなところを対症療法的に治していったらどんどん複雑な問題になっていきました。

http://racanhack.sourceforge.jp/rhdoc/intromaze.html
ここなどを参考にしました。

敵AIを作る都合上、完成目標は以下の感じなのです。
壁は0、1以上全ては床。それ以外の種類の地形は考えていません。

コード:

0000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000
0000222222222200000000000000000000000000000000000000000
0000222222222200000000000000000000000000000000000000000
0000222222222231111111000000000000000000000000000000000
0000222222222200000001000000000066666600000000000000000
0000000000000000000001000000000066666600000000000000000
0000000000000000000001111111111766666600000000000000000
0000000000000000000000000000000066666600000000000000000
0000000000000000000000000000000000070000000000000000000
0000000000000000000000000000000000010000000000000000000
0000000000000000000000000000000000010000000000000000000
0000000000000000000000000000000000010000000000000000000
0000088888800000000000000000000000010000000000000000000
0000088888891111111110000000000000010000000000000000000
0000088888800000000010000000000000050000000000000000000
0000009000000000000010000004444444444400000000000000000
0000001000000000000010000004444444444400000000000000000
0000001000000000000011111154444444444400000000000000000
0000001000000000000000000000000000000000000000000000000
0000001000000000000000000000000000000000000000000000000
0000001000000000000000000000000000000000000000000000000
0000001000000000000000000000000000000000000000000000000
0000001000000000000000000000000000000000000000000000000
...以下略
これを成すための実装順として、以下のようにしようと思っています。
1.ランダムでエリアを区切って、それぞれのエリア番号に関して、開始のx,yと縦、横を求める。(※いきなりここでつまっています)
2.それぞれのエリアのなかに1つの部屋を作る。(最も端の一マスは全て0)
3.部屋からランダムに1~4本の通路を1でエリアの区切り線まで伸ばす(ただしエリアの区切り線にたどり着かずに、端まで付いてしまう通路は作らない)
4.(4444441444441444)となっているなら(4444441111111444)と変更、(4444444444444444)となっているなら放置、(4444441444444444)となっているなら、
 繋げられていない側の部屋から通路を呼び出す。
5.1でないエリアの区切り線を全て消去。

視覚的に表現すると、
1.

コード:

0000000000000000000000004000000000000000000
0000000000000000000000004000000000000000000
0000000000000000000000004000000000000000000
0000000000000000000000004000000000000000000
0000000000000000000000004000000000000000000
2222222222222222222222222222222222222222222
0000000000000600000000000000000000000000000
0000000000000600000000000000000000000000000
0000000000000600000000000000000000000000000
0000000000000600000000000000000000000000000

area[0].x=0
area[0].y=0
area[0].yoko=24
area[0].tate=5

area[1]...以下略
(本当は102,104,106,...のようなもっと大きい数字でlineを書きますが、表現上この方が見やすいだけです)

2.

コード:

0000000000000000000000004000000000000000000
0000022222220000000000004000004444440000000
0000022222220000000000004000004444440000000
0000022222220000000000004000000000000000000
0000000000000000000000004000000000000000000
2222222222222222222222222222222222222222222
0000000000000600000000000000000000000000000
0000066000000608888888800000000000000000000
0000066000000608888888800000000000000000000
0000000000000600000000000000000000000000000

room[0].x=5
room[0].y=1
room[0].yoko=7
room[0].tate=3
エリアの一番端は0以外になりません。

3.

コード:

             ↓(例えばこの行は1が一つしかないので4の部屋から通路を呼び出す。)
0000000000000000000000004000000000000000000
0000022222220000000000004000004444440000000
0000022222223111111111111000004444440000000
0000022222220000000000004000000005000000000
0000000003000000000000004000000001000000000
2222212221222222222222122222222221222222222
0000070000000600000000900000000000000000000
0000066000000608888888800000000000000000000
0000066000000198888888800000000000000000000
0000000000000600000000000000000000000000000

4.

コード:

0000000000000000000000004000000000000000000
0000022222220000000000001111154444440000000
0000022222223111111111111000004444440000000
0000022222220000000000004000000005000000000
0000000003000000000000004000000001000000000
2222211111111111111111111111111111222222222
0000070000000600000000900000000000000000000
0000066000000608888888800000000000000000000
0000066000000198888888800000000000000000000
0000000000000600000000000000000000000000000
5.

コード:

0000000000000000000000000000000000000000000
0000022222220000000000001111154444440000000
0000022222223111111111111000004444440000000
0000022222220000000000000000000005000000000
0000000003000000000000000000000001000000000
0000011111111111111111111111111111000000000
0000070000000000000000900000000000000000000
0000066711111108888888800000000000000000000
0000066000000198888888800000000000000000000
0000000000000000000000000000000000000000000
とまあこんなとこまで書いてなんですが、
簡単そうに見える1.で既に僕には意味のわからない問題が起こっています。

コード:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

typedef struct{
	int x,y;
	int tate;
	int yoko;	
} area_t;

typedef struct{
	int x,y;
	int tate;
	int yoko;	
} room_t;


int GetRandom(int min,int max)
{
	return min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
}

int main(void) 
{//min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
        int i,j,k,l,m,n;int cut;//切る方向。0なら縦、1なら横。
		int line=1;int where;//切るとこ
		int cut_count;//切る回数
		int block[35][55];
		int area_select;
		int area_select_MAX=0;
		area_t area[30];
		room_t room[30];

        area[0].x=0;
		area[0].y=0;
		area[0].tate=35;
		area[0].yoko=55;

        /* 乱数系列の変更 */
        srand((unsigned) time(NULL));

        for (i=0; i<=34; i++) {
                for (j=0; j<=54; j++) {
                        block[i][j]=0;
                }
        }

		cut_count=GetRandom(2,9);
		printf("cut_count:%d\n",cut_count);
		

		for(k=1;k<=cut_count;k++){

			do{
    		cut=GetRandom(0,1);
			printf("cut:%d\n",cut);
			area_select=GetRandom(0,area_select_MAX);
			printf("area_select:%d\n",area_select);
        	printf("area_select_MAX:%d\n",area_select_MAX);
			printf("cut==0 && area[area_select].yoko-5>=4:%d\n",cut==0 && area[area_select].yoko-5>=4);
			printf("cut==1 && area[area_select].tate-5>=4:%d\n",cut==1 && area[area_select].tate-5>=4);
			}while((cut==0 && area[area_select].yoko-5>=4)==0 && (cut==1 && area[area_select].tate-5>=4)==0);
			
			if(cut==0){//縦
		    	where=GetRandom(5,area[area_select].yoko-5);
		    	printf("where:%d\n",where);
				if(area[area_select].y!=0){//このifは意味もわからないまま対症療法的に追加した要素(cut_countが小さい時は上手く成り立つ)
        		for (i=area[area_select].y-1; i<=area[area_select].y+area[area_select].tate-2; i++) {
                	block[i][area[area_select].x+where-1]=line;
        		}
			    }
				if(area[area_select].y==0){
        		for (i=area[area_select].y; i<=area[area_select].y+area[area_select].tate-1; i++) {
                	block[i][area[area_select].x+where-1]=line;
        		}
			    }
    			area_select_MAX++;
				area[area_select_MAX].x=area[area_select].x+where+1;
				area[area_select_MAX].y=area[area_select].y;
				area[area_select_MAX].yoko=area[area_select].yoko-where;
				area[area_select_MAX].tate=area[area_select].tate;
				
				area[area_select].yoko=where-1;
			}
			if(cut==1){//横
		    	where=GetRandom(5,area[area_select].tate-5);
		    	printf("where:%d\n",where);
				if(area[area_select].x!=0){
        		for (j=area[area_select].x-1; j<=area[area_select].x+area[area_select].yoko-2; j++) {
                	block[area[area_select].y+where-1][j]=line;
        		}
			    }
				if(area[area_select].x==0){
        		for (j=area[area_select].x; j<=area[area_select].x+area[area_select].yoko-1; j++) {
                	block[area[area_select].y+where-1][j]=line;
        		}
			    }
    			area_select_MAX++;
				area[area_select_MAX].x=area[area_select].x;
				area[area_select_MAX].y=area[area_select].y+where+1;
				area[area_select_MAX].yoko=area[area_select].yoko;
				area[area_select_MAX].tate=area[area_select].tate-where;
				
				area[area_select].tate=where-1;
	    	}


			line++;


			for(l=0;l<=area_select_MAX;l++){
		    printf("---------------\n");
			printf("area[%d].x:%d\n",l,area[l].x);
			printf("area[%d].y:%d\n",l,area[l].y);
			printf("area[%d].yoko:%d\n",l,area[l].yoko);
			printf("area[%d].tate:%d\n",l,area[l].tate);
		    printf("---------------\n\n");
		    }

		for (m=0; m<=34; m++) {
                for (n=0; n<=54; n++) {
                        printf("%d",block[m][n]);
                }
				printf("\n");
        }

			
		}

        return 0;
}
このようなコードを書くと以下のようなミスが見られてしまいます。

コード:

0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003000000000000090000
0000000000000000000000000000000000003444444444444444444
0000000000000000000000000000000000003000000000000000000
0000000000000000000000000000000000003000000000000000000
0000000000000000000000000000000000003000000000000000000
0000000000000000000000000000000000003000000000000000000
2222222222222222222222222222222222222222222222222222222
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
6666666666666666666666666666500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000800000000000000
0000000000000000000000000000500000000000000000000000000//8が一個少なかったり
0000000000000000000000000000577777777777777777777777777
7000000000000000000000000000500000000000000000000000000//7が一個多かったり
0000000000000000000000000000500000000000000000000000000
0000000000000000000000000000500000000000000000000000000
0000000000000000000000000000500000000000000000000000000
0000000000000000000000000000500000000000000000000000000
0000000000000000000000000000500000000000000000000000000
0000000000000000000000000000500000000000000000000000000
0000000000000000000000000000500000000000000000000000000

area[9].x=51
area[9].y=0
area[9].yoko=5//一個多い

//そもそも強制終了したり
このまま無理やりroom作成(2.)に移行するとどんどん悪化していくので、ここの実装は完璧にしたいのですが、(強制終了している時点で欠陥品ですけど)
是非問題点を教えていただけると嬉しいです。

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: ランダムダンジョン自動生成に関して

#2

投稿記事 by usao » 12年前

>//このifは意味もわからないまま対症療法的に追加した要素
ご自身で何やってるかわからないコードを書かれているのであれば,
そもそもまともに動く確率はかなり低いような気がしますが.
そんな投げ出した感がある状況で人にコードを読めというのは…
(まぁ,かなーりやさしい人なら読んでくれるかもしれませんが,とりあえず私はパスですね.)

まず,自身で把握できないコードを継ぎ足すのではなく
問題が発生する状況を作り出して,ちゃんとデバッグすべきだと思います.
常にうまくいかないのか,乱数系列次第なのか知りませんが,とりあえず
srandの引数に 定数を設定 して(うまくいかない状況で)処理を追えばよいのではないでしょうか.

・最初はとりあえず切る方向を縦あるいは横のいずれかに固定するなどすればデバッグしやすいかもしれません.
・強制終了するのであれば,例えば配列領域外を参照したりしていないか?等に注意して見ると良いかもしれません.

アバター
namari
記事: 111
登録日時: 12年前

Re: ランダムダンジョン自動生成に関して

#3

投稿記事 by namari » 12年前

>usaoさん
確かにそうですよね、すみません。
言うとおり、cutをひとつに絞ったら、
根本的なひとつの問題までたどり着きました。

コード:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

typedef struct{
	int x,y;
	int tate;
	int yoko;	
} area_t;

typedef struct{
	int x,y;
	int tate;
	int yoko;	
} room_t;


int GetRandom(int min,int max)
{
	return min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
}

int main(void) 
{//min + (int)(rand()*(max-min+1.0)/(1.0+RAND_MAX));
        int i,j,k,l,m,n;int cut;//切る方向。0なら縦、1なら横。
		int line=1;int where;//切るとこ
		int cut_count;//切る回数
		int block[35][55];
		int area_select;
		int area_select_MAX=0;
		area_t area[30];
		room_t room[30];

        area[0].x=0;
		area[0].y=0;
		area[0].tate=35;
		area[0].yoko=55;

        /* 乱数系列の変更 */
        srand(6);

        for (i=0; i<=34; i++) {
                for (j=0; j<=54; j++) {
                        block[i][j]=0;
                }
        }

		cut_count=GetRandom(2,2);
		printf("cut_count:%d\n",cut_count);
		

		for(k=1;k<=cut_count;k++){

			do{
    		cut=GetRandom(1,1);
			printf("cut:%d\n",cut);
			area_select=GetRandom(0,area_select_MAX);
			printf("area_select:%d\n",area_select);
        	printf("area_select_MAX:%d\n",area_select_MAX);
			printf("cut==0 && area[area_select].yoko-5>=4:%d\n",cut==0 && area[area_select].yoko-5>=4);
			printf("cut==1 && area[area_select].tate-5>=4:%d\n",cut==1 && area[area_select].tate-5>=4);
			}while((cut==0 && area[area_select].yoko-5>=4)==0 && (cut==1 && area[area_select].tate-5>=4)==0);
			
			if(cut==0){//縦
		    	where=GetRandom(5,area[area_select].yoko-5);
		    	printf("where:%d\n",where);
        		for (i=area[area_select].y; i<=area[area_select].y+area[area_select].tate-1; i++) {
                	block[i][area[area_select].x+where-1]=line;
			    }
    			area_select_MAX++;
				area[area_select_MAX].x=area[area_select].x+where+1;
				area[area_select_MAX].y=area[area_select].y;
				area[area_select_MAX].yoko=area[area_select].yoko-where;
				area[area_select_MAX].tate=area[area_select].tate;
				
				area[area_select].yoko=where-1;
			}
			if(cut==1){//横
		    	where=GetRandom(5,area[area_select].tate-5);
		    	printf("where:%d\n",where);
        		for (j=area[area_select].x; j<=area[area_select].x+area[area_select].yoko-1; j++) {
                	block[area[area_select].y+where-1][j]=line;
        		}
    			area_select_MAX++;
				area[area_select_MAX].x=area[area_select].x;
				area[area_select_MAX].y=area[area_select].y+where+1;
				area[area_select_MAX].yoko=area[area_select].yoko;
				area[area_select_MAX].tate=area[area_select].tate-where;
				
				area[area_select].tate=where-1;
	    	}


			line++;


			for(l=0;l<=area_select_MAX;l++){
		    printf("---------------\n");
			printf("area[%d].x:%d\n",l,area[l].x);
			printf("area[%d].y:%d\n",l,area[l].y);
			printf("area[%d].yoko:%d\n",l,area[l].yoko);
			printf("area[%d].tate:%d\n",l,area[l].tate);
		    printf("---------------\n\n");
		    }

		for (m=0; m<=34; m++) {
                for (n=0; n<=54; n++) {
                        printf("%d",block[m][n]);
                }
				printf(" %d\n",m);
        }

			
		}

        return 0;
}
ここで、area[1].tate、yとarea[2].tate、yがおかしな数値を示す可能性があることが要因と分かりました。
そのせいで、誤差が生まれ、それが積み重なると、領域外にアクセスしてしまうことまであるんですね。

そして、例えば
srand(1)では上記の問題が起き、
srand(6)では上記の問題が起きないという具体例をおかげで見つけられました。
この二つは1と2の上下が逆なので、area[0]とarea[1]を切るときの違いなのかとは思うのですが、
プログラミング上のミスを見つけられません。

srand(1)の場合、

コード:

00000000000000000000000000000000000 0
00000000000000000000000000000000000 1
00000000000000000000000000000000000 2
00000000000000000000000000000000000 3
00000000000000000000000000000000000 4
00000000000000000000000000000000000 5
00000000000000000000000000000000000 6
00000000000000000000000000000000000 7
00000000000000000000000000000000000 8
00000000000000000000000000000000000 9
00000000000000000000000000000000000 10
00000000000000000000000000000000000 11
00000000000000000000000000000000000 12
11111111111111111111111111111111111 13
00000000000000000000000000000000000 14
00000000000000000000000000000000000 15
00000000000000000000000000000000000 16
00000000000000000000000000000000000 17
00000000000000000000000000000000000 18
00000000000000000000000000000000000 19
00000000000000000000000000000000000 20
22222222222222222222222222222222222 21
00000000000000000000000000000000000 22
00000000000000000000000000000000000 23
00000000000000000000000000000000000 24
00000000000000000000000000000000000 25
00000000000000000000000000000000000 26
00000000000000000000000000000000000 27
00000000000000000000000000000000000 28
00000000000000000000000000000000000 29
00000000000000000000000000000000000 30
00000000000000000000000000000000000 31
00000000000000000000000000000000000 32
00000000000000000000000000000000000 33
00000000000000000000000000000000000 34


area[1].x=0
area[1].y=15
area[1].yoko=55
area[1].tate=6

area[2].x=0
area[2].y=23
area[2].yoko=55
area[2].tate=14




srand(6)の場合、

コード:

00000000000000000000000000000000000 0
00000000000000000000000000000000000 1
00000000000000000000000000000000000 2
00000000000000000000000000000000000 3
00000000000000000000000000000000000 4
00000000000000000000000000000000000 5
00000000000000000000000000000000000 6
00000000000000000000000000000000000 7
00000000000000000000000000000000000 8
00000000000000000000000000000000000 9
00000000000000000000000000000000000 10
00000000000000000000000000000000000 11
00000000000000000000000000000000000 12
22222222222222222222222222222222222 13
00000000000000000000000000000000000 14
00000000000000000000000000000000000 15
00000000000000000000000000000000000 16
00000000000000000000000000000000000 17
00000000000000000000000000000000000 18
00000000000000000000000000000000000 19
00000000000000000000000000000000000 20
00000000000000000000000000000000000 21
00000000000000000000000000000000000 22
00000000000000000000000000000000000 23
00000000000000000000000000000000000 24
00000000000000000000000000000000000 25
00000000000000000000000000000000000 26
00000000000000000000000000000000000 27
00000000000000000000000000000000000 28
11111111111111111111111111111111111 29
00000000000000000000000000000000000 30
00000000000000000000000000000000000 31
00000000000000000000000000000000000 32
00000000000000000000000000000000000 33
00000000000000000000000000000000000 34

area[1].x=0
area[1].y=31
area[1].yoko=55
area[1].tate=5

area[2].x=0
area[2].y=15
area[2].yoko=55
area[2].tate=15

アバター
usao
記事: 1889
登録日時: 12年前
連絡を取る:

Re: ランダムダンジョン自動生成に関して

#4

投稿記事 by usao » 12年前

(なんかこのサイトが繋がらなくなっていたためか)
他に誰も回答されていないようですから,一つアドバイス(のようなもの)を.

なんというか,処理の単純さに対してコードがごちゃごちゃしすぎているような印象です.
短いんだけどデバッグ時に追いにくそう,というか.
例えば,どうしても今のコードの問題点がわからないとか直せないとかいうことであれば,
ひとまずそのソースコードは別に保存しておいて,
挙動が把握できる結果が各段階で出来上がっていく形に書きなおすとデバッグしやすいかもしれません.

・ある処理単位を関数にでもして,処理のINとOUTをきちっと決める
・処理フローをきちっと決定する&そのことをコード内にコメントとして入れる
ということをやってみてはどうでしょうか?
例えば,↓のような感じとか.

コード:

//エリアCutTgtAreaを,可能であれば左右に分割する.
//CutTgtAreaがサイズ的に左右に分割可能である場合は,
//分割結果できる2つのエリアの情報を
// 左側のエリア → pLeftResultArea
// 右側のエリア →  pRightResultArea
//に格納する.
//また,分割線となったX座標をpLineXに格納する.
//以上の処理が成功した時は0でない値を返す.
//何かエラーがあった際や,CutTgtAreaがサイズ的に左右に分割できない場合は0を返す.
//(その際,引数に指定された3つの結果受取用領域の内容は不定である)
int CutArea_LR( area_t CutTgtArea, area_t *pLeftResultArea, area_t *pRightResultArea, int *pLineX )
{
  //(1)CutTgtAreaのデータがまともな内容か? & サイズ的に分割可能かをチェック.
  //引数のポインタ値がNULLでないことも最低限チェックする.
  //なにかしらダメなら0を返す.
  ...
  //(2)分割座標Xの取り得る範囲を計算し,その範囲内でXを乱数で決定する.
  ...
  *pLineX = X;  //結果を格納
  //(3)(2)の座標で左右に分割した結果の2エリアを計算する.
  //(単純に値を代入していくだけの非常に簡単なコードであるはず)
    //(3.1)左側エリア
  ...
    //(3.2)右側エリア
  ...
  //うまくいったら0でない値を返す
  return 1;
}
これならデバッグ時にどの段階で失敗しているか(各段階の結果値がどうなっていればいいのか)
がわかりやすいですよね.

non
記事: 1097
登録日時: 14年前

Re: ランダムダンジョン自動生成に関して

#5

投稿記事 by non » 12年前

whereの意味がわかりません。これは行数を1から数えているか0から数えているのか・・・・何の数なのか?
また、-5の持つ意味など、注釈してもらわないと、たぶん、こうだろうなと思っても、それがあなたの設計仕様なのか、正しく動いていないのだから
はっきりしてもらわないとわかりません。

さらに、seedを固定しても、環境によっては異なるわけですから、こちらは同じ結果を再現できません。例として載せてある結果はwhereの値など省略されているので、どこが間違っているのか追うこともできません。

質問ですが 86行目
area[area_select_MAX].y=area[area_select].y+where+1;
最後に+1をする理由は何ですか?
仮にarea[area_select].yが0で、whereが5なら
左辺は6、すなわち、y座標は6ということから、
whereは上のエリアの行数になりますが、あってますか。
すると、0行目から4行目までが上のエリアになり、5行目にLINEを引くことになります。
しかし、82行目
block[area[area_select].y+where-1][j]=line;
となってますから、4行目に線を引いてますので、上のエリアは0~3行目の4行になっちゃう。あれれ???

ということで、仕様をはっきり示してもらえないので、解析は困難です。
non

アバター
namari
記事: 111
登録日時: 12年前

Re: ランダムダンジョン自動生成に関して

#6

投稿記事 by namari » 12年前

>usaoさん
前回のデバッグのしやすさの話から、単純化する検証法で、なんとか問題は解決までたどり着けました。ありがとうございます。

また、今テストコードでこれからゲーム本編に埋め込むんですが、
この処理と、これからの処理合わせて、なるべく分かりやすい(デバッグの容易な)方法(おっしゃっているコメント挿入、関数化など)を心がけていきたいです。

コード:

    			area_select_MAX++;
				area[area_select_MAX].x=area[area_select].x;
				area[area_select_MAX].y=area[area_select].y+where+1;
				area[area_select_MAX].yoko=area[area_select].yoko;
				area[area_select_MAX].tate=area[area_select].tate-where-1;
				
				area[area_select].tate=where;
//改善。
//問題を単純化させて、冷静に考えたら本当に簡単な問題でした。
>nonさん
人に聞くのに、明らかな説明不足ですみませんでした。
自分で分かっている仕様をつい当たり前のようにスルーすることはあってはなりませんよね。
次に人に質問するときは、投げやりな質問になってしまわないように気をつけます。

また結局のところ、
>whereの意味がわかりません。これは行数を1から数えているか0から数えているのか・・・・何の数なのか?
まさにここの部分付近の勘違いが問題でした。
配列を0から数えることを失念しがちなため、以下に書かれたような矛盾が生じてしまいました。


閉鎖

“C言語何でも質問掲示板” へ戻る