≫ EDIT

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。





↓ランキングに参加しています!お手数ですが、よろしければ3つとも1日1回クリックをお願いしますm(__)m↓
にほんブログ村 大学生日記ブログ 理系大学生へ
にほんブログ村


【カテゴリー:スポンサー広告 comments(-)

≫ EDIT

FFL.ver2.4(コンピュータリバーシ)



まずは関連記事を貼りたいと思います。


【関連記事】
【C言語】私が作った弱小コンピュータリバーシ(オセロ)のソースコード


リバーシのプログラムを開発しました。名前はFFLと言います。UVERworldが好きで、そのバンドの曲のFight For Libertyの頭文字から取りました。




先週の出来事です。従兄弟(小4)と対戦しました。






俺「コンピュータで動くオセロのプログラムを作ったんだけど対戦してみない?(ドヤァ」


従兄弟(小4)「いいよ」


俺「マジか、やろう(勝利確信」


(〜〜〜〜対局開始〜〜〜〜)


FFL「序盤は圧勝やろ(確信 」


FFL「やっぱ余裕やわwwwww小4相手に負ける訳なかろうがwwww」


FFL「あ、あれ?よく分からないけど角取られちゃった・・・」


FFL「ちょwwwwwwwwww角2つ取られたwwwwwwwww」


FFL「やめてwwwwwwwww」


FFL「おいwwwwwwwwww    おい・・・・」


FFL「」


(〜〜〜〜コンピュータ敗北〜〜〜〜)


従兄弟(小4)「俺君が作ったプログラムはあんまり強くないね(笑」











屈辱の極みwwwwwwwwwwwwwwwwwwwwwww





序盤は圧勝でしたが、中盤以降に角を取られ、圧倒的にコンピュータが優勢とされる終盤ではフルボッコにされますた・・・。




実はもうリバーシプログラムの開発はしないと断言しましたが、流石に悔しいのでちょっと改良を加えました・・・。


以下にソースコードを貼りたいと思います。




//コンピューターオセロ



//確定石を計算するアルゴリズムを書く




#include

/******************************* 根幹部分に関する記述 *******************************************/
//マスの状態を定義
#define NONE 0 //空きマス
#define BLACK 1 //黒駒
#define WHITE 2 //白駒
//ボード(左上を[0][0])
int board[8][8];
//マスの状態の数
int NONE_NUMBER; //空きマス
int BLACK_NUMBER; //黒駒
int WHITE_NUMBER; //白駒
//ターン
int turn = 1; //1が先手、2が後手
//コンピュータ・人間のターン
int human, computer;
//方向ベクトルを定義
int vec_x[] = { 0, 1, 1, 1, 0, -1, -1, -1 };
//方向ベクトルを定義
int vec_y[] = { -1, -1, 0, 1, 1, 1, 0, -1 };
//変換関数のプロトタイプ宣言
int Trans_x(int place); //多次元配列のx要素に変換
int Trans_y(int place); //多次元配列のy要素に変換
int Trans_place(int x, int y); //多次元配列のx,y要素を人間が入力する値に変換
int EnemyColor(int turn); //相手の色を出力
int StretchVec(int a); //その方向のベクトルを1つ伸ばす(成分を入力すると、1つ伸ばした成分を出力する)
//重要関数のプロトタイプ宣言
void Initia(void); //初期化
void Disp(void); //現在のボードを描画
int CanGo(int place, int turn); //有効な場所かどうかを判断(有効な場合は1、有効でない場合は0を返却)
int CanPut(int turn); //そのターンが駒を置けるかどうかを判別(置ける場合は1、置けない場合は0を返却)
void Count(const int ThinkBoard[8][8]); //空きマス、黒駒、白駒の数をカウント
void Flip(int place, int turn); //駒を裏返す
void Change(void); //ターンを入れ替える
void Judge(void); //勝敗を決定

/* ***************************探索アルゴリズムに関する記述************************************* */
void BestPlace(int ThinkBoard[8][8], int turn); //コンピューターの評価点を表示し最善の場所をグローバル変数bestplaceに保存
int minimax(int ThinkBoard[8][8], int turn, int depth); //minimax法で評価点を出力



//探索アルゴリズムに関する設定
#define DEPTH 5 //読みの深さを設定

//グローバル宣言
int bestplace; //最善の場所を保存する変数
int saveboard[8][8][DEPTH]; //局面を保存する変数
long count = 0; //読み込んだ局面数を保存する変数

/* ***************************評価関数に関する記述********************************************* */
//評価関数のプロトタイプ宣言
void ChangeStage(const int ThinkBoard[8][8]); //局面を判断して評価関数のパラメーターを変化
int Evalu_Total(const int ThinkBoard[8][8], int turn); //評価値の合計を計算(評価する局面とターンを値渡し)
int Evalu_HowMany(const int ThinkBoard[8][8], int turn); //着手可能手数を計算して返却(評価する局面とター73ンを値渡し)
int Evalu_BoardScore(const int ThinkBoard[8][8], int turn); //マスの評価値の合計を計算して数値を返却
int Evalu_HowManyStones(const int ThinkBoard[8][8], int turn); //駒の数を計算して数値を返却
int Evalu_HowManyFixedStones(const int ThinkBoard[8][8], int turn); //確定石を計算して数値を返却(辺上のみ)
#define EVALUATION_POINTS 4

//評価関数の設定に関する記述
//Evalu_BoardScore()のマスの得点を定義
const int CellScore[8][8] = {

{ 350, -50, 60, 10, 10, 60, -50, 350 },

{ -50, -100, -20, -20, -20, -20, -100, -50 },

{ 50, -20, 10, 10, 10, 10, -20, 60 },

{ 10, -20, 10, 0, 0, 10, -20, 10 },

{ 10, -20, 10, 0, 0, 10, -20, 10 },

{ 60, -20, 10, 10, 10, 10, -20, 60 },

{ -50, -100, -20, -20, -20, -20, -100, -50 },

{ 350, -50, 60, 10, 10, 60, -50, 350 },

};

//序盤、中盤、終盤を定義(その空きマスの数まで)
#define FIRST 30 //64 - 30マスまでが序盤
#define MIDDLE 10 //31 - 10マスまでが中盤
#define FINAL 0 //11 - 0マスまでが終盤

//グローバル変数の定義
int w[EVALUATION_POINTS]; //各々の評価関数のウェイト
//序盤、中盤、終盤の各々の評価関数のパラメーター
//左から【自分の着手可能手数】、【自分のマスの評価値の合計】、【自分の駒の数】、【自分の確定石の数】
const int w_first[EVALUATION_POINTS] = { 2, 6, 0, 30 }; //序盤
const int w_middle[EVALUATION_POINTS] = { 3, 6, 1, 40 }; //中盤
const int w_final[EVALUATION_POINTS] = { 3, 0, 8, 10 }; //終盤


int main(void){

//コンティニューするかどうかを保存する変数
int retry;

//リトライする時はここでループ
while (1){

//初期化
Initia();

//人間が先手・後手を決める
while (1){
printf("先手が黒、後手が白です。\n");
printf("あなたは先手ですか?後手ですか?\n先手なら1、後手なら2を入力してください。\n");
printf("入力:"); scanf("%d", &human);

if (human == 1){
break;
}
else if (human == 2){
break;
}
printf("無効な値です。\a\a\a\n\n");
}
if (human == 1){
computer = 2;
}
else{
computer = 1;
}
printf("\n\n");

//空きマスがある・パスの時はここでループ
while (1){

//ボードを描画
Disp();
printf("\n");

//人間の手
if (turn == human){
//有効な手であるまでループ
while (1){

//削除する表現
BestPlace(board, human);
printf("人間の予想場所:%d\n\n", bestplace);
printf("コンピュータの確定石の数 = %d\n\n", Evalu_HowManyFixedStones(board, computer));

//場所を入力
int human_place;
printf("場所:"); scanf("%d", &human_place);
if (!(CanGo(human_place, human))){
printf("無効な数値です。もう一度入力してください。\a\a\a\n\n");
continue;
}
Flip(human_place, human);
break;
}
}

//コンピュータの手
if (turn == computer){
printf("思考中・・・\n\n\n");
//コンピューターの評価点を表示し最善の場所をグローバル変数bestplaceに保存
BestPlace(board, computer);
printf("読み込んだ局面数:%ld\n", count);
printf("コンピュータは%dに置きました。\n\n", bestplace);
//エラー判定
if (!(CanGo(bestplace, computer))){
printf("エラー3\n\n\a\a\a");
return(0);
}

//裏返す
Flip(bestplace, computer);
}

//黒駒・白駒・空きマスをカウント
Count(board);

//終了の時はループをブレイク
if (NONE_NUMBER == 0){
printf("空きマスが無くなったので終了です。\n\n");
break;
}

//一色になったら終了
if (BLACK_NUMBER == 0){
printf("ボード上に白しかありません。\n\n");
break;
}
else if (WHITE_NUMBER == 0){
printf("ボード上に黒しかありません。\n\n");
break;
}

//パスの場合はここでループ
if (!(CanPut(EnemyColor(turn)))){
if (EnemyColor(turn) == human){
puts("人間は置く場所がありません。");
}
else if (EnemyColor(turn) == computer){
puts("コンピューターは置く場所がありません。");
}
else{
puts("エラー1");
}
continue;
}


//ターンチェンジ
Change();



}

//ボードを描画
Disp();

//結果を出力
Judge();

printf("\n\n\n");
puts("リトライするときは1、そうでない場合は2を入力してください。");
printf("入力:"); scanf("%d", &retry);

if (retry == 1){
continue;
}
else{
break;
}

}

return(0);
}





/******************************************************************************** 評価関数 ******************************************************************************************/

//評価値の合計を計算
int Evalu_Total(const int ThinkBoard[8][8], int turn){

//評価値の合計
int totalscore = 0;

//評価関数のパラメーターを変化させる
ChangeStage(ThinkBoard);

//各々の評価値
//【自分の着手可能手数】、【相手の着手可能手数】、【自分のマスの評価値の合計】、【自分の駒の数】、【自分の確定石の数】
int e[EVALUATION_POINTS] = { Evalu_HowMany(ThinkBoard, turn),
Evalu_BoardScore(ThinkBoard, turn), Evalu_HowManyStones(ThinkBoard, turn), Evalu_HowManyFixedStones(ThinkBoard, turn) };

for (int i = 0; i < EVALUATION_POINTS; i++){
totalscore += w[i] * e[i];
}

return(totalscore);
}


//着手可能手数を計算して返却(評価する局面とターンを値渡し)
int Evalu_HowMany(const int ThinkBoard[8][8], int turn){

//着手可能手数を保存する変数
int count = 0;

//総当りで解析
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
if (CanGo(Trans_place(j, i), turn) == 1){
count++;
}
}
}

return(count);
}

//マスの評価値の合計を計算して数値を返却
int Evalu_BoardScore(const int ThinkBoard[8][8], int turn){

//評価値を保存する変数
int score = 0;

for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
if (ThinkBoard[i][j] == turn){
score += CellScore[i][j];
}
}
}

return(score);
}

