数字推論ゲームの設計と実装

ゲームエントリーポイント

import random, sys, time
from config import *
from character import *
from game_mechanic import *
from core import *

game_session  = GameSession()

while game_session.booth.is_active and game_session.booth.participants[0].is_playing:    
    game_session.update_state()
    time.sleep(DELAY)
    result = GameResult(game_session)
    time.sleep(DELAY)
    print(f"\n------ゲーム終了------\n")
    if restart_game():
        print("ゲーム再開!\n\n")
        game_session  = GameSession()
    else:
        print("またのご利用をお待ちしております")
        
exit_program()

ゲームコアロジック

import random, time
from config import *
from core import *
from character import *
from game_mechanic import *

class GameSession():
    def __init__(self):
        self.booth = GameBooth(2)
        print("------ゲーム準備完了!------\n")

    def update_state(self):
        if self.booth.participants[0].is_playing:
            time.sleep(DELAY)
            self.get_player_input()
        while self.booth.is_active and self.booth.participants[0].is_playing:
            self.booth.process_turn()
            
    def get_player_input(self):
        print(f"店主{self.booth.participants[0].name}に{RANGE_MIN}~{RANGE_MAX}の数字を教えてください")
        while True:
            try:
                secret_number = int(input())
                if secret_number in VALID_RANGE:
                    self.booth.participants[0].memorize(secret_number)
                    time.sleep(DELAY)
                    print(f"{self.booth.participants[1].name}は聞き耳を立てたが何も聞こえなかった")
                    return secret_number
                else:
                    print(f"有効な数字を{RANGE_MIN}~{RANGE_MAX}の範囲で入力してください")
            except ValueError:
                print("無効な入力です! 数字を入力してください")

ゲームメカニズム

import random, time
from config import *
from character import *

class GameBooth:
    def __init__(self, capacity):
        self.name = "数字推論ブース"
        self.capacity = capacity
        self.participants = []
        self.is_active = True
        self.turn_count = 0
        self.owner = self.create_owner(0)
        self.participants.append(self.owner)
        self.owner_name = self.owner.name
        for i in range(1, self.capacity):
            player = self.create_player(self.owner_name, i)
            self.participants.append(player)
    
    def process_turn(self):
        print("\n------ゲーム開始!------")
        self.participants[0].opponent = f"{self.participants[1].name}"
        self.participants[1].possible_numbers = VALID_RANGE
        hint_value = 0
        while self.participants[0].is_playing and self.is_active:
            time.sleep(DELAY)
            self.turn_count += 1
            print(f"\n------{self.participants[1].name}の{self.turn_count}回目の挑戦------")
            player_guess = self.participants[1].make_guess(hint_value)
            hint_value = self.participants[0].evaluate_guess(player_guess)
            self.check_game_state()

    def create_owner(self, idx):
        char_id = random.randint(0, CHAR_NAMES.MAX - 1)
        role = CharacterRole.OWNER
        owner = Character(char_id, role, idx)
        print(f"店主{owner.name}が{self.name}をオープンしました")
        return owner
    
    def check_game_state(self):
        if self.participants[0].is_playing and self.turn_count >= MAX_TURNS:
            self.is_active = False
            print(f"------{self.name}は閉店しました------")
        elif self.participants[0].is_playing:
            print("------ゲーム続行------")
        else:
            print("------正解!------")

    def get_game_status(self):
        return self.participants[0].is_playing
    
    def create_player(self, owner_name, idx):
        char_id = random.randint(0, CHAR_NAMES.MAX - 1)
        attempts = 0
        while CHAR_NAMES[char_id] == owner_name:
            attempts += 1
            char_id = random.randint(0, CHAR_NAMES.MAX - 1)
        role = CharacterRole.PLAYER
        player = Character(char_id, role, idx)
        print(f"プレイヤー{player.name}が{self.name}に参加しました")
        return player

キャラクターシステム

import random
from config import *

