• ベストアンサー

教えてください(丸罰ゲーム)

三目ゲーム(9マスの丸罰ゲーム)のプログラムを書いてコンピューターを相手に対戦したとき、コンピュータの勝率をできるだけあげるにはどうしたらいいんでしょうか??何か参考になることなんでも教えてください。ホームページなど教えてもらえれば光栄です。お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • age_momo
  • ベストアンサー率52% (327/622)
回答No.11

No10です。斜めの判断に記述間違いがあったんでついでに少し書き足して関数にしました。 int tsuginote(int *a) { int i,j,tate,yoko,naname1=0,naname2=0,kari=99; for(i=0;i<3;i++){ for(j=0;j<3;j++){ if(a[j][i]==0){ tate=a[(j+1)%3][i]*a[(j+2)%3][i]; yoko=a[j][(i+1)%3]*a[j][(i+2)%3]; if(i==j){ naname1=a[(j+1)%3][(i+1)%3]*a[(j+2)%3][(i+2)%3]; } if(i+j==2){ naname2=a[(j+1)%3][(i+2)%3]*a[(j+2)%3][(i+1)%3]; } if((tate==4)||(yoko==4)||(naname1==4)||(naname2==4)){ return 10*i+j; }else if((tate==1)||(yoko==1)||(naname1==1)||(naname2==1)){ kari=10*i+j } } } } return kari; } これで戻り値が99のときはランダムに、0-22の時はその指示通りにでどうでしょう。

その他の回答 (10)

  • age_momo
  • ベストアンサー率52% (327/622)
回答No.10

少し検索していて面白そうな質問にたどり着きました。 >例えば2つ並んだら3つ目は必ず取りに行くようなプログラムは書けるでしょうか? 例えば最初は全て0で、相手が取れば1、自分がとれば2を配列に入れておけば for(i=0;i<3;i++){ for(j=0;j<3;j++){ tate=a[(j+1)%3][i]*a[(j+2)%3][i]; yoko=a[j][(i+1)%3]*a[j][(i+2)%3]; if(i+j==4){ naname1=a[(j+1)%3][(i+1)%3]*a[(j+2)%3][(i+2)%3]; naname2=a[(j+1)%3][(i+2)%3]*a[(j+2)%3][(i+1)%3]; }else{naname1=0; naname2=0; } } } でtate,toko,naname1,2に4があれば無条件にループを抜け出して終了、1があれば(i,j)を記憶しておいて一通り調べて他のところに4がなければ優先的に、0,2は放っておくということでどうでしょう?tate,yoko,naname1,2は配列にしてもいいですしループを抜ける条件等を適当に付け足してください。 基本的にはVB使いですので文法が間違ってたらごめんなさい。

回答No.9