//自分の駒の数を計算して数値を返却
int Evalu_HowManyStones(const int ThinkBoard[8][8], int turn){

//カウントする
Count(ThinkBoard);

if (turn == 1){
return(BLACK_NUMBER);
}
else if (turn == 2){
return(WHITE_NUMBER);
}

//エラー
return(-10000);
}

//確定石を計算して数値を返却(辺のみ)
int Evalu_HowManyFixedStones(const int ThinkBoard[8][8], int turn){

/*

【確定石のアルゴリズム】
(1)辺が全て埋まっている時の辺の駒
(2)角から空きマスまでの駒が全て自分の時の駒

*/

int fixed = 0; //確定石のカウント
bool flag_up = true;
bool flag_right = true;
bool flag_down = true;
bool flag_left = true;


//角の駒(確定石)の数をカウント
if (board[0][0] == turn) fixed++;
if (board[0][7] == turn) fixed++;
if (board[7][7] == turn) fixed++;
if (board[7][0] == turn) fixed++;


//辺が全て埋まっているかどうかを判定
for (int i = 0; i < 8; i++){
if (flag_up == true && board[0][i] == NONE) flag_up = false; //上の辺を探索
if (flag_right == true && board[i][7] == NONE) flag_right = false; //右の辺を探索
if (flag_down == true && board[7][i] == NONE) flag_down = false; //下の辺を探索
if (flag_left == true && board[i][0] == NONE) flag_left = false; //左の辺を探索
}

//上の辺をカウント
if (flag_up == true){ //上の辺が全て埋まっている場合
for (int i = 1; i < 7; i++){
if (board[0][i] == turn) fixed++;
}
}
else if (flag_up == false) { //上の辺に空きマスがある場合
if (board[0][0] == turn){
for (int i = 1; i < 7; i++){ //左から右へ探索
if (board[0][i] == NONE || board[0][i] == EnemyColor(turn)) break;
fixed++;
}
}
if (board[0][7] == turn){ //右から左へ探索
for (int i = 1; i < 7; i++){
if (board[0][7 - i] == NONE || board[0][7 - i] == EnemyColor(turn)) break;
fixed++;
}
}
}
else{
printf("エラー6\n\n");
return(-10000);
}


//右の辺をカウント
if (flag_right == true){ //右の辺が全て埋まっている場合
for (int i = 1; i < 7; i++){
if (board[i][7] == turn) fixed++;
}
}
else if (flag_right == false) { //右の辺に空きマスがある場合
if (board[0][7] == turn){
for (int i = 1; i < 7; i++){ //上から下へ探索
if (board[i][7] == NONE || board[i][7] == EnemyColor(turn)) break;
fixed++;
}
}
if (board[7][7] == turn){ //下から上へ探索
for (int i = 1; i < 7; i++){
if (board[7 - i][7] == NONE || board[7 - i][7] == EnemyColor(turn)) break;
fixed++;
}
}
}
else{
printf("エラー7\n\n");
return(-10000);
}

//下の辺をカウント
if (flag_down == true){ //下の辺が全て埋まっている場合
for (int i = 1; i < 7; i++){
if (board[7][i] == turn) fixed++;
}
}
else if (flag_down == false) { //下の辺に空きマスがある場合
if (board[7][0] == turn){
for (int i = 1; i < 7; i++){ //左から右へ探索
if (board[7][i] == NONE || board[7][i] == EnemyColor(turn)) break;
fixed++;
}
}
if (board[7][7] == turn){ //右から左へ探索
for (int i = 1; i < 7; i++){
if (board[7][7 - i] == NONE || board[7][7 - i] == EnemyColor(turn)) break;
fixed++;
}
}
}
else{
printf("エラー8\n\n");
return(-10000);
}

//左の辺をカウント
if (flag_left == true){
for (int i = 1; i < 7; i++){
if (board[i][0] == turn) fixed++;
}
}
else if (flag_left == false) { //左の辺に空きマスがある場合
if (board[0][0] == turn){
for (int i = 1; i < 7; i++){ //上から下へ探索
if (board[i][0] == NONE || board[i][0] == EnemyColor(turn)) break;
fixed++;
}
}
if (board[7][0] == turn){ //下から上へ探索
for (int i = 1; i < 7; i++){
if (board[7 - i][0] == NONE || board[7 - i][0] == EnemyColor(turn)) break;
fixed++;
}
}
}
else{
printf("エラー9\n\n");
return(-10000);
}

return(fixed);
}


