2019年 春期 応用情報技術者試験 問3
券売機の注文の状態を判定するプログラム
T社では、U社が経営する飲食店の店舗に設置する券売機のシステムを開発している。U社が店舗で提供する商品には、丼物や定食などのメイン商品のほか、みそ汁やサラダなどのサイドメニューがある。
U社では、特定の種類の商品を組み合わせたものをセットメニューとし、単品で注文した場合よりも安く提供している。
【食券購入時の要件】
食券購入時の主な要件を図1に示す。
【食券購入時の操作の流れ】
- 利用者は、券売機の画面上に表示されるボタンを押すことで食券を購入する。
- 食券の購入は1名ずつ行う。
- 利用者は、購入したい全ての商品を指定後、合計金額を投入し、発券ボタンを押す。
【メニューの構成】
- 商品はメイン商品、サイドメニュー1、サイドメニュー2、オプションに分類される。商品には、サイズやドレッシングの種類など、オプションの指定が必須なものがある。
- メイン商品は必ず1品注文する必要がある。サイドメニューの注文は任意である。
- メイン商品1品に対し、サイドメニューは複数注文することができる。
- 券売機の画面は、メイン商品の選択画面、サイドメニュー1の選択画面、サイドメニュー2の選択画面の順に遷移する。サイドメニュー1を注文しない場合は、サイドメニュー1の選択画面での注文をスキップできる。オプションは、オプションの指定が必須な商品の選択画面で指定できる。
【発券ボタンの制御】
- 発券ボタンはメイン商品の注文後、任意のタイミングで押すことができる。ただし、オプションの指定が必須な商品でオプションが未指定の場合は、押すことができない。
【セットメニューの値引きのルール】
- セットメニューに適用できるメイン商品、サイドメニュー1、サイドメニュー2を、それぞれ1品以上選んだ場合、50円値引きする。値引きは食券購入ごとに1回だけ適用される。
商品と分類の具体例を表1に示す。表1中のNは分類番号、Sはセットメニューへの適用可否、Oはオプションの指定に関する情報である。Sは1のものがセットメ
分類名 | メイン商品 | サイドメニュー1 | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
分類番号 | 1 | 2 | ||||||||
商品 | 名称 | N | S | O | 価格 | 名称 | N | S | O | 価格 |
牛丼 | 1 | 1 | 1 | 380 | 野菜サラダ | 2 | 1 | 2 | 100 | |
豚丼 | 1 | 1 | 1 | 350 | ポテトサラダ | 2 | 1 | 2 | 130 | |
鮭定食 | 1 | 1 | 0 | 450 | 漬物 | 2 | 1 | 0 | 100 | |
− | − | − | − | − | 生卵 | 2 | 0 | 0 | 60 | |
− | − | − | − | − | 温泉卵 | 2 | 0 | 0 | 70 |
分類名 | サイドメニュー2 | オプション | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
分類番号 | 3 | 4 | ||||||||
名称 | N | S | O | 価格 | 名称 | N | S | O | 価格 | |
商品 | みそ汁 | 3 | 1 | 0 | 60 | 並 | 4 | 0 | 1 | 0 |
豚汁 | 3 | 0 | 0 | 190 | 大盛り | 4 | 0 | 1 | 100 | |
スープ | 3 | 1 | 0 | 200 | 特盛り | 4 | 0 | 1 | 200 | |
− | − | − | − | − | ゴマドレッシング | 4 | 0 | 2 | 0 | |
− | − | − | − | − | 和風ドレッシング | 4 | 0 | 2 | 0 |
ニューへの適用可の商品である。分類番号1〜3で、Oが0以外のものは、オプションの指定が必須であることを示し、Oの値は、分類番号4のOの値と対応している。オプションを指定する際には、Oの値が一致するオプションだけが選択できる。
【注文の状態の判定手順】
券売機は、画面上で商品を選択するボタンが押されるたびに、商品の情報を蓄積する。そして、蓄積した商品の情報を用いて状態遷移を初期状態から評価し直し、注文の状態を判定する。状態の判定には図2の状態遷移図を用いる。初期状態は0である。表1のN、S、Oを左から順に並べた3桁の数をイベントコードと呼び、イベントコードの値によって状態の遷移先を制御する。

