チートイツと国士無双を除く通常手のアガリ判定とシャンテン数を算出する処理を紹介します。
プログラムの解説と実行
アガリ判定とシャンテン数のチェックをする処理を紹介します。アガリ判定とシャンテン数は手牌(tehai)の中身を調べて行います。国士無双、チートイツ、通常手(4面子+1雀頭)の3つの処理に分けて調査します。
通常手のシャンテン数を求める
麻雀は「4メンツ+1雀頭」を集めるゲームです(通常手の場合)。メンツ(コーツやシュンツ)とメンツ候補になるターツやトイツが増える毎にシャンテン数は減っていきます。シャンテン数を求める式は次のようになります。
上記の式の場合、テンパイは「0」でアガリは「-1」になります。なお、国士無双とチートイツの扱いは別になり、シャンテン数を求める計算式も異なります。このページでは今回は扱いません。
- 雀頭を抜き出す→コーツを抜き出す→シュンツを抜き出す→ターツを抜き出す
- 雀頭を抜き出す→シュンツを抜き出す→コーツを抜き出す→ターツを抜き出す
雀頭を抜き出す→コーツを1つだけ抜き出す→シュンツを抜き出す→コーツを抜き出す→ターツを抜き出す
- コーツを抜き出す→シュンツを抜き出す→ターツを抜き出す
各手順で算出されたシャンテン数を比較して最小のシャンテン数を結果として採用します。プログラムでは手牌の元となるtehai配列から完全に独立したコーツとシュンツを前もって抜いてからクローン(tempTehai配列)を生成し、再帰呼び出しでシャンテン数を計算していきます。 大まかな手順はこんな感じです。コードには まだ手を入れないといけませんが、参考になると幸いです。
リンク牌理/牌効率学習ツール
シャンテン数を求めてみよう
手牌を作ってプログラムの動作を確認してみましょう。操作は簡単です。牌をクリックすると下のパネル内に牌が追加されていくます。[シャンテン数を調べる]ボタンを押すとシャンテン数を調査する手順が表示されます。
面子多々(めんつたーた)の場合の処理
ターツの抜き出しとカウントを途中で中断して処理を抜けています。したがって算出したターツ数が実際のターツ数と異ります。
たとえば、下の手牌は「2メンツ+3ターツ+1雀頭」ですが、プログラム内部ではターツを2つ抽出した時点で処理を抜けて「ターツ数 = 2」を返すようにしています。
現状での不具合と解決策(解決済2015/03/18)
カンツが混じっている場合シャンテン数が正確に算出されない不具合が見つかっています(2015年3月時点)。下の手牌のシャンテン数は1にならないといけないのですが、結果はテンパイになってしまいます。
これは「東がコーツ、残り1枚の東の単騎待ち」「東が雀頭、残り2枚の東とのシャンポン待ち」に解釈されるためです。いずれ解決しないといけませんが、今回はとりあえずここまでにしておきます。
プログラムの修正や最新版情報は動作チェックとバグ取りをしっかりやろう~通常手編に掲載しています。ここで紹介しているプログラムが新しくなっていることがありますので、チェックしてみてください。
再帰呼び出しで組み直したプログラムも紹介しています。シュンツ抜き取り漏れが解決しています。ご参考ください。通常手のアガリとシャンテン数を算出する~再帰呼び出し版
JavaScriptソースコード
本記事で紹介したサンプルプログラムをダウンロードできます。
ダウンロードをする前にお読みください
- サイトで紹介している記事の内容や公開しているプログラムの動作は100%保障するものではありません。
- 当プログラム使用による如何なる不具合やトラブル、損害の責任も負いかねます。
- 当プログラムは断り無く内容が変わることがあります。
- 当プログラムを別サイトで配布することは禁止します。
- サポートはいたしません。
- 自己責任にてご利用くださいませ。
以上をご確認の上、プログラムのダウンロードをお願いいたします。
- 本プログラムはjQueryを組み込んだ状態でのみ動作します。ご注意ください。
- アガリ判定とシャンテン数を算出する処理は「麻雀C言語プログラム集」のシャンテン数を参考にしています。感謝です。
サンプルプログラムのソースコード
ソースコードは折りたたんであります。[+]を押すと、折りたたまれたソースコードが開きます。[-]を押すと、コードは折りたたまれます。
+ program_009.jsを開く
//============================================================================ //牌の配列:JSON形式 //============================================================================ var paiType = [ {"No":0,"paiName":"赤五萬","cssSprite":"man0","paigaNo":4}, {"No":1,"paiName":"一萬","cssSprite":"man1","paigaNo":0}, {"No":2,"paiName":"二萬","cssSprite":"man2","paigaNo":1}, {"No":3,"paiName":"三萬","cssSprite":"man3","paigaNo":2}, {"No":4,"paiName":"四萬","cssSprite":"man4","paigaNo":3}, {"No":5,"paiName":"五萬","cssSprite":"man5","paigaNo":5}, {"No":6,"paiName":"六萬","cssSprite":"man6","paigaNo":6}, {"No":7,"paiName":"七萬","cssSprite":"man7","paigaNo":7}, {"No":8,"paiName":"八萬","cssSprite":"man8","paigaNo":8}, {"No":9,"paiName":"九萬","cssSprite":"man9","paigaNo":9}, {"No":10,"paiName":"赤五筒","cssSprite":"pin0","paigaNo":14}, {"No":11,"paiName":"一筒","cssSprite":"pin1","paigaNo":10}, {"No":12,"paiName":"二筒","cssSprite":"pin2","paigaNo":11}, {"No":13,"paiName":"三筒","cssSprite":"pin3","paigaNo":12}, {"No":14,"paiName":"四筒","cssSprite":"pin4","paigaNo":13}, {"No":15,"paiName":"五筒","cssSprite":"pin5","paigaNo":15}, {"No":16,"paiName":"六筒","cssSprite":"pin6","paigaNo":16}, {"No":17,"paiName":"七筒","cssSprite":"pin7","paigaNo":17}, {"No":18,"paiName":"八筒","cssSprite":"pin8","paigaNo":18}, {"No":19,"paiName":"九筒","cssSprite":"pin9","paigaNo":19}, {"No":20,"paiName":"赤五索","cssSprite":"sou0","paigaNo":24}, {"No":21,"paiName":"一索","cssSprite":"sou1","paigaNo":20}, {"No":22,"paiName":"二索","cssSprite":"sou2","paigaNo":21}, {"No":23,"paiName":"三索","cssSprite":"sou3","paigaNo":22}, {"No":24,"paiName":"四索","cssSprite":"sou4","paigaNo":23}, {"No":25,"paiName":"五索","cssSprite":"sou5","paigaNo":25}, {"No":26,"paiName":"六索","cssSprite":"sou6","paigaNo":26}, {"No":27,"paiName":"七索","cssSprite":"sou7","paigaNo":27}, {"No":28,"paiName":"八索","cssSprite":"sou8","paigaNo":28}, {"No":29,"paiName":"九索","cssSprite":"sou9","paigaNo":29}, {"No":30,"paiName":"裏","cssSprite":"ji0","paigaNo":30}, {"No":31,"paiName":"東","cssSprite":"ji1","paigaNo":31}, {"No":32,"paiName":"南","cssSprite":"ji2","paigaNo":32}, {"No":33,"paiName":"西","cssSprite":"ji3","paigaNo":33}, {"No":34,"paiName":"北","cssSprite":"ji4","paigaNo":34}, {"No":35,"paiName":"白","cssSprite":"ji5","paigaNo":35}, {"No":36,"paiName":"發","cssSprite":"ji6","paigaNo":36}, {"No":37,"paiName":"中","cssSprite":"ji7","paigaNo":37} ]; //============================================================================ //グローバル変数 //============================================================================ //var tehai = new Array(37);//手牌の配列:37種 var tehai=[];//手牌の配列:37種 tehai = [0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0]; //var preTempTehai = new Array(37);//tempTehaiの前処理用クローン。事前に完全メンツや孤立牌を抜いておく //var tempTehai = new Array(37);//tehai配列のクローン var preTempTehai=[];//tempTehaiの前処理用クローン。事前に完全メンツや孤立牌を抜いておく var tempTehai=[];//tehai配列のクローン var red5manCount = 0;//赤5マンの数 var red5pinCount = 0;//赤5ピンの数 var red5souCount = 0;//赤5ソウの数 //マンズ関連 var manMentsuMax; var manTaatsuMax; //ピンズ関連 var pinMentsuMax; var pinTaatsuMax; //ソーズ関連 var souMentsuMax; var souTaatsuMax; //字牌関連 var jiTaatsuMax; var preMentsuCount;//kanzen_koutsu_suuとkanzen_shuntsu_suu格納用 var koutsuCount;//コーツ数カウント用 //============================================================================ //赤ドラの有無をチェックしてカウントする処理【赤ドラのカウントを事前にしなかった場合に使う】 //各赤ドラはtehai配列の0,10,20番地にあるものとする //============================================================================ function checkReddora(){ //グローバル変数の初期化 red5manCount = 0;//赤5マンの数 red5pinCount = 0;//赤5ピンの数 red5souCount = 0;//赤5ソウの数 //赤五萬の有無をチェックしてカウントする if(tehai[0]){red5manCount += tehai[0];}//赤五萬の牌数を追加 //赤五筒の有無をチェックしてカウントする if(tehai[10]){red5pinCount += tehai[10];}//赤五筒の牌数を追加 //赤五索の有無をチェックしてカウントする if(tehai[20]){red5souCount += tehai[20];}//赤五索の牌数を追加 } //============================================================================ //赤ドラの有無をチェックして配列操作する処理【シャンテン数やテンパイチェックを実行する前に使う】 //tehai配列内を0→5、10→15、20→25 //============================================================================ function moveReddora(){ //赤五萬の有無をチェックして番地を移動させる処理 if(tehai[0]&&red5manCount){ tehai[5]+=tehai[0];//赤五萬の牌数を五萬の番地5に追加 tehai[0]=0;//番地0を初期化 } //赤五筒の有無をチェックして番地を移動させる処理 if(tehai[10]&&red5pinCount){ tehai[15]+=tehai[10];//赤五筒の牌数を五筒の番地15に追加 tehai[10]=0;//番地10を初期化 } //赤五索の有無をチェックして番地を移動させる処理 if(tehai[20]&&red5souCount){ tehai[25]+=tehai[20];//赤五索の牌数を五索の番地25に追加 tehai[20]= 0;//番地20を初期化 } } //============================================================================ //赤ドラの有無をチェックして配列内の元の番地に戻す処理 //tehai配列内を5→0、15→10、25→20 //============================================================================ function removeReddora(){ //赤五萬の有無をチェックして番地を移動:5→0 if(!tehai[0]&&tehai[5]&&red5manCount){ tehai[5]--; tehai[0]++; } //赤五筒の有無をチェックして番地を移動:15→10 if(!tehai[10]&&tehai[15]&&red5pinCount){ tehai[15]--; tehai[10]++; } //赤五索の有無をチェックして番地を移動:25→20 if(!tehai[20]&&tehai[25]&&red5souCount){ tehai[25]--; tehai[20]++; } } //============================================================================ //アガリ判定とシャンテン数を返す関数 //============================================================================ function syantenCheck(tehaimode){ var i; var toitsu_suu=0;//雀頭 var syanten_temp=0;//シャンテン数(計算用) var syanten_suu=8; var manMentsuTaatsu_suu; var pinMentsuTaatsu_suu; var souMentsuTaatsu_suu; var jiTaatsu_suu; //グローバル変数の初期化 //マンズ関連 manMentsuMax=0; manTaatsuMax=0; //ピンズ関連 pinMentsuMax=0; pinTaatsuMax=0; //ソーズ関連 souMentsuMax=0; souTaatsuMax=0; //字牌関連(ターツのみ) jiTaatsuMax=0; koutsuCount=0;//コーツ数カウント用 //tehai配列のバックアップを取る preTempTehai = $.extend(true, [], tehai); //前もって完全なシュンツ・コーツ・孤立牌を抜いておく var kanzen_koutsu_suu = KanzenKoutsuCheck();//完全に独立したコーツを抜き出して個数を返す関数の実行 var kanzen_shuntsu_suu = kanzenShuntsuCheck();//完全に独立したシュンツを抜き出して個数を返す関数の実行 //【ボツ】var kanzen_taatsu_suu = kanzenTaatsuCheck();//完全に独立した1ターツを抜き出して個数を返す関数の実行 preMentsuCount=kanzen_koutsu_suu+kanzen_shuntsu_suu;//グローバル変数に格納 //5枚目の単騎待ちを阻止する処置 var kanzen_Koritsu_suu=KanzenKoritsuCheck();//完全に独立した孤立牌を抜き出して個数を返す関数の実行 //【ボツ】var kanzen_kantsuCheck = koutsu.indexOf(koritsu)//4枚未満の場合は-1を返す //独立した完全トイツのチェック var kanzen_toitsu_check=KanzenToitsuCheck();//ある場合は「1」、無い場合は「0」を返す //マンズ・ピンズ・ソーズの有無のチェック var isCheckMan=preTempTehai[1]+preTempTehai[2]+preTempTehai[3]+preTempTehai[4]+preTempTehai[5]+preTempTehai[6]+preTempTehai[7]+preTempTehai[8]+preTempTehai[9]; var isCheckPin=preTempTehai[11]+preTempTehai[12]+preTempTehai[13]+preTempTehai[14]+preTempTehai[15]+preTempTehai[16]+preTempTehai[17]+preTempTehai[18]+preTempTehai[19]; var isCheckSou=preTempTehai[21]+preTempTehai[22]+preTempTehai[23]+preTempTehai[24]+preTempTehai[25]+preTempTehai[26]+preTempTehai[27]+preTempTehai[28]+preTempTehai[29]; var isCheckJi=preTempTehai[31]+preTempTehai[32]+preTempTehai[33]+preTempTehai[34]+preTempTehai[35]+preTempTehai[36]+preTempTehai[37]; var adjustment=kanzen_koutsu_suu+kanzen_shuntsu_suu;//前もって抜いたメンツと手牌調整用パラメータを格納する //【雀頭あり】雀頭抜き出し→コーツ抜き出し→シュンツ抜き出し→ターツ候補抜き出し for(i=1;i<38;i++){ if(!i%10){continue;} if(preTempTehai[i]>=2){//同種牌が2つ以上ある場合トイツを抜き出す preTempTehai[i]-=2;//雀頭を抜き出す jantou=i;//雀頭の番号を格納する toitsu_suu=1;//雀頭をカウントする if(isCheckMan>0){//マンズがある場合実行 manMentsuMax=0; manTaatsuMax=0; manMentsuTaatsu_suu=manMentsuTaatsuCheck(1);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckPin>0){//ピンズがある場合実行 pinMentsuMax=0; pinTaatsuMax=0; pinMentsuTaatsu_suu=pinMentsuTaatsuCheck(1);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckSou>0){//ソーズがある場合実行 souMentsuMax=0; souTaatsuMax=0; souMentsuTaatsu_suu=souMentsuTaatsuCheck(1);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckJi>0){//字牌がある場合実行 jiTaatsuMax=0; jiTaatsu_suu=jiTaatuCheck();//字牌ターツを抜き出して個数を返す関数呼び出し } //シャンテン数の算出 syanten_temp=syantenHnatei(toitsu_suu,adjustment);//仮のシャンテン数を算出 if(syanten_suu>syanten_temp){syanten_suu = syanten_temp;}//シャンテン数を比較 if(!syanten_suu&&(isCheckMan+isCheckPin+isCheckSou+preMentsuCount*3)==tehaimode){ return 0;//テンパイ判定 } if(syanten_suu==-1){ return -1;//アガリ判定 } preTempTehai[i]+=2; toitsu_suu--; } }//for var i //【雀頭あり】雀頭抜き出し→シュンツ抜き出し→コーツ抜き出し→ターツ候補抜き出し if(koutsuCount){//コーツが見つからなかった場合、処理がダブるのでスルー for(i=1;i<38;i++){ if(!i%10){continue;} if(preTempTehai[i]>=2){//同種牌が2つ以上ある場合トイツを抜き出す preTempTehai[i]-=2;//雀頭を抜き出す jantou=i;//雀頭の番号を格納する toitsu_suu=1;//雀頭をカウントする if(isCheckMan>0){//マンズがある場合実行 manMentsuMax=0; manTaatsuMax=0; manMentsuTaatsu_suu=manMentsuTaatsuCheck(2);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckPin>0){//ピンズがある場合実行 pinMentsuMax=0; pinTaatsuMax=0; pinMentsuTaatsu_suu=pinMentsuTaatsuCheck(2);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckSou>0){//ソーズがある場合実行 souMentsuMax=0; souTaatsuMax=0; souMentsuTaatsu_suu=souMentsuTaatsuCheck(2);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckJi>0){//字牌がある場合実行 jiTaatsuMax=0; jiTaatuCheck();//字牌ターツを抜き出して個数を返す関数呼び出し } //シャンテン数の算出 syanten_temp=syantenHnatei(toitsu_suu,adjustment);//仮のシャンテン数を算出 if(syanten_suu>syanten_temp){syanten_suu = syanten_temp;}//シャンテン数を比較 if(!syanten_suu&&(isCheckMan+isCheckPin+isCheckSou+preMentsuCount*3)==tehaimode){ return 0;//テンパイ判定 } if(syanten_suu==-1){ return -1;//アガリ判定 } preTempTehai[i]+=2; toitsu_suu--; } }//for var i } //【雀頭無し】コーツ抜き出し→シュンツ抜き出し→ターツ候補抜き出し if(!kanzen_toitsu_check){//完全トイツが見つかった場合は実行しない if(isCheckMan>0){//マンズがある場合実行 manMentsuMax=0; manTaatsuMax=0; manMentsuTaatsu_suu=manMentsuTaatsuCheck(1);//シュンツを抜き出して個数を返す関数呼び出し } if(isCheckPin>0){//ピンズがある場合実行 pinMentsuMax=0; pinTaatsuMax=0; pinMentsuTaatsu_suu=pinMentsuTaatsuCheck(1);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckSou>0){//ソーズがある場合実行 souMentsuMax=0; souTaatsuMax=0; souMentsuTaatsu_suu=souMentsuTaatsuCheck(1);//コーツ・シュンツ・ターツを抜き出して個数を返す関数呼び出し } if(isCheckJi>0){//字牌がある場合実行 jiTaatsuMax=0; jiTaatuCheck();//字牌ターツを抜き出して個数を返す関数呼び出し } //シャンテン数の算出 syanten_temp=syantenHnatei(toitsu_suu,adjustment);//仮のシャンテン数を算出 if(syanten_suu>syanten_temp){syanten_suu = syanten_temp;}//シャンテン数を比較 if(!syanten_suu&&(isCheckMan+isCheckPin+isCheckSou+preMentsuCount*3)==tehaimode){ return 0;//テンパイ判定 } if(syanten_suu==-1){ return -1;//アガリ判定 } } return syanten_suu;//シャンテン数を返す } //============================================================================ //シャンテン数を算出する関数 //============================================================================ function syantenHnatei(toitsu_suu,adjustment){ var syanten_temp=0; var block_suu=0; block_suu=(manMentsuMax+pinMentsuMax+souMentsuMax+adjustment)+(manTaatsuMax+pinTaatsuMax+souTaatsuMax+jiTaatsuMax); //シャンテン数算出 if(block_suu>4){ syanten_temp=8-(manMentsuMax+pinMentsuMax+souMentsuMax+adjustment)*2-(manTaatsuMax+pinTaatsuMax+souTaatsuMax+jiTaatsuMax)-toitsu_suu+(block_suu-4); }else{ syanten_temp=8-(manMentsuMax+pinMentsuMax+souMentsuMax+adjustment)*2-(manTaatsuMax+pinTaatsuMax+souTaatsuMax+jiTaatsuMax)-toitsu_suu; } return syanten_temp; } //============================================================================ //字牌ターツ抜き出し //============================================================================ function jiTaatuCheck(){ var jiTaatsu=0; var i; for(i=31;i<38;i++){ if(tempTehai[i]==2){ tempTehai[i]-=2;//トイツを抜き出す jiTaatsu++; } } jiTaatsuMax=jiTaatsu; return jiTaatsu; } //============================================================================ //マンズのコーツを抜き出して個数を返す関数 //n=1:最初に見つかったコーツを1つだけ抜く //============================================================================ function manKoutsuCheck(n){ var koutsu_suu=0; for(var i=1;i<10;i++){ if(tempTehai[i]>=3){ tempTehai[i]-=3; koutsu_suu++; koutsuCount++; //「n=1」の時、1回だけコーツを抜いて処理を抜ける if(n==1){ return koutsu_suu; } } } return koutsu_suu; } //============================================================================ //マンズのコーツ・シュンツ・ターツを抜き出して個数を返す関数 //n=1:コーツ→シュンツ→ターツの順に抜く //n=2:シュンツ→コーツ→ターツの順に抜く //n=3:1コーツ→シュンツ→コーツ→ターツの順に抜く //============================================================================ function manMentsuTaatsuCheck(n){ var suujishuntsu_suu=0; var manMentsu; var manTaatsu; var manMentsu_temp; var isCheckMan; var i,j; var manMax_temp=0; for(j=0;j<8;j++){ manMentsu=0; manTaatsu=0; tempTehai = $.extend(true, [], preTempTehai);//preTempTehai配列の内容をコピーする if(n==1){manMentsu+=manKoutsuCheck(0);}//マンズのコーツを抜いてコーツ数を返す関数の実行 if(n==3){manMentsu+=manKoutsuCheck(1);}//マンズのコーツを抜いてコーツ数を返す関数の実行 //マンズのシュンツを抜く処理 for(i=1;i<8;i++){//通常処理 while(tempTehai[i+j]>=1&&tempTehai[i+1+j]>=1&&tempTehai[i+2+j]>=1&&(i+j)<8){ tempTehai[i+j]--; tempTehai[i+1+j]--; tempTehai[i+2+j]--; manMentsu++; } }//for //マンズのシュンツを抜く処理2 if(j>3){ for(i=1;i<8;i++){//通常処理 while(tempTehai[i]>=1&&tempTehai[i+1]>=1&&tempTehai[i+2]>=1&&i<8){ tempTehai[i]--; tempTehai[i+1]--; tempTehai[i+2]--; manMentsu++; } }//for } if(n==2||n==3){manMentsu+=manKoutsuCheck(0);}//マンズのコーツを抜いてコーツ数を返す関数の実行 //マンズのターツを抜く理 for(i=1;i<8;i++){ //トイツの抜き出し if(tempTehai[i]>=2&&i<10){ tempTehai[i]-=2;//トイツを抜き出す manTaatsu++; } //リャンメンとペンチャンの抜き出し if(tempTehai[i]&&tempTehai[i+1]&&i<9){ tempTehai[i]--; tempTehai[i+1]--; manTaatsu++; } //カンチャンの抜き出し if(tempTehai[i]&&!tempTehai[i+1]&&tempTehai[i+2]&&i<8){ tempTehai[i]--; tempTehai[i+2]--; manTaatsu++; } manMentsu_temp=manMentsu*10+manTaatsu; if(manMentsu_temp>manMax_temp) { manMax_temp=manMentsu_temp; manMentsuMax=manMentsu; manTaatsuMax=manTaatsu; suujishuntsu_suu=manMentsu*10+manTaatsu; }//if isCheckMan=tempTehai[1]+tempTehai[2]+tempTehai[3]+tempTehai[4]+tempTehai[5]+tempTehai[6]+tempTehai[7]+tempTehai[8]+tempTehai[9]; if(!isCheckMan){return suujishuntsu_suu;} }//for isCheckMan=tempTehai[1]+tempTehai[2]+tempTehai[3]+tempTehai[4]+tempTehai[5]+tempTehai[6]+tempTehai[7]+tempTehai[8]+tempTehai[9]; if(!isCheckMan){return suujishuntsu_suu;} if(!manMentsu){return suujishuntsu_suu;} }//for j return suujishuntsu_suu; } //============================================================================ //ピンズのコーツを抜き出して個数を返す関数 //n=1:最初に見つかったコーツを1つだけ抜く //============================================================================ function pinKoutsuCheck(n){ var koutsu_suu=0; for(var i=11;i<20;i++){ if(tempTehai[i]>=3){ tempTehai[i]-=3; koutsu_suu++; koutsuCount++; //「n=1」の時、1回だけコーツを抜いて処理を抜ける if(n==1){ return koutsu_suu; } } } return koutsu_suu; } //============================================================================ //ピンズのコーツ・シュンツ・ターツを抜き出して個数を返す関数 //n=1:コーツ→シュンツ→ターツの順に抜く //n=2:シュンツ→コーツ→ターツの順に抜く //n=3:1コーツ→シュンツ→コーツ→ターツの順に抜く //============================================================================ function pinMentsuTaatsuCheck(n){ var suujishuntsu_suu=0; var pinMentsu; var pinTaatsu; var pinMentsu_temp; var isCheckPin; var i,j; var pinMax_temp=0; for(j=0;j<8;j++){ pinMentsu=0; pinTaatsu=0; tempTehai = $.extend(true, [], preTempTehai);//preTempTehai配列の内容をコピーする if(n==1){pinMentsu+=pinKoutsuCheck(0);}//ピンズのコーツを抜いてコーツ数を返す関数の実行 if(n==3){pinMentsu+=pinKoutsuCheck(1);}//ピンズのコーツを抜いてコーツ数を返す関数の実行 //ピンズのシュンツを抜く処理 for(i=11;i<18;i++){//通常処理 while(tempTehai[i+j]>=1&&tempTehai[i+1+j]>=1&&tempTehai[i+2+j]>=1&&(i+j)<18){ tempTehai[i+j]--; tempTehai[i+1+j]--; tempTehai[i+2+j]--; pinMentsu++; } }//for //ピンズのシュンツを抜く処理2 if(j>3){ for(i=11;i<18;i++){//通常処理 while(tempTehai[i]>=1&&tempTehai[i+1]>=1&&tempTehai[i+2]>=1&&i<18){ tempTehai[i]--; tempTehai[i+1]--; tempTehai[i+2]--; pinMentsu++; } }//for } if(n==2||n==3){pinMentsu+=pinKoutsuCheck(0);}//ピンズのコーツを抜いてコーツ数を返す関数の実行 //ピンズのターツを抜く理 for(i=11;i<18;i++){ //トイツの抜き出し if(tempTehai[i]>=2&&i<20){ tempTehai[i]-=2;//トイツを抜き出す pinTaatsu++; } //リャンメンとペンチャンの抜き出し if(tempTehai[i]&&tempTehai[i+1]&&i<19){ tempTehai[i]--; tempTehai[i+1]--; pinTaatsu++; } //カンチャンの抜き出し if(tempTehai[i]&&!tempTehai[i+1]&&tempTehai[i+2]&&i<18){ tempTehai[i]--; tempTehai[i+2]--; pinTaatsu++; } pinMentsu_temp=pinMentsu*10+pinTaatsu; if(pinMentsu_temp>pinMax_temp) { pinMax_temp=pinMentsu_temp; pinMentsuMax=pinMentsu; pinTaatsuMax=pinTaatsu; suujishuntsu_suu=pinMentsu*10+pinTaatsu; }//if isCheckPin=tempTehai[11]+tempTehai[12]+tempTehai[13]+tempTehai[14]+tempTehai[15]+tempTehai[16]+tempTehai[17]+tempTehai[18]+tempTehai[19]; if(!isCheckPin){return suujishuntsu_suu;} }//for isCheckPin=tempTehai[11]+tempTehai[12]+tempTehai[13]+tempTehai[14]+tempTehai[15]+tempTehai[16]+tempTehai[17]+tempTehai[18]+tempTehai[19]; if(!isCheckPin){return suujishuntsu_suu;} if(!pinMentsu){return suujishuntsu_suu;} }//for j return suujishuntsu_suu; } //============================================================================ //ソーズのコーツを抜き出して個数を返す関数 //n=1:最初に見つかったコーツを1つだけ抜く //============================================================================ function souKoutsuCheck(n){ var koutsu_suu=0; for(var i=21;i<30;i++){ if(tempTehai[i]>=3){ tempTehai[i]-=3; koutsu_suu++; koutsuCount++; //「n=1」の時、1回だけコーツを抜いて処理を抜ける if(n==1){ return koutsu_suu; } } } return koutsu_suu; } //============================================================================ //ソーズのコーツ・シュンツ・ターツを抜き出して個数を返す関数 //n=1:コーツ→シュンツ→ターツの順に抜く //n=2:シュンツ→コーツ→ターツの順に抜く //n=3:1コーツ→シュンツ→コーツ→ターツの順に抜く //============================================================================ function souMentsuTaatsuCheck(n){ var suujishuntsu_suu=0; var souMentsu; var souTaatsu; var souMentsu_temp; var isCheckSou; var i,j; var souMax_temp=0; for(j=0;j<8;j++){ souMentsu=0; souTaatsu=0; tempTehai = $.extend(true, [], preTempTehai);//preTempTehai配列の内容をコピーする if(n==1){souMentsu+=souKoutsuCheck(0);}//ソーズのコーツを抜いてコーツ数を返す関数の実行 if(n==3){souMentsu+=souKoutsuCheck(1);}//ソーズのコーツを抜いてコーツ数を返す関数の実行 //ソーズのシュンツを抜く処理 for(i=21;i<28;i++){//通常処理 while(tempTehai[i+j]>=1&&tempTehai[i+1+j]>=1&&tempTehai[i+2+j]>=1&&(i+j)<28){ tempTehai[i+j]--; tempTehai[i+1+j]--; tempTehai[i+2+j]--; souMentsu++; } }//for //ソーズのシュンツを抜く処理2 if(j>3){ for(i=21;i<28;i++){//通常処理 while(tempTehai[i]>=1&&tempTehai[i+1]>=1&&tempTehai[i+2]>=1&&i<28){ tempTehai[i]--; tempTehai[i+1]--; tempTehai[i+2]--; souMentsu++; } }//for } if(n==2||n==3){souMentsu+=souKoutsuCheck(0);}//ソーズのコーツを抜いてコーツ数を返す関数の実行 //ソーズのターツを抜く理 for(i=21;i<28;i++){ //トイツの抜き出し if(tempTehai[i]>=2&&i<30){ tempTehai[i]-=2;//トイツを抜き出す souTaatsu++; } //リャンメンとペンチャンの抜き出し if(tempTehai[i]&&tempTehai[i+1]&&i<29){ tempTehai[i]--; tempTehai[i+1]--; souTaatsu++; } //カンチャンの抜き出し if(tempTehai[i]&&!tempTehai[i+1]&&tempTehai[i+2]&&i<28){ tempTehai[i]--; tempTehai[i+2]--; souTaatsu++; } souMentsu_temp=souMentsu*10+souTaatsu; if(souMentsu_temp>souMax_temp) { souMax_temp=souMentsu_temp; souMentsuMax=souMentsu; souTaatsuMax=souTaatsu; suujishuntsu_suu=souMentsu*10+souTaatsu; }//if isCheckSou=tempTehai[21]+tempTehai[22]+tempTehai[23]+tempTehai[24]+tempTehai[25]+tempTehai[26]+tempTehai[27]+tempTehai[28]+tempTehai[29]; if(!isCheckSou){return suujishuntsu_suu;} }//for isCheckSou=tempTehai[21]+tempTehai[22]+tempTehai[23]+tempTehai[24]+tempTehai[25]+tempTehai[26]+tempTehai[27]+tempTehai[28]+tempTehai[29]; if(!isCheckSou){return suujishuntsu_suu;} if(!souMentsu){return suujishuntsu_suu;} }//for j return suujishuntsu_suu; } //============================================================================ //完全コーツを抜き出して個数を返す関数 //============================================================================ function KanzenKoutsuCheck(){ var Kanzenkoutsu_suu = 0; var i,j; //字牌の完全コーツを抜き出す for(i=31;i<38;i++){ if(preTempTehai[i]>=3){ preTempTehai[i]-=3; Kanzenkoutsu_suu++; } }//for //数牌の完全コーツを抜き出す for(i=0;i<30;i+=10){ if(preTempTehai[i+1]>=3&&!preTempTehai[i+2]&&!preTempTehai[i+3]){ preTempTehai[i+1]-=3; Kanzenkoutsu_suu++; } if(!preTempTehai[i+1]&&preTempTehai[i+2]>=3&&!preTempTehai[i+3]&&!preTempTehai[i+4]){ preTempTehai[i+2]-=3; Kanzenkoutsu_suu++; } //3~7の完全コーツを抜く for(j=0;j<5;j++){ if(!preTempTehai[i+j+1]&&!preTempTehai[i+j+2]&&preTempTehai[i+j+3]>=3&&!preTempTehai[i+j+4]&&!preTempTehai[i+j+5]){ preTempTehai[i+j+3]-=3; Kanzenkoutsu_suu++; } } if(!preTempTehai[i+6]&&!preTempTehai[i+7]&&preTempTehai[i+8]>=3&&!preTempTehai[i+9]){ preTempTehai[i+8]-=3; Kanzenkoutsu_suu++; } if(!preTempTehai[i+7]&&!preTempTehai[i+8]&&preTempTehai[i+9]>=3){ preTempTehai[i+9]-=3; Kanzenkoutsu_suu++; } }//for return Kanzenkoutsu_suu; } //============================================================================ //完全シュンツを抜き出して個数を返す関数 //============================================================================ function kanzenShuntsuCheck(){ var kanzenshuntsu_suu=0; var i; //123,456のような完全に独立したシュンツを抜き出すための処理 ////【注意】番地0,10,20,30が「0」の必要あり。事前に赤ドラを移動させる処理をしておく。 for(i=0;i<30;i+=10){//マンズ→ピンズ→ソーズ //123▲▲ if(preTempTehai[i+1]==2&&preTempTehai[i+2]==2&&preTempTehai[i+3]==2&&!preTempTehai[i+4]&&!preTempTehai[i+5]){ preTempTehai[i+1]-=2; preTempTehai[i+2]-=2; preTempTehai[i+3]-=2; kanzenshuntsu_suu+=2; } //▲234▲▲ if(!preTempTehai[i+1]&&preTempTehai[i+2]==2&&preTempTehai[i+3]==2&&preTempTehai[i+4]==2&&!preTempTehai[i+5]&&!preTempTehai[i+6]){ preTempTehai[i+2]-=2; preTempTehai[i+3]-=2; preTempTehai[i+4]-=2; kanzenshuntsu_suu+=2; } //▲▲345▲▲ if(!preTempTehai[i+1]&&!preTempTehai[i+2]&&preTempTehai[i+3]==2&&preTempTehai[i+4]==2&&preTempTehai[i+5]==2&&!preTempTehai[i+6]&&!preTempTehai[i+7]){ preTempTehai[i+3]-=2; preTempTehai[i+4]-=2; preTempTehai[i+5]-=2; kanzenshuntsu_suu+=2; } //▲▲456▲▲ if(!preTempTehai[i+2]&&!preTempTehai[i+3]&&preTempTehai[i+4]==2&&preTempTehai[i+5]==2&&preTempTehai[i+6]==2&&!preTempTehai[i+7]&&!preTempTehai[i+8]){ preTempTehai[i+4]-=2; preTempTehai[i+5]-=2; preTempTehai[i+6]-=2; kanzenshuntsu_suu+=2; } //▲▲567▲▲ if(!preTempTehai[i+3]&&!preTempTehai[i+4]&&preTempTehai[i+5]==2&&preTempTehai[i+6]==2&&preTempTehai[i+7]==2&&!preTempTehai[i+8]&&!preTempTehai[i+9]){ preTempTehai[i+5]-=2; preTempTehai[i+6]-=2; preTempTehai[i+7]-=2; kanzenshuntsu_suu+=2; } //▲▲678▲ if(!preTempTehai[i+4]&&!preTempTehai[i+5]&&preTempTehai[i+6]==2&&preTempTehai[i+7]==2&&preTempTehai[i+8]==2&&!preTempTehai[i+9]){ preTempTehai[i+6]-=2; preTempTehai[i+7]-=2; preTempTehai[i+8]-=2; kanzenshuntsu_suu+=2; } //▲▲789 if(!preTempTehai[i+5]&&!preTempTehai[i+6]&&preTempTehai[i+7]==2&&preTempTehai[i+8]==2&&preTempTehai[i+9]==2){ preTempTehai[i+7]-=2; preTempTehai[i+8]-=2; preTempTehai[i+9]-=2; kanzenshuntsu_suu+=2; } } for(i=0;i<30;i+=10){//マンズ→ピンズ→ソーズ //123▲▲ if(preTempTehai[i+1]==1&&preTempTehai[i+2]==1&&preTempTehai[i+3]==1&&!preTempTehai[i+4]&&!preTempTehai[i+5]){ preTempTehai[i+1]--; preTempTehai[i+2]--; preTempTehai[i+3]--; kanzenshuntsu_suu++; } //▲234▲▲ if(!preTempTehai[i+1]&&preTempTehai[i+2]==1&&preTempTehai[i+3]==1&&preTempTehai[i+4]==1&&!preTempTehai[i+5]&&!preTempTehai[i+6]){ preTempTehai[i+2]--; preTempTehai[i+3]--; preTempTehai[i+4]--; kanzenshuntsu_suu++; } //▲▲345▲▲ if(!preTempTehai[i+1]&&!preTempTehai[i+2]&&preTempTehai[i+3]==1&&preTempTehai[i+4]==1&&preTempTehai[i+5]==1&&!preTempTehai[i+6]&&!preTempTehai[i+7]){ preTempTehai[i+3]--; preTempTehai[i+4]--; preTempTehai[i+5]--; kanzenshuntsu_suu++; } //▲▲456▲▲ if(!preTempTehai[i+2]&&!preTempTehai[i+3]&&preTempTehai[i+4]==1&&preTempTehai[i+5]==1&&preTempTehai[i+6]==1&&!preTempTehai[i+7]&&!preTempTehai[i+8]){ preTempTehai[i+4]--; preTempTehai[i+5]--; preTempTehai[i+6]--; kanzenshuntsu_suu++; } //▲▲567▲▲ if(!preTempTehai[i+3]&&!preTempTehai[i+4]&&preTempTehai[i+5]==1&&preTempTehai[i+6]==1&&preTempTehai[i+7]==1&&!preTempTehai[i+8]&&!preTempTehai[i+9]){ preTempTehai[i+5]--; preTempTehai[i+6]--; preTempTehai[i+7]--; kanzenshuntsu_suu++; } //▲▲678▲ if(!preTempTehai[i+4]&&!preTempTehai[i+5]&&preTempTehai[i+6]==1&&preTempTehai[i+7]==1&&preTempTehai[i+8]==1&&!preTempTehai[i+9]){ preTempTehai[i+6]--; preTempTehai[i+7]--; preTempTehai[i+8]--; kanzenshuntsu_suu++; } //▲▲789 if(!preTempTehai[i+5]&&!preTempTehai[i+6]&&preTempTehai[i+7]==1&&preTempTehai[i+8]==1&&preTempTehai[i+9]==1){ preTempTehai[i+7]--; preTempTehai[i+8]--; preTempTehai[i+9]--; kanzenshuntsu_suu++; } } return kanzenshuntsu_suu; } //============================================================================ //完全孤立牌を抜き出して個数を返す関数 //============================================================================ function KanzenKoritsuCheck(){ var KanzenKoritsu_suu=0; var i,j; //字牌の完全孤立牌を抜き出す for(i=31;i<38;i++){ if(preTempTehai[i]==1){ //koritsu = i ;//孤立牌を変数に格納する preTempTehai[i]--; KanzenKoritsu_suu++; } } //数牌の完全孤立牌を抜き出す for(i=0;i<30;i=i+10){//マンズ→ピンズ→ソーズ //1の孤立牌を抜く if(preTempTehai[i+1]==1&&!preTempTehai[i+2]&&!preTempTehai[i+3]){ //koritsu = i+1;//孤立牌を変数に格納する preTempTehai[i+1]--; KanzenKoritsu_suu++; } //2の完全孤立牌を抜く if(!preTempTehai[i+1]&&preTempTehai[i+2]==1&&!preTempTehai[i+3]&&!preTempTehai[i+4]){ preTempTehai[i+2]--; KanzenKoritsu_suu++; } //3~7の完全孤立牌を抜く for(j=0;j<5;j++){ if(!preTempTehai[i+j+1]&&!preTempTehai[i+j+2]&&preTempTehai[i+j+3]==1&&!preTempTehai[i+j+4]&&!preTempTehai[i+j+5]){ preTempTehai[i+j+3]--; KanzenKoritsu_suu++; } } //8の完全孤立牌を抜く if(!preTempTehai[i+6]&&!preTempTehai[i+7]&&preTempTehai[i+8]==1&&!preTempTehai[i+9]){ preTempTehai[i+8]--; KanzenKoritsu_suu++; } //9の完全孤立牌を抜く if(!preTempTehai[i+7]&&!preTempTehai[i+8]&&preTempTehai[i+9]==1){ preTempTehai[i+9]--; KanzenKoritsu_suu++; } } return KanzenKoritsu_suu; } //============================================================================ //完全トイツをチェックする関数:見つかった場合は「1」を、見つからなかった場合は「0」を返す //雀頭が無い場合の処理をスルーするための措置 //============================================================================ function KanzenToitsuCheck(){ var i,j; //字牌のトイツチェック for(i=31;i<38;i++){ if(preTempTehai[i]==2){return 1;} } //数牌の完全トイツをチェック for(i=0;i<30;i+=10){ //1の完全トイツをチェック if(preTempTehai[i+1]==2&&!preTempTehai[i+2]){return 1;} //2の完全トイツをチェック if(!preTempTehai[i+1]&&preTempTehai[i+2]==2&&!preTempTehai[i+3]){return 1;} //3~7の完全トイツをチェック for(j=0;j<5;j++){ if(!preTempTehai[i+j+2]&&preTempTehai[i+j+3]==2&&!preTempTehai[i+j+4]){return 1;} } //8の完全トイツをチェック if(!preTempTehai[i+7]&&preTempTehai[i+8]==2&&!preTempTehai[i+9]){return 1;} //9の完全トイツをチェック if(!preTempTehai[i+8]&&preTempTehai[i+9]==2){return 1;} } return 0; } //============================================================================ //抜き出した牌とシャンテン数を出力させる処理【動作チェック用】 //============================================================================ $("#SyantenCheckBtn").click(function() { moveReddora();//赤ドラを配列内で移動させる var syanten_suu = syantenCheck();//シャンテン数を求める関数の呼び出し $("#paiTehaiSyantenCheck").empty().append("シャンテン数 = " + syanten_suu); }); //============================================================================
+ paiput.jsを開く
var PaiCount = 0; //入力された牌の枚数 //牌画を挿入する関数 $("span","#haiga").on('click', function(event){ var paiNo = $(this).attr("name"); //牌の番号を取得 var paiName = $(this).attr("class"); //CSSスプライト用のクラス名を取得 //alert(paiNo); if(PaiCount<14){ if(tehai[paiNo]>3){ alert("5枚以上の同種牌を置くことはできません。"); return false; }else{ tehai[paiNo] ++; paiga = "<span class=\"" + paiName + "\"></span>";//cssスプライトの牌画を配置 $("#paiTehai").append(paiga); PaiCount ++; $("#paikazu").empty().append(PaiCount); } }else{ alert("これ以上は牌を置けません。"); return false; } }); //手牌を並べ替える処理 $("#PaiSortBtn").on('click', function(event){ var i,k,kazu; var paiga=""; $("#paiTehai").empty(); (function (){ for(i=0;i<38;i++){ //通常の手牌表示処理 if(tehai[i]){ kazu = tehai[i]; for(k=0;k<kazu;k++){ paiga = "<span class=\"" + paiType[i].cssSprite + "\"></span>";//cssスプライトの牌画を配置 $("#paiTehai").append(paiga); } } } })(); }); //手牌を消去する処理 $("#PaiClreaBtn").on('click', function(event){ $("#paiTehai").empty(); tehai = [0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0]; PaiCount = 0; });
+ program_009.cssを開く
@charset "utf-8"; #paiTehai > span , #haiga > span, .haiga > span{ background-color:transparent; background-image:url(../images/pai.png); background-repeat:no-repeat; background-attachment:scroll; display:inline-block; color:#000; } .paishadow{ box-shadow: 0px 0px 5px 2px rgba(0, 256, 256, 1); } .man1{background-position:0px 0px;height:47px;width:31px;} .man2{background-position:-31px 0px;height:47px;width:31px;} .man3{background-position:-62px 0px;height:47px;width:31px;} .man4{background-position:-93px 0px;height:47px;width:31px;} .man5{background-position:-124px 0px;height:47px;width:31px;} .man6{background-position:-155px 0px;height:47px;width:31px;} .man7{background-position:-186px 0px;height:47px;width:31px;} .man8{background-position:-217px 0px;height:47px;width:31px;} .man9{background-position:-248px 0px;height:47px;width:31px;} .man0{background-position:-279px 0px;height:47px;width:31px;} .pin1{background-position:0px -47px;height:47px;width:31px;} .pin2{background-position:-31px -47px;height:47px;width:31px;} .pin3{background-position:-62px -47px;height:47px;width:31px;} .pin4{background-position:-93px -47px;height:47px;width:31px;} .pin5{background-position:-124px -47px;height:47px;width:31px;} .pin6{background-position:-155px -47px;height:47px;width:31px;} .pin7{background-position:-186px -47px;height:47px;width:31px;} .pin8{background-position:-217px -47px;height:47px;width:31px;} .pin9{background-position:-248px -47px;height:47px;width:31px;} .pin0{background-position:-279px -47px;height:47px;width:31px;} .sou1{background-position:0px -94px;height:47px;width:31px;} .sou2{background-position:-31px -94px;height:47px;width:31px;} .sou3{background-position:-62px -94px;height:47px;width:31px;} .sou4{background-position:-93px -94px;height:47px;width:31px;} .sou5{background-position:-124px -94px;height:47px;width:31px;} .sou6{background-position:-155px -94px;height:47px;width:31px;} .sou7{background-position:-186px -94px;height:47px;width:31px;} .sou8{background-position:-217px -94px;height:47px;width:31px;} .sou9{background-position:-248px -94px;height:47px;width:31px;} .sou0{background-position:-279px -94px;height:47px;width:31px;} .ji1{background-position:0px -141px;height:47px;width:31px;} .ji2{background-position:-31px -141px;height:47px;width:31px;} .ji3{background-position:-62px -141px;height:47px;width:31px;} .ji4{background-position:-93px -141px;height:47px;width:31px;} .ji5{background-position:-124px -141px;height:47px;width:31px;} .ji6{background-position:-155px -141px;height:47px;width:31px;} .ji7{background-position:-186px -141px;height:47px;width:31px;} .ji0{background-position:-217px -141px;height:47px;width:31px;} #haiga{ background-color:#173B0B; padding:5px 15px 3px 15px; margin-bottom:5px; color:#fff; -moz-user-select: none; -webkit-user-select: none; -ms-user-select: none;} }
おすすめレンタルサーバー
エックスサーバー|高速・高機能レンタルサーバー
「オールSSDの快適ハイスペック環境」「国内管理、大容量バックボーン」「独自SSLが無料」「FastCGIなどの高速化機能」「最新のPHP7を実装」など、高機能・高コストパフォーマンスなレンタルサーバーです。※当サイトも「エックスサーバー」で運用しています。