前提・実現したいこと
オセロのAIの関数を作っていて「Bus error 10」が表示されます。
再帰関数で手番を交代していきながら、必要な情報を手に入れるという内容です。以下に具体的に書いています。
Bus error は配列のインデックスが超えたりすると起こったりするとの認識なのですが、
疑問に思っていることは、あまりにも探索時間(処理時間)が長い場合に、Bus error 10は出たりしますか?
<内容>
注意!ここでの 自分 はコンピュータ側のことを指します。
<前提>
相手は常に最善の手を打ってくる。
ohelloAI関数が呼ばれると、その手番から勝敗が決定する最終局面まで再帰関数で処理して、その結果を返り値で返す(自分の、勝利は1を、引き分け・敗北はZERO(=0)。
相手の手番にZERO(=0)が返り値として返ってくると、その(自分は敗北する・相手は負けない)マスに打たれて、自分は敗北する。ので、相手手番に複数置ける場所があったとして、複数箇所を探索する前にZEROが返ってくるとif文でreturn ZEROを返します。
自分の手番の時には、上記とは逆で、ZERO(=0)でない返り値が返ってくるとそこに打つというようにします。同様に複数置ける場所があったとして、複数箇所探索する前にZERO以外が帰ってくるとif文で関数の都合上return (そのマスの座標)を返します。
該当のソースコード
c
1int othelloAI(void) 2{ 3 static int mass[60][SIZE][SIZE]; 4 static int t = 0; 5 6 memcpy(mass[t], c_mas2, sizeof(mass[t])); 7 8 return othello_AI_check(t, mass); 9} 10 11int othello_AI_check(int ar_turn, int mass[60][SIZE][SIZE]) 12{ 13 static int counta[70] = {0}; 14 static int countb[70] = {0}; 15 static int eva_count[70]; 16 static int skip_count = 0; 17 18 if (E_cnt_AI(mass[ar_turn]) == 0) //最後までいった(マスが全て埋まった)とき 19 { 20 skip_count = 0; //連続してパスはなかったので初期化する 21 if (result_AI(mass[ar_turn]) == 1) 22 return 10 * countb[ar_turn] + counta[ar_turn]; 23 } 24 25 eva_count[ar_turn] = 0; //初期化する。他のcount変数はfor文で初期化されている 26 27 turn_change(ar_turn); 28 29 if (ar_turn % 2 == 0)//自分の手番 30 { 31 for (counta[ar_turn] = 1; counta[ar_turn] <= 8; counta[ar_turn]++) 32 { 33 for (countb[ar_turn] = 1; countb[ar_turn] <= 8; countb[ar_turn]++) 34 { 35 if (check_AI(ar_turn, mass[ar_turn], counta[ar_turn], countb[ar_turn]) == 1)//置ける箇所か判定し、置ける時は1を返します 36 { 37 mass[ar_turn][counta[ar_turn]][countb[ar_turn]] = my_color; 38 gl_y = counta[ar_turn];//calcularionaiで使う 39 gl_x = counta[ar_turn]; 40 calculationai(mass[ar_turn]);//駒をひっくり返す 41 memcpy(mass[ar_turn + 1], mass[ar_turn], sizeof(mass[ar_turn]));//ar_turn+1のますに現在のマスをコピー 42 43 if (othello_AI_check(ar_turn + 1, mass) != 0) //自分の手番で、返り値が1の時、それ以降は調べる必要がなくなる。また相手の時も同様に返り値が0の時それ以降は調べる必要がなくなる。 44 return 10 * countb[ar_turn] + counta[ar_turn]; 45 eva_count[ar_turn]++; 46 } 47 } 48 } 49 50 if (eva_count[ar_turn] == 0) //置く所がなかった(パスの時) 51 { 52 if (skip_count == 1)//両方打てなくなった時(スキップが二回続いた時) 53 { 54 if (result_AI(mass[ar_turn]) == 1) 55 return 10 * countb[ar_turn] + counta[ar_turn]; 56 else 57 ZERO; 58 } 59 skip_count = 0; //連続してパスはなかったのでリセットする 60 skip_count++; 61 memcpy(mass[ar_turn + 1], mass[ar_turn], sizeof(mass[ar_turn])); 62 return othello_AI_check(ar_turn + 1, mass); 63 } 64 else //置くところはあるが返り値が全てZERO(=0)であった場合 65 skip_count = 0; //連続してパスはなかったのでリセットする 66 return ZERO; 67 } 68//_______________________________________________________________相手の手番 以下似た処理 69 70 else//相手の手番 71 { 72 for (counta[ar_turn] = 1; counta[ar_turn] <= 8; counta[ar_turn]++) 73 { 74 for (countb[ar_turn] = 1; countb[ar_turn] <= 8; countb[ar_turn]++) 75 { 76 if (check_AI(ar_turn, mass[ar_turn], counta[ar_turn], countb[ar_turn]) == 1) 77 { 78 mass[ar_turn][counta[ar_turn]][countb[ar_turn]] = my_color; 79 gl_y = counta[ar_turn]; 80 gl_x = counta[ar_turn]; 81 calculationai(mass[ar_turn]); 82 memcpy(mass[ar_turn + 1], mass[ar_turn], sizeof(mass[ar_turn])); 83 if (othello_AI_check(ar_turn + 1, mass) == ZERO) 84 return ZERO; 85 eva_count[ar_turn]++; 86 } 87 } 88 } 89 90 if (eva_count[ar_turn] == 0) //置く所がなかった(パスの時) 91 { 92 if (skip_count == 1)//両方打てなくなった時(スキップが二回続いた時) 93 { 94 if (result_AI(mass[ar_turn]) == 1) 95 return 10 * countb[ar_turn] + counta[ar_turn]; 96 else 97 ZERO; 98 } 99 skip_count = 0; //連続してパスはなかったのでリセットする 100 skip_count++; 101 memcpy(mass[ar_turn + 1], mass[ar_turn], sizeof(mass[ar_turn])); 102 return othello_AI_check(ar_turn + 1, mass); 103 } 104 else //置くところはあったが返り値が全て1であった場合 105 skip_count = 0; //連続してパスはなかったのでリセットする 106 return 10 * countb[ar_turn] + counta[ar_turn]; 107 } 108}
試したこと
再帰関数で一度は再帰関数で呼び出せることは確認.
配列のインデックスが超えることもないと思います。(確認する限り)
補足情報(FW/ツールのバージョンなど)
c言語
mac pro
vscode
回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。