麻雀プログラム用メモ

戻る
C#のSharpPcapで天鳳パケットキャプチャサンプル 天鳳のログ解析まとめ
自作麻雀AIのoccamは期待順位値の計算のmjai-manueさんが行っている方法をそのまま使用しちゃっている。 その方法は、牌譜を解析してあらかじめ得点差と席の関係から勝率表を作成しておき プログラムから参照するというものである。 この方法を使うには起動時に勝率表のlight_game_stats.jsonというファイルをメモリに読み込む必要がある。 ただ6MB近くあるのでちょっと重い。のでどうにかしたい。 とりあえずグラフで表示。 なんか超シグモイド関数ぽい。 というわけでRでフィッティングしてみる。 普通にやると「勾配が特異です」というエラーが出た。値が大きすぎると出るエラーらしい。 なので点差を全て割る100して実行。 > data <- read.csv("/path/to/csv/E1,0,1.csv", header=TRUE) > nls(win_prob ~ 1/(1+exp(-a*(point_diff-b))), data, start=list(a=1,b=0)) Nonlinear regression model model: win_prob ~ 1/(1 + exp(-a * (point_diff - b))) data: data1 a b 0.008511 2.486363 residual sum-of-squares: 0.04412 Number of iterations to convergence: 9 Achieved convergence tolerance: 1.702e-06 エクセルでグラフ化。 いけるやん! で、全パターン調べた結果↓ 一覧 ※ 東1 = E1 ~ 南4 = S4 ※ 「E1,0,1」とは東1で席番号0(起家)と席番号1(起家の下家)との点差と勝率の関係 ※ point_diffは上記の通り得点差/100のこと ※ point_diffの範囲は+140000~-140000くらいの範囲(統一されてない) この回帰式使えば6MB節約できるよYATTANE! P.S この勝率表の問題点は親の連チャンが考慮されてないことなんだけど、まあそれはまた別の話。
// 平均の逐次更新 // http://qiita.com/awakia/items/f58e90b3b2562d787aa5 #include using namespace std; // @param total 回数 // @param value 今回の値 // @param average 現在の平均値 // @return 平均 double onlineAvg(double total, double value, double average) { return average + (value - average) / total; } int main() { double total = 0; double average = 0; double test[] = {20,30,40}; for(int i = 0;i <3;i++) { total++; average = onlineAvg(total,test[i],average); cout << average << endl; } return 0; }
GitHub
DeepLearningって結局、主成分分析と同じで入力ベクトルの次元削減手法の事で、 削減されたベクトルを使ってSVMなり何なりで分類しなきゃならない。 軽く調べた感じこんな印象なんだけど合ってるだろうか・・・
DLL defファイルの追加 http://eternalwindows.jp/else/dll.html まうじゃんDLL作る時とかにハマり注意
/* * 自風を取得 * プレイヤー番号 = 逆時計回りで0~3 * * @param 親のプレイヤー番号 0~3 * @param プレイヤー番号 0~3 * @return 自風 0:東 1:南 2:西 3:北 */ int getJikaze(int chicha,int player) { return (4 + player + chicha) % 4; }
麻雀の合法手一覧 ※用語 ツモ局面・・・自分がツモしている状態 鳴き局面・・・他家が牌を捨てた状態 ※注 フーロ数や巡目によって選択肢は減り得る ●ツモ局面時にプレイヤーが取り得る選択肢は以下の36種類 ・ツモあがりする ・九種九牌倒牌する ・左から1牌目の手牌を切る ・左から2牌目の手牌を切る ・左から3牌目の手牌を切る ・左から4牌目の手牌を切る ・左から5牌目の手牌を切る ・左から6牌目の手牌を切る ・左から7牌目の手牌を切る ・左から8牌目の手牌を切る ・左から9牌目の手牌を切る ・左から10牌目の手牌を切る ・左から11牌目の手牌を切る ・左から12牌目の手牌を切る ・左から13牌目の手牌を切る ・ツモ切る ・左から1牌目の手牌を切ってリーチする ・左から2牌目の手牌を切ってリーチする ・左から3牌目の手牌を切ってリーチする ・左から4牌目の手牌を切ってリーチする ・左から5牌目の手牌を切ってリーチする ・左から6牌目の手牌を切ってリーチする ・左から7牌目の手牌を切ってリーチする ・左から8牌目の手牌を切ってリーチする ・左から9牌目の手牌を切ってリーチする ・左から10牌目の手牌を切ってリーチする ・左から11牌目の手牌を切ってリーチする ・左から12牌目の手牌を切ってリーチする ・左から13牌目の手牌を切ってリーチする ・ツモ切ってリーチする ・左から数えて1つ目のアンカン可能な牌を使ってアンカンする ・左から数えて2つ目のアンカン可能な牌を使ってアンカンする ・左から数えて3つ目のアンカン可能な牌を使ってアンカンする ・左から数えて1つ目の加カン可能な牌を使って加カンする ・左から数えて2つ目の加カン可能な牌を使って加カンする ・左から数えて3つ目の加カン可能な牌を使って加カンする ●鳴き局面時にプレイヤーが取り得る選択肢は以下の7種類 ・何もしない ・ロン ・ポン ・チー(左) ・チー(中) ・チー(右) ・ミンカン
シャンテン数が悪くなる鳴きが存在する。 一萬:麻雀王国三萬:麻雀王国五筒:麻雀王国七筒:麻雀王国九筒:麻雀王国二索:麻雀王国二索:麻雀王国三索:麻雀王国四索:麻雀王国五索:麻雀王国白:麻雀王国白:麻雀王国白:麻雀王国 1シャンテン から一索:麻雀王国を鳴くと 一萬:麻雀王国二萬:麻雀王国五筒:麻雀王国七筒:麻雀王国九筒:麻雀王国二索:麻雀王国四索:麻雀王国五索:麻雀王国白:麻雀王国白:麻雀王国白:麻雀王国一索横:麻雀王国二索:麻雀王国三索:麻雀王国 2シャンテンになる(雀頭が消えたので)。 知らなかった←
2ちゃん麻雀質問スレテンプレ 牙突式麻雀辞書 for MS-IME UCT探索による不完全情報下の行動決定 コンピュータ将棋の知識 ニューラルネットワーク解説(岐阜高専) Support Vector Machine って,なに? まうじゃんで強いプラグインを調べてみた(前編) まうじゃんで強いプラグインを調べてみた(後編) 降りるべき局面の認識による1人麻雀プレイヤの4人麻雀への適用 gimite / mjai-manue //一時変数を使わないswap $b=$a+$b; $a=$b-$a; $b=$b-$a; //ただし一時変数を使った方が早い
孤立牌を含まない牌姿で最も高いシャンテン数は4 例:124689m12468s12p
・麻雀AIが判断する場面 麻雀には何を切るか選択する「ツモ局面」と 誰かが牌を捨てた時に鳴き等を選択する「捨て牌局面」に分類できる。 *フローチャート ---------------------------------- 【ツモ局面】 ↓ (1)ツモ和了する? ↓(NO) (2)暗槓する? ↓(NO) (3)リーチする? ↓(NO) (4)切る牌選択 ---------------------------------- 【捨て牌局面】 ↓ (5)ロンする? ↓(NO) (6)ポンする? ↓(NO) (7)明槓する? ↓(NO) [全てのチー可能な組み合わせについて] (8)チーする?(1~4種類、「12345赤5」に3が切られた場合に4パターンとれる) ↓(NO) 何もしない ---------------------------------- 重要度は (4)>>>>>>>>>(6)(8)>>>>(3)>>>(1)(5)>(2)>(7) という感じ(?)

