Pythonで釣りゲームを作ろう 基礎編6

2024年04月23日(月)

乱数を使ったガチャを作成してみましょう。

1 もくじ

2 乱数

randomモジュールを用いると、ランダムな数を生成したり、リストからランダムに抽出することができます。

2.1 random.randint()

img

random.randint(a,b)を使ってa~bまでの整数を生成します。

以下のコードを実行してみてください。さいころと同じふるまいをします。 1行目のimport randomで、randomモジュールを読み込み、使用できるようにしています。

import random

print(random.randint(1,6))

実行結果

3



ヒント: 2から100までの偶数を数学的に書くと2n (1 <= n <= 50)となります。

解答

Challenge6-1: print(random.randint(1,50))

Challenge6-2: print(random.randint(1,50) * 2)


2.2 random.choice()

random.choice(list)を使ってlistからランダムに要素を選択します。

以下のコードを実行してみてください。魚の名前が入ったリストからランダムに選択して表示します。

import random

fishes = ["アジ","サバ","イワシ","タイ","サメ"]
print(random.choice(fishes))

実行結果

アジ


2.3 random.choices()

random.choices(list,k,weights)を使ってlistからランダムに複数の要素を選択します。

random.choices()で選択された要素は重複することがあります。重複させたくない場合はrandom.sample()が用意されています。

以下のコードを実行してみてください。魚の名前が入ったリストからランダムに3つ選択して表示します。

import random

fishes = ["アジ","サバ","イワシ","タイ","サメ"]
print(random.choices(fishes,k=3))

実行結果

['タイ', 'イワシ', 'イワシ']


さらには重みをつけることもできます。引数weightsで確率を指定します。

import random

fishes = ["アジ","サバ","イワシ","タイ","サメ"]
fish_weights =[30,30,30,8,2] #アジ,サバ,イワシ30%、タイ8%、サメ2%
print(random.choices(fishes,k=10,weights = fish_weights))

実行結果

['サバ', 'イワシ', 'アジ', 'サメ', 'アジ', 'サバ', 'イワシ', 'アジ', 'イワシ', 'イワシ']


配列からランダムな要素を重み付きで取り出す

random.choices()を使えば、random.choice()ではできなかった、重みをつけて要素を取り出す操作ができました。 では、魚の名前のリストではなく魚の名前そのものが欲しいとき、どうすれば良いでしょうか。

まずは、先ほどのコードをk=1と書き換えて実行してみましょう。

import random

fishes = ["アジ","サバ","イワシ","タイ","サメ"]
fish_weights =[30,30,30,8,2] #アジ,サバ,イワシ30%、タイ8%、サメ2%
print(random.choices(fishes,k=1,weights = fish_weights))

実行結果

['イワシ']


ここで注意したいのは、k=1と指定しても、要素数1の配列が返ってくることです。配列の要素を取り出すには、list[0]のようにインデックスで指定します。

random.choices(・・・)[0]と指定することで、配列からランダムな要素を重み付きで取り出せます。

import random

fishes = ["アジ","サバ","イワシ","タイ","サメ"]
fish_weights =[30,30,30,8,2] #アジ,サバ,イワシ30%、タイ8%、サメ2%
print(random.choices(fishes,k=1,weights = fish_weights)[0])

実行結果

イワシ


2.4 応用

img

以下の要件を満たすプログラムを作成していきましょう。

STAR_1 = ["アジ","サバ","イワシ"]
STAR_2 = ["カワハギ","タチウオ","メバル"]
STAR_3 = ["タイ","スズキ","カサゴ"]


先ほどの例をそのまま使えば以下のようになりますが、これではあまりよくありません。

import random

FISH_LIST = ["アジ","サバ","イワシ","カワハギ","タチウオ","メバル","タイ","スズキ","カサゴ"]
FISH_WEIGHT = [25,25,25,20/3,20/3,20/3,5/3,5/3,5/3] #それぞれの排出率
print(random.choices(FISH_LIST,k=1,weights=FISH_WEIGHT)[0])

要件通りには動くのですが、他人や未来の自分にとって読みにくく、何か改良しようとすると大変なコードです。具体的には以下の欠点が挙げられます。


これらを解決するためにはどうすれば良いでしょうか。

今回は初めにレア度を排出率に従って決定し、次にその中からランダムに魚を選ぶ方法を取りましょう。まずは排出率に従って「★n」と表示するプログラムを作成します。

import random

FISH_LIST = ["★1","★2","★3"] 
FISH_WEIGHT = [75,20,5] #★1~3の排出率
print(random.choices(FISH_LIST,k=1,weights=FISH_WEIGHT)[0])

実行結果

★1


次に、「★n」の部分をそれぞれの魚のリストに置き換えます。

import random

STAR_1 = ["アジ","サバ","イワシ"]
STAR_2 = ["カワハギ","タチウオ","メバル"]
STAR_3 = ["タイ","スズキ","カサゴ"]

FISH_LIST = [STAR_1,STAR_2,STAR_3] #2次元配列であることに注意!
FISH_WEIGHT = [75,20,5] #★1~3の排出率
print(random.choices(FISH_LIST,k=1,weights=FISH_WEIGHT)[0])

実行結果

['アジ', 'サバ', 'イワシ']


リストが出力されているので、さらにこれをrandom.choice()で選択すれば良いですね。

import random

STAR_1 = ["アジ","サバ","イワシ"]
STAR_2 = ["カワハギ","タチウオ","メバル"]
STAR_3 = ["タイ","スズキ","カサゴ"]

FISH_LIST = [STAR_1,STAR_2,STAR_3] #2次元配列であることに注意!
FISH_WEIGHT = [75,20,5] #★1~3の排出率

print(random.choice(random.choices(FISH_LIST,k=1,weights=FISH_WEIGHT)[0]))

実行結果

サバ


うまくいきました!これは釣りゲームの部品になるので、後で再利用できるように適当な名前を付けて保存しておきましょう。 これはよくない例と比較して格段に修正、改造しやすくなっています。次のChallengeで確認してください。