実際に打った人 http://amou0.blog62.fc2.com/blog-entry-56.html
学生に打たせた論文 http://ci.nii.ac.jp/naid/110006407435/
どうやら非常に疲れるらしい。しかし Computer-Aided にして情報を集約するか、プログラムを作って機械同士で対戦させるとかすれば面白いかも。後付けアリにしたらリンシャンを待ち牌にしてカンするとかすれば不確定性が減るかも。
頭の体操
N回ツモ後の13+N枚をソートする。その中から14枚選んであがれるかどうかを判定しあがれる最小のNを見つける。そのために必要なサブルーチン:
入力は 1123334456 とか、ソートしたマンズのみとかソーズのみとかのデータ。ここからコーツとシュンツを最大何個作れるかを、トイツを一個作る場合と作らない場合について計算する。
入力例
- 1222345
- 1233345
- 1112333
とりあえずアガリ判定コード書いたよ。int agari(int *pai) マンズ、ソーズ、ピンズ、字牌の9+9+9+7種類をそれぞれ何枚持ってるか入っている int pai[9+9+9+7] を渡すと14枚選んで上がれれば1を、そうでなければ0を返します。
#include <stdio.h> #include <stdlib.h> // get and remove leftmost shuntu if avail static int getshun1(int pai[9], int imin) { int i; for(i=imin;i<=6;i++) { if (pai[i]!=0 && pai[i+1]!=0 && pai[i+2]!=0) { pai[i]--; pai[i+1]--; pai[i+2]--; return i; } } return -1; } // get all available shuntu // return number of shuntu static int getshun(int pai[9], int *res) { int tmp[9]; int i; // copy for(i=0;i<9;i++) tmp[i]=pai[i]; int imin=0; while(pai[imin]==0 && imin<8)imin++; int tot=0; while(1) { int t1= getshun1(tmp, imin); if (t1==-1)break; res[tot]=t1; tot++; if (tot==4)break; while(pai[imin]==0 && imin<8)imin++; } return tot; } // get max avail number of shuntu + kotu int getall(int pai[9]) { int tmp[9]; int shund[10]; int nkotu=0; int i,ii; int kidx[3], kflag[3]; int nmax=0; int nk; // count kotu for(i=0;i<9;i++) { if (pai[i]>=3) { if (nkotu==3) return 4; kidx[nkotu]=i; nkotu++; } } nmax=nkotu; int imax = 1<<nkotu; // loop over all possible kotu on/off for(ii=0;ii<imax;ii++) { int b; nk=0; for(i=0;i<9;i++) tmp[i]=pai[i];//copy // init flags for(b=0;b<nkotu;b++) { if ((1<<b)&ii) { kflag[b]=1; nk++; tmp[ kidx[b]]-=3; } else kflag[b]=0; } int ns= getshun(tmp, shund); nk = nk+ns; if (nk >= nmax) { nmax=nk; } } return nmax; } // get max avail number of shuntu + kotu after removing toitu static int getall_h(int pai[9]) { int res=-1; int i; for(i=0;i<9;i++) { if(pai[i]<2)continue; // make it toitu pai[i] -=2; int r2 = getall(pai); pai[i] +=2; // restore if (r2 > res) res=r2; } return res; } // get number of jihai kotu, with and without toitu static int getji(int pai[7], int h) { int res=0; int i; int head=0; for(i=0;i<7;i++) { if(pai[i]>=3) res++; if(pai[i]==2) head=1; } if(h==0) return res; if (head==1) return res; else return res-1; } // 7 toitu static int toi7(int pai[9*3+7]) { int res=0; int i; for(i=0;i<9*3+7;i++) if (pai[i]>=2) res++; if (res>=7) return 1; return 0; } // kokusi static int kokusi(int pai[9*3+7]) { //191919 jjjj jjj int kpai[13]={0, 0+8, 9, 9+8, 18, 18+8, 27, 28, 29, 30, 31, 32, 33}; int i; int res=1; for(i=0;i<13;i++) { int n=pai[kpai[i]]; if (n==0) res=0; else if (n>=2 && res==1) res = 2; } if (res==2) return 1; return 0; } int agari(int *pai) { // toi7 first if (toi7(pai))return 1; if (kokusi(pai))return 1; int *manz=pai; int *soz=&pai[9]; int *pinz=&pai[18]; int *ji=&pai[27]; int m1 = getall(manz); int m2 = getall_h(manz); int s1 = getall(soz); int s2 = getall_h(soz); int p1 = getall(pinz); int p2 = getall_h(pinz); int ji1 = getji(ji, 0); int ji2 = getji(ji, 1); if ((m2!=-1 && m2+s1+p1+ji1 >=4) || (s2!=-1 && m1+s2+p1+ji1>=4) || (p2!=-1 && m1+s1+p2+ji1 >=4) || (ji2!=-1 && m1+s1+p1+ji2 >=4)) { return 1; } return 0; }