CurioStation Okayama

岡山市のプログラミング教室 Python言語 サンプルプログラム

Python言語でサイコロを回すサンプルプログラム

https://youtu.be/q7NI1Xkqj-4

 

「簡単だ!?」と言われているプログラミング言語、Pythonですが、どんなことができるのか?
実際に作りながら、試してみました。プログラミング言語により得意なこと、苦手なことがります。そんな相談もしながらプログラミングを楽しむプログラミング教室です。

 

Pythonで複数のスレッド実行できるのか?

通常のプログラムは、シングルタスクで動きます。一つの処理が終わってから、次の処理にといった感じです。
複数処理を同時に行うには、スレッド処理、別タスク、別プロセスで動かすといったプログラミングをする必要があります。

 

Python には、スレッド (threading)、スレッドプール (concurrent.futures)、プロセスプール (concurrent.futures)
といった複数の関数(モジュール)を実行できる機能(importで指定)が用意されていますので作るモノによって適用して下さい。

 

PythonでWindow画面を作る

まずは、画面を作るには?っと、ここから悩むかも知れませんね
作るイメージとしては、「Start」が押されると、画像をかえながら「Stop」ボタンが押されるのを待つ
画像の置き換えと、ループ処理中にイベントの受け取りです。
タイマーイベントなどを使用して多重タスクっぽくできるプログラミング言語もありますが、Pythonでは?どうなるでしょう?

 

ボタンの制御も確認してみます

有効とか、無効にできるのかな?
特に気にされない方もいますけど、やはり、明確に使用できる。使用できない。といった魅せ方ができるのか?
UI(画面構成)的にも解りやすくできるのかな?の確認も含めてしてみました。

 

実際にコーディングしたのは、こんな感じです。

import tkinter -----> 画面を作る
import random -----> 乱数
import time --------> タイマー
import threading --> スレッド

ランダムな番号で画像を置き換える処理
def disp_img(i):
    if i==1 :
        panel.configure(image = image1)
        panel.image = image1
    if i==2 :
        panel.configure(image = image2)
        panel.image = image2
・・省略・・
    return

ランダムな番号で画像を置き換える処理
def roolet():
    while not event.is_set(): --> イベント発生まで
        i = random.randint(1,6) --> 乱数取得
        disp_img(i) --> 表示を変える
        time.sleep(0.3) --> 一定時間待つ
    return

ボタンが押されたときの処理
# clickイベント
def btn_click():
    t = threading.Thread(target=roolet) --> スレッド
    btn1.configure(state=tkinter.DISABLED) --> ボタン制御
    btn2.configure(state=tkinter.NORMAL)
    event.clear() --> イベントをクリア
    t.daemon=True
    t.start() --> スレッドの開始
    return
 
def btn_stop():
    btn2.configure(state=tkinter.DISABLED)
    btn1.configure(state=tkinter.NORMAL)
    event.set() --> イベントをセットする
    i = random.randint(1,6)
    disp_img(i) --> 最後の表示
    return
 
def btn_end():
    exit() --> 終了条件もなく強制終了
    return

# 画面作成
tki = tkinter.Tk()
tki.geometry('300x400')
tki.title('サイコロ')
 
image0 = tkinter.PhotoImage(file = './images/s000.png')
image1 = tkinter.PhotoImage(file = './images/s001.png')
・・省略・・
image6 = tkinter.PhotoImage(file = './images/s006.png')
 
panel = tkinter.Label(tki, image = image0)
panel.place(x=10, y=0)
panel.pack
 
# ボタン
btn1 = tkinter.Button(tki, width=7, text='Start', command=btn_click)
btn1.place(x=50, y=350)
btn1.configure(state=tkinter.NORMAL)
 
btn2 = tkinter.Button(tki, width=7, text='Stop', command=btn_stop)
btn2.place(x=120, y=350)
btn2.configure(state=tkinter.DISABLED)
 
btn3 = tkinter.Button(tki, width=7, text='終わり', command=btn_end)
btn3.place(x=190, y=350)
btn3.configure(state=tkinter.NORMAL)
 
event = threading.Event()
 
# 画面をそのまま表示
tki.mainloop()

 

スレッドで実行されるループ処理(画像を変える)の終了条件として、単純に、event がセットされたか?
といった条件にしています。グローバル変数を使って試してみましたが、思い通りの動作にならなかったので、単純にevent.setのOn/Offを使用しました。
方法はいろいろありますので、まずは、正確に動くこと、そして、スマートに記述できれば、よいでしょう。
 

簡単なプログラミングなので、スレッドクラスを作らずに実装しましたが、 作るモノによっては、別のクラスモジュールを作って実装したほうがよいかも知れません。
エラー処理、終了時の条件なども組み込んでいませんので、製品として扱うのであれば、実装して下さい。

 

プログラミングは作るのが早い、遅いといった単純なスピード勝負ではありませんが、
早く正確に作ることを心がけるとスキルアップしていきます。

 

Python言語を学びたい理由のひとつに、簡単だから?ということをよく聞きますが、プログラミングをはじめて学ぶ方にとっては、そんなに簡単なハズもないです

 

記述、コーディング量が少なくなるといった内容が「簡単」といったイメージになっているだけで、ロジック、手順は他のプログラミング言語で作ろうとも変わりません。
仕組み、使用する関数などは違いますが、機能は同じになることでしょう。

 

記述は違えど、完成品は同じということです。スマホのアプリケーションを使うのに、どのプログラミング言語で作っているか?など気にしませんよね