1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Python】競馬シミュレーションアプリを作ろう!

Last updated at Posted at 2023-06-13

プロジェクト概要

このプログラムは、競馬のシミュレーションアプリです。静岡大学の峰野研究室での夏休み課題として利用され、ユーザーが競馬のレース予測や馬券購入を楽しめるような機能が実装されています。本プロジェクトでは、GUIによる操作性の向上やAIによる予測機能を備えたユーザーフレンドリーなインターフェースを実現しています。

主な機能の説明

馬券購入画面(AI予想付き)

馬券購入画面では、ユーザーがAIの予測を参考にしながら、好きな馬に賭けることができます。

馬券購入画面

レース画面(購入馬券のハイライト表示)

購入した馬券の馬がレース中に色付きで表示され、視覚的にレースを楽しめます。

レース画面

オッズ計算画面(自動差分計算機能)

オッズ計算画面では、異なる馬の組み合わせに対するオッズの差分が自動的に計算され、適切な賭け金の設定に役立ちます。

オッズ計算画面

使用ライブラリ

本プログラムで使用している主なライブラリは以下の通りです。

  • pandas: レースデータの処理
  • PySimpleGUI: GUIの構築
  • pickle: 学習モデルの保存と読み込み
  • playsound: サウンド再生

全ライブラリのインポートは以下のようになっています。

import random
import time
import datetime
import pandas
import PySimpleGUI
import sys
import os
import pickle
import warnings
from playsound import playsound

各機能の詳細

観戦モード

「観戦モード」では、レース予測は行わず、レース観戦のみが可能です。アプリ起動時にモード選択画面が表示され、観戦モードを選ぶとその後のレースは予測不可の観戦モードになります。

def viewing_mode_gui():
    layout = [[sg.Text('観戦モードにしますか?')],
            [sg.Button('いいえ', button_color=(None, '#dc3545')), sg.Button('はい')]]
    window = sg.Window('--競馬シミュレーションアプリ--', layout, size=(400,75), element_justification='center')
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        sys.exit()
    window.close()

    return event, values

馬情報

レースに参加する馬は各属性(馬番、馬名、騎手、調子、タイプ)の情報を持ちます。各レースには6頭の馬が参加し、それぞれの馬の属性はランダムに設定されます。重複の有無を選択しながら、必要な数の馬情報を生成します。

def random_select(all, num, deplication):
    list = []
    if deplication == None:
        for a in random.sample(all, num):
            list.append(a)
    elif deplication == True:
        for a in range(num):
            for b in random.sample(all, 1):
                list.append(b)
    return list

レース情報

レースの属性(レース長、天気、グラウンドタイプ、レース名)をランダムに設定します。

# レース情報の各属性リスト
all_length = [1000, 1600, 2000, 2500]
all_weather = ['', '曇り', '晴れ']
all_ground = ['', 'ダート']
all_race_name = ['有馬記念','菊花賞','大阪杯','桜花賞','天皇賞','宝塚記念','皐月賞']

# 使用例
length = random_select(all_length, 1, True)
weather = random_select(all_weather, 1, True)
ground = random_select(all_ground, 1, True)
race_name = random_select(all_race_name, 1, True)

レースの反復処理

レース終了後、所持金があれば次のレースに継続するか確認画面が表示されます。

def Yes_or_No_gui():
    layout = [[sg.Text('このまま次のレースに参加しますか?')],
            [sg.Button('いいえ'), sg.Button('はい', button_color=(None, '#dc3545'))]]
    window = sg.Window('--競馬シミュレーションアプリ--', layout, size=(400,75), element_justification='center')
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        sys.exit()
    window.close()

    return event, values

サウンド再生

プログラムの要所でサウンドを再生します。playsoundライブラリを使用し、バックグラウンド再生も可能です。

playsound("XXX.mp3")
playsound("XXX.mp3", None)

激アツモード

5%の確率で「激アツモード」に突入し、そのレースのオッズが5倍になります。確率に応じたサウンドも再生されます。

if random.randint(1,100) >= 95:
    playsound("チャンス用サウンド.mp3")
    if random.randint(1,5) >= 3:
        playsound("激アツモード突入用サウンド.mp3")
        gekiatu = 1

馬券の種類

馬券は3種類あり、単勝、複勝、2連複で賭けることができます。不適切な入力がある場合はエラーメッセージを表示し、再入力を促します。

def predict_input_gui(money):
    layout = [[sg.Text('予想してください(馬番を入力しないことも可能です)')],
              [sg.Text('所持金[¥]: ' + str(money))],
            [sg.Text('単勝: '), sg.Input(default_text='馬番', size=(4,5), justification='center'), sg.Text('賭け金[¥]: '), sg.Input(default_text='数字', size=(8,5), justification='center')],
            [sg.Text('複勝: '), sg.Input(size=(4,5), justification='center'), sg.Text('賭け金[¥]: '), sg.Input(size=(8,5), justification='center')],
            [sg.Text('2連複: '), sg.Input(size=(2,5), justification='center'), sg.Text(""), sg.Input(size=(2,5), justification='center'), sg.Text('賭け金[¥]: '), sg.Input(size=(8,5), justification='center')],
            [sg.Button('次へ')]]
    window = sg.Window('--競馬シミュレーションアプリ--', layout, size=(600,170), element_justification='center', text_justification='center')
    event, values = window.read()
    if event == sg.WIN_CLOSED:
        sys.exit()
    window.close()

    return event, values

オッズ計算アルゴリズム

オッズは馬の能力やレース情報に基づいて決定されます。「激アツモード」が発動するとオッズが変動します。また、馬券の種類ごとに異なるオッズが適用されます。

レース処理アルゴリズム

レースの進行は複数の関数で実現されています。各馬の進行速度やゴールの判定、順位決定のために、データフレームに記録しながら順位を確定します。

AI予想

LightGBMで学習済みのAIモデルを利用し、各馬の勝率を予測します。さらに、レース情報やAIの予測に基づいて、AIがレースに対するコメントを出力します。

def ai_predict(lane, num, size, all_length, gs, output):
    ai_predict = []
    lane_sum = []
    lane_base = 0
    max_ai_predict =

 -1
    comment = ""
    # 確率予測
    for a in range(num):
        sum = 0
        for b in range(1, size):
            if b == 4:
                if race_info[1] == all_length[0]:
                    sum += 8 - lane[a][b]
                elif race_info[1] == all_length[1]:
                    sum += lane[a][b]
                elif race_info[1] == all_length[2]:
                    sum += 2 * lane[a][b]
                elif race_info[1] == all_length[3]:
                    sum += 2 ** lane[a][b]
            else:
                sum += lane[a][b]
        lane_sum.append(sum * (output[a] + 1))
        lane_base += lane_sum[a]
    for c in range(num):
        ai_predict_lane = round(lane_sum[c] / lane_base, 2)
        ai_predict.append(ai_predict_lane)
        if ai_predict_lane > max_ai_predict:
            max_ai_predict = ai_predict_lane
    if max_ai_predict >= 0.35:
        comment = "今回は自信ありますよ~!!"
    elif max_ai_predict <= 0.25:
        comment = "今回は予想するのが難しいですね~"
    if gs == 0:
        comment += "大波乱の予感がします!!"
    elif gs == 1:
        comment += "レースは少し荒れそうな感じがします"
    elif gs == 2:
        comment += "可もなく不可もないレースになりそうです"
    elif gs == 3:
        comment += "馬場の状態は良さそうですね"
    elif gs == 4:
        comment += "手堅い結果になると思います!!"
    
    return ai_predict, comment

マイページ

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?