質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

3回答

1951閲覧

3次元オセロのプログラミング

TakumiMiyamoto

総合スコア11

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2016/09/20 03:05

このプログラミングで実行すると、どこにもコマをおけない上に、何行目かの入力をするとどこに置くこともなく順番交代してしまいます。
おそらくcheckという関数のどこかとcontinueやgotoの使い方がまずいのかと考えているのですが、なにがまずいのかわかりません。
問題点を教えてください。
返信お待ちしております。

C++

1コード 2#include <iostream> 3using namespace std; 4 5int check_dir(int tate, int yoko, int ue, int block[4][4][4], 6 int junban, int dtate, int dyoko, int due){ 7 8for(dtate=-1;dtate<=1;dtate++){ 9 for(dyoko=-1;dyoko<=1;dyoko++){ 10 for(due=-1;due<=1;due++){ 11 if(dtate==0 && dyoko==0 && due==0){ 12 continue; 13 } 14 15 tate += dtate; //隣に移動 16 yoko += dyoko; //隣に移動 17 ue += due; //隣に移動 18 19 if ( tate < 0 || tate > 3 || yoko < 0 || yoko > 3 || ue < 0 || ue >3 ){ 20 return 0; //枠外で即アウト 21 } 22 if ( block[tate][yoko][ue] == 0 ){ 23 return 0; //隣が空なので即アウト 24 } 25 26 if ( block[tate][yoko][ue] == junban ){ 27 return 0; //隣が自分の色なのでアウト 28 } 29 30 while(1){ 31 32 tate += dtate; //さらに隣に移動 33 yoko += dyoko; //さらに隣に移動 34 ue += due; //さらに隣に移動 35 36 if ( tate < 0 || tate > 3 || yoko < 0 || yoko > 3 || ue < 0 || ue > 3 ){ 37 return 0; //枠外でアウト 38 } 39 40 if ( block[tate][yoko][ue] == 0 ){ 41 return 0; //空のマスにぶつかってアウト 42 } 43 if ( block[tate][yoko][ue] == junban ){ 44 return 1; //自分の色の石にぶつかってOK 45 break; 46 } 47 } 48 } 49 } 50 } 51} 52 53int check(int tate, int yoko, int ue, int block[4][4][4], int junban){ 54 if ( block[tate][yoko][ue] != 0 ){ //その場所が空じゃない時 55 return 0; //そこにはおけないので値0を返す 56 } 57 //26方向をそれぞれ調べる。いずれかがOKなら、石が置けることが 58 //わかったので、その段階で1を返して関数を終了。 59 int i; 60 int j; 61 int k; 62 63 for( i=-1; i<=1; i++ ){ 64 for( j=-1; j<=1; j++ ){ 65 for( k=-1; k<=1; k++ ){ 66 if( i==0 && j==0 && k==0){ 67 continue; 68 if ( check_dir(tate,yoko,ue,block,junban, i, j, k) == 1 ){ 69 return 1; 70 } 71 if ( check_dir(tate,yoko,ue,block,junban, i, j, k) == 0 ){ 72 return 0; 73 } 74 return 0; //その他のケースはおけない 75 76 } 77 } 78 } 79 } 80} 81int passcheck(int block[4][4][4], int junban){ 82 for(int tate=0; tate<4; tate++ ){ 83 for(int yoko=0; yoko<4; yoko++){ 84 for(int ue=0; ue<4; ue++){ 85 if(check(tate,yoko,ue,block,junban)==1){ //おける! 86 return 0; //0を返して関数終わり 87 } 88 } 89 } 90 return 1; //おける場所が1箇所もなかった 91 } 92} 93void reverse_dir(int tate, int yoko, int ue, int block[4][4][4],int junban, int dtate, int dyoko, int due) { 94 95 tate += dtate; // 隣に移動 96 yoko += dyoko; // 隣に移動 97 ue += due; // 隣に移動 98 99 block[tate][yoko][ue] = junban; // 隣は自分の色に置き換え 100 101 while ( 1 ) { 102 103 tate += dtate; // さらに隣に移動 104 yoko += dyoko; // さらに隣に移動 105 ue += due; // さらに隣に移動 106 107 if ( block[tate][yoko][ue] == junban ) { 108 return; // 自分の色の石にぶつかったら終了 109 } 110 111 block[tate][yoko][ue] = junban; // 自分の色に置き換え 112 113 } 114} 115 116void reverse(int tate, int yoko, int ue, int block[4][4][4], int junban) { 117int i; 118int j; 119int k; 120 for( i=-1; i<=1; i++ ){ 121 for( j=-1; j<=1; j++ ){ 122 for( k=-1; k<=1; k++ ){ 123 124 if ( check_dir(tate, yoko,ue, block, junban, i, j, k ) == 1 ) { 125 reverse_dir(tate, yoko, ue, block, junban, i, j, k ); 126 } 127 } 128 } 129 } 130 } 131 132int main(void){ 133 cout <<" OOOO h l l 333333 DDDDD \n"; 134 cout <<"OO OO t h eeeee l l @ 3 33 D DDD \n"; 135 cout <<"O O ttttttt h hhh ee eee l l oooo nnnn 3 3 D DD \n"; 136 cout <<"O O t hh h eeeeeeee l l o o i n nn 3333 D D \n"; 137 cout <<"OO OO t h h e l l o o i n n 3 3 D DD \n"; 138 cout <<" OOOO t h h eeeee l l oooo i n n 3 33 D DDD \n"; 139 cout <<" 333333 DDDDDD \n"; 140 141 //三次元配列 block[][][] の準備 142 int block[4][4][4]; 143 for(int i=0;i<=3; i++){ 144 for(int j=0;j<=3; j++){ 145 for(int k=0;k<=3; k++){ 146 block[i][j][k]=0; 147 } 148 } 149 block[1][1][1]=block[2][2][2]=block[2][1][1]=1; 150 block[1][1][2]=block[2][2][1]=block[1][2][2]=2; 151 } 152 //順番の指定 153 int junban=2; //黒から始める 154 155 int copy[4][4][4]; 156 157 int tate,yoko,ue; 158 159 int shiro,kuro; 160 161 int red1,red2; 162 red1=0; 163 red2=0; 164 165 while(1){ 166 167 168 //オセロ盤の表示 169 170 for(int k=0;k<=3;k++){ 171 cout << k+1 << "段目\n"; 172 cout << " 1 2 3 4 \n"; 173 for(int i=0;i<=3; i++){ 174 cout << " +---+---+---+---+\n"; 175 cout << i+1 << " |"; 176 177 for(int j=0;j<=3;j++){ 178 179 if(block[i][j][k]==0){ 180 cout << " " << "|"; 181 } 182 if(block[i][j][k]==1){ 183 cout << " O " << "|"; 184 } 185 if(block[i][j][k]==2){ 186 cout << " @ " << "|"; 187 } 188 } 189 cout << "\n"; 190 } 191 cout << " +---+---+---+---+\n"; 192 cout << "\n"; 193 } 194 195 //枚数を数えて表示 196 197 shiro=kuro=0; //shiroとkuroを0にリセット 198 for(int i=0; i<4; i++){ 199 for(int j=0; j<4; j++){ 200 for(int k=0; k<4; k++){ 201 if(block[i][j][k]==1){ 202 shiro++; 203 } 204 if(block[i][j][k]==2){ 205 kuro++; 206 } 207 } 208 } 209 } 210 cout << "O: " << shiro << "枚 @: " << kuro << "枚" 211 << " 合計: " << shiro + kuro << "枚\n"; 212 213 214 215 //必要ならループを抜ける 216 if( ( shiro + kuro ) == 64 || shiro== 0 || kuro== 0 ){ 217 break; 218 } 219 220 //順番の表示 221 if(junban==1){ 222 cout << "Oの番だよ\n"; 223 }else{ 224 cout << "@の番だよ\n"; 225 } 226 227 //縦位置tateの入力 228 do{ 229 cout << "何行目?[1~4]:"; 230 cin >> tate; 231 232 }while(tate < -1 || tate > 5 ); 233 tate--; 234 235 if(tate==-1){ 236 break; //retire機能 237 } 238 239 240 241 if(tate==4){ 242 243 if(red1==1){ 244 break; 245 } //2回パスしたらその時点でゲーム終了 246 if(red2==1){ 247 break; 248 } 249 if(junban==2){ 250 red1++; 251 } 252 if(junban==1){ 253 red2++; 254 } 255 256 goto finish; //pass機能 257 } 258 259 if(tate=-2){ 260 block[4][4][4]=copy[4][4][4]; 261 goto finish; 262 } //一つ前の状態に戻す 263 264 265 //横位置yokoの入力 266 do { 267 cout << "何列目?[1~4]:"; 268 cin >> yoko; 269 yoko--; 270 } while(yoko < 0 || yoko > 3 ); 271 272 //段ueの入力 273 do{ 274 cout << "何段目?[1~4]:"; 275 cin >> ue; 276 ue--; 277 }while(ue< 0 || ue > 3 ); 278 279 copy[4][4][4]=block[4][4][4]; //返す前の状態を記憶 280 281 if( check(tate, yoko, ue, block, junban) == 1 ){ 282 //石をひっくり返す 283 reverse(tate,yoko,ue,block,junban); 284 285 //石を置く 286 block[tate][yoko][ue] = junban; 287 288 finish: 289 //順番交代 290 junban = 3-junban; 291 } else{ 292 cout << "そこにはおけないよ!\n"; 293 } 294 295 296 } //while(1)の終わり 297 298 //終了処理 299 cout << "ゲーム終了\n"; 300 if( shiro > kuro ){ 301 cout << "0の勝ち!\n"; 302 } 303 if( shiro < kuro ){ 304 cout << "@の勝ち!\n"; 305 } 306 if( shiro == kuro ){ 307 cout << "引き分け・・・\n"; 308 } 309 return 0; 310 } 311 312 313 314

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

