トリッキーコードネット トップへ戻る   C/C++, Java, Perl, PHP, JavaScript, アルゴリズム, ショートコーディング, IOCCCコードの解説, 等々

サイト情報

トリッキーなコード

7行プログラミング

物凄いコード集

アルゴリズム

データ構造

C/C++な話題

コードサンプル

ツール/環境構築

開発ノウハウ 等

ネタ/ジョーク集

おススメ書籍/サイト

サイトTOP >> 7行プログラミング >> 人間 VS コンピュータ(AI)オセロ対局 (C言語)

人間 VS コンピュータ(AI)対局プログラミング (C言語)

人間 VS コンピュータでオセロ対局を行うプログラムです。
7行のコード中に、なんとAI(人工知能)まで組み込まれています!

#include <stdio.h>
int p,t,a,d,c,v,i,m[90]={0},s,r[]={-10,-9,-8,-1,1,8,9,10};void k(){if(m[p]==0)
for(i=0;i<8;i++){for(c=0,v=p+r[i];m[v]==3-t;v+=r[i])c++;if(c&&m[v]==t){a+=c;v=
p;if(d)do m[v]=t,v+=r[i];while(m[v]!=t);}}}char*h="・○●\n";int main(){for(i=
1,m[41]=m[49]=2;i<10;m[i++*9]=3)m[40]=m[50]=t=s=1;for(;;a=d=0){for(p=9;p<82;++
p)k(),printf("%.2s",&h[m[p]*2]);if(a)for(d=a=s=p=8;a==8;k())t-2?(scanf("%d %d"
,&p,&i),p+=i*9):++p;else if(s)s=0,printf("pass");else break;t=3-t;}return 0;}
【プログラムの使い方】 ・人間は○のコマを使います。 ・コマを置く場所は、座標で指定します。⇒ X座標(半角スペース)Y座標(半角スペース)(Enterキー) ・エラーチェックはしていないので悪しからず。 実行結果は以下の通り~。 開始時: 7行C言語オセロプログラミング1 途中経過:(管理人 VS コンピュータの対局ですw)
・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・○●・・・ ・・・●○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 3 5 ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・●●●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 3 3 ・・・・・・・・ ・・・・・・・・ ・・○・・・・・ ・・○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・○・・・・・ ・●●●●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 4 3 ・・・・・・・・ ・・・・・・・・ ・・○○・・・・ ・●●○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・・●・・・・・ ・・●●・・・・ ・●●○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 3 1 ・・○・・・・・ ・・○・・・・・ ・・○●・・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ・●○・・・・・ ・・●・・・・・ ・・○●・・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 1 1 ○○○・・・・・ ・・●・・・・・ ・・○●・・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ○○○・・・・・ ・・●●・・・・ ・・●●・・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 4 1 ○○○○・・・・ ・・●○・・・・ ・・●○・・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ○○○○●・・・ ・・●●・・・・ ・・●○・・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 6 1 ○○○○○○・・ ・・●●・・・・ ・・●○・・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ○○○○○○・・ ・・●●・・・・ ・・●●●・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 2 2 ○○○○○○・・ ・○●●・・・・ ・・○●●・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ○○○○○○・・ ●●●●・・・・ ・・○●●・・・ ・●○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 1 3 ○○○○○○・・ ○○●●・・・・ ○・○●●・・・ ・○○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ○○○○○○・・ ○○●●・・・・ ○●●●●・・・ ・○○○●・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 5 2 ○○○○○○・・ ○○○○○・・・ ○●●○○・・・ ・○○○○・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ ○○○○○○・・ ○○○○○・・・ ○●●●●●・・ ・○○○○・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ 7 3 ○○○○○○・・ ○○○○○・・・ ○○○○○○○・ ・○○○○・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・ pass ○○○○○○・・ ○○○○○・・・ ○○○○○○○・ ・○○○○・・・ ・・○○○・・・ ・・・・・・・・ ・・・・・・・・ ・・・・・・・・
終了時:(管理人の圧勝^^;) 7行C言語オセロプログラミング2 以下のコードが、冒頭のコードの最適化されていないバージョンです。
 1 : #include <stdio.h>
 2 :
 3 : int put, turn, all, done, pass, count, cur, i,
 4 :
 5 : // 盤状態:横9*縦10で、使用は8*8
 6 : // 0:無し 1:1player 2:2player 3:改行
 7 : // y*9+xというイメージ。0行目と9行目は番兵
 8 : map[90] = {0},
 9 :