//局面を判断して評価関数のパラメーターを変化
void ChangeStage(const int ThinkBoard[8][8]){

//左から【着手可能手数】、【マスの評価値の合計】、【自分の駒の数】、【相手の駒の数】
//各々の評価関数のウェイトを書き換える
if (NONE_NUMBER >= FIRST){ //【序盤】
for (int i = 0; i < EVALUATION_POINTS; i++){
w[i] = w_first[i];
}
}
else if (FIRST > NONE_NUMBER && NONE_NUMBER >= MIDDLE){ //【中盤】
for (int i = 0; i < EVALUATION_POINTS; i++){
w[i] = w_middle[i];
}
}
else if (MIDDLE > NONE_NUMBER && NONE_NUMBER >= FINAL){ //【終盤】
for (int i = 0; i < EVALUATION_POINTS; i++){
w[i] = w_final[i];
}
}
else{
for (int i = 0; i < EVALUATION_POINTS; i++){ //エラー
w[i] = -10000;
}
printf("エラー2\n\n");
}

}


/******************************************************************************** 探索アルゴリズム ******************************************************************************************/

//コンピューターの評価点を表示し最善の場所をグローバル変数bestplaceに保存
void BestPlace(int ThinkBoard[8][8], int turn){

//局面数カウントをリセット
count = 0;


//minimax()で評価点を記録し最善手をグローバル変数bestplaceに記録
int score = minimax(board, turn, DEPTH);

//評価点を出力
if (turn == human) printf("\n人間の評価点は%dです。\n", score);
if (turn == computer) printf("\nコンピューターの評価点:%d\n", score);

//ボード上のカウントを戻す
Count(ThinkBoard);

}

