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

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

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

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

463閲覧

C言語でオセロに機能を追加したい

otogen

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2019/01/27 04:02

前提・実現したいこと

C言語の初心者でC言語でオセロを作っています。
配置可能箇所を表示する機能を実装したいのですが、中々うまくいきません。
どうかお力添えいただけないでしょうか。

発生している問題・エラーメッセージ

help機能の動作、呼び出しがうまくいきません。

該当のソースコード

C

1#include <stdio.h> 2#include <ctype.h> 3//-----------------------------------マクロ定義 4//盤面の大きさ 5#define SIZE 8 // 8x8のサイズとする 6 7//状態を定義 8#define NONE 0 //空 9#define BLACK 1 //黒 10#define WHITE 2 //白 11//-----------------------------------グローバル変数 12//盤面 13int board[ SIZE ][ SIZE ]; //board[ 縦 ][ 横 ] 14 15//プレーヤー BLACK or WHITE 16int player = BLACK; //先手は黒 17 18//コマを置く位置 x:横 y:縦 範囲は0~SIZE-1 19int x = 0, y = 0; 20 21//-----------------------------------関数のプロトタイプ宣言 22void vanish( void ); 23void display( void ); 24void input( void ); 25int is_ok( void ); 26void put( void ); 27int check( int x, int y, int dx, int dy ); 28void flip( int x, int y, int dx, int dy); 29int simple_check_end( void ); 30void help( int y,int x ); 31//----------------------------------- 32//メイン関数 33// 34int main(int argc, char **argv) 35{ 36 37 vanish(); //盤面の初期化 38 39 player = BLACK; //先手は黒 40 while( 1 ){ //ゲームのループ(無限ループなので、このままでは終われない!) 41 42 //ここで手番を表示 43 44 display(); //盤面表示 45 46 input(); //コマの位置を入力 47 48 put(); //コマを置き,裏返す 49 50 if( player == BLACK ){ //手番交替 51 player = WHITE; 52 } 53 else{ 54 player = BLACK; 55 } 56 if(simple_check_end()==1) 57 { 58 printf("\n"); 59 display(); //盤面表示 60 break; 61 } 62 } 63 return 0; 64 65} 66//----------------------------------- 67//初期化関数 68// 機能:盤面に初期値を設定する 69// 引数:なし 70// 戻り値:なし 71// 72void vanish( void ) 73{ 74 int i,j ; 75 76 77 for( i = 0; i < SIZE; i++ ){ //縦のループ 78 for( j = 0; j < SIZE; j++ ){ //横のループ 79 board[ i ][ j ] = NONE; //とりあえず全部空きにしておく 80 board[3][3] = WHITE; 81 board[4][4] = WHITE; 82 board[3][4] = BLACK; 83 board[4][3] = BLACK; 84 } 85 } 86 //それから中央にコマを配置する 87 return; 88} 89 90//----------------------------------- 91//盤面表示関数 display 92// 機能:現在の盤面を表示する 93// 引数:なし 94// 戻り値:なし 95//一文字の時にhelpを呼び出す 96void display( void ) 97{ 98 int i ; 99 int j ; 100 printf(" "); 101 printf(" A B C D E F G H "); 102 printf("\n"); 103 104 for( i = 0; i < SIZE; i++ ){ //縦のループ 105 printf( "%2d", i ); //縦の位置を示す数字 106 for( j=0; j < SIZE; j++ ){ //横のループ 107 108 if( board[ i ][ j ] == NONE ){ //空なら 109 printf( "・" ); 110 }else if( board[ i ][ j ] == BLACK ){ //黒なら 111 printf( "●" ); 112 }else if( board[ i ][ j ] == WHITE ){ //白なら 113 printf( "○" ); 114 }else { 115 printf( "?" ); //今のところ、それ以外はない 116 } 117 118 } 119 printf( "\n" ); //横の最後は改行しておく 120 } 121 return; 122} 123//----------------------------------- 124//入力関数 125// 機能:キーボードからコマを置く位置をx,yに入力する 126// 引数:なし 127// 戻り値:なし 128// 129void input( void ) 130{ 131// int x, y; //コマを置く位置 132 char c; 133 while( 1 ){ //正しく入力されるまで繰り返す 134 135 printf( "横と縦を空白区切りで入力 >" ); 136 scanf( "%c %d", &c, &y ); 137 while(getchar()!='\n'); 138 x=tolower(c)-'a'; 139 //盤面内か確認 140 141 if(c=="p"||y=="\0") 142 { 143 help(y,x); 144 continue; 145 } 146 if(x<0 || x>=SIZE || y<0 || y>=SIZE ) 147 { 148 printf("指定可能範囲外です。\n"); 149 continue; 150 } 151 //空いているか確認 152 if(board[y][x]!=NONE) 153 { 154 printf("\n"); 155 printf("コマが存在します\n"); 156 continue; 157 } 158 //裏返すことができるか確認 159 if(is_ok() == 0) 160 { 161 printf("\n"); 162 printf("コマを反転できません\n"); 163 continue; 164 } 165 return; //正しく入力できたら戻る 166 } 167 //ここには来ないはず 168} 169 170//----------------------------------- 171//コマを置き,裏返す関数 put 172// 機能:全ての方向に,裏返せるならば,裏返す 173// 引数:なし 174// 戻り値:なし 175// 176void put( void ) 177{ 178 179 //まずコマを置く 180 board[ y ][ x ] = player; 181 182 183 //全方向について裏返せるか確認して、裏返す 184 if( check( x, y, 1, -1 ) == 1 ) //右上 185 flip( x, y, 1, -1 ); 186 if( check( x, y, 1, 0 ) == 1 ) //右 187 flip( x, y, 1, 0 ); 188 if( check( x, y, 1, 1 ) == 1 ) //右下 189 flip( x, y, 1, 1 ); 190 if( check( x, y, 0, -1 ) == 1 ) //上 191 flip( x, y, 0, -1 ); 192 if( check( x, y, 0, 1 ) == 1 ) //下 193 flip( x, y, 0, 1 ); 194 if( check( x, y, -1, -1 ) == 1 ) //左上 195 flip( x, y, -1, -1 ); 196 if( check( x, y, -1, 0 ) == 1 ) //左 197 flip( x, y, -1, 0 ); 198 if( check( x, y, -1, 1 ) == 1 ) //左下 199 flip( x, y, -1, 1 ); 200 201 return; 202} 203 204//----------------------------------- 205//チェック関数 check 206// 機能:指定された方向について、裏返るコマがあるか確認する 207// 引数:x,y:コマを置く位置,dx,dy:移動する方向への差分(±1) 208// 戻り値:0は裏返らない,1は裏返る 209// 210int check( int x, int y, int dx, int dy ) 211{ 212 int flag = 0; //相手のコマがあったかどうか 0:ない 1:ある 213 while( 1 ){ 214 x += dx; //x方向に移動してみる 215 y += dy; //y方向に移動してみる 216 217 if( x < 0 || y < 0 || x > SIZE-1 || y > SIZE-1) 218 return 0; //盤面の外に出ていたら終了 219 220 if( board[ y ][ x ] == NONE ) 221 return 0; //空きマスだったら終了 222 223 //相手のコマがあったらフラグを立てて、その先を探す 224 if( board[ y ][ x ] != player ){ //このチェック方法は要注意! 225 flag = 1; 226 continue; //続ける 227 } 228 if( board[ y ][ x ] == player ){ //ここまで来たら自分のコマのはず 229 if( flag == 1 ) 230 return 1; //もしフラグがたっていれば戻り値1で終了。いなければ終了 231 else 232 return 0; 233 } 234 //ここには来ないはず 235 } 236} 237 238//----------------------------------- 239//挟まれた相手のコマを裏返す関数 flip 240// 機能:指定された方向について、実際に裏返す 241// 引数:x,y:コマを置く位置,dx,dy:移動する方向への差分(±1) 242// 戻り値:なし 243// 244void flip( int x, int y, int dx, int dy) 245{ 246 while( 1 ){ 247 x += dx; 248 y += dy; 249 250 if( board[ y ][ x ] == player ) 251 break; //自分のコマまできたら終了 252 253 board[ y ][ x ] = player; //そうでなければ相手のコマなので自分のコマに変える 254 } 255 return; 256} 257 258//----------------------------------- 259//簡易版終了チェック関数 simple_check_end 260// 機能:終了を調べる 261// 引数:なし 262// 戻り値:1:終了 0:終了でない 263// 264int simple_check_end( void ) 265{ 266 int i, j; 267 int flag; 268 269 flag = 1; //とりあえず終了にしておく 270 for( i = 0; i < SIZE; i++ ){ //縦のループ 271 for( j = 0; j < SIZE; j++ ){ //横のループ 272 if( board[ i ][ j ] == NONE ) flag = 0; //空きがあった 273 } 274 } 275 if( flag == 0 ) 276 return 0; //空きがあれば続けるの戻り値 277 else 278 return 1; //空きがなければ終了の戻り値 279} 280//----------------------------------- 281//コマが置けるかどうか(裏返せるかどうか)調べる関数 is_ok 282// 機能:いずれかの方向に置けるかを調べる 283// 引数:なし 284// 戻り値:0は置けない,1は置ける 285// 286int is_ok( void ) 287{ 288 int ok = 1; //裏返せる(置ける)と仮定 289 if( check( x, y, 1, -1 ) == 1 ) //右上 290 return ok; //置ける 291 if( check( x, y, 1, 0 ) == 1 ) //右 292 return ok; //置ける 293 if( check( x, y, 1, 1 ) == 1 ) //右下 294 return ok; //置ける 295 if( check( x, y, 0, -1 ) == 1 ) //上 296 return ok; //置ける 297 if( check( x, y, 0, 1 ) == 1 ) //下 298 return ok; //置ける 299 if( check( x, y, -1, -1 ) == 1 ) //左上 300 return ok; //置ける 301 if( check( x, y, -1, 0 ) == 1 ) //左 302 return ok; //置ける 303 if( check( x, y, -1, 1 ) == 1 ) //左下 304 return ok; //置ける 305 // ここまで来たら 306 ok = 0; //置けない 307 return ok; 308} 309//----------------------------------- 310// 配置確認関数 help 311// 機能:配置可能個所の確認 312// 引数:なし 313// 戻り値:なし 314void help( int y,int x ) 315{ 316 317 int i; 318 int box[8][8]={ 319 {0,1,2,3,4,5,6,7},//0,n 320 {0,1,2,3,4,5,6,7},//1,n 321 {0,1,2,3,4,5,6,7},//2,n 322 {0,1,2,3,4,5,6,7},//3,n 323 {0,1,2,3,4,5,6,7},//4,n 324 {0,1,2,3,4,5,6,7},//5,n 325 {0,1,2,3,4,5,6,7},//6,n 326 {0,1,2,3,4,5,6,7} //7,n 327 }; 328 for(i=0; SIZE>box[y][x];i++){ 329 //盤面内か確認 330 if(x<0 || x>=SIZE || y<0 || y>=SIZE ) 331 { 332 i++; 333 } 334 //空いているか確認 335 if(box[y][x]!=NONE) 336 { 337 i++; 338 } 339 //裏返すことができるか確認 340 if(is_ok() == 0) 341 { 342 i++; 343 } 344 //配置可能である場合 345 if(box[y][x]==NONE&&is_ok() == 1) 346 { 347 printf("%d\n",box[8][8]); 348 i++; 349 } 350 } 351return; 352} 353