> 二つ並んでる場合を1つずつ列挙して、そのときはここ、そのときはここってif文に当てはめていけばいいんですか? だらだら書き並べてみました。。。9通り if (((a[0][0]==AKI)&&(a[0][1]==MARU)&&(a[0][2]==MARU))||((a[0][0]==AKI)&&(a[1][0]==MARU)&&(a[2][0]==MARU))||((a[0][0]==AKI)&&(a[1][1]==MARU)&&(a[2][2]==MARU))) a[0][0]=MARU; if (((a[2][0]==AKI)&&(a[0][0]==MARU)&&(a[1][0]==MARU))||((a[2][0]==AKI)&&(a[2][1]==MARU)&&(a[2][2]==MARU))||((a[2][0]==AKI)&&(a[1][1]==MARU)&&(a[0][2]==MARU))) a[2][0]=MARU; if (((a[0][2]==AKI)&&(a[0][0]==MARU)&&(a[0][1]==MARU))||((a[0][2]==AKI)&&(a[1][2]==MARU)&&(a[2][2]==MARU))||((a[0][2]==AKI)&&(a[1][1]==MARU)&&(a[2][0]==MARU))) a[0][2]=MARU; if (((a[2][2]==AKI)&&(a[2][0]==MARU)&&(a[2][1]==MARU))||((a[2][2]==AKI)&&(a[0][2]==MARU)&&(a[1][2]==MARU))||((a[2][2]==AKI)&&(a[1][1]==MARU)&&(a[0][0]==MARU))) a[2][2]=MARU; if (((a[0][1]==AKI)&&(a[0][0]==MARU)&&(a[0][2]==MARU))||((a[0][1]==AKI)&&(a[1][1]==MARU)&&(a[2][1]==MARU))) a[0][1]=MARU; if (((a[1][0]==AKI)&&(a[0][0]==MARU)&&(a[2][0]==MARU))||((a[1][0]==AKI)&&(a[1][1]==MARU)&&(a[1][2]==MARU))) a[1][0]=MARU; if (((a[1][2]==AKI)&&(a[1][0]==MARU)&&(a[1][1]==MARU))||((a[1][2]==AKI)&&(a[0][2]==MARU)&&(a[2][2]==MARU))) a[1][2]=MARU; if (((a[2][1]==AKI)&&(a[0][1]==MARU)&&(a[1][1]==MARU))||((a[2][1]==AKI)&&(a[2][0]==MARU)&&(a[2][2]==MARU))) a[2][1]=MARU; if (((a[1][1]==AKI)&&(a[0][0]==MARU)&&(a[2][2]==MARU))||((a[1][1]==AKI)&&(a[0][2]==MARU)&&(a[2][0]==MARU))) a[1][1]=MARU;

回答No.8

> 二つ並んでる場合を1つずつ列挙して、そのときはここ、そのときはここってif文に当てはめていけばいいんですか? いいんじゃないですか。 だらだら書き並べたところで高々8通りですから。

回答No.7

プログラム例・・・適当に書いたので長いです。すいません。 #include <stdio.h> #define MARU 1 #define BATU 4 #define DRAW 10 /* 3x3の盤 0:空き MARU:○ BATU:× */ typedef struct { char xy[3][3]; } MATRIX; /* 勝敗チェック 0:未 MARU:○ BATU:× DRAW:引き分け */ int check(MATRIX ban) { int i,j,p; /* 引き分け? */ for (p=0,i=0; i<3; i++) for (j=0; j<3; j++) p += (ban.xy[i][j]==0)?0:1; if (p==9) return DRAW; /* 縦横? */ for (i=0; i<3; i++) { p=ban.xy[i][0]+ban.xy[i][1]+ban.xy[i][2]; if (p==MARU*3) return MARU; else if (p==BATU*3) return BATU; p=ban.xy[0][i]+ban.xy[1][i]+ban.xy[2][i]; if (p==MARU*3) return MARU; else if (p==BATU*3) return BATU; } /* 斜め */ p=ban.xy[0][0]+ban.xy[1][1]+ban.xy[2][2]; if (p==MARU*3) return MARU; else if (p==BATU*3) return BATU; p=ban.xy[2][0]+ban.xy[1][1]+ban.xy[0][2]; if (p==MARU*3) return MARU; else if (p==BATU*3) return BATU; return 0; } void display(MATRIX ban) { int i,j; for (i=0; i<3; i++) { for (j=0; j<3; j++) { switch(ban.xy[i][j]) { case 0: printf(" %d",i*3+j+1); break; case MARU: printf(" O"); break; case BATU: printf(" X"); break; default: printf(" ?"); } } printf("\n"); } printf("\n"); } void man(MATRIX *ban, int turn) { int i; for(;;) { printf("? "); scanf("%d",&i); i--; if ((i<0)||(i>8)) continue; if (ban->xy[i/3][i%3]==0) { ban->xy[i/3][i%3]=turn; break; } } } void com(MATRIX *ban, int turn) { int i,j; MATRIX tmp; tmp= *ban; /* 次の手で勝つ? */ for (i=0; i<3; i++) { for (j=0; j<3; j++) { if (tmp.xy[i][j]==0) { tmp.xy[i][j]=turn; if (check(tmp)>0) { ban->xy[i][j] = turn; return; } tmp.xy[i][j]=0; } } } /* 相手が勝つ? */ for (i=0; i<3; i++) { for (j=0; j<3; j++) { if (tmp.xy[i][j]==0) { tmp.xy[i][j]=(turn==MARU)?BATU:MARU; if (check(tmp)>0) { ban->xy[i][j]=turn; return; } tmp.xy[i][j]=0; } } } /* 空いているところに打つ */ for (i=0; i<3; i++) { for (j=0; j<3; j++) { if (tmp.xy[i][j]==0) { ban->xy[i][j]=turn; return; } } } } int main(void) { MATRIX ban={{{0,0,0},{0,0,0},{0,0,0}}}; int r; display(ban); for (;;) { man(&ban, MARU); display(ban); if ((r=check(ban)) != 0) break; com(&ban, BATU); display(ban); if ((r=check(ban)) != 0) break; } switch(r) { case MARU: printf("○の勝ち\n"); break; case BATU: printf("×の勝ち\n"); break; default: printf("引き分け\n"); } return 0; }