//minimax法で評価点を出力
int minimax(int ThinkBoard[8][8], int ThinkTurn, int depth){


//ボード上をカウント
Count(ThinkBoard);

//即死局面
if (BLACK_NUMBER == 0 || WHITE_NUMBER == 0){

//削除する表現
printf("即死局面\n\n");

if (ThinkTurn == turn) return(-32768); //自分が即死局面
if (ThinkTurn == EnemyColor(turn)) return(32768); //相手が即死局面
}

//空きマスが無い場合
if (NONE_NUMBER == 0){
return(Evalu_Total(ThinkBoard, turn));
}

//リーフの場合は評価値を返却する
if (depth == 0) return(Evalu_Total(ThinkBoard, turn));

int score = -32768;
int var;

//局面を保存する
for (int k = 0; k < 8; k++){
for (int l = 0; l < 8; l++){
saveboard[k][l][depth - 1] = ThinkBoard[k][l];
}
}

for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){

if (CanGo(Trans_place(j, i), ThinkTurn)){

//実際に裏返す
Flip(Trans_place(j, i), ThinkTurn);

//局面数をカウント
count++;

//再帰
if (CanPut(EnemyColor(ThinkTurn))) var = minimax(ThinkBoard, EnemyColor(ThinkTurn), depth - 1); //着手可能な場所がある
if (!(CanPut(EnemyColor(ThinkTurn)))) var = minimax(ThinkBoard, ThinkTurn, depth - 1); //着手可能な場所がない


//得点と最善手を更新
if (ThinkTurn == turn && score <= var){
score = var;
if (depth == DEPTH){
bestplace = Trans_place(j, i);
}
}
if (ThinkTurn == EnemyColor(turn) && score <= -var){
score = -var;
}

//局面を1手戻す
for (int k = 0; k < 8; k++){
for (int l = 0; l < 8; l++){
ThinkBoard[k][l] = saveboard[k][l][depth - 1];
}
}

}
}
}

