小粒プログラミング 牌記号

#18 MPSZ形式牌記号を牌姿に復元する

Javascriptで遊ぶ麻雀小粒プログラミング MPSZ形式の牌記号を牌姿に復元するプログラムを紹介します。牌姿を画像で保存しておかなくてもフレキシブルに牌姿を再現できるのでとても便利です。

プログラムの解説と実行

前回のお題牌記号を生成するで生成したMPSZ形式の牌記号を牌姿に復元するプログラムを紹介します。牌記号で投稿した何切る問題を牌姿のイメージで見た時や、麻雀問題を牌記号で保存しておきたい時などに利用できます。いちいち牌姿を画像で保存しなくて済み、フレキシブルに牌姿を生成することができてとても便利です。

mpsz形式の牌記号割当一覧
▲MPSZ形式牌記号の割り当て名
MPSZ形式牌記号の記述例
MPSZ形式牌記号の割り当て名

456m406p456s1177z

同種牌の最後に、牌種を識別する記号(m|p|s|z)を付加します。

実行してみよう

牌記号入力欄にMPSZ形式の牌記号を入力して[牌姿の復元]ボタンを押してください。牌記号は牌記号を生成する天鳳牌理入力支援ツールで作ったものをコピー&ペーストしてご利用ください。

復元した手牌
 



JavaScriptソースコード

本記事で紹介したサンプルプログラムをダウンロードできます。

ダウンロードをする前にお読みください

  • サイトで紹介している記事の内容や公開しているプログラムの動作は100%保障するものではありません。
  • 当プログラム使用による如何なる不具合やトラブル、損害の責任も負いかねます。
  • 当プログラムは断り無く内容が変わることがあります。
  • 当プログラムを別サイトで配布することは禁止します。
  • サポートはいたしません。
  • 自己責任にてご利用くださいませ。

以上をご確認の上、プログラムのダウンロードをお願いいたします。

  • 本プログラムはjQueryを組み込んだ状態じゃないと動作しません。ご注意ください。

サンプルプログラムのソースコード

ソースコードは折りたたんであります。[+]を押すと、折りたたまれたソースコードが開きます。もう一度[+]を押すと、コードは折りたたまれます。

+ program_018.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種
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 red5manCount = 0;//赤5マンの数
var red5pinCount = 0;//赤5ピンの数
var red5souCount = 0;//赤5ソウの数
//============================================================================
//赤ドラの有無をチェックする処理
//============================================================================
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];//赤五索の牌数を格納
	}
}
//============================================================================
//牌記号を出力する処理
//============================================================================
$("#restorePaikigouBtn").click(function() {
	//グローバル変数の初期化
	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];
	red5manCount = 0;//赤5マンの数
	red5pinCount = 0;//赤5ピンの数
	red5souCount = 0;//赤5ソウの数

	var paikigou = $("#inputPaikigou").val();//牌記号の取得

	//手牌表示処理
	restoreMpszPaikigou(paikigou);//MPSZ形式牌記号を復元してtehai配列に格納する関数の呼び出し
	checkReddora();//赤ドラをチェックする関数の呼び出し

	(function (){
        var i,k,kazu;
        var paiga="";
        $("#paiTehai").empty();
        for(i=0;i<38;i++){
        	if(i%10===0){continue;}
            //赤五萬を表示する
            if(i==5 && red5manCount==1){
                paiga = "<span class=\"" + paiType[0].cssSprite + "\"></span>";//cssスプライトの牌画を配置
                $("#paiTehai").append(paiga);
            }

            //赤五筒の表示する
            if(i==15 && red5pinCount==1){
                paiga = "<span class=\"" + paiType[10].cssSprite + "\"></span>";//cssスプライトの牌画を配置
                $("#paiTehai").append(paiga);
            }

            //赤五索を表示する
            if(i==25 && red5souCount==1){
                paiga = "<span class=\"" + paiType[20].cssSprite + "\"></span>";//cssスプライトの牌画を配置
                $("#paiTehai").append(paiga);
            }

            //通常の手牌表示処理
            if(tehai[i]){
                kazu = tehai[i];
                for(k=0;k<kazu;k++){
                    paiga = "<span class=\"" + paiType[i].cssSprite + "\"></span>";//cssスプライトの牌画を配置
                    $("#paiTehai").append(paiga);
                }
            }
        }
    })();
});
//============================================================================
/**
 * 全角から半角への変革関数
 * 入力値の英数記号を半角変換して返却
 * [引数]   strVal: 入力値
 * [返却値] String(): 半角変換された文字列
 */