回答No.6

> 例えば2つ並んだら3つ目は必ず取りに行くようなプログラムは書けるでしょうか? 空いているところに1個ずつ入れてみて3個並ぶかどうか調べればいいと思います。。 試しにゲーム木を作ってみましたが、回転・鏡像を考えないで255168通り(oの勝ち131184通り、xの勝ち77904通り、引き分け46080通り)でした。(違ってるかも)

hyokkorri
質問者

補足

なんかうまく書けないんですけど。。プログラム例とゆーか書いてもらえないでしょうか。。すいませんお願いします!!

回答No.5

> 例えば2つ並んだら3つ目は必ず取りに行くようなプログラムは書けるでしょうか? なにか難しい点がありますか? 二つ並んだ箇所を探すだけでしょうに。

hyokkorri
質問者

お礼

そーなんですよね。。二つ並んでる場合を1つずつ列挙して、そのときはここ、そのときはここってif文に当てはめていけばいいんですか?

回答No.4

九つのマスを○×で埋める組み合わせは3024通りしかありませんから、全てを列挙し、負ける手を打たせなければよいのでは、と。

hyokkorri
質問者

補足

#include<stdio.h> #include <stdlib.h> #include <time.h> //座標の構造体 typedef struct{ int gyou; int retu; }matrix_t; //プロトタイプ宣言 matrix_t input(int a[][3]); //プレイヤーの入力 int chk(int a[][3]); //そろったかどうかを判定 void display(int a[][3]); //ボードを表示。 matrix_t sikou(int a[][3]); //コンピュータの思考 (中略) //コンピュータの思考 matrix_t sikou(int a[][3]) { matrix_t temp; int i,j; //ランダムな場所を指定 srand((unsigned int)time(NULL)); while(1){ temp.gyou=rand()%3; temp.retu=rand()%3; if(!a[temp.gyou][temp.retu])return temp; } } コンピュータの思考がランダムに与えられている部分をうまく変えたいんですよ。これだけではわかりにくいと思いますが。。何かいい方法はないでしょうか?例えば2つ並んだら3つ目は必ず取りに行くようなプログラムは書けるでしょうか?

回答No.3

対戦プログラムの場合、一般的にはゲーム木を考えます。 3×3マスでしたら全パターンを調べてもそんなに時間はかからないでしょう。将棋やチェスだと木が大きくなるので枝狩りをする必要がありますし、強いプログラムを作ろうと思ったら枝狩りの方法や評価関数など工夫が必要です。 「ゲーム理論」で検索すると参考になるサイトがヒットするかもしれません。。

noname#8185
noname#8185
回答No.2

先手であれば「勝ち」か「引き分け」に持っていけます ということは後手では 「負け」か「引き分け」ですね 説明は長くなります

  • twk
  • ベストアンサー率29% (18/62)
回答No.1