とりあえず麻雀研究始めてみました 放置してたことへの懺悔とパラメータ表の公開 2011-04-16(Sat) http://epsilon69399.blog20.fc2.com/blog-entry-58.html にて公開されているパラメータ表を、非常に有益と思ったため、エクセルに見やすくまとめました。 出来過ぎたまねでしたらお許しください。 nisi5028様作成 パラメータ表.xls
直接対決でどちらが強いか、χ2 適合度検定で求める ↓解説 http://lbm.ab.a.u-tokyo.ac.jp/~omori/kokusai/kokusai10_1004.html 【例】 A 君と B 君が直接対戦し、10 局やったところ,A 君の 7 勝 3 敗であった。 A 君と B 君の強さに違いがあるか。 【エクセルのCHITESTで求める】 私の場合は理屈を知りたいというより、道具として使いたいため エクセルで検定する方法を記す。 ちなみに1000試合では ・Aが531勝以上で0.05以下 ・Aが541勝以上で0.01以下 になる。 【提案】 2つの麻雀プログラムのどちらが強いかを測定する方法として ・プログラムA ・プログラムB ・ダミー("普通"に打つプログラム。強くなくて良い。高速である事が望ましい) ・ダミー のメンツで1000試合対戦させ、プログラムA、Bの直接対決の結果(順位で判断)を 上記のように検定すればできると思う。 しかし各プログラムからみて 「どの対戦相手が比較相手かわからない事」が保証されている事が必要。
・翻(ハン)は「ひるがえる」で変換すると出る ・最高の符は110符 ・最大役複合数は15~カンドラ別表記でいっても17か ・手牌が面前チンイツで14枚揃っているときは必ず1向聴以下 ・東風荘のR分布は平均値=R1500(2.5位)、標準偏差=R167.5(0.15位)のガウス分布(とつげき東北HP参考)。 例えば「R1300は下位何%?」を知りたいならエクセルで正規分布関数NORMDISTを使い「=NORMDIST(1300,1500,167.5,TRUE)」とすれば出る。 vc2008→vc2010変換時注意点 [プロジェクト]→[プロパティ]→[マニフェストツール]→[入力と出力]→[埋め込みマニフェスト]を「いいえ」にする
//手牌の孤立牌を列挙。孤立牌の牌番号が入る //para1:vector<int>のポインタ渡し(結果) //para2:非フーロ牌(赤統合済み) void ChkKoritu(vector<int>* koritu,int tehai[]) { int i=0; for(;i<=37;i++){ for(;!tehai[i];i++);if(i>=38) continue; //数牌 if(i<30&tehai[i]==1){ if(i%10==1) if(!tehai[i+1]&!tehai[i+2]) koritu->push_back(i); if(i%10==2) if(!tehai[i-1]&!tehai[i+1]&!tehai[i+2]) koritu->push_back(i); if(i%10>=3 &&i%10<=7) if(!tehai[i-1]&!tehai[i+1]&!tehai[i-2]&!tehai[i+2]) koritu->push_back(i); if(i%10==8) if(!tehai[i+1]&!tehai[i-1]&!tehai[i-2]) koritu->push_back(i); if(i%10==9) if(!tehai[i-1]&!tehai[i-2]) koritu->push_back(i); } //字牌 else if(i>30) if(tehai[i]==1) koritu->push_back(i); } }
/* 孤立牌の評価関数 text by 理想雀士氏 ttp://majanjan.com/research-life/strategy-tactics/020/ にちょっと加えたものを実装してみた。上の関数のkorituを使う。 【種類】 【評価値】 4,5,6の牌 15 3,7の牌 14 2,8の牌 13 1,9を使った 1間面子 12 1間ターツ 11 【追加】連風牌 10 役牌 9 リャンカン孤立牌 8 面子スジ孤立牌 7 ターツスジ孤立牌 6 孤立牌 5 オタ風牌 4 【追加】2枚切れ字牌 3 スジ孤立牌 2 連続スジ孤立牌 1 */ int EvalKoritsuhai(vector<int> koritu,int tehai[],int nokorihai[],int bakaze,int jikaze,int dora[]) { const int MAX = 16; int point[42]= {0, 0,MAX-2,MAX-1,MAX,MAX,MAX,MAX-1,MAX-2,0, 0, 0,MAX-2,MAX-1,MAX,MAX,MAX,MAX-1,MAX-2,0, 0, 0,MAX-2,MAX-1,MAX,MAX,MAX,MAX-1,MAX-2,0, 0, 0,0,0,0,10,10,10, MAX+1,MAX+1,MAX+1,//赤 -1}; //1.9牌 for(int i=1;i<30;i+=10){ //1間面子 if(tehai[i+2]&tehai[i+3]&tehai[i+4]){ point[i]=MAX-3; } //1間ターツ else if(tehai[i+2]&tehai[i+3]){ point[i]=MAX-4; } //リャンカン孤立 else if(tehai[i/10+5]){ point[i]=MAX-7; } //面子スジ else if(tehai[i+3]&tehai[i+4]&tehai[i+5]){ point[i]=MAX-8; } //ターツスジ else if(tehai[i+3]&tehai[i+4]){ point[i]=MAX-9; } //スジ孤立 else if(tehai[i+3]==1&!tehai[i+2]&!tehai[i+4]){ point[i]=MAX-14; } //連続スジ孤立 else if(tehai[i+3]>=2&!tehai[i+2]&!tehai[i+4]){ point[i]=MAX-15; } //孤立 else{ point[i]=MAX-10; } } for(int i=9;i<30;i+=10){ //1間面子 if(tehai[i-2]&tehai[i-3]&tehai[i-4]){ point[i]=MAX-3; } //1間ターツ else if(tehai[i-2]&tehai[i-3]){ point[i]=MAX-4; } //リャンカン孤立 else if(tehai[i/10+5]){ point[i]=MAX-7; } //面子スジ else if(tehai[i-3]&tehai[i-4]&tehai[i-5]){ point[i]=MAX-8; } //ターツスジ else if(tehai[i-3]&tehai[i-4]){ point[i]=MAX-9; } //スジ孤立 else if(tehai[i-3]==1&!tehai[i-2]&!tehai[i-4]){ point[i]=MAX-14; } //連続スジ孤立 else if(tehai[i-3]>=2&!tehai[i-2]&!tehai[i-4]){ point[i]=MAX-15; } //孤立 else{ point[i]=MAX-10; } } //字牌 for(int i=31;i<=37;i++){ //2枚切れ if(nokorihai[i]<=2){ point[i]=MAX-13; } //連風牌 else if(i==bakaze&&i==jikaze){ point[i]=MAX-5; } //役牌 else if(i==bakaze||i==jikaze||i>=35){ point[i]=MAX-6; } //オタ風 else{ point[i]=MAX-11; } } //ドラ //ドラは孤立牌の中で価値が最も高いと仮定 //doraは現物 for(int i=0;dora[i];i++){ point[dora[i]]=MAX+1; } //切る牌選択 int ret=0 for(unsigned int i=1;i < koritu.size();i++){ if(point[koritu[i]] < point[ret]) ret=koritu[i]; } return ret; }
//@ brief ドラ表→現物 //@ para1 int r ドラ表 //@ return 現物 int DoraGenbutu(int r) { if(r<30&&r%10==9) return (r/10)*10+1; else if(r==34) return 31; else if(r==37) return 35; return r+1; } //@ brief ドラかどうか ↑のDoraGenbutuを使う //@ para1 int num 判定牌 //@ para1 int[5] dora ドラ配列 0:ドラ数 1~4:ドラ表 //@ return trueでドラ bool isDora(int num,int dora[]){ for(int i=1;i<5;i++){ if(dora[i] && num == DoraGenbutu(dora[i])) return true; } return false; } //@ brief 裏ドラの期待枚数(裏ドラ枚数*確率) //@ para1 int nokori[38] まだ見えていない牌 //@ para2 int tehai[38] 手牌(赤統合済み) //@ para3 int dorasuu めくれてるドラ数 //@ return 期待枚数 float ExpectUradora(int nokori[],int tehai[],int dorasuu) { float sum=0.0,ret=0.0; for(int i=0;i<38;i++) if(nokori[i]) sum+=(float)nokori[i]; for(int i=0;i<38;i++) if(tehai[i]) ret+=((float)nokori[DoraGenbutu(i)]/sum)*(float)tehai[i]; return ret*dorasuu; } //@ brief 裏ドラが1枚以上乗る確率 //@ para1 int nokori[38] まだ見えていない牌 //@ para2 int tehai[38] 手牌(赤統合済み) //@ para3 int dorasuu めくれてるドラ数 //@ return 確率 float ProbUradora(int nokori[],int tehai[],int dorasuu) { float sum=0.0,n=0.0; for(int i=0;i<38;i++) if(nokori[i]) sum+=(float)nokori[i]; for(int i=0;i<38;i++) if(tehai[i]) n+=(float)nokori[DoraGenbutu(i)]; return (float)(1.0-pow(1.0-n/sum,dorasuu)); }
東風荘形式牌譜出力C++クラス TonpuHaifu ver β0.1 tonpuhaifu.h(ヘッダ) tonpuhaifu.cpp(本体、使用するソースと共にビルド) 東風荘形式の牌譜を出力するクラス。 改善点1)エラーチェックをしていない。 改善点2)デストラクタで既存牌譜との統合処理をしているので、異常終了した場合正しく出力されない。 ・使い方 1.初期化。以下メソッドで希望のデータを初期化する。無視した場合は規定のデータが入る。 //名前。初期値は「プレイヤーN(N=1~4)」。15バイト以内 void SetName1(char *n); void SetName2(char *n); void SetName3(char *n); void SetName4(char *n); //レート設定。初期値は1500 void SetRate1(int r); void SetRate2(int r); void SetRate3(int r); void SetRate4(int r); //東風戦設定。東風ならtrue。初期値は東南戦 void SetTonpu(bool t); //持ち点設定。初期値は25000 void SetMotiten(int m); //卓番号。初期値は100 void SetTaku(int t); //供託リー棒。初期値は0 void SetRiichibou(int t); //本場。初期値は0 void SetHonba(int t);; //局。0=東1局~ void SetKyoku(int t); //ファイルネーム。初期値はmjscore.txt void SetFilename(char f[]); 2.呼び出し ※ゲームスタート前に初期化を済ませておくこと //ゲームスタート //exeの同階層にファイルが作成される void GameStart(); --------↓ここからGameEndが呼ばれるまでループ↓------------ 次にファイルに書き込まれるのはKyokuEnd()メソッドが呼び出された時。 その前に以下のメソッドを最低1回ずつ呼ばないと正しい牌譜にならない。 //配牌 //2次元配列の行にプレイヤー番号、列にint[42]の配列 void SetHaipai(int tehai[][42]); //ドラ 表示牌でなく現物 size int[8] //0123→表ドラ 4567→裏ドラ void SetDora(int dora[]); //結果 //その局での点数増減 //添え字がプレイヤー番号のtensuu[4]に点数の増減を入れる //例:プレイヤー1が満貫ツモなら tensuu[4]={8000,-2000,-2000,-4000}; void SetResult(int tensuu[]); //役名等 //fuに符 //fanに翻数(数え役満は39、役満は40、ダブル役満は41……) //tumoはツモアガリなら1、ロンなら0 //riyuuは流局理由の事。流局でないなら0、流局ならRIYUU列挙子から //string[]に役名(「断ヤオ 平和 門前清模和 」とか) void SetYaku(int fu,int fan,int tumo,int riyuu,char string[]); //RIYUU列挙子 enum RIYUU{ ARAHAI=1,//荒牌(残り牌無し) TRIPLE_RON,//トリプルロン SUUKAI_KAN,//四開槓 KYUUSYU_KYUUHAI,//九種九牌 SUUFUU_RENDA,//四風連打 YONIN_RIICHI//四人リーチ }; //アクション //typeにアクション(ACTION列挙子に従う) //haiに牌番号、赤ポン赤チーなら赤の番号 //playerにプレイヤー番号 void Action(int type,int hai,int player); //ACTION列挙子 enum ACTION{ TUMO, TEDASI, TUMOGIRI, RIICHI, KAN, PON, CHII, AGARI }; //局エンド void KyokuEnd(); --------↑ここまでGameEndが呼ばれるまでループ↑------------ //ゲームエンド //局エンドの直後に呼ぶ事 //@para1 rank 順位 int[4] 中身が席順(0~3) 添え字が順位-1 //@para2 score 順位点 ウマオカ込切り上げ切り捨て÷1000済みの、10,5,-5,-10みたいなやつね void GameEnd(int rank[],int score[]);
Q.C言語プログラムの時間を計測するには? 簡単になら #include "time.h" clock_t start,end; start = clock(); /* 何かの処理 */ end = clock(); printf("%.2f秒かかりました\n",(float)(end-start)/CLOCKS_PER_SEC);
//向聴数を落とさない牌の列挙 //vector int のポインタ渡し //これだけで棒聴AIができるかも //当HPのsyantenクラスを使っている //通常手しか考慮していない void SyantenOtosanai(vector<int> result[]) { Syanten a; a.set_tehai(tehai); int syan=a.NormalSyanten(); for(int i=0;i<=41;i++){ for(;!tehai[i];i++);if(i>=42) continue; tehai[i]--; a.set_tehai(tehai); if(a.NormalSyanten()==syan) result->push_back(i); tehai[i]++; } } //↑を使った目先の有効牌「種類数」が最も多い牌を返す関数 //要するに棒聴関数 //当HPのyuukouhaiクラスを使っている int Bouten(int tehai[]) { Yuukouhai y; y.set_tehai(tehai); vector<int> r,s; SyantenOtosanai(&r); int ret=0,w=0; for(int i=0;i<(signed)r.size();i++){ tehai[r[i]]--; y.set_tehai(tehai); y.NormalYuukou(&s); w<=(signed)s.size()?ret=r[i],w=(signed)s.size():ret=ret; //ここで返却用データに代入している //有効牌「種類数」ではなく「枚数」にするには //残り牌のデータを用意しないといけない // //同じ有効牌種類数だと牌番号の大きいものが選択されてしまうので //135から5を切るなど牌効率が悪い選択をしてしまう //評価関数が必要 tehai[r[i]]++; } return ret; }
//マージャンforeach for(int i=0;i<=41;i++){ for(;!tehai[i];i++);if(i>=42) continue; //処理 }
//C++ pairとfor_eachの基本的な使用例 #include <iostream> #include <algorithm> #include <vector> using namespace std; //for_eachで使う関数 void disp(const pair<int, int>& p) { cout << '[' << p.first << ',' << p.second << ']' << endl; } int main() { typedef pair<int, int> value_type; vector<value_type> v; //メイクペア v.push_back(make_pair(5, 3)); v.push_back(make_pair(5, 1)); v.push_back(make_pair(3, 4)); //ファーストキーでソートされ //ファーストキーが同じなら、セカンドキーでソートされる sort(v.begin(), v.end()); //for_each for_each(v.begin(), v.end(), disp); }
身長 | 目的変数:体重 150 |  65(kg) 172 |  73(kg) というデータがある場合 正規化するには 正規化後の値 = (正規化前の値 - 最小値) / 最大値 - 最小値 もとに戻すには 正規化後の値=A 正規化前の値=B 最大値=Max 最小値=Min とすると、 A=(B-Min)/(Max-Min) よって (Max-Min)A-Min=B [偏差値の求め方] (標準偏差)=sqrt({(個々の生徒の得点-平均点)^2の総和}/ 生徒の総数 ) (偏差値)= { (得点 - 平均点) / 標準偏差 } × 10 + 50 例えば、得点が75点で、平均点は65点、標準偏差は18点であるとします。その際の偏差値は {(75-65)/18}×10+50=55.6
int tehai[42]={ 0, 0,0,0,0,0,0,0,0,0,//1~9 0, 0,0,0,0,0,0,0,0,0,//11~19 0, 0,0,0,0,0,0,0,0,0,//21~29 0, 0,0,0,0,0,0,0,//31~37 0,0,0,//38,39,40 0 }; int nokori[38]={ 0, 4,4,4,4,4,4,4,4,4,//1~9 0, 4,4,4,4,4,4,4,4,4,//11~19 0, 4,4,4,4,4,4,4,4,4,//21~29 0, 4,4,4,4,4,4,4//31~37 };
vector<int> removeTyoufukuAndSort(vector<int> vec){ set<int> s(vec.begin(), vec.end()); vector<int> vec2(s.begin(), s.end()); return vec2; }
long double comb_func(int n,int m) { int i; long double c=1; for(i=n; i>=n-m+1; i--) c*=(double)i; return(c); } //combination(nCr)を求める long double comb(int n,int m) { if (m <= 0) return 1; return comb_func(n,m)/comb_func(m,m); } //http://totutohoku.b23.coreserver.jp/hp/mjcom_p6.htm //↑の一番下計算するだけ #include <iostream> #include <cmath> using namespace std; int main() { const int SIAISUU=100; const int SYOURI=60; long double ans=0; for(int i=SYOURI;i<=SIAISUU;i++){ ans+=comb(SIAISUU,i)*pow(0.5,SIAISUU); } cout<<ans<<endl; }
//フーロ数GET //MJEXEIO.dll形式のフーロ牌配列からフーロ数を取得する //@param1 フーロ配列 int getFuuro(int fuuro[]){ int ret=0; for (int i = 0; i < 20; i+=4) { if(fuuro[i]) ret++; } return ret; }
//親の席番号 //@return 0:自分 1:上家 2:対面 3:下家 //@param1 0:自分が東 1:自分が南 2:自分が西 3:自分が北 bool getOyaNum(int num){ switch(num){ case 0: return 0; case 1: return 3; case 2: return 2; case 3: return 1; default:return -1; //Error } }
//順位計算 //@param1 0:自分 1:上家 2:対面 3:下家 //@param2 得点が入っている配列 int[4] int getJyuni(int num,int tokuten[]){ int ret=4; for(int i=0;i<4;i++){ if(i==num) continue; if(tokuten[i] <= tokuten[num]) ret--; } return ret; }
//通常手有効牌のvector vector<int> getNormalYuukouHai(int tehai[],int fuurosuu){ vector<int> ret; Yuukouhai yuukou; yuukou.set_tehai(tehai); yuukou.set_fuurosuu(fuurosuu); yuukou.NormalYuukou(&ret); return ret; } //七対子有効牌のvector vector<int> getTiitoiYuukouHai(int tehai[],int fuurosuu){ vector<int> ret; Yuukouhai yuukou; if(fuurosuu > 0) return ret; yuukou.set_tehai(tehai); yuukou.set_fuurosuu(fuurosuu); yuukou.TiitoiYuukou(&ret); return ret; } //国士無双有効牌のvector vector<int> getKokusiYuukouHai(int tehai[],int fuurosuu){ vector<int> ret; Yuukouhai yuukou; if(fuurosuu > 0) return ret; yuukou.set_tehai(tehai); yuukou.set_fuurosuu(fuurosuu); yuukou.KokusiYuukou(&ret); return ret; }
//ログ出力 //http://replication.hatenablog.com/entry/2014/07/28/180145 #include <time.h> #include <tchar.h> #include <Windows.h> #define Log_d(lpszFormat, ...) OutputLog(_T(__FUNCTION__), lpszFormat, __VA_ARGS__) void OutputLog(LPCTSTR lpszFuncName, LPCTSTR lpszFormat, ...) { va_list args; va_start(args, lpszFormat); TCHAR szBuffer[1024] = { 0 }; _vstprintf(szBuffer, lpszFormat, args); // 現在時刻の取得 SYSTEMTIME st; GetSystemTime(&st); char szTime[25] = { 0 }; wsprintf(szTime, "%04d/%02d/%02d %02d:%02d:%02d %03d", st.wYear, st.wMonth, st.wDay, st.wHour + 9, st.wMinute, st.wSecond, st.wMilliseconds); FILE *fp; fp = fopen("debug.txt", "a"); // 現在時刻,[関数名],任意のログ出力内容 fprintf(fp, "%s, [%s], %s\n", szTime, lpszFuncName, szBuffer); fclose(fp); va_end(args); }
MJSIM0
my_memo all.h BP法_XOR_コード 単一ニューロン
inserted by FC2 system