//最大値を返却
if (ThinkTurn == turn){
return(score);
}
//最小値を返却
if (ThinkTurn == EnemyColor(turn)){
return(-score);
}

//エラー判定
printf("¥a¥a¥aエラー4");
return(99999);


}




/********************************************************* 根幹部分の関数(基本的に改変する必要が無い) ******************************************************************************************/

//多次元配列のx要素に変換
int Trans_x(int place){
return((place % 10) - 1);
}

//多次元配列のy要素に変換
int Trans_y(int place){
return((place / 10) - 1);
}

//多次元配列のx,y要素を人間が入力する値に変換
int Trans_place(int x, int y){
return((1 + y) * 10 + (x + 1));
}


//敵の色を出力
int EnemyColor(int turn){
if (turn == 1){
return(2);
}
else if (turn == 2){
return(1);
}
//エラー
return(-1);
}

//その方向のベクトルを1つ伸ばす
int StretchVec(int a){

int b = a;

if (a > 0){
b++;
}
else if (a < 0){
b--;
}
return(b);
}

//初期化
void Initia(void){

//全てのマスを空きにする
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
board[i][j] = NONE;
}
}

//最初の4マスを定義
board[4][3] = BLACK;
board[3][4] = BLACK;
board[3][3] = WHITE;
board[4][4] = WHITE;

}