○×ゲームは、両者最善を尽くすと必ず引き分けになります。 先読みをしても良いですが、パターンは限られているので、ある程度手順を記憶させておいても良いかもしれません。

hyokkorri
質問者

補足

#include<stdio.h> #include <stdlib.h> #include <time.h> //座標の構造体 typedef struct{ int gyou; int retu; }matrix_t; //プロトタイプ宣言 matrix_t input(int a[][3]); //プレイヤーの入力 int chk(int a[][3]); //そろったかどうかを判定 void display(int a[][3]); //ボードを表示。 matrix_t sikou(int a[][3]); //コンピュータの思考 (中略) //コンピュータの思考 matrix_t sikou(int a[][3]) { matrix_t temp; int i,j; //ランダムな場所を指定 srand((unsigned int)time(NULL)); while(1){ temp.gyou=rand()%3; temp.retu=rand()%3; if(!a[temp.gyou][temp.retu])return temp; } } コンピュータの思考がランダムに与えられている部分をうまく変えたいんですよ。これだけではわかりにくいと思いますが。。何かいい方法はないでしょうか?例えば2つ並んだら3つ目は必ず取りに行くようなプログラムは書けるでしょうか?

関連するQ&A

  • 三目並べ

    三目並べ 三目並べ(○×ゲーム)のプログラムにコンピュータとの対戦を付けたいのですがどうすればいいのでしょうか。教えてください。 ソースプログラム↓↓ http://ime.nu/codepad.org/wfwkEbVP 実行結果はこんな感じにしたいです。 1Pと2Pとの交互に対戦しますか? 1Pとコンピュータとの対戦にしますか? プレイヤ同士の対戦なら1を、コンピュータとの対戦なら2を入力してください: こんな感じで選らばせて対戦できるようにしてほしいです。 ※1Pのマスは○でコンピュータのマスは×でお願いします。

  • ○×ゲーム

    ○×ゲーム ○×ゲームを作ってますがコンピュータとの対戦の時、先攻後攻をジャンケンで決めれるようにしたいのと、コンピュータがマスを置くAIをしっかりとしたものにしたいのですがプログラム上でどうすればよろしいでしょうか。どなたか教えてください。 ソースコード↓ http://codepad.org/haIjhQhY

  • 罰ゲームの食材は?

    新年会の宴会ゲームの罰ゲームでジューサーを使う罰ゲームを考えています。内容はジューサーに3種類の食材を入れ、かき混ぜて飲ませるというゲームです。 自分で考えた食材は納豆、コーラ、ゴーヤです。これだとかなりキツイですかね?皆さんでしたらどんな3種類の食材が盛り上がると思いますか?参考にしたいのでご意見お聞かせください。宜しくお願いします。

  • 罰ゲームで告白

    することになってしまったんですが。 僕はしたくありません。 相手のことも傷つけるし、好きでもないのに告白するのは失礼だと思うからです。 でも、ゲームで負けたのにしないってのも卑怯な気がします・・・。 どうにかうまくやり過ごす方法はないでしょうか? 「罰ゲームだから気にしないで」っていうのも考えたんですが、友達から「『罰ゲームだから』ってのは無しだからな!」と言われているので出来そうにありません・・。 告白する子はよく話す方なんですが、好きという感情は全然ありません。 告白して学校でギクシャクするのがとても嫌です。 皆さんどうにかアドバイスお願いします。

  • 罰ゲーム?内容

    好きな人とテストで賭けをしていて、私が勝ちました!!罰ゲームは『負けたほうが勝ったほうの言うことを聞く』って内容なんですが、何がいいと思いますか?なかなか良いのが思い付かなくて… やっぱり好きな人相手だから、普通に何かおごってもらうとかじゃつまらないかなって考えてるんですけど…(-ω-;)

  • 将棋のゲーム

    20年ほど前から家庭用ファミリーコンピューターで将棋のゲームが出ていたのですが、今思うと将棋のコンピューター対戦のプログラムはものすごいように思います。強さも選択ができたと思います。 いったい将棋ゲームのコンピューターはどんな風に作ってあるのでしょうか!??

  • 罰ゲームで告白

    大学3年女子です。 さきほど、罰ゲームで告白されました。 相手は、同じサークルで同学年で三年間なかよくしてきた人です。 すごくおちゃらけている人ですが、分別はある人だと思っていました。 それに、大学3年にもなってそんな下らない罰ゲームをする神経が理解できません。 私は女の子らしい方ではなく、どっちかと言えば男子に混ざってワイワイしたり、男扱いされるような性格ですし、いじられやすく、後輩にまでいじられることもよくあります。 でも、今回は人のことを馬鹿にしすぎだし、度が過ぎていると感じました。それに今まで同学年として一緒に仕事してきて、対等だと思っていたのに、すごく見下されてると感じました。 私は前付き合っていた人を引きずっていて、彼もそのことを知っています。 みなさんは罰ゲームで告白することについて、どう思いますか? すごくショックなのですが、私は広い心で許すべきでしょうか。電話でブチギれてしまいました…

  • 罰ゲームを逃れる方法について

    私は大学一回生で先輩2回生男子4人と私1人のサークルに入っています 今度新歓ということで先輩の家で鍋パをすることになったのですが、そこで罰ゲームトランプを使ってゲームをするそうです ただ私はそういうのが本当に苦手です! モノマネとか歌とか考えただけで消えたくなります 先輩たちは男ばっかりだし同期の友達だからそんなにダメージはないのでしょうが・・・ 私は見た目がギャル系なので多少恥をかかせても問題ないと思われている気がします・・・ どうにかして罰ゲームトランプを回避する方法はないでしょうか?(>_<) 先輩たちともそこまで仲良くなれていないので嫌だ!って主張できないです 本当に困ってます よろしくお願いいたします

  • 罰ゲーム(長文注意)

    中学3年生の男です。 ぼくは現在いじめのようなものを受けています。 いじめかどうか自分自身でも確信が持てませんが相談させていただきます。 僕は学習塾に通っているのですが、僕は話す相手がいません。 簡単にいえば孤立状態です。 でも僕は望んで孤立しています。なぜなら学習塾とは本来勉強を教わる場であって、 友達同士でわいわいやるところではないと思っているからです。 これまではお互いに干渉することなく過ごしていたのですが、何やら罰ゲームのようなものが流行り始めました。 じゃんけんで負けた人が、僕に話しかけなけらばならないというものです。 そのゲームが始まって以来、ヒソヒソ話しや嘲笑が聞こえるようになりました。 僕は罰ゲームの材料になっているということです。 しかしここで問題なのは、相手がまだ自分に話しかけてきていないということです。ただ単に相手に度胸(?)がないのか、 僕に「お前はいじめられているんだぞ」という不安を植え付けたいのかよくわかりません。 何が言いたいのかといえば、放っといてくれということです。 正直、今の「自分が罰の対象になっている」という空気に耐えられません。 自分から言う勇気がないので、無視を決め込むしかないのでしょうか。 いまいち分かりづらい話ではありますが、回答よろしくお願いします。

  • 友達との罰ゲームで……。

    私は、ある賭けをして負けてしまいました。 かけで負けた人は、I先輩に抱きつくということになっています。 =私がやることになったのですが、  その先輩は、なんとなく…雰囲気がこわくって、  話しかけないでオーラが凄い出ています。 なんとか、「すきだから抱きついた」や、「罰ゲームだから」というのが、 周りにも、相手にも分からないような抱きつく方法はありませんでしょうか? わたし一人では考えられません。 さらに、ちゃんと私が納得したものでなければやりたくないんです。 お願いします。皆さんの知恵をお貸しください。 ※私は、相手にとっては失礼なものであり、友達を説得して辞めるのが得策だということは、承知しています。しかし、友達関係や、賭けをしてしまったことを考えると、どうしてもできません。 「やめろ」とか、「失礼だ」と言った意見ではないものを下さると幸いです。 宜しくお願いします。

専門家に質問してみよう