オセロゲームのプログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
milk
記事: 9
登録日時: 8年前

オセロゲームのプログラム

#1

投稿記事 by milk » 8年前

お世話になっております。
C言語の課題で、オセロゲームを作成することになりました。
しかし、課題内容に沿うような表示が出来ません。また、ひっくり返す際はどのようにしたらよいのかがわからず困っています。 

長くなってしまいますが課題内容とソースコードです。

<課題>

文字型で10×10の配列を用意し、main 関数内で宣言定義し、配列の内側8×8の要素を用い文字(大文字エックス)'X'、(大文字オー)'O'、(空白文字)' 'をランダムに各要素(升目)に入力を行う。これをオセロゲームの一つの局面と考え(ランダム配置なので実際にはあり得ない局面かもしれないが)、各' 'の升目に対し、'X'は置けるのか'O'は置けるのかの判定を、関数 (setpos) でおこなうプログラムを作成しなさい。またsetpos関数では指定により裏返し処理も実行できるようにすること。

•'X'は黒、'O'は白、' 'は空白と考える
•' 'の位置は main 関数で検出し、関数setposに引数として知らせる(渡す)こと
•setpos関数は戻り値として置けない場合には0、置ける場合には裏返る数を返すこと
•都合上関数setposは次の形で宣言定義する

int setpos(int y, int x, char c, char p[ ][10], int on);

◦y: 置きたい升目の行
◦x: 置きたい升目の列
◦c: 置きたい文字('X' or 'O')
◦p[ ][10]:局面の配列
◦on: 裏返し処理実行無しは0、有りは1

•別の関数(名前はdisp)で、上図のように配列の内容を表示するプログラムを作成し、ランダム入力の後、表示を行うこと
•標準入力から升目を入力する場合にはA5、B8のような形で行えるようにすること
•main関数の機能で' 'の位置情報と裏返せる数の結果を表示させること
(例えば B0 X :1、 O :0)

<プログラム>

コード:

#define _CRT_SECURE_NO_WARNINGS

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



int setpos(int y, int x, char c, char p[][10], int on) {
	int vecY;
	int vecX;
	int reverseEach;
	int reverseTotal = 0;
	int i, j;

	for (vecY = -1; vecY <= 1; vecY++) {
		for (vecX = -1; vecX <= 1; vecX++) {

			if (vecX == 0 && vecY == 0) {
				continue;
			}

			reverseEach = 0;
			for (i = y + vecY, j = x + vecX; p[i][j] != ' '; i += vecY, j += vecX) {
				if (p[i][j] != c) {
					reverseEach++;
				}
				else if (reverseEach == 0)
					break;

				else {
					reverseTotal++;
				}
			}


			if (reverseTotal == 0)
				return 0;
			else {
				return reverseTotal;
			}

		}
	}
}

void disp(char *a)
{
	printf("  %c", *a);
}

int main(void) {
	int y, x;
	char a[10][10];

	int i = 0, j = 0, k, l;

	srand((unsigned)time(NULL));

	for (k = 0; k <= 7; k++) {
		for (l = 0; l <= 7; l++) {

			a[i][j] = (rand() % 3 + 0);

			if (a[i][j] == 2)
				a[i][j] = 'O';
			else if (a[i][j] == 1)
				a[i][j] = 'X';

			else {
				a[i][j] = ' ';

			}

			disp(&a[i][j]);


		}

		printf("\n");

	}

	printf("\n");

//	scanf("%d", &y);
//	scanf("%d", &x);

	setpos(1, 2, 'O', a, 0);

	return 0;

}

 
この課題内容に沿うプログラムを作成するにはどのようにしたらよいのか、お手数ですがご教授いただけましたら幸いです。

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: オセロゲームのプログラム

#2

投稿記事 by みけCAT » 8年前

milk さんが書きました: 課題内容に沿うような表示が出来ません。
milk さんが書きました: この課題内容に沿うプログラムを作成するにはどのようにしたらよいのか
この課題内容に沿うプログラムを考えて入力し、必要に応じてデバッグすればいいでしょう。
具体的には、表示の書式(「上図」)がここに書かれていないのでわかりません。
milk さんが書きました:配列の内側8×8の要素を用い
外側のマスが必ず空白になるようにし、番兵にしろという意味だと思います。
番兵を活用するには、
・盤面の左上を[0][0]ではなく[1][1]にする
・配列の盤面の外側のにあたる部分も空白で初期化する
ようにするといいでしょう。
ちなみに、初期化していない自動変数の値は不定です。
milk さんが書きました: また、ひっくり返す際はどのようにしたらよいのかがわからず困っています。
まずは、今のように左上だけ調べてreturnするのではなく、8方向の調査をするようにしましょう。
そして、ある方向でひっくり返せることがわかったら、コマを置く位置から順にひっくり返す位置に置くコマの記号を代入するとよさそうだと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

milk
記事: 9
登録日時: 8年前

Re: オセロゲームのプログラム

#3

投稿記事 by milk » 8年前

お返事遅くなり大変申し訳ありません。
ある程度完成したのですが、ひっくり返す時周囲すべてをひっくり返してしまいます。
どのように書けば挟まれているものだけをひっくり返すことが出来るようになるでしょうか・・。