10 : // 盤を走査する場合、縦横斜め方向に向かうために足されるべき数
11 : dir[]={-10, -9, -8, -1, 1, 8, 9, 10};
12 :
13 :
14 : void check()
15 : // putに駒を置いた場合ひっくり返せる枚数をallに足す
16 : {
17 :     if(map[put] == 0)
18 :         for (i=0; i<8; i++)
19 :         // 8方向走査
20 :         {
21 :             // dir[i]の方向の相手のコマの数を確認
22 :             for(count = 0, cur = put+dir[i]; map[cur] == 3-turn; cur += dir[i])
23 :                 count++;
24 :
25 :             if(count && map[cur] == turn)
26 :             // 1枚以上存在し、その上端が自分のコマだったら
27 :             {
28 :                 all += count;
29 :                 cur  = put;
30 :
31 :                 if(done)
32 :                    // doneがtrueの場合は、実際にひっくり返す
33 :                     do
34 :                        map[cur] = turn, cur += dir[i];
35 :                    while (map[cur] != turn);
36 :             }
37 :         }
38 : }
39 :
40 :
41 : // mapに対応するオセロ駒&改行
42 : char *h="・○●\n";
43 :
44 : int main()
45 : {
46 :     // 初期化
47 :     for(i=1, map[41] = map[49] = 2; i<10; map[i++*9] = 3)
48 :         map[40] = map[50] = turn = pass = 1;
49 :
50 :     for (;; all = done = 0) // ループのたびにallとdoneを初期化(セミコロンを1つ削除するため)
51 :    {
52 :         // 盤の表示。今回のデータ構造だとこれで表示できる
53 :         // ついでにdone=0でcheckを呼び、何枚駒を置けるのかチェック
54 :         for(put = 9; put<82; ++put)
55 :             check(), printf("%.2s",&h[map[put]*2]);
56 :
57 :         if(all)
58 :             // 1枚でも駒が置けた場合はcomは左上から走査、人は置けるまで繰り返す
59 :             // 置けた(=allの値が変わった)らturn終了
60 :             for(done = all = pass = put = 8; all==8; check())
61 :                 turn - 2 ? (scanf("%d %d",&put,&i), put+=i*9): ++put;
62 :
63 :         else if(pass)
64 :             // 駒を置けない。s=0にしてフラグを立てる
65 :             pass=0,printf("pass");
66 :
67 :         else
68 :             // 両者とも駒を置けないので終了
69 :             break;
70 :
71 :
72 :        // turn交代
73 :         turn = 3 - turn;
74 :     }
75 :
76 :     return 0;
77 : }
(プログラムの解説は、コード中に詳細にコメントが書かれている為、割愛します。) 私としては、 マップを一次配列にして、(8行目) 走査方向をあらかじめ配列に固定しておき、(11行目) マスの全方向の走査を、ループでスマートに行う(18~37行目) 部分に、ほほぉ~と感心しました。 (私だったら、このような場合、マップを二次元配列にしてプログラミングするからです ^^;) # この技は、オセロだけではなく、テトリス等にも応用できそうな気がします。 また、73行目のturn交代部分では、ターンフラグを 1 ⇔ 2 と切り替える際、こちらでご紹介した技が使われています♪ 最後に一言。 このオセロプログラムのAIは、と に か く 弱 い です。(← おそらく幼稚園児並??) しかし、人間 VS コンピュータのオセロ対局プログラムは、すでにコンピュータが必勝するアルゴリズムが発見されており、 ここでオセロAIの強さをあれこれ論じるのはナンセンス。 このプログラムがゲームとして成り立つかどうか?? はさほど重要ではなく、 たった7行のコードにAIまで組み込んだ匠の技を、いかにして盗みとるのかが大事だよな~~と、独り思ってみたりします^^;)
ひょっとしたら参考になるかもしれないページ : オセロ対局シュミレーションプログラミング
         このエントリーをはてなブックマークに追加   


作業効率化・ライフハックのオススメ記事




コンピュータ・テクノロジーのオススメ記事





恋愛・人間関係のオススメ記事




※ 当サイトは、トップページからリンクで辿る事の出来るページに限り、リンクフリーです。
※ 当サイトの閲覧/利用によって生じた如何なる損害も、当サイト管理人は責任を負いません。
※ 当サイトの内容を転載される場合は、当サイトへのリンクをお願い致します。