プロが教えるわが家の防犯対策術!

以下のようにプログラムをつくりました

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

void cleanSquare(void);
void hand(char);
void hand_CPU(char);
void printSquare(void);
void judge(void);
void three(char, char, char);
char square[3][3];
int nokori = 9;

int main( void )
{
cleanSquare();
printSquare();

while(1)
{
printf("Your turn.\n");
printf("Input (x,y) :");
hand('o');
printf("CPU chose (x,y):");
hand_CPU('x');
}
}

void cleanSquare(void)
{
int x, y;
for(x = 0; x < 3; x++)
{
for(y = 0; y < 3; y++ )
{
square[x][y] = ' ';
}
}
}

void hand(char mark)
{
int h, v;
scanf("%1d%1d", &h, &v);

while(square[h][v] != ' ' )
{
printf("%1d-%1dは埋まっています。再入力(横縦):", h, v);
scanf("%1d%1d", &h, &v);
}
square[h][v] = mark;
nokori--;
printSquare();
judge();
if(!nokori)
{
printf("引き分け\n");
exit(1);
}
}

void hand_CPU(char mark)
{
int h, v;
srand(time(NULL));
//scanf("%1d%1d", &h, &v);
h = rand() % 3;
v = rand() % 3;

printf("(%d,%d)\n", h, v);

while(square[h][v] != ' ' )
{
printf("%1d-%1dは埋まっています。再入力(横縦):", h, v);
scanf("%1d%1d", &h, &v);
}
square[h][v] = mark;
nokori--;
printSquare();
judge();
if(!nokori)
{
printf("Tie \n");
exit(1);
}
}

void printSquare(void)
{
int cnt;
printf("\n 0 1 2\n");
printf(" -------------\n");
for(cnt = 0; cnt < 3; cnt++)
{
printf("%1d| %c | %c | %c |\n", cnt, square[0][cnt], square[1][cnt], square[2][cnt]);
printf(" -------------\n");
}
}

void judge(void)
{
int x, y;
for(y = 0; y < 3; y++)
{
three(square[0][y], square[1][y], square[2][y]);
for(x = 0; x < 3; x++)
{
three(square[x][0], square[x][1], square[x][2]);
three(square[0][0], square[1][1], square[2][2]);
three(square[2][0], square[1][1], square[0][2]);
}
}
}

void three(char a, char b, char c)
{
if(a == ' ')
{
return;
}
if(a == b && b == c)
{
if(a == 'o')
{
printf("Win! \n");
}
else
{
printf("Lose. \n");
}
exit(1);
}
return;
}

以前、学校の課題としてでたものを復習していたのですが、わからない部分がでてきました。
このプログラムを次のように改造したいのですが、どのように改造すればいいのかわかりません

1.ゲーム全体を関数化する
main関数でこの関数を呼び出すと何回もゲームができるようにする
int game(int n)と宣言しようと考えています

2.マス目の大きさを関数game()が引数として受け取ったnを、n×nのマス目でゲームができるようにする
nは、ゲームごとにmain関数で入力
10×10までの大きさ

3.自分の番の時に、座標を入力する時に負の値が入力されたら、ゲームを終了させる
4.勝敗の記録と表示

例えば、引き分けを0、勝ちを1、負けを2、途中終了を-1
を戻り値として返すようにして、途中終了以外の場合はゲームの成績を
勝ち:3、負け:2、引き分け:0のように表示する

5.ゲーム終了後に続けるか、やめるかの選択
文字を一文字入力して、'y'なら1を返し、'n'なら0を返す
それ以外の文字だったら、再入力させるという処理を関数化する
int newgame(void)として宣言しようと考えています
また、この関数の戻り値が0の場合プログラムの終了、1なら新しいゲームの開始

です。長くて申し訳ないですm(_ _)m
よろしくお願いしますm(_ _)m

A 回答 (1件)

1. main関数も「関数」です。


とりあえず、 int main( void ) を int game(int n)に書き換えて、
新しく int main(void) { game(0); } とでも加えれば、1回だけはできます。

2回以上続けられないのは、exit を使っているからです。
game関数を呼び出しても、いろんなところから強制的にプログラム終了されてしまうため、制御できないのです。
exitは本当に致命的なエラーのときだけにして、通常はreturnで呼び出し側に戻るようにします。

例えば、 関数three は 戻り値をintにして
-1: ○がそろった
0:揃ってない
+1:×がそろった
を返すようにします。WinだのLoseだのは、ここではやりません。

threeの結果を呼び出し側のjudgeで受けます。
この戻り値で0で無いものがあれば、それがこの局面での勝敗です。
そこで、同じく-1,0,1を返します。
それを呼び出した側で受け取って...
と次々呼び出した側に戻していきます。
最終的に、どこかで、 if ( result==-1) { printf ("Win");}て感じに戻り値で分岐すればいいのです。
例えば、game()までこのように戻していくと、main関数内で

result=game(3);
if (result==-1) {
printf("WIN");
countWin ++ ;
} else if (result==1) {
...

とすれば、4.も実現が容易です。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!