//ボードを描画
void Disp(void){

//行を描画
printf(" ");
for (int i = 1; i <= 8; i++){
printf("%2d", i);
}
putchar('\n');
//マスを描画
for (int i = 0; i < 8; i++){
//列を描画
printf("%2d", (i + 1) * 10);
for (int j = 0; j < 8; j++){
switch (board[i][j]){
case NONE: printf("□"); break;
case BLACK: printf("●"); break;
case WHITE: printf("○"); break;
default: printf("¥a¥a¥aerror"); break;
}
}
putchar('\n');
}
}

//有効な場所かどうかを判断(有効な場合は1、有効でない場合は0を返却)
int CanGo(int place, int turn){

//相手の色を定義
int enemy = EnemyColor(turn);
//x,yの要素を取り出す
int x = Trans_x(place);
int y = Trans_y(place);

//指定された場所がボード上でない
if (x < 0 || y < 0 || x > 7 || y > 7){
return(0);
}

//指定された場所に既に駒がある場合
if (board[y][x] != NONE){
return(0);
}

for (int i = 0; i < 8; i++){
//周りに相手の駒があるかどうかを判別
if (board[y + vec_y[i]][x + vec_x[i]] == enemy){

//ベクトルの成分をコピー
int vec_xx = vec_x[i];
int vec_yy = vec_y[i];

//その方向を詳しく調べる
while (1){
//ベクトルを1つ伸ばす
vec_xx = StretchVec(vec_xx);
vec_yy = StretchVec(vec_yy);

//探索ベクトルがボード外
if ((x + vec_xx) < 0 || (y + vec_yy) < 0 || (x + vec_xx) > 7 || (y + vec_yy) > 7){
break;
}//空きマスに出た
else if (board[y + vec_yy][x + vec_xx] == NONE){
break;
}//自分の駒に出た
else if (board[y + vec_yy][x + vec_xx] == turn){
return(1);
}
}
}
}
return(0);
}

//駒を置けるかどうかを判別(置ける場合は1、置けない場合は0を返却)
int CanPut(int turn){

//総当りで解析
for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
if (CanGo((i + 1) * 10 + (j + 1), turn) == 1){
return(1);
}
}
}
return(0);
}