class Character:
    def __init__(self, name_id, role, idx):
        self.name = CHAR_NAMES[name_id]
        self.secret_number = None
        self.role = role
        self.idx = idx
        self.opponent = "あなた"
        self.is_playing = True
        self.possible_numbers = VALID_RANGE
        self.current_range = VALID_RANGE
        self.excluded_numbers = []
        self.hint_type = 0
            
    def memorize(self, num):
        self.secret_number = num
        print(f"{self.name}は数字{self.secret_number}を記憶しました")
    
    def evaluate_guess(self, guess):
        if self.secret_number == guess:
            print(f"{self.name}:{self.opponent}の正解です!")
            self.is_playing = False
        elif self.secret_number > guess and self.secret_number - guess > HINT_THRESHOLD:
            print(f"{self.name}:{self.opponent}の推測値は小さすぎます")
            self.hint_type = 1
        elif self.secret_number > guess and self.secret_number - guess <= HINT_THRESHOLD:
            print(f"{self.name}:{self.opponent}の推測値は少し小さいです")
            self.hint_type = 2
        elif self.secret_number < guess and guess - self.secret_number > HINT_THRESHOLD:
            print(f"{self.name}:{self.opponent}の推測値は大きすぎます")
            self.hint_type = 3
        elif self.secret_number < guess and guess - self.secret_number <= HINT_THRESHOLD:
            print(f"{self.name}:{self.opponent}の推測値は少し大きいです")
            self.hint_type = 4
        return self.hint_type
        
    def make_guess(self, hint):
        self.adjust_range(hint)
        self.possible_numbers = self.current_range
        self.secret_number = random.choice(self.possible_numbers)
        print(f"{self.name}:数字{self.secret_number}ですか?")
        return self.secret_number
    
    def adjust_range(self, hint):
        if hint == 1:
            self.excluded_numbers = list(range(self.secret_number + HINT_THRESHOLD + 1, RANGE_MAX + 1))
            self.current_range = [num for num in self.excluded_numbers if num in self.possible_numbers]
            print(f"{self.name}は範囲を{self.current_range}に絞り込みました")
        elif hint == 2:
            self.excluded_numbers = list(range(self.secret_number + 1, RANGE_MAX + 1))
            self.current_range = [num for num in self.excluded_numbers if num in self.possible_numbers]
            print(f"{self.name}は範囲を{self.current_range}に絞り込みました")
        elif hint == 3:
            self.excluded_numbers = list(range(RANGE_MIN, self.secret_number - HINT_THRESHOLD))
            self.current_range = [num for num in self.excluded_numbers if num in self.possible_numbers]
            print(f"{self.name}は範囲を{self.current_range}に絞り込みました")
        elif hint == 4:
            self.excluded_numbers = list(range(RANGE_MIN, self.secret_number))
            self.current_range = [num for num in self.excluded_numbers if num in self.possible_numbers]
            print(f"{self.name}は範囲を{self.current_range}に絞り込みました")

リザルト処理

import random, sys
from config import *
from character import *
from game_mechanic import *
from core import *
from special_events import *

class GameResult:
    def __init__(self, game):
        self.game = game
        self.turns = self.game.booth.turn_count
        self.player = self.game.booth.participants[0].opponent
        self.status = self.game.booth.is_active
        if self.status and self.turns == 1:
            print(f"\nゲーム終了!{self.player}は{self.turns}回で正解!\nレジェンダリーラック!")
            SpecialEvent()
        elif self.status and self.turns < MAX_TURNS:
            print(f"\nゲーム終了!{self.player}は{self.turns}回で正解!\nおめでとう!")
        elif self.status and self.turns == MAX_TURNS:
            print(f"\nゲーム終了!{self.player}は{self.turns}回目で正解!\n危機一髚の勝利!")
        elif not self.status:
            print(f"\nゲーム終了!{self.player}は{self.turns}回失敗\n残念...")

def restart_game():
    while True:
        user_input = input("ゲームを再開しますか? (y/n):\n")
        if user_input.lower() in ["y", "yes", "はい"]:
            print("再開します!\n")
            return True
        elif user_input.lower() in ["n", "no", "いいえ"]:
            print("終了します\n")
            return False
        else:
            print("y/nで答えてください")

def exit_program():
    print("(終了 - 任意のキーを押してください)")
    counter = 0
    while counter <= 30:
        if input().isalpha():
            break
        else:
            print("(終了 - 任意のキーを押してください)")
        counter += 1

設定値管理

import random
class CharacterRole:    
    PLAYER = 1
    OWNER = 0

class CharNames:
    NAME1 = 0
    NAME2 = 1
    NAME3 = 2
    NAME4 = 3
    NAME5 = 4
    NAME6 = 5
    NAME7 = 6
    MAX = 7
    
NameOrder = list(range(0, 7))

CHAR_NAMES = {
    CharNames.NAME1 : "白滝",
    CharNames.NAME2 : "蒼空",
    CharNames.NAME3 : "翠風",
    CharNames.NAME4 : "玄夜",
    CharNames.NAME5 : "紅蓮",
    CharNames.NAME6 : "琥珀",
    CharNames.NAME7 : "紺碧",
    CharNames.MAX: "--"
}

RANGE_MIN = 0
RANGE_MAX = 1000
VALID_RANGE = list(range(RANGE_MIN, RANGE_MAX))

DELAY = 0.5
HINT_THRESHOLD = int((RANGE_MAX - RANGE_MIN) * 0.26 + 1.3)
MAX_TURNS = int(len(VALID_RANGE) * 0.2 + 2.3)

SPECIAL_MESSAGES = {
    0 : "\n伝説の運勢、まさに人生の勝者!",
    1 : "\n驚異の幸運にただただ感服!",
    2 : "\n桁外れの強運、天選の証!",
    3 : "\n稀代の幸運に言葉を失う!",
    4 : "\n神がかり的な強運の持ち主!",
    5 : "\n揺るぎない幸運の象徴!",
    6 : "\n前人未到の幸運の軌跡!",
    7 : "\n次元を超えた幸運の体現者!",
    8 : "\n不滅の幸運を具現化した存在!",
    9 : "\n空前絶後の幸運の申し子!"
}

スペシャルイベント

import time
from config import *

class SpecialEvent:
    def __init__(self):
        self.index = 0
        while self.index <= 9:
            print(SPECIAL_MESSAGES[self.index])
            self.index += 1
            time.sleep(0.3)

タグ: Python ゲーム開発 AI対戦 推論アルゴリズム オブジェクト指向

7月21日 01:46 投稿