概要と趣旨
タイトルの通り、ダイスを実装するよ。
(2022.10.09追記)
以下の2点を確かめるのが趣旨だよ。
- 同じシード値で生成した乱数列は常に同じ。
- 「シード値を変えれば異なる乱数列が生成される。
コメントにある通りクラス化するメリットのない(むしろ害のある)実装になっているのでおいおい改修していくよ。
とりあえず、今の実装で上に列挙した2点を確かめることは可能。
仕様
- シード値は、現在のタイムスタンプをint化した値を使用する。
- シード値を明示的に指定したい場合は、コンストラクタの引数から渡すことが可能。
- 出目の最大値は、ダイスを転がす都度指定する。転がすたびに面数が変わる不思議なダイスだね!
- 出目の最小値は1。
‐ ダイスの面数=出目の最大値で、出目は全て整数値。回りくどい表現だけど「出目が2、4、6、8の4面ダイス」のようなものは想定しない、ってことが言いたい。
とりあえず実装
こんな感じ。
Dice.py
'''
Created on 2022/10/08
@author: 芸夢 作郎
'''
import random
import time
class Dice():
seedValue = None
def __init__(self, aSeedValue = None):
if (aSeedValue == None):
self.seedValue = int(time.time() * 1000)
else:
self.seedValue = aSeedValue
random.seed(self.seedValue)
return
def roll(self, aMaxSidesNum):
ret = random.randint(1, aMaxSidesNum)
return ret
# (続く)
__init__メソッド
- コンストラクタ。Javaとは異なり、シグネチャの異なる__init__メソッドを複数定義することは不可。
- 第1引数selfは所謂おまじない。「自分自身のインスタンス」を示すキーワードだけど、ここではPythonの基本には触れない。
- 第2引数 aSeedValue でシード値を受け取る。
- 第2引数が指定されない場合は、time.time()関数で取得した現在のタイムスタンプをint型に変換し、シード値として使用する。
roll()メソッド
- 実際にサイコロを転がすメソッド。
- 引数 aSideNum に、出目の最大値を指定する。
- random.randint()関数で指定した範囲内の乱数を取得し、呼び出し元に返却する。
テスト
先ほどのソースコードの末尾に、以下を追記する。
Dice.py
# (続き)
if __name__ == "__main__":
# シード値に350を指定する
diceExplicit1 = Dice(350)
print('① シード値指定1回目/シード値: [{}]'.format(diceExplicit1.seedValue))
for i in range(0, 100, 1):
# 1000面ダイスを100回転がす
print(diceExplicit1.roll(1000))
print()
time.sleep(2)
# シード値を指定しない
diceTimestamp1 = Dice()
print('② シード値にタイムスタンプを使用1回目/シード値: [{}]'.format(diceTimestamp1.seedValue))
for i in range(0, 100, 1):
# 1000面ダイスを100回転がす
print(diceTimestamp1.roll(1000))
print()
time.sleep(2)
# シード値に350を指定する
diceExplicit2 = Dice(350)
print('③ シード値指定2回目/シード値: [{}]'.format(diceExplicit2.seedValue))
for i in range(0, 100, 1):
# 1000面ダイスを100回転がす
print(diceExplicit2.roll(1000))
print()
time.sleep(2)
# シード値を指定しない
diceTimestamp2 = Dice()
print('④ シード値にタイムスタンプを使用2回目/シード値: [{}]'.format(diceTimestamp2.seedValue))
for i in range(0, 100, 1):
# 1000面ダイスを100回転がす
print(diceTimestamp2.roll(1000))
print()
time.sleep(2)
# シード値に350を指定する
diceExplicitTheOtherSide = Dice(350)
print('⑤ シード値指定3回目(面数を変更)/シード値: [{}]'.format(diceExplicitTheOtherSide.seedValue))
for i in range(0, 100, 1):
# 2000面ダイスを100回転がす
print(diceExplicitTheOtherSide.roll(2000))
print()
実行すると、以下の出力結果を確認できる。
- シード値と最大面数がが同じであれば、乱数の生成結果は同じ(①と③の比較結果)
- タイムスタンプを乱数シードに指定すれば、都度異なる生成結果を得ることができる(②と④の比較結果)
- シード値が同じでも、最大面数が異なれば生成結果は全く異なったものになる(①と⑤の比較結果)
おわりに
(2022.10.09追記)
コメント欄でもらった指摘(インスタンス変数で使ってるつもりの変数が実はクラス変数だった問題)について、次の記事で不具合を検証したよ。
改修は後日改めて。
以上