処理をスキップしているところにデバッグ文を入れて、想定外の条件になっていないかを確認すると良いと思います。
あるいは、デバッガを利用して、デバッグ文を入れる代わりにbreak pointを設定すると良いでしょう。

投稿2016/09/20 04:45

t_obara

総合スコア5488

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

0

とりあえずちょっと見た感じ block は大域変数にするかオセロクラスを作ってメンバにするかなんかした方がいいと思う。

投稿2016/09/21 10:48

WoodenHamlet

総合スコア306

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakumiMiyamoto

2016/09/22 02:41

ありがとうございます。 もう少し勉強して、このプログラムを根本的に改善する際にやってみます。
guest

0

ベストアンサー

checkという関数しか見ていませんが、とりあえず

for( i=-1; i<=1; i++ ){ for( j=-1; j<=1; j++ ){ for( k=-1; k<=1; k++ ){ if( i==0 && j==0 && k==0){ continue; if ( check_dir(tate,yoko,ue,block,junban, i, j, k) == 1 ){ return 1; } if ( check_dir(tate,yoko,ue,block,junban, i, j, k) == 0 ){ return 0; } return 0; //その他のケースはおけない } } } }

の部分についてはcontinueの後でif文が終っておらず、continueの後ろにcheck_dirによる判定があります。しかしcontinueの後ろにある為これらは実行されません。
またfor文内でどこにも引っかからずにそのまま終わり、return文が定義されていない為不定値が関数の戻り値として帰ります。スタックの状態によっては0だったり1だったりするでしょう。
またcontinueが正常になったとしても、1回目のforの実行で必ず何らかのreturnで帰る記述になっている為、forの意味がありません。
もう少し色々と見直した方が良いでしょう。

投稿2016/09/20 06:31

drednote

総合スコア336

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

TakumiMiyamoto

2016/09/22 02:39

ありがとうございます。恥ずかしながら、基礎的な部分でミスをしていました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問