注記2 メイン、サイド1、サイド2は、それぞれメイン商品、サイドメニュー1、サイドメニュー2を表す。
注記3 複数のイベントコードで同じ状態遷移をする場合は、イベントコードをカンマで区切って表記する。
状態の判定処理では、商品の情報を入力された順に取得し、状態遷移図に基づいて状態遷移を評価する。例えば牛丼、大盛り、漬物を注文した場合、状態は0、1、2、4の順に遷移する。この場合、最後の状態が発券可の状態なので、発券ボタンを押すことができる。また、値引きのルールの条件を満たさないので、値引きはしない。
【状態遷移表】
状態遷移図をプログラムとして実装するためには、状態遷移図を状態遷移表にして取り扱う。注文の状態遷移表を表2に示す。表2は、状態番号とイベントコードの組合せの表であり、表の各マスには遷移先の状態番号と、遷移の際の値引きの金額が入る。
例えば、図2で状態が2のときに漬物の注文が入ると状態4に遷移し、値引きは発生しないので、表2では、状態番号が2でイベントコードが210のマスには4:0が入る。遷移後の状態が発券可の状態なので、発券ボタンを押すことができる。
イベントコード | 発券可 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
110 | 111 | 200 | 210 | 212 | 300 | 310 | 401 | 402 | |||
状態番号 | 0 | 2:0 | 1:0 | E:0 | E:0 | E:0 | E:0 | E:0 | E:0 | E:0 | false |
1 | E:0 | E:0 | E:0 | E:0 | E:0 | E:0 | E:0 | 2:0 | E:0 | false | |
2 | E:0 | E:0 | 2:0 | 4:0 | 3:0 | 5:0 | 5:0 | E:0 | E:0 | true | |
3 | E:0 | E:0 | E:0 | E:0 | E:0 | E:0 | E:0 | E:0 | 4:0 | ア | |
4 | E:0 | E:0 | 4:0 | 4:0 | イ | 4:0 | 5:50 | E:0 | E:0 | true | |
5 | E:0 | E:0 | E:0 | E:0 | E:0 | 5:0 | 5:0 | E:0 | E:0 | true |
注記2 Eは想定しない遷移であることを意味する。
【券売機の注文の状態を判定するプログラム】
券売機の注文の状態を判定するプログラム(以下、判定プログラムという)を作成した。判定プログラムは、画面上で商品を選択するボタンが押されるたびに実行される。注文の状態を判定する手順を図3に示す。判定プログラム中で利用する主な変数、定数及び関数を表3に、作成した判定プログラムを図4に示す。
- 状態番号を0、注文金額を0、値引き金額を0として初期化する。
- 注文された商品を先頭から順に一つ参照し、商品の金額を注文金額に加算する。
- 注文された商品のイベントコードを算出する。
- 状態遷移表の路の値引きの金額を取得し、値引き金額に加算する。
- 状態遷移表を参照し、現在の状態番号とイベントコードから次の状態番号を取得して、状態番号を更新する。
- (5)で取得した次の状態番号がEだった場合は、エラー終了として処理を中断する。
- 未処理の注文が残っていれば(2)に戻って次の商品を処理する。
- 状態遷移表を参照し、発券の可否を判定して、発券ボタンの状態を変化させる。
名称 | 種類 | 内容 |
---|---|---|
status_table[stat][ev] | 配列 | 表2の注文の状態遷移表を格納した2次元配列である。statは遷移前の状態番号、evはget_event_index()で取得する値又はACCEPT_INDEXである。配列の要素は構造体で、status_table[stat][ev].statusで遷移先の状態番号を、status_table[stat][ev].discountで値引きの金額を、status_table[stat][ACCEPT_INDEX].acceptで、発券可の列の値を参照できる。 |
ACCEPT_INDEX | 定数 | 配列status_tableの、発券可の列のインデックス番号である。 |
get_event_index(code) | 関数 | codeにイベントコードを指定して実行すると、それに対応する、配列status_tableの列のインデックス番号を返す。codeは整数である。 |
order[ ] | 配列 | 注文された商品の情報が順番に入る配列である。商品の情報を格納する構造体を要素にもつ。i番目の注文については、order[i].N、order[i].S、order[i].O、order[i].Aで、それぞれ表1のN、S、O及び商品の金額を参照できる。配列の添字は1から始まる。N、S、O及び商品の金額は整数である。 |
order_count | 変数 | 注文された商品の数である。 |
status ← 0 // 状態番号 amount ← 0 // 注文金額 discount ← 0 // 値引き金額 accepted ← falsefor( i を 1 から order_count まで繰り返す ) amount ← amount + ウ event_code ← エ + order[ i ].O event_index ← get_event_index( event_code ) discount ← discount + オ status ← カ if( status が E に等しい ) エラー終了 endif endfor
accepted ← status_table[ status ][ ACCEPT_INDEX ].accept if ( キ ) 発券ボタンを押せるようにする else 発券ボタンを押せないようにする endif