プログラミング入門
第
7
回「状態遷移図によるシステムの記述」
講師
:
斉藤 賢爾
ks91@sfc.wide.ad.jp ∆ 棟 N205 2004 年度秋学期今日のメニュー
はじめに
前回のおさらい
課題レビュー
状態遷移図で描く
練習問題
:
ストップウォッチ
課題の出題
実習
はじめに
今週の配布物
みなさんのコメントから どこまで来たかな?
今週の配布物
次のものをみなさんに配布します Cricket 本体 × 1 個 (+電池) 赤外線インタフェース × 1 個 (+電池) シリアルケーブル × 1 本 モーター (グレイ: 中速, 赤: 低速) × 各 2 個 モーターケーブル × 2 本 4 桁ディスプレイ × 1 個 バスケーブル × 1 本 タッチセンサー × 1 個 光センサー × 1 個 反射センサー (距離センサー) × 1 個 授業が終わったら回収しますみなさんの
コメントから
1
すごく難しかったです
プログラムができなくて
blue
な気持ちになった
⇒
今日は、これまでのおさらい的な意味合いの授業です
今日の授業では、特に先週体験したマルチタスク処理を振り返ります その中で、新しい表現の技法を学びます PAD で考えるのは苦しい領域に入ってきています⇒
でも、スロットマシンを作るという問題自体は、みな
さんが思うほど難しくないのでは?
みなさんにとっては難しく見えた、というところがポイントだと思います 問題が難しく見えるというのは、どういうことなのか、この機会にちょっと考え問題には
適切な表現があります
15 ゲームTick-Tack-Toe (3 目並べ)
15
ゲーム
15
ゲーム
∼
ルール
1
2
3
4
5
6
7
8
9
1 から 9 までの数字が書かれた 9 枚の カードを用います 2 人でプレイします 交互に 1 枚ずつカードを選びます 一度選ばれたカードはもう選べません 選んだカードのうち、3 枚の合計が先に 15 になった方の勝ちです15
ゲーム
∼
やってみよう
1
2
3
4
5
6
7
8
9
A vs. B A-8 B-2 A-4 B-3 A-5 さぁ、B の次の手は?15
ゲーム
∼
正解は
. . .
1
2
3
4
5
6
7
8
9
A vs. B A-8 B-2 A-4 B-3 A-5 B-6 できたかな? A の次の手は?Tick-Tack-Toe (3
目並べ
)
Tick-Tack-Toe
∼
ルール
○
×
井型を描きます 2 人でプレイします 9 つのスペースの中のどれかに、交互 に ○/× を描きます 自分の描いた記号が先に 3 つ並んだ方 の勝ちですTick-Tack-Toe
∼
やってみよう
○
○
×
×
×
A(×) vs. B(○) さぁ、B の次の手は?Tick-Tack-Toe
∼
正解は
. . .
○
○
○
×
×
×
A(×) vs. B(○) A の次の手は?p
問題と表現
問題を解くということは ⇓
p
問題と表現
問題を解くということは ⇓
みなさんの
コメントから
2
頭がこんがらがってしまったので、解いてからもう一
度やります
⇒
ぜひ、そうしてみてください
問題を解くということは、問題の表現を作るということですが、みなさんはその ための表現技法を、すでにひとつ学んでいますそれは PAD (Problem Analysis Diagram; 問題分析図) です 整理して問題を表現すると、こんがらがった頭も解けます
もしかしたら、みなさんは PAD を忘れているかも知れませんので、おさらいし ましょう
PAD
、おぼえてますか
連接、選択、反復だけの世界
p
PAD
のおさらい
∼
連接
意味 形 例 連接 処理 1 処理 2 朝食を作る 朝食を食べる Logo(Blocks) では、ふつうの文 (ブロック) を縦に並べることに対応しています ある処理をしてから次の処理を行なうことを示しますp
PAD
のおさらい
∼
選択
意味 形 例 選択 条件EE
真の場合の処理 偽の場合の処理 投げたコインが表
EE
牛丼を食べる 寿司を食べる Logo(Blocks) では、if や ifelse に対応しています 条件に応じて、ふたつの候補のうちどちらかの処理が選ばれることを示します
p
PAD
のおさらい
∼
反復
意味 形 例
反復
条件 反復する処理 満腹でない 一皿食べる
Logo(Blocks) では、repeat, loop, waituntil に対応しています 条件が成立している間、処理を繰り返すことを示します
PAD
クイズ
p
PAD
クイズ 第
1
問
電車に乗ってない [1] 電車が来てない [2] 何もしない [3] 電車が混んでる [4]EE
やり過ごす [5] 各駅停車だ [6]
EE
やり過ごす [7] 電車に乗る [8] (1) ある人物 A がこのアルゴリズムを実行したとします。アルゴリズムの実行が終了した 直後の A の状態を最もよく表すものを選んでください。 (a) 電車に乗っている (b) 電車に乗っていない (c) 電車に乗っていることがある (d) A の状態については何も言えない
p
PAD
クイズ 第
2
問
電車に乗ってない [1] 電車が来てない [2] 何もしない [3] 電車が混んでる [4]EE
やり過ごす [5] 各駅停車だ [6]
EE
やり過ごす [7] 電車に乗る [8] (2) 次の順序で電車が来た場合、[5] は何回実行されますか。 1. 混んでいる各駅停車 2. 混んでいない各駅停車 3. 混んでいる急行 4. 混んでいない急行 5. 混んでいる各駅停車
p
PAD
クイズ 第
3
問
電車に乗ってない [1] 電車が来てない [2] 何もしない [3] 電車が混んでる [4]EE
やり過ごす [5] 各駅停車だ [6]
EE
やり過ごす [7] 電車に乗る [8] (3) このアルゴリズムの実行を開始してから A が電車に乗るまでに [7] が 2 回だけ実行さ れ、A が乗った電車を含めて 4 本の電車が A のいたプラットフォームに到着したと します。その間、1 度だけ実行されたと確実に言えるのは [1]∼[8] のどれでしょうか。 すべて答えてください。
p
PAD
クイズ 第
4
問
電車に乗ってない [1] 電車が来てない [2] 何もしない [3] 電車が混んでる [4]EE
やり過ごす [5] 各駅停車だ [6]
EE
やり過ごす [7] 電車に乗る [8] (4) 設問 (3) で、1 度だけ実行された可能性がありますが、確実にそうとは言えないのは [1]∼[8] のどれでしょうか。すべて答えてください。
p
PAD
クイズ 第
5
問
電車に乗ってない [1] 電車が来てない [2] 何もしない [3] 電車が混んでる [4]EE
やり過ごす [5] 各駅停車だ [6]
EE
やり過ごす [7] 電車に乗る [8] (5) 次のうち、A が踏んだステップとしてあり得ないものをひとつ選んでください。 (a) [1]→ [2]→ [4]→ [6]→ [8] (b) [1]→ [2]→ [3]→ [2]→ [3]→ [4]→ [6]→ [8] (c) [1]→ [2]→ [3]→ [2]→ [3]→ [2]→ [4]→ [5]→ [1]→ [2]→ [4]→ [6]→ [8] (d) [1]→ [2]→ [4]→ [5]→ [1]→ [2]→ [4]→ [6]→ [7]→ [1]→ [2]→ [4]→ [6]→ [8]
p
PAD
クイズ 第
6
問
電車に乗ってない [1] 電車が来てない [2] 何もしない [3] 電車が混んでる [4]EE
やり過ごす [5] 各駅停車だ [6]
EE
やり過ごす [7] 電車に乗る [8] (6) このアルゴリズムを実行した A は何をしたかったのか、できるだけ詳細に説明してく ださい。
みなさんの
コメントから
3
スロットマシンをつくる課題は制約
(
全体的な流れをす
でに決められていた
)
がありすぎでした
最初から最後まで自分でプログラムを組むほうがよい
と思いました
⇒
それは一理ありますね
でも、プログラミングの本当の力は、他人のプログラムを読めるかなのです 外語といっしょで、自分で喋るなら、言いたいことを言えばよいだけですが、 他の人と会話する場合は、相手の言うことを理解する必要があります そのときに、言葉の本当の力はつくのです 今日は、中間的に、ひとつのテーマとガイドラインに沿って、最初から最後ま で、ストップウォッチのプログラムを自分で作ってくださいどこまで来たかな
?
第 1 回 9/29 Cricket 入門 第 2 回 10/ 6 フローチャートで理解する 第 3 回 10/13 PAD によるアルゴリズムの表現 第 4 回 10/20 簡単なルールで動くロボットの制作 第 5 回 10/27 手続きと段階詳細化 第 6 回 11/10 例外と簡単なマルチタスク処理 第 7 回 11/17 状態遷移図によるシステムの記述 第 8 回 12/ 1 Cricket における赤外線通信 第 9 回 12/ 8 プロデューサ/コンシューマモデルによる設計 第 10 回 12/15 データの収集と利用 第 11 回 12/22 デザインワークショップ I ∼ 設計と実装 第 12 回 1/10 デザインワークショップ II ∼ テストしよう 第 13 回 1/17 デザインワークショップ III ∼ 発表今日のゴール
イベントに反応するシステムを設計できるようになる
基本的には、前回と同じことを行ないます
新しいツールとして、
状態遷移図
というものを使い
ます
システムを表現する図の描き方です
状態遷移図は、コンピュータのプログラムはもちろ
ん、家電製品や、さまざまな機械、組織の振る舞い
を整理して考えるために役立ちます
よく見ると、マニュアルなどでも使われています
今日の体験メニュー
次の練習問題や課題で体験します
1.
ストップウォッチを作ってください
(
練習問題
)
2.
身の回りにあるシステム
(
機械や組織など
)
をひと
つ例にとり、状態遷移図で記述してください
(
課題
)
今日は、練習問題を中心に進めます
課題に費やす時間は
15
∼
30
分を目標にします
(
ほぼ
宿題だと思ってください
)
真ん中で休憩を一回、とります
今日のメニュー
はじめに
前回のおさらい
課題レビュー
状態遷移図で描く
練習問題
:
ストップウォッチ
課題の出題
実習
前回のおさらい
Cricket における例外とマルチタスク処理p
例外とは
例外
(exception)
プログラムの実行中に、例外的な状況が発生して、それ以上そのまま実行を続け られなくなること 実行は中断して、例外処理を行ないます 例: 何かの数を 0 で割った場合 (Cricket では結果を 0 にします) Cricket では、例外の条件をプログラマが自由に定義できます例外処理
プログラマが自分で定義できます 例外処理が終わると、中断したところからプログラムの実行が再開します プログラムに対する割り込み処理だと考えられます 何か変なことが起こったら割り込んでプログラムの実行を中断し、事態を収 拾してからプログラムの実行を再開しますp
身近な例外と例外処理
http://www.jfa.or.jp/laws/ill_f.html ファウルが起こったら警告される ファウルの対処にもルールがある ルール = プログラム ルールはプログラマが決めるp
マルチタスクとは
1
マルチタスク
(multitask)
1 台のコンピュータで複数の作業 (タスク) を同時に処理すること プロセッサ (中央処理装置) がひとつしかないコンピュータでは、細かい時間で タスクを切り替えて、複数、同時に処理しているように見せかけますパソコンもマルチタスク処理を行なっています
ただし、みなさんがマルチタスクを実感するのは、大抵、複数のアプリケーショ ン (メーラや Web ブラウザなど) を実行しているときです それぞれの処理は独立していて、みなさんの頭の中で関係づけられています 複数のタスクが協調してひとつの目的を達成するという、マルチタスクの醍醐味 みたいなものは分かりにくいと思います今日は、マルチタスクの醍醐味を体験してください
といっても、Cricket は簡単なマルチタスク処理しかできませんから、簡単な例 で体験してもらうことになりますp
マルチタスクとは
2
電波の受信 電波強度の監視 着メロ再生 伝言再生 アニメーション再生 ボタン操作受け付け 電池残量の監視 例: 携帯電話 さまざまなタスクが同時に動い て携帯電話を実現しています もし、ひとつの処理の流れとし て書こうとすると . . . とても複雑になります 反応が遅くなります 優先順位の高いタスクは、他のタ スクに割り込むことができます 伝言を再生しているときに着 信があったら、伝言の再生を 中断して着メロを再生します 着メロの再生中に受信ボタン が押されたら、着メロの再生 を中断して通話を始めますL
Cricket
での
o
例外
/
マルチタスク処理
Cricket
では、例外とマルチタスク処理をひとつの機構
で実現しています
例外
/
マルチタスク処理を記述するには
. . .
(when)
ブロックを用います
if ブロックと同じように、条件と、条件が真のときの処理を書けます 条件が真になるまで待ち、真になると通常の処理に割り込みます · 条件が偽から真に変わる、エッジを検出します 処理が終了すると、通常の処理が割り込まれた場所から再開しますwhen
ブロックは
loop
より前で使う必要があります
when ブロックを使用する箇所で、例外/マルチタスク処理を定義して、それ を有効にしていると考えてくださいwhen
ブロックの使用には制限があります
L
時間の経過を判定する
o
(
タイマを使う
)
タイマをリセットするには
. . .
(resett)
ブロックを使います
resett は reset timer の略です
↓ の timer の値を 0 にして、タイマを開始します
タイマがリセットされてからの時間の経過を測るため
には
. . .
(timer)
ブロックを使います
1 1000 秒 (1 ミリ秒) の単位で、時間の経過を表します 数値ブロックが使える場所で使えます↑はブロックですが、
Cricket Logo
でも同じですね
今日のメニュー
はじめに
前回のおさらい
課題レビュー
状態遷移図で描く
練習問題
:
ストップウォッチ
課題の出題
実習
課題レビュー
課題をふりかえる 提出状況と傾向・総評 今週の Thumb Up!
課題
6.
機敏な自律ロボッ
トかスロットマシン
センサーが感知する周囲の変化に機敏に反応し、何ら
かの形で人間に伝えるロボットを作ってください
条件: センサー/アクチュエーターは自由に使ってください Cricket Logo で記述し、手続きとマルチタスクを使用してください 注釈で、どんなプログラムなのかを説明する文章を添えてください どのポートに何をつけるかも注記してください各自の課題
4.
のプログラムを元にするとよいでしょう
あるいは、授業の練習問題のスロットマシンを完成さ
せて提出してください
提出状況と傾向
19
人中
5
人提出
(SOI
学生含む
)
傾向と総評
ひとりしか完成させることができませんでした ヒントがあり過ぎたせいかも知れませんが、考える時間が足りなかった人が多い ようです 授業では、最後にはホワイトボードに PAD を描いたので、本当は、みんな作 れたはずだと思います ほとんど PAD = Logo だからです もしかしたら PAD のレベルでの理解が不足しているのではないかと思い、今 日は PAD のおさらいをしました 今日は、問題を整理して表現し、自然にプログラムを導いていく手法を紹介し ます今週の改善点
Thumb Up!
のとき、フルネームを表示しないようにし
ました
また、スライドのタイトルにみなさんの名前が現れ
ないようにしました
みなさんのプライバシーを保護する施策の一環です
SOI
では、これからもみなさんのプライバシーを守
りつつ、インターネットを用いた知の共有のあり方
を探求していきますので、みなさんもぜひ、ご協力
ください
今週の
Thumb Up!
1
植木さんの作品
とりあえず、出来たということが素晴らしいです あとは、人間にとって読みやすいプログラムを書くことを心がけましょう 字下げ (indentation) を活用しましょう 注釈も書きましょう (少なくとも手続きとその引数と戻り値の意味) 字下げについては、このマテリアルでの書き方を参考にしてください PAD が右に伸びるような場合、1 段下げて書きます このマテリアルでは、スペースの都合上、注釈はほぼ省略しています その代わり、ではないですが、プログラムの意味の説明はしています今日のメニュー
はじめに
前回のおさらい
課題レビュー
状態遷移図で描く
練習問題
:
ストップウォッチ
課題の出題
実習
状態遷移図で描く
p
状態遷移図の例
・腕時計のストップウォッチ機能 の使い方です ・ボタンを押すと、状態が変わる 様子を描いています ・状態に応じて、ボタンは 違った意味を持ちます 計測を始めます 計測をストップ します ラップタイム を表示します 計測をストップ します 計測を再開 します 計測を再開 します リセットします 計測中 ラップタイム ラップタイム 計測 時間 基準時間 ラップタイム をクリアしますp
状態遷移図とは
物の一生を絵で描きます
前ページの絵よりも簡略化した図形で描きます 物の状態がどう変化していくかに注目します ○の中にその状態を表す言葉を書いて、状態を表します 実は形は何でもよいのですが、□だと PAD と混乱するかも知れないので、こ の授業では状態を○で表すことにします どんなイベントでどのように状態が変化するかを考えます S→T で状態 S から状態 T への遷移を表します 矢印の上にイベントの説明を書きます物について理解する上で役立つツールです
どのくらい役立つか、ということを表すエピソードを紹介すると . . .p
ペットボトルの
o
状態遷移図
空
空で
ない
・現在入っている量に注目 ・売ったり捨てると所有者が変わるので、製造する
リサイクルする
現在の量
>
0
現在の量
==
0
飲む
飲む
捨てる
売る
存在して
いない
p
状態遷移図の考え方
描き方
物 (この授業の場合は Cricket) に注目 物に何が起こるかな? それによって、物の状態はどう変わるかな? 物の状態 = 変数の組が持つ値の範囲 · 例: ペットボトルの状態 = < 現在の量, 所有者 > デジタルコンピュータのプログラミングの本質は、表現したい物を、デジタ ル (=数値表現) な変数の組として捉えることですイベントの説明の書き方
この授業では次のように書くことにします イベント → 処理スロットマシンの例で
見てみましょう
p
やってみよう
1
から
9
までの数字を
3
桁、揃えるスロットマシンを
作ってください
ハードウェアの構成
タッチセンサー (スイッチ) をセンサーポート a につなぎます 4 桁ディスプレイをバスポートにつなぎます使い方
(
仕様
)
1. スイッチを押すと、4 桁ディスプレイに 3 桁のデタラメな数が表示され、め まぐるしく変化します 2. 1 秒ごとに、次のことが起きます 1 の位、10 の位、100 の位の順に数字が確定していきます ビープ音が鳴ります 3. 数が 3 つ揃ったらあなたはラッキー! 4. 何度でも繰り返し遊べますp
スロットマシンの
o
状態遷移図
100の位まで
決まっている
10の位まで
決まっている
1の位が
決まっている
すべての位が
決まってない
ボタン →開始 1秒経過 →1の位を決める 細かな時間 →回す 細かな時間 →回す 細かな時間 →回す 1秒経過 →10の位を 決める 1秒経過 →100の位を 決める ボタン→停止動いて
いない
p
方針を決める
状態遷移図をブレイクダウンしていく方針を考えます
状態はどんな変数で表されるかを考えます
確定された数が状態を表していますふたり
(when/run
タスク
)
で実行することを考えます
when タスクは次のことを行ないます 1 秒経過するのを待ち構えます 1 の位から順に、リールの数を確定します 100 の位まで確定したら、数を表示して、スイッチが押されるのを待ちます run タスクは次のことを行ないます まず、スイッチが押されるのを待ちます それから、スロットマシンのリールをめまぐるしく表示させます ふたつのタスクの間でやりとりされる情報は? when タスクから run タスクへ、確定された数が伝わる必要があります when タスクと run タスクは状態を共有するということですね変数で状態を表現する
fixed:
確定されたリールに表示されている数
確定していないリールに対応する桁の数字は
0
とし
ます
例
: 000
→
001
→
021
→
321
→
000
when
タスクが
fixed
の値を更新し、
run
タスクはその
値を読みます
when
タスクは
1
秒ごとに
fixed
の値を更新します
run
タスクは、
fixed
で確定していない桁にランダ
ムな数字を割り当てて、ディスプレイに表示するこ
とを繰り返します
p
スロットマシンの
o
状態遷移図
100の位まで
決まっている
fixed
>
100
10の位まで
決まっている
fixed
<
100
1の位が
決まっている
fixed
<
10
すべての位が
決まってない
fixed
<
1
ボタン →開始 スイッチ →リール回転 1秒経過 →1の位を決める 細かな時間 →回す 細かな時間 →回す 細かな時間 →回す 1秒経過 →10の位を 決める 1秒経過 →100の位を 決める ボタン→停止動いて
いない
p
when
タスクの
o
状態遷移図
タイマ待ち
スイッチ待ち
タイマ待ち
タイマ待ち
タイマ タイマ →10の位を決める, ビープ, タイマリセット タイマ →100の位を決める, ビープ, 結果表示 スイッチ →タイマリセット ・基本的にはタイマを待つ ・タイマが発火したら、今の状態に応じて 数を決める ・100の位まで決まったらスイッチを待つ このとき run タスクは止めておくfixed
<
1
fixed
<
10
fixed
<
100
fixed
>
100
p
run
タスクの
o
状態遷移図
スイッチ待ち
割り込み処理
(when
タスク)
完了待ち
実行中
スイッチ →タイマリセット, 細かな時間経過 →決まっていない桁は でたらめな数を表示 タイマ 割り込み処理 完了 ・基本的には表示し続ける ・when タスクに割り込まれることがあるp
トップレベル
run = when 起動 初期化 ¬スイッチ押下 何もしない タイマリセット リールの回転 when = loop ¬1秒経過 何もしない 経過処理L
トップレベル
global [fixed values]
to run when [timer > 1000][ processElapsed ] setfixed 0 waituntil [switcha] resett spinReels end when 文で 1 秒経過するのを待ち構え て processElapsed を実行します タイマは、スイッチが押されるまで開 始しません 変数の使い方は次の通りです fixed: 確定されたリールに表示さ れている数 確定していないリールに対応 する桁の数字は 0 とします 例: 000 → 001 → 021 → 321 → 000 values: スロットマシンのリール に表示する 3 桁の数 本当は、なくても作れなけれ ばなりませんが、Cricket Logo の不具合から必要と
p
processElapsed
の
o
デザイン
1
秒経過するごとに呼び出される手続きです
リールに表示される数を確定することがゴールです
次を行ないます
fixReels を呼び出し、確定されたリールの値を求め、fixed に格納します ビープ音を鳴らします fixed の値が 3 桁とも決まったら . . . fixed の値を表示します · 3 桁揃ったらファンファーレ、のようなことをしてもよいですね スイッチが押されるまで待ちます fixed の値を初期化します タイマをリセットしますL
解答例
:
o
processElapsed
to processElapsed fixReels beep if fixed > 100 [ display fixed waituntil [switcha] setfixed 0 ] resett end 1 秒経過するごとに呼び出される手続 きです fixReels により fixed の値を求めます fixed が 100 の位まで求まっていれ ば、結果を表示します 10 の位まで求まっている際の fixed の最大値は 99、100 の位ま で求まっている際の fixed の最小 値は 111 なので、例えば 100 と の比較を行なえば十分ですp
fixReels
のデザイン
processElapsed
から呼び出される手続きです
確定するリールの値を
fixed
に格納することがゴール
です
次を行ないます
fixed の現在の値に応じて、確定するリールの値を決めて fixed に入れます fixed が 0 なら、1 の位の値を決めます 1 の位が決まっていたら、10 の位の値を決めます 10 の位が決まっていたら、100 の位の値を決めますL
解答例
: fixReels
to fixReels
; 下 1 桁を確定します。
ifelse fixed < 1 [
setfixed getFixedValue 1 ][
; 下 2 桁までを確定します。
ifelse fixed < 10 [
setfixed (getFixedValue 10) + fixed ; 3 桁とも確定します。
][
setfixed (getFixedValue 100) + fixed ]
] end
p
spinReels
のデザイン
run
タスクの主要な仕事を行なう手続きです
リールを表示し続けることがゴールです
次をひたすら繰り返します
getReelValues を呼び出してリールの値を求め、values に格納します values を表示します※ 直接
getReelValues
の戻り値を表示させるようにする
と、
when
による割込みがうまく働かないようです
L
解答例
: spinReels
to spinReels loop [
setvalues getReelValues fixed display values ] end run タスクの主要な仕事を行なう手続きです ひたすらリールを表示し続けます processElapsed の処理中は処理が停止します
今日のメニュー
はじめに
前回のおさらい
課題レビュー
状態遷移図で描く
練習問題
:
ストップウォッチ
課題の出題
実習
練習問題
:
ストップウォッチ
この練習問題のねらい 状態遷移図で表現することを練習します 状態遷移図からのブレイクダウンによる設計を体験します やってみよう 状態遷移図を描こう 方針を決めよう PAD に落そう Cricket Logo に写そうp
やってみよう
1
レベル
1:
10
1
秒単位で時間を測るストップウォッチを
作ってください
レベル
2:
ラップタイム計測機能を付けてください
レベル
1
だけでもよいです
次ページ以降では、赤い文字はレベル
2
を表してい
ます
できるだけ、レベル
2
にチャレンジしましょう
p
やってみよう
2
ハードウェアの構成
タッチセンサー (スイッチ) をセンサーポート a につなぎます タッチセンサー (スイッチ) をセンサーポート b につなぎます 4 桁ディスプレイをバスポートにつなぎます使い方
(
仕様
)
1. ボタンを押すと、0 が表示されます 2. スイッチ a を押すと、4 桁ディスプレイに 101 秒単位で経過時間が表示されます このとき、スイッチ b を押すと、そのときの時間が止まって表示されます この間、時間の計測は続いています 再びスイッチ b を押すと、経過時間の表示に戻ります 3. 再びスイッチ a を押すと、そのときの時間が止まって表示されます 4. このとき、もう 1 度スイッチ a を押すと、時間の計測を再開します 5. そうではなく、スイッチ b を押すと、0 が表示され、2 に戻ります本物を見て確かめよう
⇒
ここでスライドを
止めてください
ストップウォッチの状態遷移図を描いてみよう 最初はレベル 1 から始めるとよいでしょう
p
ストップウォッチの
o
状態遷移図
0が表示 されている 計測された 時間が表示 されている 経過時間が 表示されて いる ボタン →開始, 0を表示 スイッチ a →計測開始 1/10秒 →更新, 表示 スイッチ a →計測 時間表示 スイッチ a →計測再開 スイッチ b →0を表示 ボタン→停止 動いて いないp
ストップウォッチの状
o
態遷移図
(
ラップ付き
)
0が表示 されている 計測された 時間が表示 されている 経過時間が 表示されて いる ラップタイム が表示されて いる (1) ラップタイム が表示されて いる (2) ボタン →開始, 0を表示 1/10秒 →更新, 表示 1/10秒 →更新 スイッチ a →計測 時間表示 スイッチ a →計測停止 スイッチ a →計測再開 スイッチ a →計測再開 スイッチ b →0を表示 ボタン→停止 動いて いない スイッチ b →表示 スイッチ b →計測時間表示ここでスライドを
止めてください
ブレイクダウンする方針を考えてみよう 状態は、どのような変数 (の組) で表せるでしょうか イベントを 2 種類に分けて、when/run タスクにそれぞれ任せましょう when タスクの方が、緊急に対処すべきイベントを受け付けるようにしますp
方針を決める
どのような変数が必要かを考えます
計測中の時間を表現できる必要があります 現在、計測中かを区別できる必要があります 現在、ラップタイムを表示しているかを区別できる必要があります ラップタイム自体の値も必要なので、ラップタイムを表す変数の値に意味を もたせる (例: ゼロ = 表示していない) ことで区別できますふたり
(when/run
タスク
)
で実行することを考えます
when タスクは、応答性が高い必要のあるイベントを待つことにします スイッチが押されるのを待ち構えて処理します run タスクは、その他のイベントを待つことにします 時間の経過を待ちますここでスライドを
止めてください
when タスクと run タスクの状態遷移図を描いてみようp
when
タスクの
o
状態遷移図
スイッチ待ち (ゼロ表示) スイッチ待ち (結果表示) スイッチ待ち (経過表示中) スイッチ待ち (ラップタイム 表示中 1) スイッチ待ち (ラップタイム 表示中 2) スイッチ a →結果表示 スイッチ a →計測停止 スイッチ a →タイマリセット スイッチ a →タイマ リセット スイッチ b →表示クリア スイッチ b →ラップタイム クリア スイッチ b →結果表示 ・基本的にはスイッチを待つ ・計測中か区別が必要 ・ラップタイムを表示しているか 区別が必要 ・計測中は run タスクに時間を 測ってもらう ・赤い部分は レベル2p
run
タスクの
o
状態遷移図
タイマリセット
待ち
割り込み処理
(when
タスク)
完了待ち
タイマ待ち
タイマ →計測中であれば タイマリセット, ラップタイム表示中 でなければ経過表示 タイマ →計測中でなければ何もしない スイッチ a スイッチ a スイッチ b スイッチ b 割り込み処理 完了 →表示クリア ・基本的にはタイマを待つ ・when タスクに割り込まれることがある ・スイッチ b が押されても 割り込まれるが、その影響はない ・赤い部分は レベル2ここでスライドを
止めてください
when タスクと run タスクのトップレベルの PAD を描いてみよう イベントへの対応を整理して考えましょう
基本的には状態で振り分けますが、スイッチ a への対応はラップタイムとは 独立しています
大雑把に考えましょう
p
run
タスクの
o
トップレベル
run = リセットする when 起動 時計機能 run タスクの本体は時計機能の手続きに任せることにします 実際に時間を測る手続きですp
when
タスクの
o
トップレベル
when = loop どちらも押されていない 何もしない ビープ音を鳴らす スイッチaが押されているE
EE
計測中
EE
計測を止める 計測を始める 計測中
EE
ラップタイム クリアする どちらかが押されている 何もしない
ここでスライドを
止めてください
PAD を詳細化して、手続きの中身の PAD を描いてみようp
リセットする
resetW atch = 計測を止める 時間をゼロにする ラップタイムをゼロにする 時間を表示する ストップウォッチを初期状態にする手続きです 時間をゼロにするので、最初に表示するのはゼロです ラップタイムがゼロのとき、ラップタイムが記録されていないことを示すことにし ますp
時計
doClockwork = loop 1/10 秒経過した 何もしない ¬ 1/10 秒経過した 何もしない 時間を計測中EE
タイマリセット 時間を増やす ラップがゼロ
EE
時間を表示する 1 10 秒ごとの時間の経過を測る手続きです 最初の waituntil がないと、どうなるでしょうか なくても動作はします
p
計測を始める
startW atch = 計測中であることにする タイマをリセットする 時間の計測を始める手続きです 計測中かどうかを区別する変数の値を設定します 計測中なら、タイマを使うことになりますので、タイマをリセットします この時を基点として時間を測り始めます 計測をいったん止めて、再開するときも大丈夫か、頭の中で確かめましょうp
計測を止める
stopW atch = 計測中でないことにする 時間の計測を止める手続きです 計測中かどうかを区別する変数の値を設定します 次のタイマ割込み時に、タイマをリセットしないようにしなければなりませんが、そ れは doClockwork の仕事ですp
ラップタイム
processLap = ラップタイムが記録されていないEE
ラップタイムを記録する 記録した時間を表示する ラップタイムをゼロにする ラップタイムを記録したりクリアする手続きです 計測中の処理です ラップタイムがゼロのとき、ラップタイムは記録されていません ラップタイムをゼロにすると、doClockwork が経過時間を表示するようにな ります ラップタイムは、現在、測っている時間を代入することで記録できます
p
クリアする
clearW atch = ラップタイムが記録されていないEE
リセットする 現在の時間を表示する ラップタイムをゼロにする ストップウォッチをリセットしたり、ラップタイムをクリアする手続きです 計測停止中の処理です ラップタイムが記録されていないなら、リセット動作をします ラップタイムが記録されているときは、計測時間の表示に戻ります 計測が止まっているので、doClockwork に表示してもらうことはできません
ここでスライドを
止めてください
Cricket Logo でプログラムを組み立ててみようL
トップレベル
global [elapsed lap moving] to run
resetWatch
when [switcha or switchb][ processPressed ] doClockwork end to false output 1 = 0 ; 偽を表します end to true output 1 = 1 ; 真を表します end 変数の意味を次のように決めます elapsed: 101 秒単位で計測してい る時間 lap: ラップタイム moving: 計測中かどうか どちらかのスイッチが押されるのを待 ち構える when タスク (中身は手続き processPressed) を起動します false/true は、定数の代わりに用意し た手続きです setmoving true のように書け ます
L
processPressed
to processPressed beep ifelse switcha [ ifelse moving [ stopWatch ][ startWatch ] ][ ifelse moving [ processLap ][ clearWatch ] ] スイッチによる割込みを処理する手続 きです 押されたのがどちらのスイッチかに よって機能を動かします スイッチ a だったら計測を開始 /停止します スイッチ b だったらクリア/ ラップタイムの処理をしますL
resetWatch
to resetWatch stopWatch setelapsed 0 setlap 0 display elapsed end ストップウォッチを初期状態にする手 続きです 計測を止めます すでに計測が止まっている場合 もこの手続きは呼ばれることが あります stopWatch は何度続けて呼ばれ ても大丈夫なように書かれてい ます 時間とラップタイムをゼロにします 4桁ディスプレイには0 が表示されますL
doClockwork
to doClockwork loop [ waituntil [timer < 100] waituntil [timer > 100] if moving [ resettsetelapsed elapsed + 1
if lap = 0 [ display elapsed ] ] ] end 1 10 秒ごとの時間の経過を測る手続き です まずタイマをリセットします (誤 差をできるだけ小さくするた めに) 時間を増やします ラップタイムが記録されていなけ れば、現在の時間を表示します 最初の waituntil で、計測停止中の無 駄な処理を抑えています 100 の代わりに 88 と比較すると、実 際の 101 秒とほぼ同じになります
L
start/stopWatch
to startWatch
setmoving true resett
end
to stopWatch
setmoving false end 時間の計測を始める/止める手続きです 計測中かどうかを設定します 計測中になるということは、タイマを 使うということですから、タイマをリ セットします そのときを基点として計測が始 まります
L
processLap
to processLapifelse lap = 0 [
setlap elapsed display lap ][ setlap 0 ] end ラップタイムを記録したりクリアする 手続きです 計測中の処理です ラップタイムが記録されていな ければ ラップタイムを記録して表示 します ラップタイムが記録されていれば ラップタイムをクリアします
L
clearWatch
to clearWatch ifelse lap = 0 [ resetWatch ][ display elapsed setlap 0 ] end ストップウォッチをリセットしたり、 ラップタイムをクリアする手続きです 計測停止中の処理です ラップタイムが記録されていな ければ リセットします ラップタイムが記録されていれば ラップタイムをクリアして、 現在の時間を表示します今日のメニュー
はじめに
前回のおさらい
課題レビュー
状態遷移図で描く
練習問題
:
ストップウォッチ
課題の出題
実習
課題の出題
課題 7. 身の回りのシステムを描く 提出方法