助けてください
Posted: 2012年10月03日(水) 17:06
このC言語のオセロプログラムで盤に評価値をつけるにはどうすればよいのでしょうか?お手数ですが教えてもらえませんか?
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define M 10 //盤の横の長さ 実際は壁の分をひいた M - 2が実際の長さ
#define N 10 //盤の縦の長さ 実際の長さは N -2
#define BLACK 1 //黒の石をdataでは1と表す
#define EMPTY 0 //石なし
#define WHITE -1//白の石をdataでは-1と表す
//各関数の宣言
void AI_comp(int data[M][N] , int pl, int op);
void turn(int x, int y, int data[M][N] , int pl, int op);
int place_ability(int x, int y, int data[M][N], int pl, int op);
void board_output(int data[M][N]);
int pass(int data[M][N], int pl, int op);
int main()
{
int i, j,k;
int player_pass_flag = 0, comp_pass_flag = 0;
int player, comp, fors, count, bl = 0, wh = 0;
int data[M][N];
FILE *fp;
fp = fopen("test.dat","a");
printf("●(白)が先行ならば0、○(黒)が先行なら1を入力してください。");
scanf_s("%d", &fors);
for(k = 1 ; k < 2; k++){
player_pass_flag = 0;
comp_pass_flag = 0;
for(i = 0; i < M; i ++){
for(j = 0; j < N; j ++){
if(i != 0 && j != 0 && i != M - 1 && j != N - 1)
data[j] = 0;
else data[j] = 5;
}
}
// 初めに黒白2つずつの石を配置
data[M / 2 - 1][M / 2 - 1] = data[M / 2][M / 2] = BLACK;
data[M / 2][M / 2 - 1] = data[M / 2 - 1][M / 2] = WHITE;
//初期状態の盤の状態を表示
board_output(data);
if(fors == 0){
player = BLACK;
comp = WHITE;
count = 0;
}
else{
player = WHITE;
comp = BLACK;
count = 0;
}
for(i = 0; i < (M -2) * (N -2) - 4; i ++){
INPUT:
if(player_pass_flag == 1 && comp_pass_flag == 1)
goto END; //二人ともパスだったら終了
if(count == 0){ //プレーヤー(対戦相手)の手
if(pass(data, player, comp) == 1){
printf("Computer パスします\n");
comp_pass_flag = 1; //パスしたときはこの変数を1とする
count = 0;
goto INPUT;
}
player_pass_flag =1;
printf("computer\n");
AI_comp(data, player, comp);
count = 1;
}
else{ //コンピュータの手
if(pass(data, comp, player) == 1){
printf("Computer パスします\n");
comp_pass_flag = 1; //パスしたときはこの変数を1とする
count = 1;
goto INPUT;
}
player_pass_flag =1;
printf("computer\n");
AI_comp(data, comp, player); //意思決定関数
count = 0;
}
//盤の状態の表示
board_output(data);
}
//勝敗がついたら盤の状態の表示
END:
printf("\n***最終局面***\n\n");
board_output(data);
for(i = 1; i < M - 1; i ++){
for(j = 1; j < N -1; j ++){
if (data[j] == WHITE) wh ++;
else if (data[j] == BLACK) bl ++;
}
}
fprintf(fp,"%4.d :",k);
printf("● = %2d, ○ = %2d\n\n", bl, wh);
fprintf(fp,"● = %2d, ○ = %2d", bl, wh);
if(bl == wh){
printf("引き分けです。\n");
fprintf(fp," 引き分けです。");
if(fors==0){
fprintf(fp," 先行は●(白)\n");
} else {
fprintf(fp," 先行は○(黒)\n");
}
}
else if((fors == 0 && bl > wh) || (fors == 1 && bl > wh)){
if(fors==0){
fprintf(fp," 先行は●(白)");
} else {
fprintf(fp," 先行は○(黒)");
}
printf("●(白)の勝ちです。\n");
fprintf(fp," ●(白)の勝ちです。\n");
}
else {
if(fors==1){
fprintf(fp," 先行は○(黒)");
} else {
fprintf(fp," 先行は●(白)");
}
printf("○(黒)の勝ちです。\n");
fprintf(fp," ○(黒)の勝ちです。\n");
}
bl = 0;
wh = 0;
}
fclose(fp);
return 0;
}
//次の一手を決定する関数
void AI_comp(int data[M][N], int pl, int op)
{
/*実際にはここからの部分を改変する。
下のソースは置けるマスの中から次の一手をランダムに選択している。*/
int xc = 0, yc = 0;
long long int t;
time(&t);
srand((unsigned int)t);
while(place_ability(xc, yc, data, pl, op) == 0){
//xc,ycにコンピュータの置く石の座標を代入する
xc = 1 + (double)rand() / RAND_MAX * (M - 2);
yc = 1 + (double)rand() / RAND_MAX * (N - 2);
}
//ここまで
turn(xc, yc, data, pl, op);
printf("(%d, %d)\n", xc, yc);
}
//石をひっくり返す関数 石を置く座標(x,y)を引数とする。
void turn(int x, int y, int data[M][N], int pl, int op)
{
int p, q, i, j;
int x2, y2; //(x,y)と(x2,y2)の二つの味方の石で、相手の石をはさむ。
data[x][y] = pl; /*まず、(x,y)に味方の石を置く。
plは、この関数がplayerから呼び出されればplayerの石の色
Computerから呼び出されればComputerの石の色のこと*/
for (p = -1; p <= 1; p ++){
for(q = -1; q <=1; q++){
if (p == 0 && q == 0) continue;
if (data [x + p] [y + q] != op) continue;
i = x + p;
j = y + q;
while (data[j] == op){
i += p;
j += q;
}
x2 = i;
y2 = j;
//(x2,y2)に味方の石があれば、間の相手の石がとれる。
//(x,y)から出発して、(p,q)ずつ進みながら、(x2,y2)に到達するまで、
//相手の石をひっくり返していく。
if (data[x2][y2] == pl){
for(i= x + p, j= y + q; !((i == x2) && (j == y2)) ; i += p, j += q){
data[j] = pl;
}
}
}
}
if (data[i = x + p][j = y + q] != op) return;
while (data[j] == op){
i = i + p;
j = j + q;
}
}
int place_ability(int x, int y, int data[M][N], int pl, int op)
{
int i, j, p, q;
//そこが空欄でないなら、置けない。
if(data[x][y] != 0) return 0;
//空欄で、1枚でもとれるなら置ける。
else{
//上下左右斜めの、8方向について、とれるか調べる
for(p = -1; p <= 1; p++){
for(q = -1; q <= 1; q ++){
if(p == 0 && q == 0) continue;
//隣りに相手の石がないと、とれない。
if (data[x + p][y + q] != op) continue;
//相手の石が続く限り、(p,q)の方向に進んでいく。
i = x + p; j = y + q;
while(data[j] == op) {i += p; j += q;}
//今、(i,j)は(p,q)方向は端の座標。
//そこに味方の石があれば、間の敵石をとれる=(x,y)における。
if (data[j] == pl) return 1;
}
}
//8方向調べたものの、敵石がとれなかった場合、
//(x,y)には置けないことになる。
return 0;
}
}
// 盤の状態の表示
void board_output(int data[M][N])
{
int i, j;
printf(" 1 2 3 4 5 6 7 8\n");
for(i = 1; i < M - 1; i ++){
printf("%d", i);
for(j = 1; j < N - 1; j ++){
switch (data[j]){
case 1: printf("●");
break;
case -1: printf("○");
break;
default: printf("・");
break;
}
}
printf("\n");
}
printf("\n");
}
int pass(int data[M][N], int pl, int op) {
//返り値が0: パスしない。どこかにおける。
// 1: パスする。どこにもおけない。
int i, j;
for (i = 1; i < M - 1; i ++){
for(j = 1; j < N - 1; j++){
if (place_ability(i, j, data, pl, op) == 1){
return 0; //置ける場所が見つかった = パスしない
}
}
}
return 1;
}
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define M 10 //盤の横の長さ 実際は壁の分をひいた M - 2が実際の長さ
#define N 10 //盤の縦の長さ 実際の長さは N -2
#define BLACK 1 //黒の石をdataでは1と表す
#define EMPTY 0 //石なし
#define WHITE -1//白の石をdataでは-1と表す
//各関数の宣言
void AI_comp(int data[M][N] , int pl, int op);
void turn(int x, int y, int data[M][N] , int pl, int op);
int place_ability(int x, int y, int data[M][N], int pl, int op);
void board_output(int data[M][N]);
int pass(int data[M][N], int pl, int op);
int main()
{
int i, j,k;
int player_pass_flag = 0, comp_pass_flag = 0;
int player, comp, fors, count, bl = 0, wh = 0;
int data[M][N];
FILE *fp;
fp = fopen("test.dat","a");
printf("●(白)が先行ならば0、○(黒)が先行なら1を入力してください。");
scanf_s("%d", &fors);
for(k = 1 ; k < 2; k++){
player_pass_flag = 0;
comp_pass_flag = 0;
for(i = 0; i < M; i ++){
for(j = 0; j < N; j ++){
if(i != 0 && j != 0 && i != M - 1 && j != N - 1)
data[j] = 0;
else data[j] = 5;
}
}
// 初めに黒白2つずつの石を配置
data[M / 2 - 1][M / 2 - 1] = data[M / 2][M / 2] = BLACK;
data[M / 2][M / 2 - 1] = data[M / 2 - 1][M / 2] = WHITE;
//初期状態の盤の状態を表示
board_output(data);
if(fors == 0){
player = BLACK;
comp = WHITE;
count = 0;
}
else{
player = WHITE;
comp = BLACK;
count = 0;
}
for(i = 0; i < (M -2) * (N -2) - 4; i ++){
INPUT:
if(player_pass_flag == 1 && comp_pass_flag == 1)
goto END; //二人ともパスだったら終了
if(count == 0){ //プレーヤー(対戦相手)の手
if(pass(data, player, comp) == 1){
printf("Computer パスします\n");
comp_pass_flag = 1; //パスしたときはこの変数を1とする
count = 0;
goto INPUT;
}
player_pass_flag =1;
printf("computer\n");
AI_comp(data, player, comp);
count = 1;
}
else{ //コンピュータの手
if(pass(data, comp, player) == 1){
printf("Computer パスします\n");
comp_pass_flag = 1; //パスしたときはこの変数を1とする
count = 1;
goto INPUT;
}
player_pass_flag =1;
printf("computer\n");
AI_comp(data, comp, player); //意思決定関数
count = 0;
}
//盤の状態の表示
board_output(data);
}
//勝敗がついたら盤の状態の表示
END:
printf("\n***最終局面***\n\n");
board_output(data);
for(i = 1; i < M - 1; i ++){
for(j = 1; j < N -1; j ++){
if (data[j] == WHITE) wh ++;
else if (data[j] == BLACK) bl ++;
}
}
fprintf(fp,"%4.d :",k);
printf("● = %2d, ○ = %2d\n\n", bl, wh);
fprintf(fp,"● = %2d, ○ = %2d", bl, wh);
if(bl == wh){
printf("引き分けです。\n");
fprintf(fp," 引き分けです。");
if(fors==0){
fprintf(fp," 先行は●(白)\n");
} else {
fprintf(fp," 先行は○(黒)\n");
}
}
else if((fors == 0 && bl > wh) || (fors == 1 && bl > wh)){
if(fors==0){
fprintf(fp," 先行は●(白)");
} else {
fprintf(fp," 先行は○(黒)");
}
printf("●(白)の勝ちです。\n");
fprintf(fp," ●(白)の勝ちです。\n");
}
else {
if(fors==1){
fprintf(fp," 先行は○(黒)");
} else {
fprintf(fp," 先行は●(白)");
}
printf("○(黒)の勝ちです。\n");
fprintf(fp," ○(黒)の勝ちです。\n");
}
bl = 0;
wh = 0;
}
fclose(fp);
return 0;
}
//次の一手を決定する関数
void AI_comp(int data[M][N], int pl, int op)
{
/*実際にはここからの部分を改変する。
下のソースは置けるマスの中から次の一手をランダムに選択している。*/
int xc = 0, yc = 0;
long long int t;
time(&t);
srand((unsigned int)t);
while(place_ability(xc, yc, data, pl, op) == 0){
//xc,ycにコンピュータの置く石の座標を代入する
xc = 1 + (double)rand() / RAND_MAX * (M - 2);
yc = 1 + (double)rand() / RAND_MAX * (N - 2);
}
//ここまで
turn(xc, yc, data, pl, op);
printf("(%d, %d)\n", xc, yc);
}
//石をひっくり返す関数 石を置く座標(x,y)を引数とする。
void turn(int x, int y, int data[M][N], int pl, int op)
{
int p, q, i, j;
int x2, y2; //(x,y)と(x2,y2)の二つの味方の石で、相手の石をはさむ。
data[x][y] = pl; /*まず、(x,y)に味方の石を置く。
plは、この関数がplayerから呼び出されればplayerの石の色
Computerから呼び出されればComputerの石の色のこと*/
for (p = -1; p <= 1; p ++){
for(q = -1; q <=1; q++){
if (p == 0 && q == 0) continue;
if (data [x + p] [y + q] != op) continue;
i = x + p;
j = y + q;
while (data[j] == op){
i += p;
j += q;
}
x2 = i;
y2 = j;
//(x2,y2)に味方の石があれば、間の相手の石がとれる。
//(x,y)から出発して、(p,q)ずつ進みながら、(x2,y2)に到達するまで、
//相手の石をひっくり返していく。
if (data[x2][y2] == pl){
for(i= x + p, j= y + q; !((i == x2) && (j == y2)) ; i += p, j += q){
data[j] = pl;
}
}
}
}
if (data[i = x + p][j = y + q] != op) return;
while (data[j] == op){
i = i + p;
j = j + q;
}
}
int place_ability(int x, int y, int data[M][N], int pl, int op)
{
int i, j, p, q;
//そこが空欄でないなら、置けない。
if(data[x][y] != 0) return 0;
//空欄で、1枚でもとれるなら置ける。
else{
//上下左右斜めの、8方向について、とれるか調べる
for(p = -1; p <= 1; p++){
for(q = -1; q <= 1; q ++){
if(p == 0 && q == 0) continue;
//隣りに相手の石がないと、とれない。
if (data[x + p][y + q] != op) continue;
//相手の石が続く限り、(p,q)の方向に進んでいく。
i = x + p; j = y + q;
while(data[j] == op) {i += p; j += q;}
//今、(i,j)は(p,q)方向は端の座標。
//そこに味方の石があれば、間の敵石をとれる=(x,y)における。
if (data[j] == pl) return 1;
}
}
//8方向調べたものの、敵石がとれなかった場合、
//(x,y)には置けないことになる。
return 0;
}
}
// 盤の状態の表示
void board_output(int data[M][N])
{
int i, j;
printf(" 1 2 3 4 5 6 7 8\n");
for(i = 1; i < M - 1; i ++){
printf("%d", i);
for(j = 1; j < N - 1; j ++){
switch (data[j]){
case 1: printf("●");
break;
case -1: printf("○");
break;
default: printf("・");
break;
}
}
printf("\n");
}
printf("\n");
}
int pass(int data[M][N], int pl, int op) {
//返り値が0: パスしない。どこかにおける。
// 1: パスする。どこにもおけない。
int i, j;
for (i = 1; i < M - 1; i ++){
for(j = 1; j < N - 1; j++){
if (place_ability(i, j, data, pl, op) == 1){
return 0; //置ける場所が見つかった = パスしない
}
}
}
return 1;
}