2019年 春期 応用情報技術者試験 問3

券売機の注文の状態を判定するプログラム

T社では、U社が経営する飲食店の店舗に設置する券売機のシステムを開発している。U社が店舗で提供する商品には、丼物や定食などのメイン商品のほか、みそ汁やサラダなどのサイドメニューがある。

U社では、特定の種類の商品を組み合わせたものをセットメニューとし、単品で注文した場合よりも安く提供している。

【食券購入時の要件】

食券購入時の主な要件を図1に示す。

【食券購入時の操作の流れ】

  • 利用者は、券売機の画面上に表示されるボタンを押すことで食券を購入する。
  • 食券の購入は1名ずつ行う。
  • 利用者は、購入したい全ての商品を指定後、合計金額を投入し、発券ボタンを押す。

【メニューの構成】

  • 商品はメイン商品、サイドメニュー1、サイドメニュー2、オプションに分類される。商品には、サイズやドレッシングの種類など、オプションの指定が必須なものがある。
  • メイン商品は必ず1品注文する必要がある。サイドメニューの注文は任意である。
  • メイン商品1品に対し、サイドメニューは複数注文することができる。
  • 券売機の画面は、メイン商品の選択画面、サイドメニュー1の選択画面、サイドメニュー2の選択画面の順に遷移する。サイドメニュー1を注文しない場合は、サイドメニュー1の選択画面での注文をスキップできる。オプションは、オプションの指定が必須な商品の選択画面で指定できる。

【発券ボタンの制御】

  • 発券ボタンはメイン商品の注文後、任意のタイミングで押すことができる。ただし、オプションの指定が必須な商品でオプションが未指定の場合は、押すことができない。

【セットメニューの値引きのルール】

  • セットメニューに適用できるメイン商品、サイドメニュー1、サイドメニュー2を、それぞれ1品以上選んだ場合、50円値引きする。値引きは食券購入ごとに1回だけ適用される。
図1 食券購入時の主な要件

商品と分類の具体例を表1に示す。表1中のNは分類番号、Sはセットメニューへの適用可否、Oはオプションの指定に関する情報である。Sは1のものがセットメ

表1 商品と分類の具体例
分類名メイン商品サイドメニュー1
分類番号12
商品名称 NSO価格名称NSO価格
牛丼111380野菜サラダ212100
豚丼111350ポテトサラダ212130
鮭定食110450漬物210100
生卵20060
温泉卵20070
分類名サイドメニュー2オプション
分類番号34
名称NSO価格名称NSO価格
商品みそ汁310604010
豚汁300190大盛り401100
スープ310200特盛り401200
ゴマドレッシング4020
和風ドレッシング4020

ニューへの適用可の商品である。分類番号1〜3で、Oが0以外のものは、オプションの指定が必須であることを示し、Oの値は、分類番号4のOの値と対応している。オプションを指定する際には、Oの値が一致するオプションだけが選択できる。

【注文の状態の判定手順】

券売機は、画面上で商品を選択するボタンが押されるたびに、商品の情報を蓄積する。そして、蓄積した商品の情報を用いて状態遷移を初期状態から評価し直し、注文の状態を判定する。状態の判定には図2の状態遷移図を用いる。初期状態は0である。表1のN、S、Oを左から順に並べた3桁の数をイベントコードと呼び、イベントコードの値によって状態の遷移先を制御する。

図2 注文の状態遷移図
注記1 nは状態番号を表す。
注記2 メイン、サイド1、サイド2は、それぞれメイン商品、サイドメニュー1、サイドメニュー2を表す。
注記3 複数のイベントコードで同じ状態遷移をする場合は、イベントコードをカンマで区切って表記する。

状態の判定処理では、商品の情報を入力された順に取得し、状態遷移図に基づいて状態遷移を評価する。例えば牛丼、大盛り、漬物を注文した場合、状態は0、1、2、4の順に遷移する。この場合、最後の状態が発券可の状態なので、発券ボタンを押すことができる。また、値引きのルールの条件を満たさないので、値引きはしない。

【状態遷移表】

状態遷移図をプログラムとして実装するためには、状態遷移図を状態遷移表にして取り扱う。注文の状態遷移表を表2に示す。表2は、状態番号とイベントコードの組合せの表であり、表の各マスには遷移先の状態番号と、遷移の際の値引きの金額が入る。

例えば、図2で状態が2のときに漬物の注文が入ると状態4に遷移し、値引きは発生しないので、表2では、状態番号が2でイベントコードが210のマスには4:0が入る。遷移後の状態が発券可の状態なので、発券ボタンを押すことができる。

表2 注文の状態遷移表
イベントコード発券可
110111200210212300310401402
状態番号02:01:0E:0E:0E:0E:0E:0E:0E:0false
1E:0E:0E:0E:0E:0E:0E:02:0E:0false
2E:0E:02:04:03:05:05:0E:0E:0true
3E:0E:0E:0E:0E:0E:0E:0E:04:0
4E:0E:04:04:04:05:50E:0E:0true
5E:0E:0E:0E:0E:05:05:0E:0E:0true
注記1 各マスには、"遷移先の状態番号:値引きの金額"が入る。
注記2 Eは想定しない遷移であることを意味する。

【券売機の注文の状態を判定するプログラム】

券売機の注文の状態を判定するプログラム(以下、判定プログラムという)を作成した。判定プログラムは、画面上で商品を選択するボタンが押されるたびに実行される。注文の状態を判定する手順を図3に示す。判定プログラム中で利用する主な変数、定数及び関数を表3に、作成した判定プログラムを図4に示す。

  1. 状態番号を0、注文金額を0、値引き金額を0として初期化する。
  2. 注文された商品を先頭から順に一つ参照し、商品の金額を注文金額に加算する。
  3. 注文された商品のイベントコードを算出する。
  4. 状態遷移表の路の値引きの金額を取得し、値引き金額に加算する。
  5. 状態遷移表を参照し、現在の状態番号とイベントコードから次の状態番号を取得して、状態番号を更新する。
  6. (5)で取得した次の状態番号がEだった場合は、エラー終了として処理を中断する。
  7. 未処理の注文が残っていれば(2)に戻って次の商品を処理する。
  8. 状態遷移表を参照し、発券の可否を判定して、発券ボタンの状態を変化させる。
図3 注文の状態を判定する手順
表3 判定プログラム中で利用する主な変数、定数及び関数
名称種類内容
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 ← false

for( 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

図4 作成した判定プログラム
注記 判定プログラムがエラー終了となった場合は、券売機の画面上にエラーが発生した旨を表示し、処理を中断する。
出典:平成31年度 春期 応用情報技術者試験 午後 問3