状態遷移

状態遷移を使って簡単な(適当な)言語を進めるプログラム書きました。

# encoding: cp932

STATE_TRANSITION_TABLE = {
  "Q1" => ["Q1","Q2","Q3"],
  "Q2" => ["Q2","A1","Q4"],
  "Q3" => ["Q3","Q4","Q5"],
  "Q4" => ["Q4","A2","Q6"],
  "Q5" => ["Q5","Q6","A4"],
  "Q6" => ["Q6","A3","A5"],
}
MESSAGE = {
  "Q1" => "静(1)と動(2)ならどちらを選ぶ",
  "Q2" => "コーヒー党(1)?それとも紅茶当(2)?",
  "Q3" => "記号(1)と言語(2)どちらを選ぶ?",
  "Q4" => "カレーは大好き?もちろん(1) それほど(2)",
  "Q5" => "規律(1)と自由(2)どちらが重要?",
  "Q6" => "古いものに勝ちを見出すタイプ?はい(1) いいえ(2)",
  "A1" => "次はjavaを学習しましょう",
  "A2" => "Haskellがあなたを待っています",
  "A3" => "次はLispへ進みましょう",
  "A4" => "やっぱりRubyですね",
  "A5" => "Python"
}

state = "Q1"

while state[0] == "Q"
  puts(MESSAGE[state])
  state = STATE_TRANSITION_TABLE[state][gets().to_i] ||
          STATE_TRANSITION_TABLE[state][0]
end

puts(MESSAGE[state])

ここで指示通りに実行していくと、問題なく状態遷移してくれます。指示通りなら。例えば、実行結果を見ると

静(1)と動(2)ならどちらを選ぶ
6
静(1)と動(2)ならどちらを選ぶ
-1
記号(1)と言語(2)どちらを選ぶ?

状態Q1から始まります。1つめの入力は6です。でも、6なんて指示してないので状態は遷移せず同じ質問が繰り返されています。次は-1と入力。すると質問が「記号(1)と言語(2)どちらを選ぶ?」となりました。これは状態Q3です。STATE_TRANSITION_TABLEを見ると、 "Q1" => ["Q1","Q2","Q3"] です。-1を入力したことで、本来2の入力があった時の遷移状態Q3へ移動してしまってます。これは問題。

なので、-1など負の値を受け付けないように修正しました。puts(MESSAGE[state])の下に以下を追加しました。

  puts(MESSAGE[state])
  i = gets().to_i()
  if i<0 || i>= STATE_TRANSITION_TABLE[state].size
    i=0
  end

状態遷移の利点は、後に状態の追加や変更に対して配列の部分を修正するだけでいいこと。