試したこと

・void help( int y,int x )が呼び出せているかの確認。
-呼び出せてはいるが、配置可能な箇所を表示せずに戻っている。
・入力関数にvoid help( int y,int x )呼び出し用のif(c=="p"||y=="\0")を追加。
-何を入力しても配置可能範囲外と表示されるようになってしまった。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

guest

回答2

0

C言語のコードを組みたいのであれば、デバッグ環境を整えましょう
WindowsであればVisualStudio、そうでなければEclipseなど、
これらの統合環境では、C言語のコードの任意の行で実行を停止させ、変数の値を参照したり、1行づつステップ実行させて変数の値を追いかけるなどができるようになります
そうすれば、あてずっぽでコードを組む、ということをしなくて済みます

投稿2019/01/27 06:03

y_waiwai

総合スコア87774

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

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

otogen

2019/01/27 06:20

回答ありがとうございます。 ツールに関して記す場所を見落としておりました、PC環境はwindowsで使用ツールに関しましてはGeanyを使っています。 が、やはりそちらの方が安心でしょうか。 導入してみて見直してみようと思います。
y_waiwai

2019/01/27 06:30

ああ、単なる老婆心でのアドバイスです。 すでにソースデバッグできる環境をお持ちなら、使い慣れている環境のほうがいいでしょう
guest

0

ベストアンサー

is_okがグローバル変数の x, y を参照しているのに対して、helpは引数の x, y を参照しているせいだと思います。この2つは別物です(ワーニング出てないでしょうか?)
x, yのような一時的な値をグローバル変数にするのはいつ値が変更されたのかがわかりにくくなりバグの元です。まずグローバル変数のx, yを削除しましょう。
is_okに引数 x, y を追加して、helpからis_ok(x, y)となるようにしてみてください。

投稿2019/01/27 05:31

toki_td

総合スコア2850

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

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

otogen

2019/01/27 06:20

回答ありがとうございます。 初期はただのオセロのプログラムだったのですが、数字を文字にする、今悩んでる機能を追加する。 としてる内に自分でもこんがらがってしまいそこまで目が回っていませんでした。 アドバイスを元に修正してみます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問