コード:


#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>

#define NUM 10


int disp(char p[NUM][NUM])
{
	int i, j, k;
	printf("     ");
	for (i = 1; i < NUM - 1; i++)
		printf("[%d] ", i);
	putchar('\n');

	for (i = 1; i < NUM - 1; i++) {
		printf("     +");
		for (k = 1; k < NUM - 1; k++)
			printf("---+");
		putchar('\n');
		printf("[%d] ", i);
		for (j = 1; j < NUM - 1; j++)
			printf("| %-2c", p[i][j]);
		puts("|");
	}
	printf("    +");
	for (k = 1; k < NUM - 1; k++)
		printf("---+");
	putchar('\n');

	return 0;
}


int setpos(int y, int x, char c, char p[][NUM], int on) {

	int vecY;
	int vecX;
	int reverseEach;
	int reverseTotal = 0;
	int a, b, i, j;

	for (vecY = -1; vecY <= 1; vecY++) {
		for (vecX = -1; vecX <= 1; vecX++) {
			
			if (vecX == 0 && vecY == 0)
				continue;
		
			reverseEach = 0;
		
			for (i = y + vecY, j = x + vecX; p[i][j] != ' '; i += vecY, j += vecX) {
				
				if (p[i][j] != c) {
				
					reverseEach++;
					p[y][x] = c;
					p[i][j] = c;
				
				}

				else {
					if (reverseEach == 0)
						break;
					else {
						reverseTotal += reverseEach;

						break;
					}
				}
			}
		}
	}


	return reverseTotal;
}



int main(void) {

	char a[NUM][NUM] = {
	
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', 'o', 'x', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', 'x', 'o', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
		{ ' ',' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' },
	};

	int i, j, k, cx, co;
	int on, mass = 0, massY = 0, massX = 0;
	char massThing;
	char c = 'o';
	char d = 'x';
	int pass = 0;

	disp(a);
	printf("\n");

	while (pass != 2 || mass == NULL) {
		while (1) {

			printf("< player 1 :x > \n\n");

			printf("置きたいマス目を入力してください:");	scanf("%d", &mass);
			printf("\n");
			massY = mass / 10;
			massX = mass - massY * 10;

			if (a[massY][massX] != ' ') {
				printf("そのマスには置くことができません\n");
				pass++;
			}
			else
				break;
		}


		co = setpos(massY, massX, c, a, 1);
		cx = setpos(massY, massX, d, a, 1);

		disp(a);
		printf("\n");
		printf("座標:%d%d,O:%d個,X:%d個\n\n", massY, massX, cx, co);


		while (1) {
			
			printf("< player 2 :o > \n\n");

			printf("置きたいマス目を入力してください:");	scanf("%d", &mass);
			printf("\n");
			massY = mass / 10;
			massX = mass - massY * 10;

			if (a[massY][massX] != ' ') {
				printf("そのマスには置くことができません\n");
				pass++;
			}
			else
				break;
		}


		co = setpos(massY, massX, d, a, 1);
		cx = setpos(massY, massX, c, a, 1);

		disp(a);
		printf("\n");

		printf("座標:%d%d,O:%d個,X:%d個\n\n", massY, massX, co, cx);

	}

	return 0;

}


アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: オセロゲームのプログラム

#4

投稿記事 by みけCAT » 8年前

milk さんが書きました:お返事遅くなり大変申し訳ありません。
ある程度完成したのですが、ひっくり返す時周囲すべてをひっくり返してしまいます。
どのように書けば挟まれているものだけをひっくり返すことが出来るようになるでしょうか・・。
ある方向でひっくり返せることがわかったら、コマを置く位置から順にひっくり返す位置に置くコマの記号を代入するように書けばいいでしょう。

コード:

int setpos(int y, int x, char c, char p[][NUM], int on) {

	int vecY;
	int vecX;
	int reverseEach;
	int reverseTotal = 0;
	int a, b, i, j;

	for (vecY = -1; vecY <= 1; vecY++) {
		for (vecX = -1; vecX <= 1; vecX++) {
			
			if (vecX == 0 && vecY == 0)
				continue;
		
			reverseEach = 0;
		
			for (i = y + vecY, j = x + vecX; p[i][j] != ' '; i += vecY, j += vecX) {
				
				if (p[i][j] != c) {
				
					reverseEach++;
					/* まだひっくり返せるかわからないのに勝手に盤面を書き換えない */
				}

				else {
					/* ある方向でひっくり返せることがわかったら */
					int ii, jj;
					/* コマを置く位置から順に */
					for (ii = y + vecY, jj = x + vecX; ii != i || jj != j; ii += vecY, jj += vecX) {
						p[ii][jj] = c; /* ひっくり返す位置に置くコマの記号を代入する */
					}

					if (reverseEach == 0)
						break;
					else {
						reverseTotal += reverseEach;

						break;
					}
				}
			}
		}
	}


	return reverseTotal;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

milk
記事: 9
登録日時: 8年前

Re: オセロゲームのプログラム

#5

投稿記事 by milk » 8年前

無事完成いたしました!!
ご教授ありがとうございました!!

閉鎖

“C言語何でも質問掲示板” へ戻る