飛び越しゲーム 計算数理2演習 課題1 2011年度(阿原) 次のようなゲームを考えます • 黒石を6つ、白石を6つ用意して、2×9の 升目の上に、下図のようにおきます。これ で準備完了です。 ●●● ●●● ○○○ ○○○ 基本ルール • 二人のプレーヤーがそれぞれ黒石・白石を動か します。黒石は左から右へ、白石は右から左へと 動かします。 • 黒石と白石は交互に動かします。動かせる状況 であるならばパスをすることは許されません。 • つながった相手の石を飛び越すことが出来ます。 (自分の石は飛び越せません。) 飛び越し方 • 下の図のように、飛び越すことが出来ます。 ●● ●○ ● ● ○● ○○ ○ ○ 飛べない例 • 隙間があったり、自分の石があると飛び越 せません ● ●● ●○● ●○ ○○ ○ ○ 上がり • 黒石は、全部右側に寄せれば上がり、白 石は全部左側に寄せれば上がりです。 黒勝ち ○○ ○ ●●● ○○○ ●●● 盤の名前の付け方 0 1 2 3 4 5 6 7 8 9 1011121314151617 2*9 0 1 2 3 4 5 6 7 8 8 9 2*10 10111213141516171819 補助的なルール • このゲームでは、動かせる場所がある場 合にはパスできません。 • 自分の石がないところを指定すると、即負 けになります。 このゲームの戦術を考えてください • あなたは黒を持って、このゲームで出来る だけ勝つようなアルゴリズムを考案してくだ さい。 • 盤のサイズが2*9,2*10の2つの場合 について戦術を考えてください。そして、そ れぞれの場合について、阿原が準備した3 人のプレーヤーからできるだけ勝ちを上げ てください。 戦術のポイント • • • 一般論としては,相手の石をたくさん飛び 越したほうが早くゴールに近づきます。 相手に自分の石を飛び越させないように することも大切です。 相手を手詰まりにもちこんで、こちらが手 を進めるという作戦もあり得ます。 戦術のポイント2 • • パスができないことを戦術に組み込むのも大切 なことです。相手が動かしたくない石を、ほかの 石を手詰まりにすることによって、無理やり動 かさせるという戦術もあり得ます。 完全情報ゲームなので,必ず先手必勝か後手 必勝があるはずですが,先手を持った場合,後 手を持った場合,どちらも善戦できるプログラ ムを作ってください.(コンピュータ側は必勝手 順で指すことはしません.) ダウンロードファイル • http://www.math.meiji.ac.jp/~ahara/sk2 e/2011jump2008.zip • http://www.math.meiji.ac.jp/~ahara/sk2 e/2011jump2010.zip をダウンロードしてください。(表紙ページにもリンクが あります。)これを解凍すると、いくつかのファイル が現れますが、それらが同じフォルダにあるように してください。(普通に解凍すればそうなります。) • jump.vcprojというファイルをダブルクリックすると, Visual C++が起動します. • 皆さんが編集してよいのはjump.cppのみです。 コンパイルと実行 • • まずはプログラムを変更することなく,「デ バッグ」メニューから「デバッグ開始」を選 んでください.[F5]キーを押しても同じこと です.以後,プログラムを動かすときには いつもこの方法を用いてください. もし,「悪いことをした心当たりがない」の にコンパイルできなくなった場合には, 「ビルド」メニューの「ソリューションのリビ ルド」を選択してください.それでも動かな かったら阿原を呼んでください. プログラムの画面 動かし方 ● ● まずは自分の手入力とプログラムとで対戦し てみてください.「盤の大きさ」「プレーヤー2選 択」をしてから,「1ゲーム(先手)」または「1ゲ ーム(後手)」をクリックしてください. プレーヤー1を手入力にしておけば,画面上 の青いコマをクリックすることによって,プレー ヤー2と対戦することができます. プログラミング開始 ● ● あらかた遊んだら,今度はプログラミングをしてましょ う.一度ゲーム画面を閉じて,Visual C++の画面に 戻ります. 左側(時に右側)に「ソリューションエクスプローラー」 をかかれた部分があり,そこに「太字のjump」をダブ ルクリックします.そして「ソースファイル」をダブルク リックして「jump.cpp」をダブルクリックします.(この 作業は一度おこなえば,次からは自動的に開いてく れます.) プログラム開始 ● Jump.cppというファイルを開くと,下のほうに ● Int Form1::myplay(void){ ・・・・・・ } という部分があり,ここが「プログラム本体」で す.ここに飛び越しゲームをプレーする戦略プ ログラムを書いてもらいます. プログラムの手引き • 盤面を左から • int board[]; • という配列変数で表します。青石(あなた) は1、赤石(相手)は2、何もないところは0 であらわされます。2*9盤の最初の状態で は、 board[0]=board[1]=board[2]=1; board[9]=board[10]=board[11]=1; です。(2列目は9~17になります。) 盤の大きさを表す変数width ● ● widthという変数があり、これで盤の幅をあら わしています。つまり、widthの変数の値は 9,10のいずれかです。 このことから、左下の升目は board[width] とあらわされることが分かります。 jump.cppの中身 int Form1::myplay(void){ int i; for(i=0;i<2*width;i++){ if(player1_movable(board,i)){ return i; } } return -1; } この中身を変更してください。 return iとは? • この関数では、「次に動かす石の位置」を指定し ます。上段一番左が0、一番右が8です。動かせ る黒石がそこにあれば、あとはプログラムが動か してくれます。もし、動かせる黒石でない場所を 指定した場合は負けです。初手で2の位置にあ る黒石を一つ右へ動かすためには、最初に return 2; とすればよいことがわかります。 使ってよいデータは • 配列変数board[]だけが参照できるデー タです。(これがゲームの情報の全てです。 完全情報ゲームといいます。) • 2*9の時には配列変数の大きさは18です が、2*10の時には20となります。この配 列変数の値から、次に動かす石の場所を 返すような関数を作ってください。 使ってよい関数 • bool player1_movable(int b[],int i); という関数を用意しました。これはi番の場所 を指定した場合、そこに黒石があって、そ の黒石が動かせる状況にあれば、trueが 返され、それ以外の場合にはfalseが返さ れる関数です。通常は if(player1_movable(board,2)){ return 2; } のように使ってください。 初級者のためのヒント(1) int i; for(i=0;i<2*width;i++){ if(player1_movable(board,i)){ return i; } } こうすることによって、「盤面の0から順に2*width-1まで 調べて、もし、動かせるコマがあればそのコマを動かす」と いう命令になります。 初級者のためのヒント(2) int i; for(i=2*width-1;i>=0;i--){ if(player1_movable(board,i)){ return i; } } こうすることによって、「盤面の2*width-1から順に0まで (減らしながら)調べて、もし、動かせるコマがあればそのコ マを動かす」という命令になります。 初級者のための練習問題 ● ● width=9だとして、盤面を、0,9,1,10,2,11,… の順番に調べたいときには、どのようにプログ ラムを組めばよいでしょうか? width=9だとして、盤面を、 8,17,7,16,6,15,…の順番に調べたいときに は、どのようにプログラムを組めばよいでしょ うか? 初級者のためのヒント ● ● 盤面の i 番を調べているときに、「一つ右隣 の盤面」を調べたいときには board[i+1] という変数を調べればよいことがわかります。 「一つ右隣に相手のコマがあれば」という条件 文は if(board[i+1]==2){ と書けばよいことがわかります。 レポートのポイント ● ● 勝つための戦略を明確にレポートしてください。「ひたすら進 める」などの漠然とした表現はだめです。 勝てなかったゲームについて、どの手がまずくて勝てなかっ たかをレポートしてください。つまり、ポイントとなる盤面を再 現し、そこであなたのプログラムは**という手を指したが、 実際には++のほうが良い手であった。という感じのレポート を作ってください。
© Copyright 2024 ExpyDoc