自力でLチカ5〜コードは短く読みやすく〜
2024年7月5日(金)は、5割ほどの出席率でした。今回も、お休みが多い日でした。先週につづき、手厚いサポートが受けられるサービスデーです。前回に引き続き、RaspberryPi Pを使って7つのLEDをプログラミングします。
- 18時00分~18時20分 タイピング練習
- 18時20分~18時35分 マウス練習
- 18時35分~19時50分 7つのLチカ
- 19時50分~20時00分 あとかたづけ
Contents
タイピング練習とマウス練習
タイピングの練習は、「寿司打」、マウスの練習は「ソリティア」です。
- 寿司打
https://sushida.net - ソリティア(クロンダイク)
https://playingcards.jp/solitaire/klondike/
いよいよ、一回のクラブ活動で出せるわたしの最高スコアをこえるメンバーが出てきました。今回のわたしの最高スコアは「10320」。メンバーの最高スコアは「11080」。
これまで1000人以上にタイピングを教えていて、はじめて超えられました。このままだと、わたしの自己ベストを超えられるのも時間の問題でしょう。くやしいけれど、超えられたときの表彰を考えておかなければ!
LED7つを点灯させるサイコロプログラム制作に向けて
しばらく、7つのLEDを光らせるプログラミングに挑戦しています。そろそろサイコロを表示するプログラムの輪郭が見えてきました。
お題を再掲します。以下のとおりです。
- ブレットボードに配線する
- プログラムを作成する
○●●●●●●(LEDを1つ点灯する)
○○●●●●●(1秒後にLEDを2つ点灯する)
○○○○○○○(1秒後にLEDを7つ点灯する)
●●●●●●●(1秒後にLEDをすべて消灯する)
(1秒後に最初から繰り返し)
このお題をプログラミングすると以下のコードを書いてくれました。
from machine import Pin
import time
led1 = Pin(12, Pin.OUT)
led2 = Pin(13, Pin.OUT)
led3 = Pin(14, Pin.OUT)
led4 = Pin(15, Pin.OUT)
led5 = Pin(16, Pin.OUT)
led6 = Pin(17, Pin.OUT)
led7 = Pin(18, Pin.OUT)
while True :
led1.value(1)
time.sleep(1)
led2.value(1)
time.sleep(1)
led3.value(1)
led4.value(1)
led5.value(1)
led6.value(1)
led7.value(1)
time.sleep(1)
led1.value(0)
led2.value(0)
led3.value(0)
led4.value(0)
led5.value(0)
led6.value(0)
led7.value(0)
time.sleep(1)
プログラム初学者なら、これが書ければまずは合格といったところ。しかし、これでOKとしないところが、光都ICTクラブの厳しく、そして優れているところです。
今回は、このプログラムコードを改良していきます。
「表面上の仕様を満たしたら正解」ではない
メンバーにもさんざんぼろくそ言われたのですが、「(わたしが)はじめに示した仕様を満たしているからOKでしょ?」と、あなたも考えますか? たしかに表面上の要求仕様は満たしています。いちおう「正解」です。
ただ、前回も指摘したとおりこのプログラムコードは以下の弱点があります。
- 全体に冗長で読みにくい
- 変更に弱い
さらに、将来的に「サイコロの目をLEDで表示したい」とはじめたプログラミングです。このコードのままでは、使いにくそうです。
プログラムは、一旦動くコードが書けたとしても、さらによいコードが書けないか考えることが重要です。うごけばいい、という考え方だけでコードを書いていると、自分コードを改良する将来のあなたや、一緒に開発をしている仲間を地獄に叩き落すことになります。
サイコロプログラムに使える形に書き換える
そのあたり、地獄の一部を見せたあとで改良プログラムを書いてもらいました。
わたしが用意したサンプルプログラムは以下です。
from machine import Pin
import utime
pin_no = [12, 13, 14, 15, 16, 17, 18]
leds = [Pin(pin_no[i], Pin.OUT) for i in range(7)]
blink_pattern =[[1, 0, 0, 0, 0, 0, 0],
[1, 1, 0, 0, 0, 0, 0],
[1, 1, 1, 1, 1, 1, 1],
[0, 0, 0, 0, 0, 0, 0]]
def blinkLED(pattern):
for i in range(len(pattern)):
for j in range(7):
leds[j].value(pattern[i][j])
utime.sleep(1)
while True :
blinkLED(blink_pattern)
新しく出てきた機能を列挙すると「リスト(一次元、二次元)」「二重ループ」「リスト内包表記」「関数」です。このプログラムでは、以下の特徴(改良点)があります。
- 同じようなコードの繰り返しが減った(←よみやすくなった)
- LEDに接続するGPIOの番号をリスト(pin_no)であたえている(←変更に強くなった)
- LEDの点灯パターンをリスト(blink_pattern)であたえている(←変更に強くなった)
- LEDを点灯させるのを関数(blinkLED)にした(←ほかに活用しやすくなった)
さて、まったく同じ動作をする2つのプログラムを、あなたもぜひ入力して比べてみてください。
最初プログラムにダメ出しされてブツブツ言っていたメンバーも、わたしが用意したプログラムを入力して、コードの説明をすると応用をはじめました。
すぐに気持ちを切り替えて、プログラムに真剣になれるところが素晴らしいと思います。