function toHalfWidth(strVal){
  // 半角変換
  var halfVal = strVal.replace(/[!-~]/g,
    function( tmpStr ) {
      // 文字コードをシフト
      return String.fromCharCode( tmpStr.charCodeAt(0) - 0xFEE0 );
    }
  );

  // 文字コードシフトで対応できない文字の変換
  return halfVal.replace(/”/g, "\"")
    .replace(/’/g, "'")
    .replace(/‘/g, "`")
    .replace(/¥/g, "\\")
    .replace(/ /g, " ")
    .replace(/〜/g, "~");
}
//============================================================================
//MPSZ形式牌記号を復元してtehai配列に格納する関数
//============================================================================
function restoreMpszPaikigou(paikigou) {

	var result = paikigou.replace( / /g , "" ) ;//半角スペースを削除
	result = result.replace( / /g , "" ) ;//全角スペースを削除
	result = toHalfWidth(result);
	$("#paiKigou1").empty().append(result);

	result = result.replace( /r5/g , "0" ) ;//赤ドラ処理
	result = result.replace( /赤5/g , "0" ) ;//赤ドラ処理
	$("#paiKigou2").empty().append(result);

	var man = ("" + result.match(/\d+m/)).slice(0,-1);//末尾の文字(m)を削除
	var pin = ("" + result.match(/\d+p/)).slice(0,-1);//末尾の文字(p)を削除
	var sou = ("" + result.match(/\d+s/)).slice(0,-1);//末尾の文字(s)を削除
	var ji = ("" + result.match(/\d+z/)).slice(0,-1);//末尾の文字(z)を削除

	//手牌数をチェック
	var mCount,pCount,sCount,jCount;
	if(man==="nul"){
		mCount=0;
	}else{
		mCount=man.length;
	}
	if(pin==="nul"){
		pCount=0;
	}else{
		pCount=pin.length;
	}
	if(sou==="nul"){
		sCount=0;
	}else{
		sCount=sou.length;
	}
	if(ji==="nul"){
		jCount=0;
	}else{
		jCount=ji.length;
	}
	if(mCount + pCount + sCount + jCount>14){return false;}//14以上の場合は、falseを返す

	var i;
	//マンズの処理
	if(man!="nul"){
//	var manlength = man.length;
		for(i=0;i<mCount;i++){
			tehai[Number(man.substring(i,i+1))]++;//手牌配列に牌番号を代入する
			if(tehai[i]>4){alert("4枚越えた");return false;}
		}
	}

	//ピンズの処理
	if(pin!="nul"){
//	var pinlength = pin.length;
		for(i=0;i<pCount;i++){
			tehai[Number(pin.substring(i,i+1)) + 10]++;//手牌配列に牌番号を代入する
		}
	}

	//ソーズの処理
	if(sou!="nul"){
//	var soulength = sou.length;
		for(i=0;i<sCount;i++){
			tehai[Number(sou.substring(i,i+1)) + 20]++;//手牌配列に牌番号を代入する
		}
	}

	//字牌の処理
	if(ji!="nul"){
//	var jilength = ji.length;
		for(i=0;i<jCount;i++){
			tehai[Number(ji.substring(i,i+1)) + 30]++;//手牌配列に牌番号を代入する
		}
	}

}
//============================================================================
//リセット処理
//============================================================================
$("#PaiClreaBtn").on('click', function(event){
	resetTehai();
});
//============================================================================
//リセット関数
//============================================================================
function resetTehai(){
	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];
	$("#inputPaikigou").val("");
	$("#paiTehai").empty();
	red5manCount = 0;//赤5マンの数
	red5pinCount = 0;//赤5ピンの数
	red5souCount = 0;//赤5ソウの数
}
//============================================================================

+ program_018.cssを開く

@charset "utf-8";

#paiTehai > span{
	background-color:transparent;
	background-image:url(../images/pai.png);
	background-repeat:no-repeat;
	background-attachment:scroll;
	display:inline-block;
}

.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;}

#paiTehai{
	height: 62px;
}


@media (max-width: 768px) {
	#paiTehai > span{
		background-color:transparent;
		background-image:url(../images/pai4.png);
		background-repeat:no-repeat;
		background-attachment:scroll;
		display:inline-block;
	}

	.man1{background-position:0px 0px;height:31px;width:23px;}
	.man2{background-position:-23px 0px;height:31px;width:23px;}
	.man3{background-position:-46px 0px;height:31px;width:23px;}
	.man4{background-position:-69px 0px;height:31px;width:23px;}
	.man5{background-position:-92px 0px;height:31px;width:23px;}
	.man6{background-position:-115px 0px;height:31px;width:23px;}
	.man7{background-position:-138px 0px;height:31px;width:23px;}
	.man8{background-position:-161px 0px;height:31px;width:23px;}
	.man9{background-position:-184px 0px;height:31px;width:23px;}
	.man0{background-position:-207px 0px;height:31px;width:23px;}
	.pin1{background-position:0px -31px;height:31px;width:23px;}
	.pin2{background-position:-23px -31px;height:31px;width:23px;}
	.pin3{background-position:-46px -31px;height:31px;width:23px;}
	.pin4{background-position:-69px -31px;height:31px;width:23px;}
	.pin5{background-position:-92px -31px;height:31px;width:23px;}
	.pin6{background-position:-115px -31px;height:31px;width:23px;}
	.pin7{background-position:-138px -31px;height:31px;width:23px;}
	.pin8{background-position:-161px -31px;height:31px;width:23px;}
	.pin9{background-position:-184px -31px;height:31px;width:23px;}
	.pin0{background-position:-207px -31px;height:31px;width:23px;}
	.sou1{background-position:0px -62px;height:31px;width:23px;}
	.sou2{background-position:-23px -62px;height:31px;width:23px;}
	.sou3{background-position:-46px -62px;height:31px;width:23px;}
	.sou4{background-position:-69px -62px;height:31px;width:23px;}
	.sou5{background-position:-92px -62px;height:31px;width:23px;}
	.sou6{background-position:-115px -62px;height:31px;width:23px;}
	.sou7{background-position:-138px -62px;height:31px;width:23px;}
	.sou8{background-position:-161px -62px;height:31px;width:23px;}
	.sou9{background-position:-184px -62px;height:31px;width:23px;}
	.sou0{background-position:-207px -62px;height:31px;width:23px;}
	.ji1{background-position:0px -93px;height:31px;width:23px;}
	.ji2{background-position:-23px -93px;height:31px;width:23px;}
	.ji3{background-position:-46px -93px;height:31px;width:23px;}
	.ji4{background-position:-69px -93px;height:31px;width:23px;}
	.ji5{background-position:-92px -93px;height:31px;width:23px;}
	.ji6{background-position:-115px -93px;height:31px;width:23px;}
	.ji7{background-position:-138px -93px;height:31px;width:23px;}
	.ji0{background-position:-161px -93px;height:31px;width:23px;}

	#paiTehai{
		height: 48px;
	}
}

