プログラミングを始めたばかりの方にとって、簡単なゲーム要素を実装することは学習のモチベーションを高める良い方法です。
本記事では、Pythonの標準ライブラリを使って「サイコロを振る」プログラムを作成する方法を、初級者向けにわかりやすく解説します。
ランダムな数を生成する「random」モジュール
Pythonでは、乱数を扱うために標準ライブラリのrandomモジュールを使います。
擬似乱数生成やさまざまな確率分布からのサンプリングを手軽に行えます。
以下では、モジュールレベル(関数/定数)と、乱数ジェネレータクラス random.Random の主なメソッド(プロパティ)に分けて解説します。
モジュールレベルの関数・定数
関数/定数 | 説明 |
---|---|
seed(a=None, version=2) | 乱数シードを設定。引数 a に同じ値を与えると、以降の乱数系列が同じ再現性ある系列になる。 |
getstate() | 現在の内部状態(シードを含む)を取得し、そのオブジェクトを返す。 |
setstate(state) | getstate() が返したオブジェクトで内部状態を復元する。 |
randbytes(n) | n バイト長の乱数バイト列を返す。(Python 3.9+) |
random() | [0.0, 1.0) 区間の浮動小数点乱数を返す。 |
uniform(a, b) | [a, b] 区間の浮動小数点乱数を返す。 |
randint(a, b) | a 以上 b 以下の整数乱数を返す(内部では randrange(a, b+1))。 |
randrange(start, stop[, step]) | start 以上 stop 未満を step 刻みで選ぶ整数を返す。 |
choice(seq) | シーケンス(リストや文字列など) seq からランダムに 1 要素を返す。 |
choices(population, weights=None, *, cum_weights=None, k=1) (Python 3.6+) | 重み付き/重複ありサンプリングを行い、長さ k のリストを返す。 |
shuffle(x[, random]) | リスト x をインプレースでシャッフル。 |
sample(population, k) | 重複なしサンプリングで長さ k のリストを返す。 |
各種確率分布
関数 | 分布 |
---|---|
betavariate(α, β) | ベータ分布 |
expovariate(λ) | 指数分布(平均 1/λ) |
gammavariate(α, β) | ガンマ分布 |
gauss(μ, σ) | 正規(ガウス)分布 |
lognormvariate(μ, σ) | 対数正規分布 |
normalvariate(μ, σ) | 正規分布(gauss と同等) |
vonmisesvariate(μ, κ) | フォン・ミーゼス分布(円形分布) |
paretovariate(α) | パレート分布 |
weibullvariate(α, β) | ワイブル(Weibull)分布 |
triangular(low, high, mode) | 三角分布 |
クラス random.Random の主なメソッド・プロパティ
実は上記モジュールレベル関数は、内部で共有の random.Random インスタンスを使っているだけです。自分でインスタンス化して使うことで、複数の独立した乱数源を作れます。
import random
# 独立した乱数ジェネレータを作る
r = random.Random(12345) # シード 12345 で初期化
print(r.random()) # 0.9296160928171479 …
メソッド一覧
メソッド | 説明 |
---|---|
seed(a=None, version=2) | インスタンス固有のシードを設定 |
getstate() | このインスタンスの状態を取得 |
setstate(state) | 状態を復元 |
getrandbits(k) | k ビット長の整数乱数を返す |
randbytes(n) | n バイトの乱数バイト列を返す |
random() | 0.0~1.0 未満の浮動小数点乱数 |
uniform(a, b) | [a, b] の浮動小数点乱数 |
randint(a, b) | a~b の整数乱数 |
randrange(start, stop[, step]) | 範囲 randonge |
choice(seq) | シーケンスから 1 つ選ぶ |
choices(population, …, k) | 重み付き、重複可のサンプリング |
shuffle(x) | シーケンスをインプレースでシャッフル |
sample(population, k) | 重複なしサンプリング |
gauss(μ, σ) | ガウス分布乱数 |
主なプロパティ
- random.VERSION
シリアライズ(pickle)の際のバージョン番号。将来互換性の判断などに使われる。 - __all__
モジュールがエクスポートしている名前のリスト。from random import * などで取り込まれるもの。
使い分けと注意点
- 再現性が欲しいとき
スクリプト実行ごとに同じ乱数系列がほしい場合は、必ず seed() を固定の値で呼び出す。 - 複数独立乱数源が必要なとき
グローバルな random とは別に、r = random.Random() で独立した RNG インスタンスを使う。 - セキュアな乱数が必要なとき
暗号的な用途(パスワード生成やトークンなど)には、secrets モジュールを使う。 - 分布の選択
正規分布なら gauss/normalvariate、指数分布なら expovariate、ベータ分布なら betavariate、… と用途に応じて呼び分ける。
サンプルコード
import random
# シード固定
random.seed(42)
# 0.0~1.0 の乱数
print(random.random())
# 整数サンプリング
print(random.randint(1, 10))
# リストからランダムに選ぶ
items = ['apple', 'banana', 'cherry']
print(random.choice(items))
# リストをシャッフル
deck = list(range(1, 10))
random.shuffle(deck)
print(deck)
# 正規分布
print(random.gauss(mu=0, sigma=1))
サイコロを振るプログラムの作成
サイコロの目は1〜6の整数ですので、random.randint()関数を利用すると簡単に実現できます。
import random
# 1から6までのランダムな整数を生成
dice = random.randint(1, 6)
print(f"サイコロの目は {dice} です!")
- import random:randomモジュールを読み込み
- random.randint(a, b):a以上b以下の整数をランダムに返す
では、実際にサイコロを振るプログラムをdice.pyとして作成してみましょう。
# dice.py
import random
def roll_dice():
"""
サイコロを振って1から6までのランダムな目を返す関数
"""
return random.randint(1, 6)
if __name__ == "__main__":
# サイコロを1回振る
result = roll_dice()
print(f"サイコロを振った結果:{result}")
- def roll_dice()::サイコロを振る処理を関数化
- if __name__ == “__main__”::このファイルが直接実行されたときのみ動作する
複数回振って集計してみよう
1回だけでなく、複数回サイコロを振って、出目の分布を確認してみましょう。
# dice_simulation.py
import random
NUM_TRIALS = 1000 # 試行回数
# 出目のカウント用リスト(インデックス0は使わない)
counts = [0] * 7
for _ in range(NUM_TRIALS):
face = random.randint(1, 6)
counts[face] += 1
for face in range(1, 7):
print(f"{face}の目:{counts[face]}回({counts[face] / NUM_TRIALS * 100:.1f}%)")
- counts = [0] * 7:インデックス1〜6を使うため、要素数7で初期化
- 試行ごとにカウントを増加し、最終的に出現割合を計算
ユーザー入力でサイコロを振る回数を指定
プログラムにユーザーからの入力機能を追加してみましょう。
# dice_input.py
import random
try:
n = int(input("サイコロを振る回数を入力してください:"))
except ValueError:
print("数値を入力してください。プログラムを終了します。")
exit(1)
for i in range(1, n + 1):
print(f"{i}回目の結果:{random.randint(1, 6)}")
- input()で文字列を受け取り、int()で整数に変換
- 例外処理(try/except)で不正な入力に対応
演習問題
以下の演習問題に挑戦して、学んだ内容を定着させましょう。
- サイコロを振った結果をファイルに保存するプログラムを作成してください。ファイル名はresults.txtとし、各行に出目を書き込むものとします。
- サイコロを振る回数をユーザーに入力させ、その結果を集計して、出目の出現回数を辞書型で表示するプログラムを作成してください。
- 6面サイコロだけでなく、カスタムの面数(例:4面、8面、20面サイコロ)にも対応できるように、関数roll_dice(sides)を作成してください。
- サイコロを振るごとに出目の目をアスキーアートで表示するプログラムを作成してください。(例:1なら「[● ]」、6なら「[●●●●●]」など)
- 上記のプログラムをモジュール化し、別のファイルからインポートして使えるようにしてください。
演習問題の解答例
1. ファイルに保存する例
import random
with open("results.txt", "w") as f:
for _ in range(100): # 例として100回振る
f.write(str(random.randint(1, 6)) + "\n")
2. 辞書型で集計する例
import random
n = int(input("振る回数:"))
counts = {i: 0 for i in range(1, 7)}
for _ in range(n):
face = random.randint(1, 6)
counts[face] += 1
print(counts)
3. カスタム面数対応の関数
import random
def roll_dice(sides=6):
"""sides面のサイコロを振ってランダムな目を返す"""
return random.randint(1, sides)
# 使用例
print(roll_dice(20)) # 20面サイコロ
4. アスキーアート表示の例
import random
def ascii_dice(face):
return "[" + "●" * face + " " * (6 - face) + "]"
for _ in range(5):
f = random.randint(1, 6)
print(f"{f} -> {ascii_dice(f)}")
5. モジュール化の例
# dice_module.py
import random
def roll_dice(sides=6):
return random.randint(1, sides)
def roll_multiple(n, sides=6):
return [roll_dice(sides) for _ in range(n)]
# main.py
from dice_module import roll_multiple
results = roll_multiple(10)
print(results)
まとめ
本記事では、Pythonのrandom
モジュールを使ってサイコロを振るプログラムをステップごとに解説しました。
基礎的なコードから始めて、関数化、集計、ユーザー入力対応、ファイル操作、モジュール化まで学ぶことで、Pythonの基本文法や標準ライブラリの使い方に慣れることができます。ぜひ演習問題にも挑戦して、理解を深めてください。
これで「Pythonでサイコロを作ってみよう」のチュートリアルは完了です。次は、今回学んだ内容を応用して、より複雑なゲームやシミュレーションに挑戦してみましょう!