• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:セグメンテーションエラーがでます)

セグメンテーションエラーがでます

このQ&Aのポイント
  • Cでオセロゲームを作っています。コンピュータと対戦できるようにしたいのですが、セグメンテーション違反になってしまいます。
  • 局所変数にして関数で受け渡しをすると、数回ループさせたところでエラーで強制終了します。
  • 関数find_legal_moveへのp[]の渡し方が悪いのだと思いますが、なぜか分かりません。

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

  • ベストアンサー
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.5

ん~, ぱっと見た感じだと「computer の中で count_turn_over を直接呼んでいる」のがあやしいんだけどなぁ.... この引数の p[?] で dr とか dc ってメンバがきちんと初期化されていないという可能性を感じたんだけどねぇ. ちなみに computer の中で count_turn_over を直接呼んでいるので, コメントとやってる内容が違うんだけどなぁ.... まあ, もともとデバッガ使っておいかけるのが正しいような気がする.

beginner07
質問者

お礼

回答ありがとうございます。 すいません、さっきチェックが甘かったようで、 max = count_turn_over() の所で、おっしゃるとおりp[0]が初期化されていませんでした。 cygwinでデバッガを使っていないので、printfデバッグでやりました。 max = 0; for (p[0].dr = -1; p[0].dr <= 1; p[0].dr++)  for (p[0].dc = -1; p[0].dc <= 1; p[0].dc++)   max += count_turn_over(board, player, p[0]); としたところ(tmpも同様に)、正常に動くようになりました。 ありがとうございます。

すると、全ての回答が全文表示されます。

その他の回答 (5)

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.6

老婆心ながら: どうせ最終的に足し算しないといけないんだから, is_legal_move で「count_turn_over の総和」を返す方がいいような気がする. それを記憶するなり, 最大のものを覚えておくなりした方がプログラムとして簡単 (かつ速い) んじゃないかな. あと, find_legal_move の if 文は, is_legal_move の返り値を比較しないで if (is_legal_move(...)) の形にした方がきれいだと思います.

beginner07
質問者

お礼

色々とアドバイスありがとうございます。 まだまだ未熟だと再確認できました。これを参考にプログラミングの勉強をしていきたいと思います。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.4

#2 です. 盤面の情報は board[][] に入っているでしょうから大丈夫だと思います>#3. で, 本質的には「構造体 Position の作りがおかしい」ということになります. この Position のおかしさがプログラム上のややこしさにつながり, 最終的におかしな挙動につながっていると思います. 具体的にいうと, Position の中に「方向」を表すメンバである dr や dc が入っているのが変. これは count_turn_over の中でまわすためだけに必要なので, Position のメンバとしては不要です. ところで, このプログラムは「コンピュータがパスしなければならないような局面」で不都合がありそうなんだけど... 気のせい?

beginner07
質問者

お礼

何度もありがとうございます。 確かに、引数が増えるのが嫌で構造体にdr,dcを入れたのが悪かったかもしれません。

beginner07
質問者

補足

少し補足させていただきます。 まず、人間対人間でやった場合、問題なくプログラムは動きます。 また、人間対コンピュータでやった場合、p[]を大域変数にすると問題なく動くのですが、 局所変数にした場合、5,6手打った後にセグメンテーションエラーで終了してしまいます。 最後に、パスについては、別の関数で判定できるようにしているのでおそらく問題ないと思います。

すると、全ての回答が全文表示されます。
  • maku_x
  • ベストアンサー率44% (164/371)
回答No.3

Position p[]; を、関数 computer() 内の自動変数にすると、関数 computer() が呼び出される度に記憶領域 p[] が割り当てられ、computer() の処理終了時に記憶領域 p[] が解放されるので、結果的に盤面の内容を覚えていないことになります。記憶領域 p[] が解放された後は、p[] の内容は何が入っているのか分かりません。こうなると、どのような不具合が生じるかは予想できません。なので、自動変数にするなら、プログラムの起動時(main()内とかで)に記憶領域 p[] を確保し、プログラム動作中はその内容を保持し続けるようなコーディングにする必要があります。

beginner07
質問者

お礼

回答ありがとうございます。 確かに自動領域の開放については良く考えていませんでした。 しかし、今回は盤面の内容はboard[][]に覚えさせていて、p[]は石を置ける場所を一時的に記憶するためにだけ使っているので大丈夫だと思います。

すると、全ての回答が全文表示されます。
  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.2

count_turn_over の中で, p.dr とか p.dc をチェックしてみたら?

beginner07
質問者

お礼

回答ありがとうございます。 チェックしてみましたが、特に問題はないようでした。 ところで、find_legal_moveからis_legal_move,count_turn_overと関数を呼び出していくと、 繰り返し処理が500回以上になってしまいます。 これが何か原因になっていないでしょうか?

すると、全ての回答が全文表示されます。
noname#98978
noname#98978
回答No.1

>セグメンテーション違反になってしまいます。 >原因を教えていただけないでしょうか。 不正なアドレスに書き込みなどしているのが原因です。

beginner07
質問者

お礼

回答ありがとうございます。 勉強になりました。

すると、全ての回答が全文表示されます。

関連するQ&A