プログラミング

Go言語で麻雀プログラミング事始め(2)~コマンドラインオプションの実装

Go言語で麻雀プログラミング事始めで作った点数計算プログラムは、符・翻・親子・アガリ方の値が固定されて、汎用性に欠けるものでした。値を変更するたびにプログラムを修正してコンパイルし直すのは現実的ではありませんよね。

今回は、これらの値をコマンドラインオプションで指定して実行できるように、プログラムを修正します。

flagパッケージを組み込む

Go言語のflagパッケージを組み込むことで、コマンドラインオプションを使えるようになります。

import "flag"

受け取ったコマンドラインオプション を変数にバインドします。変数の定義が終わったらflag.Parse関数を実行します。

var (
	hu, han            float64 //値はコマンドラインから取得
	oyakoFlg, agariFlg int     //値はコマンドラインから取得
)

//取得したフラグを変数にバインドする
flag.Float64Var(&hu, "a", 30, "help message for 符")
flag.Float64Var(&han, "b", 1, "help message for 翻")
flag.IntVar(&oyakoFlg, "c", 1, "help message for 子=1,親=2")
flag.IntVar(&agariFlg, "d", 1, "help message for 出アガリ=1,ツモアガリ=2")

flag.Parse() //コマンドラインを解析して、定義された変数にセットする

これで、コマンドラインオプションで指定した値が変数にバインドされるようになります。

オプションスイッチ名とバインドする変数は、次表を参考にしてください。flagパッケージを使えば、オプションスイッチを省略した場合の初期値も設定できます。

オプションスイッチ名バインドする変数初期値
ahu30
bhan1
coyakoFlg1
dagariFlg1

手直しした点数計算プログラムの全コードは次の通りです。

package main

import (
	"flag" //コマンドラインの引数を取得するためのパッケージ
	"fmt"
	"math"
)

func main() {
	var (
		hu, han            float64 //値はコマンドラインから取得
		oyakoFlg, agariFlg int     //値はコマンドラインから取得
		cf                 float64 //調整用
		tensu              float64 //アガリ点数
		msg                string
	)

	//取得したフラグを変数にバインドする
	flag.Float64Var(&hu, "a", 30, "help message for 符")
	flag.Float64Var(&han, "b", 1, "help message for 翻")
	flag.IntVar(&oyakoFlg, "c", 1, "help message for 子=1,親=2")
	flag.IntVar(&agariFlg, "d", 1, "help message for 出アガリ=1,ツモアガリ=2")

	flag.Parse() //コマンドラインを解析して、定義されたフラグにセットする

	switch {
	case (agariFlg == 1) && (oyakoFlg == 1):
		cf = 4 //子出アガリ
	case (agariFlg == 1) && (oyakoFlg == 2):
		cf = 6 //親出アガリ
	case (agariFlg == 2) && (oyakoFlg == 1):
		cf = 1 //子ツモアガリ
	case (agariFlg == 2) && (oyakoFlg == 2):
		cf = 2 //親ツモアガリ
	default:
		cf = 4 //初期値は「子出アガリ」
	}

	switch {
	case han >= 13: //13翻以上
		tensu = 8000 * cf
	case (han >= 11 && han <= 12): //11翻以上
		tensu = 6000 * cf
	case (han >= 8 && han <= 10): //8翻以上
		tensu = 4000 * cf
	case (han >= 6 && han <= 7): //6翻以上
		tensu = 3000 * cf
	case (han == 5): //5翻
		tensu = 2000 * cf
		//	case (han == 4): //切り上げマンガン
		//		tensu = 2000 * cf
	case (hu >= 130 && han >= 2) || (hu >= 70 && han >= 3) || (hu >= 40 && han >= 4): //マンガン
		tensu = 2000 * cf
	default:
		tensu = hu * math.Pow(2, han) * 4 * cf //通常の点数計算
	}

	switch cf {
	case 1:
		msg = "子ツモアガリ"
	case 2:
		msg = "親ツモアガリ"
	case 4:
		msg = "子出アガリ"
	case 6:
		msg = "親出アガリ"
	default:
		msg = "子出アガリ" //初期値は「子出アガリ」
	}

	fmt.Println("符:", hu)
	fmt.Println("翻:", han)
	fmt.Println("結果1:"+msg+"(切り上げ前)", tensu)
	fmt.Println("結果2:"+msg+"(切り上げ後)", math.Ceil(tensu/100)*100)
}

プログラムを実行しよう

それでは点数計算プログラムを実行してみましょう。

40符3翻子の出アガリの実行結果

C:\Users\nyang\go\src\tensu>tensu -a 40 -b 3 -c 1 -d 1
符: 40
翻: 3
結果1:子出アガリ(切り上げ前) 5120
結果2:子出アガリ(切り上げ後) 5200

50符2翻親の出アガリの実行結果

C:\Users\nyang\go\src\tensu>tensu -a 50 -b 2 -c 2 -d 1
符: 50
翻: 2
結果1:親出アガリ(切り上げ前) 4800
結果2:親出アガリ(切り上げ後) 4800

ツモアガリは、子または親の片側の結果を返します。

70符1翻子のツモアガリの実行結果

C:\Users\nyang\go\src\tensu>tensu -a 70 -b 1 -c 1 -d 2
符: 70
翻: 1
結果1:子ツモアガリ(切り上げ前) 560
結果2:子ツモアガリ(切り上げ後) 600

オプションスイッチを省略すると、初期値で計算します。

オプションスイッチを省略した場合の実行結果

C:\Users\nyang\go\src\tensu>tensu
符: 30
翻: 1
結果1:子出アガリ(切り上げ前) 960
結果2:子出アガリ(切り上げ後) 1000

オプションスイッチのヘルプ

「-h」オプションスイッチを指定すれば、オプションスイッチのヘルプを出力することができます。

オプションスイッチのヘルプを表示する

C:\Users\nyang\go\src\tensu>tensu -h
Usage of tensu:
-a float
help message for 符 (default 30)
-b float
help message for 翻 (default 1)
-c int
help message for 子=1,親=2 (default 1)
-d int
help message for 出アガリ=1,ツモアガリ=2 (default 1)

以上で、汎用性のある点数計算プログラムができました。

[amazon_link asins='B01FH3KRTI' template='mahjong-book1' store='mahjanjidaihi-22' marketplace='JP' link_id='3366284d-b422-11e7-8299-290479cca4f6']

おすすめ麻雀本

G・ウザク

三才ブックス

-プログラミング
-,