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

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

ただいまの
回答率

90.84%

  • C

    3201questions

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

C言語のオセロAI育成プログラムを作っている際に…

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 122

Removed_Past

score 1

 前提・実現したいこと

タイトルにもある通り、C言語を使って遺伝的アルゴリズムを使用したオセロのAI育成プログラムをしていて、現在その中の自動で対戦させる機構を作っています。

 発生している問題

本来打つ事が出来るはずのマス目に対する「打てるかを判定する処理」を実行した際、「打つ事が出来ない」という判断をされてしまう。


![問題が起きている画面
上写真において、例えば盤面の「E2」にあたるマス(Check:○○のところで1マスずつ判定しています)の処理結果である下文は、
E2にあたるマス「41」(書式はx-1、y-1の順番です)はResult:2と表示されています。
Resultの数字は-1なら打つ事ができない、自然数ならそこに置いた場合に獲得できる枚数を表しています。
ここで、本来打てる「D1」「E1」「A2」といったマス「40」「50」「01」は-1、つまり打てない、と判断されてしまうのです。

 該当のソースコード

//付属の自作ヘッダです
#define INCLUDE(a, b)    do{x2 = a; y2 = b; enemy = 0;}while(0)

int putboard(int x, int y, int player, int board[8][8]){
    int code = 0;
    int a;
    int enemy = 0;
    int x2, y2;

    // そのマスが空白か判定する
    if(board[y][x] != 0){
        code = -1;
        goto end;
    }

    // 八方向に挟めるかの判定
    // 上
    INCLUDE(x, y);
    while(1){
        y2--;
        if((y2 < 0) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y - a][x] = player;
        }
    }
    // 下
    INCLUDE(x, y);
    while(1){
        y2++;
        if((y2 > 8) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y + a][x] = player;
        }
    }
    // 左
    INCLUDE(x, y);
    while(1){
        x2--;
        if((x2 < 0) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y][x - a] = player;
        }
    }
    // 右
    INCLUDE(x, y);
    while(1){
        x2++;
        if((x2 > 8) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y][x + a] = player;
        }
    }
    // 左上
    INCLUDE(x, y);
    while(1){
        x2--;
        y2--;
        if((y2 < 0) || (x2 < 0) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y - a][x - a] = player;
        }
    }
    // 右上
    INCLUDE(x, y);
    while(1){
        x2++;
        y2--;
        if((y2 < 0) || (x2 > 8) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y - a][x + a] = player;
        }
    }
    // 左下
    INCLUDE(x, y);
    while(1){
        x2--;
        y2++;
        if((y2 > 8) || (x2 < 0) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y + a][x - a] = player;
        }
    }
    // 右下
    INCLUDE(x, y);
    while(1){
        x2++;
        y2++;
        if((y2 > 8) || (x2 > 8) || !(enemy < 100))        break;
        if(board[y2][x2] == 0)                        enemy += 900;
        if(board[y2][x2] == player)                enemy += 100;
        if(board[y2][x2] == player * -1)    enemy +=   1;
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
        board[y][x] = player;
        for(a = enemy - 100; a > 0; a--){
            board[y + a][x + a] = player;
        }
    }

    end:
    // codeがここまでで0なら-1に、それ以外は+1する(置いた分)
    if(code <= 0)    code = -1;
    else                    code++;

    return code;
}

//メインのCファイルです(関連する関数のみを書いてます)
void thinking(int player, const int bn, const int wn, int put[2]){
    srand(time(NULL));
    // とりま1手読み
    int code = 0, x, y, a = 0;
    int n, score, t;
    int max = -10000;
    int putx[64], puty[64];

    printf("Turn %s\n", player == 1 ? "Black" : "White");

    for(y = 0; y < 8; y++){
        for(x = 0; x < 8; x++){
            setvr();
            code = putboard(x, y, player, vboard);
            printf("Check:%d%d Result:%d\n", x, y, code);
            if(code < 0)    continue;
            score = pointcheck(player, player == 1 ? bn : wn);
            if(score > max){
                max = score;
                printf("New Max:%d\n", max);
                putx[0] = x;
                puty[0] = y;
                t = 0;
            }
            if(score == max){
                t++;
                putx[t] = x;
                puty[t] = y;
            }
        }
    }

    if(t > 0){
        n = rand() % (t + 1);
        put[0] = putx[n];
        put[1] = puty[n];
    }
    else{
        put[0] = putx[0];
        put[1] = puty[1];
    }

    printf("Max:%d\nPut:%d%d\n", max, put[0] + 1, put[1] + 1);
}

 試したこと

関数間の受け渡しの値を調節したりプログラムを読み直したりしたのですが、原因が分かりませんでした。

色々分かりにくい箇所があるかと思いますが、よろしくお願いします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

ボードの範囲外に出たときの処理が足りてない。

座標00から上方向に行ったらbreakするけど、そのままifブロック内に入ってcodeが-100になってる。
盤面は8x8で64しかないから、何をどうやってもプラスに戻ることはない。

    // 八方向に挟めるかの判定
    // 上
    INCLUDE(x, y);
    while(1){
        y2--;
        if((y2 < 0) || !(enemy < 100))        break;
(略)
    }
    if(!(enemy >= 900 || enemy - 100 == 0)){
        code += enemy - 100;
(略)
    }

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/04/12 22:31

    なるほど、確かに上方向の場合上端ならenemy=0のままwhile文を抜けるけど、それだとその直後のif文の条件に合ってしまうんですね…
    こんなに素早く的確な回答をして下さってありがとうございます!

    キャンセル

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

  • ただいまの回答率 90.84%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

  • 解決済

    オセロの白が表示されない・・・

    package reversi; import java.awt.Color; import java.awt.Dimension; import java.awt.ev

  • 受付中

    javaのオセロの自動対局について

    オセロの自動対局 javaでオセロの自動対局の機能を実装しようと思い、盤面をクリックすると100回対局を繰り返すプログラムを作ろうとしました。が、しかし、2回しか対局をしてくれま

  • 解決済

    3次元オセロのプログラミング

    このプログラミングで実行すると、どこにもコマをおけない上に、何行目かの入力をするとどこに置くこともなく順番交代してしまいます。 おそらくcheckという関数のどこかとcontin

  • 解決済

    構造体のプログラム

    いつもお世話になっています。C言語初心者でただいま勉強中です。構造体について質問させていただきます。ファイルから構造体配列に読み込んで以下のように出力するプログラムを作りたいんです

  • 解決済

    配列

    n個のデータを配列に読み込み、平均と分散を求めるプログラムを作成して、下記のデータで試せ、という問題です。 {3.9,10.4,9.5,7.5,2.8,4.8,2.9,8.1,3

  • 解決済

    配列の要素間の和を全パターン求めるプログラムを作成したい。

    皆様ありがとうございました。 前提・実現したいこと <CもしくはC++> 配列の要素間の和を全パターン求めるプログラムを作成したい。 【例】 /*-------------

  • 受付中

    プログラムを見やすく改良したい

    正常に動くプルグラムを見やすく改良したい。 具体的に教えていただければありがたいです。セグメンテーションフォルトでベスト7まで表示して停止します。173行あたりだと思うのですが、よ

  • 解決済

    関数の引数に配列を使うことが難しい

     前提・実現したいこと 0~100の整数を10個入力して、最大値と最小値を求めて表示するプログラムをかきたいです。ただし、-1が入力されると処理を中止する、最大値最小値を求める関数

同じタグがついた質問を見る

  • C

    3201questions

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