//マスの状態の数
void Count(const int ThinkBoard[8][8]){

//マスの状態の数をリセット
NONE_NUMBER = 0;
BLACK_NUMBER = 0;
WHITE_NUMBER = 0;

for (int i = 0; i < 8; i++){
for (int j = 0; j < 8; j++){
switch (ThinkBoard[i][j]){
case NONE: ++NONE_NUMBER; break;
case BLACK: ++BLACK_NUMBER; break;
case WHITE: ++WHITE_NUMBER; break;
default: printf("¥a¥a¥aerror"); break;
}
}
}
}

//駒を裏返す
void Flip(int place, int turn){

//相手の色を定義
int enemy = EnemyColor(turn);
//x,yの要素を取り出す
int x = Trans_x(place);
int y = Trans_y(place);

//指定した場所に駒を置く
board[y][x] = turn;

for (int i = 0; i < 8; i++){
//周りに相手の駒があるかどうかを判別
if (board[y + vec_y[i]][x + vec_x[i]] == enemy){

//ベクトルの成分をコピー
int vec_xx = vec_x[i];
int vec_yy = vec_y[i];
//マスをカウントする変数
int count = 0;

//その方向を詳しく調べる
while (1){

//探索ベクトルがボード外
if ((x + vec_xx) < 0 || (y + vec_yy) < 0 || (x + vec_xx) > 7 || (y + vec_yy) > 7){
break;
}//空きマスに出た
else if (board[y + vec_yy][x + vec_xx] == NONE){
break;
}//自分の駒に出た
else if (board[y + vec_yy][x + vec_xx] == turn){
//ベクトルの成分をコピー
int vec_xxx = vec_x[i];
int vec_yyy = vec_y[i];
//裏返す
for (int j = 0; j < count; j++){
//マスの書き換え
board[y + vec_yyy][x + vec_xxx] = turn;
//ベクトルを1つ伸ばす
vec_xxx = StretchVec(vec_xxx);
vec_yyy = StretchVec(vec_yyy);
}
break;
}
//ベクトルを1つ伸ばす
vec_xx = StretchVec(vec_xx);
vec_yy = StretchVec(vec_yy);
//カウントアップ
count++;
}
}
}
}

//ターンを入れ替える
void Change(void){

if (turn == 1){
turn = 2;
}
else{
turn = 1;
}
}

//勝敗を決定
void Judge(void){

//ボード上をカウント
Count(board);

printf("黒駒の数:%d個\n", BLACK_NUMBER);
printf("白駒の数:%d個\n\n", WHITE_NUMBER);

if (BLACK_NUMBER > WHITE_NUMBER){
if (human == BLACK) printf("人間の勝ちです。\n\n");
if (computer == BLACK) printf("コンピュータの勝ちです。\n\n");
}
else if (WHITE_NUMBER > BLACK_NUMBER){
if (human == WHITE) printf("人間の勝ちです。\n\n");
if (computer == BLACK) printf("コンピュータの勝ちです。\n\n");
}
else{
printf("引き分けです。\n\n");
}

}






とりあえず、私がFFL.ver2.4と戦ってみましたが、勝てませんでした。以前はリバーシ初心者の私でも「これは悪手だなぁ・・・。」と思う手をコンピュータが差していたんですが、ver2.4ではパッと見たところあんまり無いように思われます。


まだまだ改良の余地があるので、改良を加えていきたいと思います。





PS

ソースコードについてちょっと補足させてください。

scanfはどうもvisual studioではscanf_sと書き換えないと使えないみたいなので、書き換えてください。

それとコンパイルした時に黒の駒と白の駒が入れ替わって見えることがあると思いますが、それはプログラムを実行してる時に背景によります。上手くいかないときはDisp()の○と●を入れ替えてみてください。


関連記事



↓ランキングに参加しています!お手数ですが、よろしければ3つとも1日1回クリックをお願いしますm(__)m↓
にほんブログ村 大学生日記ブログ 理系大学生へ
にほんブログ村


【カテゴリー:開発・発明系 コメント(0)

コメント







(コメントの削除依頼等は右下の「連絡先」にて承ります。)

前ページ || 次ページ

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。