@media (max-width: 360px) {
	#paiTehai > span{
		background-color:transparent;
		background-image:url(../images/pai3.png);
		background-repeat:no-repeat;
		background-attachment:scroll;
		display:inline-block;
	}

	.man1{background-position:0px 0px;height:26px;width:19px;}
	.man2{background-position:-19px 0px;height:26px;width:19px;}
	.man3{background-position:-38px 0px;height:26px;width:19px;}
	.man4{background-position:-57px 0px;height:26px;width:19px;}
	.man5{background-position:-76px 0px;height:26px;width:19px;}
	.man6{background-position:-95px 0px;height:26px;width:19px;}
	.man7{background-position:-114px 0px;height:26px;width:19px;}
	.man8{background-position:-133px 0px;height:26px;width:19px;}
	.man9{background-position:-152px 0px;height:26px;width:19px;}
	.man0{background-position:-171px 0px;height:26px;width:19px;}
	.pin1{background-position:0px -26px;height:26px;width:19px;}
	.pin2{background-position:-19px -26px;height:26px;width:19px;}
	.pin3{background-position:-38px -26px;height:26px;width:19px;}
	.pin4{background-position:-57px -26px;height:26px;width:19px;}
	.pin5{background-position:-76px -26px;height:26px;width:19px;}
	.pin6{background-position:-95px -26px;height:26px;width:19px;}
	.pin7{background-position:-114px -26px;height:26px;width:19px;}
	.pin8{background-position:-133px -26px;height:26px;width:19px;}
	.pin9{background-position:-152px -26px;height:26px;width:19px;}
	.pin0{background-position:-171px -26px;height:26px;width:19px;}
	.sou1{background-position:0px -52px;height:26px;width:19px;}
	.sou2{background-position:-19px -52px;height:26px;width:19px;}
	.sou3{background-position:-38px -52px;height:26px;width:19px;}
	.sou4{background-position:-57px -52px;height:26px;width:19px;}
	.sou5{background-position:-76px -52px;height:26px;width:19px;}
	.sou6{background-position:-95px -52px;height:26px;width:19px;}
	.sou7{background-position:-114px -52px;height:26px;width:19px;}
	.sou8{background-position:-133px -52px;height:26px;width:19px;}
	.sou9{background-position:-152px -52px;height:26px;width:19px;}
	.sou0{background-position:-171px -52px;height:26px;width:19px;}
	.ji1{background-position:0px -78px;height:26px;width:19px;}
	.ji2{background-position:-19px -78px;height:26px;width:19px;}
	.ji3{background-position:-38px -78px;height:26px;width:19px;}
	.ji4{background-position:-57px -78px;height:26px;width:19px;}
	.ji5{background-position:-76px -78px;height:26px;width:19px;}
	.ji6{background-position:-95px -78px;height:26px;width:19px;}
	.ji7{background-position:-114px -78px;height:26px;width:19px;}
	.ji0{background-position:-133px -78px;height:26px;width:19px;}

	#paiTehai{
		height: 40px;
	}
}

おすすめレンタルサーバー

エックスサーバー|高速・高機能レンタルサーバー

オールSSDの快適ハイスペック環境」「国内管理、大容量バックボーン」「独自SSLが無料」「FastCGIなどの高速化機能」「最新のPHP7を実装」など、高機能・高コストパフォーマンスなレンタルサーバーです。※当サイトも「エックスサーバー」で運用しています。

ウザク式麻雀牌効率学習

麻雀の牌効率を覚えたい初心者向け決定版。読者に大好評の麻雀 定石「何切る」301選麻雀 傑作「何切る」300選の著者が「初心者が何切るを解く前に読んでもらうことで、効率よく学習してもらいたい」という願いを込めた一冊です。

-小粒プログラミング, 牌記号
-,