#!/usr/bin/env python3
from random import randint
# メッセージ分離方式
メッセージ = { 'ようこそ' : '単語当てゲームへようこそ!' ,
'回数' : '挑戦回数は{}回です!' ,
'入力' : '1文字、入力してください: ' ,
'不正解' : '不正解!残りの挑戦回数: {}' ,
'正解' : '正解!現在の単語: {}' ,
'おめでとう' : 'おめでとう!単語は\' {}\' でした!\n {}' ,
'残念' : '残念!正解は\' {}\' でした。\n {}' ,
'終了' : 'ゲーム終了。' }
# 単語リスト
単語リスト = [ "banana" , "orange" , "apple" , "kiwi" ]
# 環境データ
class 環境( object ) :
__match_args__ = ( '問題' , '挑戦回数' , '状態' , '正誤' )
def __init__ ( self , 問題, 挑戦回数, 状態, 正誤) :
self .問題 = 問題
self .挑戦回数 = 挑戦回数
self .状態 = 状態
self .正誤 = 正誤
# デバッグ用
def __repr__ ( self ) :
return f'{self.問題} {self.挑戦回数} {self.状態} {self.正誤}'
# 環境の初期化
def 初期化( ) :
問題 = 単語リスト[ randint( 0 , len ( 単語リスト) - 1 ) ]
文字数 = len ( 問題)
env = 環境( 問題, 文字数, '_' * 文字数, None )
print ( メッセージ[ '回数' ] .format ( env.挑戦回数) )
return env
# 入力
def 入力( ) :
s = input ( メッセージ[ '入力' ] )
if s.isdecimal ( ) or len ( s) != 1 :
return 入力( )
else :
return s
# 評価
## ユーザー定義例外
class GameOverSuccess( Exception ) :
def __init__ ( self , 引数) :
self .引数 = 引数
def __str__ ( self ) :
return メッセージ[ '正解' ] .format ( self .引数)
class GameOverFail( Exception ) :
def __init__ ( self , 引数) :
self .引数 = 引数
def __str__ ( self ) :
return メッセージ[ '不正解' ] .format ( self .引数)
def 評価( x, env) :
match env:
case 環境( 問題, 挑戦回数, 状態, 正誤) if x in 問題:
状態 = [ i if i == x else j for i, j in zip ( 問題, 状態) ]
if '_' not in 状態:
raise GameOverSuccess( 状態)
else :
return 環境( 問題, 挑戦回数, 状態, True )
case 環境( 問題, 挑戦回数, 状態, 正誤) :
挑戦回数 -= 1
if 挑戦回数 == 0 :
raise GameOverFail( 挑戦回数)
else :
return 環境( 問題, 挑戦回数, 状態, False )
# 出力
def 出力( env) :
match env:
case 環境( 問題, 挑戦回数, 状態, 正誤) if 正誤:
print ( メッセージ[ '正解' ] .format ( 状態) )
case 環境( 問題, 挑戦回数, 状態, 正誤) :
print ( メッセージ[ '不正解' ] .format ( 挑戦回数) )
return env
# Read-Eval-Print Loop
def REPL( env) :
try :
return REPL( 出力( 評価( 入力( ) , env) ) )
except GameOverSuccess as e:
print ( e)
print ( メッセージ[ 'おめでとう' ] .format ( env.問題, メッセージ[ '終了' ] ) )
except GameOverFail as e:
print ( e)
print ( メッセージ[ '残念' ] .format ( env.問題, メッセージ[ '終了' ] ) )
if __name__ == '__main__' :
print ( メッセージ[ 'ようこそ' ] )
REPL( 初期化( ) )
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwpmcm9tIHJhbmRvbSBpbXBvcnQgcmFuZGludAoKIyDjg6Hjg4Pjgrvjg7zjgrjliIbpm6LmlrnlvI8K44Oh44OD44K744O844K4ID0geyfjgojjgYbjgZPjgZ0nOiAn5Y2Y6Kqe5b2T44Gm44Ky44O844Og44G444KI44GG44GT44GdIScsCiAgICAgICAgICflm57mlbAnOiAn5oyR5oim5Zue5pWw44Gve33lm57jgafjgZkhJywKICAgICAgICAgJ+WFpeWKmyc6ICcx5paH5a2X44CB5YWl5Yqb44GX44Gm44GP44Gg44GV44GEOiAnLAogICAgICAgICAn5LiN5q2j6KejJzogJ+S4jeato+inoyHmrovjgorjga7mjJHmiKblm57mlbA6IHt9JywKICAgICAgICAgJ+ato+inoyc6ICfmraPop6Mh54++5Zyo44Gu5Y2Y6KqeOiB7fScsCiAgICAgICAgICfjgYrjgoHjgafjgajjgYYnOiAn44GK44KB44Gn44Go44GGIeWNmOiqnuOBr1wne31cJ+OBp+OBl+OBnyFcbnt9JywKICAgICAgICAgJ+aui+W/tSc6ICfmrovlv7Uh5q2j6Kej44GvXCd7fVwn44Gn44GX44Gf44CCXG57fScsCiAgICAgICAgICfntYLkuoYnOiAn44Ky44O844Og57WC5LqG44CCJ30KCiMg5Y2Y6Kqe44Oq44K544OICuWNmOiqnuODquOCueODiCA9IFsiYmFuYW5hIiwgIm9yYW5nZSIsICJhcHBsZSIsICJraXdpIl0KCiMg55Kw5aKD44OH44O844K/CmNsYXNzIOeSsOWigyhvYmplY3QpOgogICAgX19tYXRjaF9hcmdzX18gPSAoJ+WVj+mhjCcsICfmjJHmiKblm57mlbAnLCAn54q25oWLJywgJ+ato+iqpCcpCiAgICBkZWYgX19pbml0X18oc2VsZiwg5ZWP6aGMLCDmjJHmiKblm57mlbAsIOeKtuaFiywg5q2j6KqkKToKICAgICAgICBzZWxmLuWVj+mhjCA9IOWVj+mhjAogICAgICAgIHNlbGYu5oyR5oim5Zue5pWwID0g5oyR5oim5Zue5pWwCiAgICAgICAgc2VsZi7nirbmhYsgPSDnirbmhYsKICAgICAgICBzZWxmLuato+iqpCA9IOato+iqpAogICAgIyDjg4fjg5Djg4PjgrDnlKgKICAgIGRlZiBfX3JlcHJfXyhzZWxmKToKICAgICAgICByZXR1cm4gZid7c2VsZi7llY/poYx9IHtzZWxmLuaMkeaIpuWbnuaVsH0ge3NlbGYu54q25oWLfSB7c2VsZi7mraPoqqR9JwoKIyDnkrDlooPjga7liJ3mnJ/ljJYKZGVmIOWIneacn+WMligpOgogICAg5ZWP6aGMID0g5Y2Y6Kqe44Oq44K544OIW3JhbmRpbnQoMCwgbGVuKOWNmOiqnuODquOCueODiCkgLSAxKV0KICAgIOaWh+Wtl+aVsCA9IGxlbijllY/poYwpCiAgICBlbnYgPSDnkrDlooMo5ZWP6aGMLCDmloflrZfmlbAsICdfJyAqIOaWh+Wtl+aVsCwgTm9uZSkKICAgIHByaW50KOODoeODg+OCu+ODvOOCuFsn5Zue5pWwJ10uZm9ybWF0KGVudi7mjJHmiKblm57mlbApKQogICAgcmV0dXJuIGVudgoKIyDlhaXlipsKZGVmIOWFpeWKmygpOgogICAgcyA9IGlucHV0KOODoeODg+OCu+ODvOOCuFsn5YWl5YqbJ10pCiAgICBpZiBzLmlzZGVjaW1hbCgpIG9yIGxlbihzKSAhPSAxOgogICAgICAgIHJldHVybiDlhaXlipsoKQogICAgZWxzZToKICAgICAgICByZXR1cm4gcwoKIyDoqZXkvqEKCiMjIOODpuODvOOCtuODvOWumue+qeS+i+WklgpjbGFzcyBHYW1lT3ZlclN1Y2Nlc3MoRXhjZXB0aW9uKToKICAgIGRlZiBfX2luaXRfXyhzZWxmLCDlvJXmlbApOgogICAgICAgIHNlbGYu5byV5pWwID0g5byV5pWwCiAgICBkZWYgX19zdHJfXyhzZWxmKToKICAgICAgICByZXR1cm4g44Oh44OD44K744O844K4WyfmraPop6MnXS5mb3JtYXQoc2VsZi7lvJXmlbApCiAgICAKY2xhc3MgR2FtZU92ZXJGYWlsKEV4Y2VwdGlvbik6CiAgICBkZWYgX19pbml0X18oc2VsZiwg5byV5pWwKToKICAgICAgICBzZWxmLuW8leaVsCA9IOW8leaVsAogICAgZGVmIF9fc3RyX18oc2VsZik6CiAgICAgICAgcmV0dXJuIOODoeODg+OCu+ODvOOCuFsn5LiN5q2j6KejJ10uZm9ybWF0KHNlbGYu5byV5pWwKQogICAgICAgIAogICAgCmRlZiDoqZXkvqEoeCwgZW52KToKICAgIG1hdGNoIGVudjoKICAgICAgICBjYXNlIOeSsOWigyjllY/poYwsIOaMkeaIpuWbnuaVsCwg54q25oWLLCDmraPoqqQpIGlmIHggaW4g5ZWP6aGMOgogICAgICAgICAgICDnirbmhYsgPSBbaSBpZiBpID09IHggZWxzZSBqIGZvciBpLCBqIGluIHppcCjllY/poYwsIOeKtuaFiyldCiAgICAgICAgICAgIGlmICdfJyBub3QgaW4g54q25oWLOgogICAgICAgICAgICAgICAgcmFpc2UgR2FtZU92ZXJTdWNjZXNzKOeKtuaFiykKICAgICAgICAgICAgZWxzZToKICAgICAgICAgICAgICAgIHJldHVybiDnkrDlooMo5ZWP6aGMLCDmjJHmiKblm57mlbAsIOeKtuaFiywgVHJ1ZSkKICAgICAgICBjYXNlIOeSsOWigyjllY/poYwsIOaMkeaIpuWbnuaVsCwg54q25oWLLCDmraPoqqQpOgogICAgICAgICAgICDmjJHmiKblm57mlbAgLT0gMQogICAgICAgICAgICBpZiDmjJHmiKblm57mlbAgPT0gMDoKICAgICAgICAgICAgICAgIHJhaXNlIEdhbWVPdmVyRmFpbCjmjJHmiKblm57mlbApCiAgICAgICAgICAgIGVsc2U6CiAgICAgICAgICAgICAgICByZXR1cm4g55Kw5aKDKOWVj+mhjCwg5oyR5oim5Zue5pWwLCDnirbmhYssIEZhbHNlKQoKIyDlh7rlipsKZGVmIOWHuuWKmyhlbnYpOgogICAgbWF0Y2ggZW52OgogICAgICAgIGNhc2Ug55Kw5aKDKOWVj+mhjCwg5oyR5oim5Zue5pWwLCDnirbmhYssIOato+iqpCkgaWYg5q2j6KqkOgogICAgICAgICAgICBwcmludCjjg6Hjg4Pjgrvjg7zjgrhbJ+ato+inoyddLmZvcm1hdCjnirbmhYspKQogICAgICAgIGNhc2Ug55Kw5aKDKOWVj+mhjCwg5oyR5oim5Zue5pWwLCDnirbmhYssIOato+iqpCk6CiAgICAgICAgICAgIHByaW50KOODoeODg+OCu+ODvOOCuFsn5LiN5q2j6KejJ10uZm9ybWF0KOaMkeaIpuWbnuaVsCkpCiAgICByZXR1cm4gZW52CgojIFJlYWQtRXZhbC1QcmludCBMb29wCmRlZiBSRVBMKGVudik6CiAgICB0cnk6CiAgICAgICAgcmV0dXJuIFJFUEwo5Ye65YqbKOipleS+oSjlhaXlipsoKSwgZW52KSkpCiAgICBleGNlcHQgR2FtZU92ZXJTdWNjZXNzIGFzIGU6CiAgICAgICAgcHJpbnQoZSkKICAgICAgICBwcmludCjjg6Hjg4Pjgrvjg7zjgrhbJ+OBiuOCgeOBp+OBqOOBhiddLmZvcm1hdChlbnYu5ZWP6aGMLOODoeODg+OCu+ODvOOCuFsn57WC5LqGJ10pKQogICAgZXhjZXB0IEdhbWVPdmVyRmFpbCBhcyBlOgogICAgICAgIHByaW50KGUpCiAgICAgICAgcHJpbnQo44Oh44OD44K744O844K4Wyfmrovlv7UnXS5mb3JtYXQoZW52LuWVj+mhjCwg44Oh44OD44K744O844K4WyfntYLkuoYnXSkpCgppZiBfX25hbWVfXyA9PSAnX19tYWluX18nOgogICAgcHJpbnQo44Oh44OD44K744O844K4WyfjgojjgYbjgZPjgZ0nXSkKICAgIFJFUEwo5Yid5pyf5YyWKCkpCg==
compilation info
Traceback (most recent call last):
File "/usr/lib/python3.9/py_compile.py", line 144, in compile
code = loader.source_to_code(source_bytes, dfile or file,
File "<frozen importlib._bootstrap_external>", line 918, in source_to_code
File "<frozen importlib._bootstrap>", line 228, in _call_with_frames_removed
File "./prog.py", line 62
match env:
^
SyntaxError: invalid syntax
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "/usr/lib/python3.9/py_compile.py", line 150, in compile
raise py_exc
py_compile.PyCompileError: File "./prog.py", line 62
match env:
^
SyntaxError: invalid syntax
stdout