忍者ブログ
なんとなくだらだらと。方向性はまだ決まってない。 当方のプログラムでは、山田巧さん作成のDXライブラリを利用させていただいてます。 本サイト http://homepage2.nifty.com/natupaji/DxLib/index.html DX Library Copyright (C) 2001-2008 Takumi Yamada.
[64] [63] [62] [61] [60] [59] [58] [57] [56] [55] [54]
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

この「○×ゲーム」の肝の部分、CPU対戦が出来てしまった。思考部分はたぶん完成。
小学生の頃、○×ゲームの必勝パターンをフローチャートに書いて以来、いつか
プログラムで組んでやろうとずーっと思ってたんだよ。



v012

ダウンロード http://hiyayakko.sarashi.com/MaruBatu/MB012.zip (2009.09.07)



ノートにパターンをまとめて、少しづつ判定条件を増やしていくかと読んでたんだけど
まとめる方法が見えた瞬間に、すべてがきれいに折りたたまれた。

しかしこれ、何をやってるのか俺にも理解不能の挙動不審。
プログラムの解説だけでは絶対に伝わらない自信がある。

main.cpp
// CPU思考ルーチン
void CpuTurn()
{
    int x,y;
    int bx,by;
    // 点数評価テーブル
    int tb[3][3]={0};
    int c=-99;

    // (1)次に自分が勝てる手があれば迷わずそこへ置く
    if(CheckDouble(game.Player,bx,by)){
        board[by][bx]=game.Player;
        ChangeTurn();
        return;
    }

    // (2)相手からのリーチはなるべく阻止!
    if(CheckEnemyDouble(game.Player,bx,by)){
        board[by][bx]=game.Player;
        ChangeTurn();
        return;
    }

    // 4隅にゲタをはかせる
    tb[0][0]++;
    tb[0][2]++;
    tb[2][0]++;
    tb[2][2]++;

    // 2ターン目、×側は中央が空いてたら最優先
    if(game.Turn==1)tb[1][1]+=50;

    // 評価点加点
    for(y=0;y<3;y++){
        for(x=0;x<3;x++){
            if(board[y][x]==game.Player){
                for(int i=0;i<3;i++){
                    tb[y][i]+=10;
                    tb[i][x]+=10;
                }
                if(x==y){
                    tb[0][0]+=10;
                    tb[1][1]+=10;
                    tb[2][2]+=10;
                }
                if(((x-y)*(y-x)==-4)||(x==1&&y==1)){
                    tb[0][2]+=10;
                    tb[1][1]+=10;
                    tb[2][0]+=10;
                }
            } else if(board[y][x]!=NONE){
                for(int i=0;i<3;i++){
                    tb[y][i]-=10;
                    tb[i][x]-=10;
                }
                if(x==y){
                    tb[0][0]-=10;
                    tb[1][1]-=10;
                    tb[2][2]-=10;
                }
                if(((x-y)*(y-x)==-4)||(x==1&&y==1)){
                    tb[0][2]-=10;
                    tb[1][1]-=10;
                    tb[2][0]-=10;
                }
            }
        }
    }

    // 対角でにらみあいが発生したときは角の優先度を上げる
    if(((board[0][0]!=NONE)&&(board[1][1]==NONE)&&(board[2][2]!=NONE))||
       ((board[0][2]!=NONE)&&(board[1][1]==NONE)&&(board[2][0]!=NONE))) {
        tb[0][0]+=15;
        tb[0][2]+=15;
        tb[2][0]+=15;
        tb[2][2]+=15;
    }

    // 評価点のいちばん高いポイントを探す
    bx = by = c = -99;
    for(y=0;y<3;y++){
        for(x=0;x<3;x++){
            if((board[1][1]!=game.Player)&&(tb[y][x]==0))continue;
            if((board[y][x]==NONE)&&(tb[y][x]>c)){
                bx = x;
                by = y;
                c = tb[y][x];
            }
        }
    }
    if(c!=-99){
        board[by][bx]=game.Player;
        ChangeTurn();
    } else {
        // ここに来ることはない。はず!
        while(1){
            bx = GetRand(2);
            by = GetRand(2);
            if(board[by][bx]==NONE){
                board[by][bx]=game.Player;   // 手番のひとのカーソルを置く
                ChangeTurn();
                break;
            }
        }
    }

    // 評価点表示
    if((game.Scene==PLAYER_TURN)||(game.Scene==CPU_TURN)){
        DrawScene();
        static const int WHITE = GetColor(255,255,255);
        for(y=0;y<3;y++){
            for(x=0;x<3;x++){
                //if(board[y][x]==NONE)
                    DrawFormatString(x*100+135,y*100+145,WHITE,"[%d]",tb[y][x]);
            }
        }
        ScreenFlip();
        WaitKey();
        ClearDrawScreen();
    }
}


盤面評価用に int tb[3][3] を用意します。
盤面の全てのマスをチェックして、自分のコマを見つけたら、そのマスの上下左右斜めに
+10点を与えます。逆に相手のコマなら10点減点します。
下の図のようなイメージで、相手に影響されてないマスがあぶり出されます。
これで一番点数の高いマスが次に打つべき候補になります。
MB012-1.png
ただ、この場合だと右上隅に置けば勝ち確定だけど、左辺に打ったら引き分けになる。
こういった細かい条件をごまかすために、いろいろとあやしい追加点を入れてたり。

このチェックのときに、いっしょにリーチ状態も見つけられそうな感じだったけど
とりあえず昨日作ったのをそのまま使って、真っ先に処理してしまうことにした。


こんな感じですべて書きだしてみたノート8P分+α が、今日のこのプログラムに詰まってる。
がんばって条件全部図解しないと、このブログで○×ゲーム解説した意味無くなるんだろうな。
やるしかないか。



ブログエントリ
○×ゲームを作る(1)
http://http://hiyayakkoprog.blog.shinobi.jp/Entry/53/

ダウンロードHP
http://hiyayakko.sarashi.com/Marubatu/MaruBatu.html

したらば掲示板
http://jbbs.livedoor.jp/bbs/read.cgi/computer/42268/1251347335/-100


PR


忍者ブログ [PR]
カレンダー
11 2024/12 01
S M T W T F S
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
フリーエリア
バーコード
ブログ内検索
P R
アクセス解析
カウンター