きょこみのーと

技術に関係ないほうのブログ

Goでlotteryという抽選ライブラリを作った

単なるmath/randのラッパーですが。

もしかしたら他にも似たようなやつあるかもしれませんが、見つからなかったので作りました。

github.com

指定した確率

20%の確率で〜みたいな処理をしたいときです。

lot := lottery.New(rand.New(rand.NewSource(time.Now().UnixNano())))

if lot.Lot(20) {
    // 20%の時の処理
}

抽選リストから1件抽選

以下のような複数の抽選対象から1件だけ抽選するときのinterfaceもあります。

  • A: 10%
  • B: 20%
  • C: 30%
  • D: 40%

Prob() intというインターフェースを実装すればOKです。

type DropItem struct {
    ItemName string
    DropProb int
}

func (d DropItem) Prob() int {
    return d.DropProb
}

var _ lottery.Interface = (*DropItem)(nil)

抽選はこんな感じにやる。

lot := lottery.New(rand.New(rand.NewSource(time.Now().UnixNano())))

// 抽選対象リスト
dropItems := []lottery.Interface{
    DropItem{ItemName: "エリクサ", DropProb: 10},      // 10%
    DropItem{ItemName: "エーテル", DropProb: 20},      // 20%
    DropItem{ItemName: "ポーション", DropProb: 30},    // 30%
    DropItem{ItemName: "ハズレ", DropProb: 40},       // 40%
}

// 抽選
lotIdx := lot.Lots(dropItems...)
if lotIdx == -1 {
    // errorです(抽選リストの指定ミスかと)
}

// 抽選結果のItem
dropItem := dropItems[lotIdx].(DropItem)

以下のテストコードも参考にしていただければと。

lottery/lottery_test.go at 2c0264f14a47bf1be830ae12d2c84a90ce9f1ffa · kyokomi/lottery · GitHub

200万回実行した結果は以下になります。

f:id:kyokomi:20150726150526p:plain

2015/07/26 15:51 追記

@tenntenn さんが「袋の中に球が3種類入っていてそれを順次取り出して行く」ような使い方を見つけてくれたので、紹介させていただきます。

ありがとうございます!