なんとなくだらだらと。方向性はまだ決まってない。
当方のプログラムでは、山田巧さん作成のDXライブラリを利用させていただいてます。
本サイト http://homepage2.nifty.com/natupaji/DxLib/index.html
DX Library Copyright (C) 2001-2008 Takumi Yamada.
× [PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。
この「○×ゲーム」の肝の部分、CPU対戦が出来てしまった。思考部分はたぶん完成。
小学生の頃、○×ゲームの必勝パターンをフローチャートに書いて以来、いつか プログラムで組んでやろうとずーっと思ってたんだよ。 ダウンロード 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点減点します。 下の図のようなイメージで、相手に影響されてないマスがあぶり出されます。 これで一番点数の高いマスが次に打つべき候補になります。 ただ、この場合だと右上隅に置けば勝ち確定だけど、左辺に打ったら引き分けになる。 こういった細かい条件をごまかすために、いろいろとあやしい追加点を入れてたり。 このチェックのときに、いっしょにリーチ状態も見つけられそうな感じだったけど とりあえず昨日作ったのをそのまま使って、真っ先に処理してしまうことにした。 こんな感じですべて書きだしてみたノート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 |
カレンダー
カテゴリー
フリーエリア
最新記事
(01/29)
(01/28)
(01/26)
(12/28)
(12/27)
(12/25)
(12/20)
(09/09)
(09/09)
(09/09)
(09/08)
(09/08)
(09/08)
(09/06)
(09/05)
(08/27)
(08/27)
(08/27)
(08/25)
(08/23)
ブログ内検索
P R
アクセス解析
カウンター
|