• ベストアンサー

配列 隣の要素を参照するのですが

最初に 8つの要素を持つint型の配列(配列名dat)があるとして、最初全要素に「0」が代入されています。scanf関数でn番の要素に「1」が代入されたとします。n番なのでどこに「1」が代入されたかはわからないです。 問題 for文を使用して何番目に「1」が入力されたかを調べますが、以下のルールに従がわなくてなならいです。 ルール ・現在の要素から隣の要素を参照しなくてはいけない。 ・参照する範囲は要素の数「0~7」番 #include<stdio.h> void main() { int i, dat[8]; for(i=0;i<8;i++){ dat[i]=0; } i=0; scanf("%d",&i); dat[i] = 1; for(i=0;i<8;i++){ if(dat[i+1] == 1){print("%d列目に「1」がありました", i+1); } } でも…こうすると0番目の要素が参照されないですそれを回避するには?そして… 最大の要素(dat[7])にきたときは隣を参照しないようにするにはどうすればよいのでしょう?

  • nVIDIA
  • お礼率46% (520/1121)

質問者が選んだベストアンサー

  • ベストアンサー
  • nagare
  • ベストアンサー率33% (280/831)
回答No.7

やりたいことと、質問内容と補足内容が合ってないので混乱が発生してますね そもそもの質問の答えは if(dat[i] == 1){print("%d列目に「1」がありました", i+1); でOKだと思います それで >他の石と隣接しているかを調べ、一箇所も隣接してないときはNG、隣接している場所はOKとするため、隣の要素を参照して判断しようとしたのですが、端のマスだと隣を参照するとはみ出してしまい、隣接の判断がつかなくなるので困ってるのです。だからこのような質問を。 ということなので 「接近した8方向1マスのチェック」と思ってfor分はいらないと書いたのですが >自分の置こうとしている場所(座標)から自分と同じ色の石が置かれている座標まで検索すればよいのですから ということなのでforもしくはwhileは必要でしょう やり方というか考え方(思いつくのは)は ・No6さんの配列を大きくしてしまう ・検索対象座標テーブルを作成して検索対象座標テーブルから検索する (もっとあると思いますが) 私なら後者で作ります ・検索対象座標テーブル作成でルールを吸収 ・検索ロジックが1箇所となる ・デバグしやすい ※話がそれているのでこの質問を閉めて再質問したらどうでしょうか? またfor・whileどちらが適しているかですが、違いが分かればおのずと決まります よね

その他の回答 (7)

noname#16581
noname#16581
回答No.8

http://www.junkudo.co.jp/detail2.jsp?ID=0199227761 上記の本にオセロゲームの作り方が載っています。 参考になると思います。

参考URL:
http://www.junkudo.co.jp/detail2.jsp?ID=0199227761
nVIDIA
質問者

お礼

オセロは四方八方に検索しますので、それを原点にもどってシミュレーションしてみた結果、この問題見事に解決しました。また、同時に検索した方向の途中で同色の石があった場合、そのマスを起点、検索を始めたマスを終点と考えれば、こんど逆方向に行けば石を反転出来る事にきがつきました。 最初は、オセロゲーム制作で悩んでいた1週間ですが、一度オセロゲーム制作から離れて考えてみたら、数時間で解決しました。 アルゴリズムで一度つまずいたら本題から離れてみて基礎から(別の場所から)考えてみるといいようです。それでも分からなかったら、ここに応援をたのむのがいいですね。そのほうがどのような質問すれば良いかまとまりますし。 みなさんありがとうございました。 #8さんオセロゲームの作りかたのURLありがとうございます。でも、あえて自分で作るから意味があると先生は言うし、私もそう思うので見るのはやめました。ご親切にありがとうございます。

noname#30727
noname#30727
回答No.6

以前の質問は的確だったと思います。 例えば下のような感じで、座標の範囲が有効かどうかも一緒に調べてやればいいと思います。 (この質問とは全然無関係になってしまいますが) if ( (tate > 0 && data[tate - 1][yoko] != OTHELLO_NON) || /* 上 */ (tate > 0 && yoko < 7 && data[tate - 1][yoko + 1] != OTHELLO_NON) || /* 右上 */ ***以下略*** ) { return 1; } return 0; 前の質問の#1さんが配列を10×10にすれば範囲を絞る必要がないと言われていましたよね。 良いアドバイスだと思います。

  • nagare
  • ベストアンサー率33% (280/831)
回答No.5

forで検索していますが、オセロとなると8方向検索となるため下記のようになりますよね (forで検索しているからルールに無理がでているような) (これは左右検索の一例です) char result[3]; strcpy (&result[0], "NG"); if (0 == i) then { if(dat[i+1] == 1) { strcpy (&result[0], "OK"); } } elseif (7 == i) then { if(dat[i-1] == 1) { strcpy (&result[0], "OK"); } } else { if((dat[i-1] == 1) or (dat[i+1] == 1)) { strcpy (&result[0], "OK"); } } print("%d列目の結果は%s\n", i, &result[0])

nVIDIA
質問者

補足

オセロでどこに石が置けるかを実際のオセロをしてみて検討してみたところ、置ける条件は一つ、8方向の先に自分と同じ色の石がある時に限る 事がわかりました。 という事は、自分の置こうとしている場所(座標)から自分と同じ色の石が置かれている座標まで検索すればよいのですから、for文よりwhile文が有効ですか?

  • nagare
  • ベストアンサー率33% (280/831)
回答No.4

if(dat[i] == 1){print("%d列目に「1」がありました", i+1); のような気がしますけど ルールの ・現在の要素から隣の要素を参照しなくてはいけない ですが、 「現在の要素が1の場合は0を参照」 ではないのでしょうか?

  • n_tan
  • ベストアンサー率50% (3/6)
回答No.3

No.2です。 隣の要素を参照しなくてはいけないのでしたね。すみません。m(__)m 要素MAXの場合に0を参照する様にすればいいのは

  • n_tan
  • ベストアンサー率50% (3/6)
回答No.2

気づいたこと 1.scanfで8以上の値がくることは考慮しなくていいんですか? 2.配列要素8の添字は0~7で、printの文言を列の先頭は1として表示するだけですからdatの参照する添字iに+1する必要はないですね。  forの条件はiが8になったらぬけるのでOkです。 3.これはどうでもいいですが、1が見つかったらforから抜けてもいいかな...

nVIDIA
質問者

補足

言語の質問するのって結構難しくて考えてこのような例をとらせていただきました。 本来は2次元配列で、今オセロゲームを制作してるのですが、他の石と隣接しているかを調べ、一箇所も隣接してないときはNG、隣接している場所はOKとするため、隣の要素を参照して判断しようとしたのですが、端のマスだと隣を参照するとはみ出してしまい、隣接の判断がつかなくなるので困ってるのです。だからこのような質問を。 でも、これもわかりにくかったようです。 もうどう質問すればいいか自分でも分からなくなってきちゃいます><

  • BLUEPIXY
  • ベストアンサー率50% (3003/5914)
回答No.1

よくわかりませんが、 >0番目の要素が参照されないです すべての要素を調べてみて1が見つからなかったら必然的に0番目の要素に1が入っている(すでに代入されたのだから) >dat[7])にきたときは隣を参照しないようにする i<8 を i<8-1 にする 見当違いだったらすみません

関連するQ&A

  • 配列の問題

    配列の問題です。 n個の要素を持つ一次元配列の値(変数値)をまったく逆に入れ替えるプログラムを作りたいのですが、この場合どのようにして逆を表現すればよいのかわかりません。 (nの値は読み込み、配列は奇数個でも偶数個でも使えるプログラムでなければなりません) 参考書を見ながら作ってみたのですが…だめでした。 プログラム初心者です。アドバイスお願いします。 int main(void) { int i,n; int vc[n]; printf("n個の要素を持つ一次元配列をつくる\n"); printf("nの値を入力してください\n"); scanf("%d",&n); for (i=0;i<n+1;i++) vc[i]=i+1; for (i=0;i<5;i++) printf("vc[%d]=%d\n",i,vc[i]); printf("この配列を逆に入れ替えると\n); return 0; }

  • 二つのint型配列を一つにするには?

    2種類のint型配列にそれぞれ数が重ならないように数字を代入して行きます。この2種類のプログラムの違いは値を代入する方法以外はすべて同じです。ですから、ユーザー関数で一つにまとめようと考えてます。 2種類の違い:値を代入する方法がが違う。 (1)scanf()関数で人間が値を各要素に代入する。 (2)rand()関数でPC側が値を各要素に代入する。 配列への代入のルール (1)同じ値の場合は代入しなおさなければならない。 基本的には 人間側が値を要素に代入する場合 for( i = 0 ; i < 6 ; i++){ while(1){ scanf("%d",&dut[i]); for (j = 0; j < i ; j++){ if(dut[i] == dut[j]){flg = 1; break;} } if (flg == 0){break;} } } PC側がrand()関数を使い各要素に入力した場合 for( i = 0 ; i < 6 ; i++){ while(1){ pc[i] = rand()%43 + 1; for (j = 0; j < i ; j++){ if(pc[i] == pc[j]){flg = 1; break;} } if (flg == 0){break;} } } 以上の二つの違うところは「rand()関数かscanf()」どちらかが入るだけです。あとはみな同じつづりなのです。だから一つに出来ると思うのです。 共有して使える関数はどんどんまとめちゃうのが私の考えですので。 ※ヘッダ呼び出しや、変数定義など基本的な部分は省いてあります。 間違いがあるときはおしえてください。 ※また、別の方法があるときはぜひおしえてください。

  • 非常にはずかしい質問ですが 配列の質問です。

    C言語の勉強で時間が経つごとに、肝心の基礎が忘れがちになるのですよね。 それに、配列に対しての説明ってほとんど文字列ばかりで整数はみつからないです。 今回の質問は ・int型配列の要素ひとつずつ代入するにはどうするか? ・同じ数字を代入させないにはどうするか? ・配列中n個の要素を表示させるにはどうするのか? 条件 1、配列の要素はn個 2、同じ数は× 一応かいてみました。 { int buffer[6], i, j, signal ; srand((unsigned int)time(NULL)); for( i = 0 ; i < 6 ; i++){ buffer[i] = rand()%42+1; for( signal = 0 , j = 0 ; j < i ; j++ ){ if(buffer[i] == buffer[j]){signal = 1; break;} } if(signal == 0){break;} } printf("%d\n",buffer);

  • 複数の配列からfor構文の中で任意の要素を表示させる

    @dat1=(12,11,16,17); @dat2=(21,26,23,20); ・・・ @dat17=(22,34,31,18); for($i=1;$i<=$17;$i++){ print @{"dat$i"};print "\n"; } といったように,@dat1から@dat17まで配列が用意されているときに上の例では当然ながら@dat1全ての要素が表示されます。これを任意の要素のみを表示させたい場合にはどのようにすればよいでしょうか? 例えば@dat1から@dat17までの0番目の要素($dat1~17[0])と1番目の要素($dat1~17[1])のみを表示させたいのですが...

    • ベストアンサー
    • Perl
  • 配列の頭に要素を挿入する方法

    初心者です。配列でご教授お願いします。 インデックス0からひとつずつ要素をずらして、配列の一番前に要素を挿入するにはどうしたらいいのでしょうか? int[] a = new int[10]; int n = a.length; for (int i = n-1; i < 1; i--){ a[i] = a[i-1]; } a[0] = 新しい要素 といった感じで書いたのですが、どうもループの中が実行されていないようなのです。 よろしくお願いいたします。

  • 二次元配列に関する質問です。

    一次元配列はわかるのですが二次元配列になると、わからない時があります。 <ソース> #include<stdio.h> int main() { int dat[2][5]={1,2,3,4,5,6,7,8,9,10}; int i; int j; for(i=0;i<2;i++){ for(j=0;j<5;j++){ printf("dat[%d][%d] %d\n",i,j,dat[i][j]); } } return 0; } このプログラムでわからないのは、 int dat[2][5]={1,2,3,4,5,6,7,8,9,10};の部分です。 普段は、int dat[2][5]={{1,2,3,4,5}, {6,7,8,9,10}, }; という使い方をしているのですが・・・。 どうちがうのでしょうか?

  • 引数で指定された配列の要素数の取得

    どうもこんにちは。 C言語でプログラムを作成しています。 ある関数に配列を渡すことを考えていますが、渡した配列の要素数を取得する方法は何かありますか? 標準の関数を見ても、配列の先頭アドレスのポインタとともに、配列の要素数を渡しているものばかりで、配列のポインタを渡しているものは見かけません。 要素数があらかじめわかっていれば、それを引数の型に指定できますが、呼び出されるまで不明な場合はうまくいきません。 配列の要素数も引数として一緒に渡す必要がありますか? [作ってみたサンプル] #include <stdio.h> #include <stdlib.h> #include <string.h> // func1 と func2 をまとめられないだろうか。。。 void func1(int (*p)[10]) { ________int n = sizeof(*p) / sizeof((*p)[0]); ________int i; ________for (i = 0; i < n; i++) { ________________printf("%d\n", (*p)[i]); ________} ________printf("\n"); } void func2(int (*p)[5]) { ________int n = sizeof(*p) / sizeof((*p)[0]); ________int i; ________for (i = 0; i < n; i++) { ________________printf("%d\n", (*p)[i]); ________} ________printf("\n"); } int main(int argc, char *argv[]) { ________int ary1[10] = { 2, 4, 6, 8, 0, 1, 3, 5, 7, 9 }; ________int ary2[5] = { 3, 6, 9, 12, 15 }; ________func1(&ary1); ________func2(&ary2); ________return 0; }

  • 配列のプログラム作成

    【質問】 次の処理を行うプログラムを作成します。 (1)10個の要素を持つ一次配列dat[10]を宣言します (2)dat[0]に0、dat[1]に1をセットします (3)dat[2]以降の要素には、前の2つの要素の和を計算し入力します (4)配列の各要素の値を表示します 【プログラム作成例】 dat[ 0] = 0 dat[ 1] = 1 dat[ 2] = 1 dat[ 3] = 2 dat[ 4] = 3 dat[ 5] = 5 dat[ 6] = 8 dat[ 7] = 13 dat[ 8] = 21 dat[ 9] = 34 上記の解答は下記の通りなのですが、下記以外の解答方法を教えてはいただけないでしょうか? C言語に詳しい方よろしくお願いいたします。 #include <stdio.h> main() { int i, dat[10]; dat[0] = 0; dat[1] = 1; for (i=2; i<10; i++) { dat[i] = dat[i-2] + dat[i-1]; } for (i=0; i<10; i++) { printf ("dat[%2d] = %2d\n", i, dat[i]); } return (0); }

  • 配列の要素に1年の始めから終わりまでの日付を入れたい。

     String date = new String[365]; という配列の各要素に2002.1.1から 2002.12.31までを入れたいのですが。。 int y; //year int m; //month int d; //day for(int i = 0; i < 365; i++){ date[i] = y + "." + m + "." + d; } 上記の様な感じで配列の要素を入れたいと思っているのですが、y , m , d の取得の仕方が全然分かりません。  誰か知っている人がいたら教えてください。また、上記の様な方法でなくても、配列に日付を入れることができたら、どんな方法でも、構いません。 よろしくお願いします。

    • ベストアンサー
    • Java
  • 配列の要素

    #include <iostream> using namespace std; int main() { int n[10] ={1,2,3,4,5,6,7,8,9,10}; int i; for(i = 0; i < 10; i++){ cout << "a[" << i << "] = " << n[i] << endl; } return 0; } ここまでは完成することはできたのですが この要素の並びをシャッフルしてランダムな順に並び変える方法がわかりません。