#!/usr/bin/env python3
from random import choice
import os, sys
# 英語辞書定義
with open('dictionary.txt', 'r') as f:
dictionary = [line.rstrip() for line in f]
# カウンター上限値
count_max = 10
# メッセージ
msg = {'': '',
'a': '\nAlready guessed \'{}\' ',
'n': '\nNot a valid guess: \'{}\' ',
'p': '\nPlease type \'y\' or \'n\' ',
's': '\nSorry, the word was \"{}\"\nAnother word? ',
'y': '\nYou got it!Another word? '}
# 画面表示テンプレート
temp = '''
{2}
{1} {3}
{1} {4} Guessed: {0}
{1} {8}{5}{9}
{1} {6} Word #: {Word_No}
{1} {7} {10} Current Average: {Current:.3f}
__{1}_____ Overall Average: {Overall:.3f}
| |___
|_________|
Word: {Word}
Guess: {msg}'''
# ハングマン表示部品
parts_table = {1: ('|', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '),
2: ('|', '______', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '),
3: ('|', '______', '|', ' ', ' ', ' ', ' ', ' ', ' ', ' '),
4: ('|', '______', '|', '0', ' ', ' ', ' ', ' ', ' ', ' '),
5: ('|', '______', '|', '0', '|', ' ', ' ', ' ', ' ', ' '),
6: ('|', '______', '|', '0', '|', '|', ' ', ' ', ' ', ' '),
7: ('|', '______', '|', '0', '|', '|', '/', ' ', ' ', ' '),
8: ('|', '______', '|', '0', '|', '|', '/', '/', ' ', ' '),
9: ('|', '______', '|', '0', '|', '|', '/', '/', '\\', ' '),
10: ('|', '______', '|', '0', '|', '|', '/', '/', '\\', '\\')}
# 環境
class Env(object):
def __init__(self, theWord, Word, count = 1, Guessed = [], Word_No = 1,\
Current = 0, Overall = 0, msg = msg['']):
self.theWord = theWord
self.Word = Word
self.count = count
self.Guessed = Guessed
self.Word_No = Word_No # 何回目の挑戦なのか
self.Current = Current # 何回間違えてきたか
self.Overall = Overall # 通算で何回間違えてきたか(Currentの移動先)
self.msg = msg # 出力用メッセージ
# デバッグ用
def __repr__(self):
return f'<the Word: {self.theWord}, Word: {self.Word}, \
count: {self.count}, Guessed: {self.Guessed}, Word #: {self.Word_No}, \
Current: {self.Current}, Overall: {self.Overall}, msg: {self.msg}>'
# 初期化
def initialize():
theWord = choice(dictionary)
return Env(theWord, ''.join(['-' for i in theWord]))
# Eval
def interp(x, env):
x = x.lower()[0]
if env.count == count_max or env.theWord == env.Word:
if x == 'y':
theWord = choice(dictionary)
return Env(theWord, ''.join(['-' for i in theWord]),
1, [], env.Word_No + 1,
env.Current, env.Current + env.Overall, msg[''])
elif x == 'n':
sys.exit()
else:
return Env(env.theWord, env.Word, env.count, env.Guessed,\
env.Word_No, env.Current, env.Overall, msg['p'])
elif x.isalpha():
if x in env.Guessed:
return Env(env.theWord, env.Word, env.count, env.Guessed,\
env.Word_No, env.Current, env.Overall, msg['a'].format(x))
else:
return Env(env.theWord,
''.join([x if x == i[0] else i[1] for i in\
zip(env.theWord, env.Word)]) if x\
in env.theWord else env.Word,
env.count if x in env.theWord\
else env.count + 1,
sorted([x] + env.Guessed),
env.Word_No,
env.Current if x in env.theWord\
else env.Current + 1,
env.Overall, msg[''])
else:
return Env(env.theWord, env.Word, env.count, env.Guessed,\
env.Word_No, env.Current, env.Overall, msg['n'].format(x))
# Print
def display(env):
os.system('cls' if os.name == 'nt' else 'clear')
print(temp.format(''.join(env.Guessed), *parts_table[env.count],\
Word_No = env.Word_No,\
Current = env.Current / env.Word_No,
Overall = env.Overall if env.Word_No == 1 else\
env.Overall / (env.Word_No - 1) , Word = env.Word,
msg = (msg['s'].format(env.theWord)\
if env.count == count_max\
else msg['y'] if env.theWord == env.Word\
else "") + env.msg),\
end = '')
return env
if __name__ == '__main__':
env = display(initialize())
while True:
env = display(interp(input(), env))
IyEvdXNyL2Jpbi9lbnYgcHl0aG9uMwoKZnJvbSByYW5kb20gaW1wb3J0IGNob2ljZQppbXBvcnQgb3MsIHN5cwoKIyDoi7Hoqp7ovp7mm7jlrprnvqkKd2l0aCBvcGVuKCdkaWN0aW9uYXJ5LnR4dCcsICdyJykgYXMgZjoKICAgIGRpY3Rpb25hcnkgPSBbbGluZS5yc3RyaXAoKSBmb3IgbGluZSBpbiBmXQoKIyDjgqvjgqbjg7Pjgr/jg7zkuIrpmZDlgKQKY291bnRfbWF4ID0gMTAKCiMg44Oh44OD44K744O844K4Cm1zZyA9IHsnJzogJycsCiAgICAgICAnYSc6ICdcbkFscmVhZHkgZ3Vlc3NlZCBcJ3t9XCcgJywKICAgICAgICduJzogJ1xuTm90IGEgdmFsaWQgZ3Vlc3M6IFwne31cJyAnLAogICAgICAgJ3AnOiAnXG5QbGVhc2UgdHlwZSBcJ3lcJyBvciBcJ25cJyAnLAogICAgICAgJ3MnOiAnXG5Tb3JyeSwgdGhlIHdvcmQgd2FzIFwie31cIlxuQW5vdGhlciB3b3JkPyAnLAogICAgICAgJ3knOiAnXG5Zb3UgZ290IGl0IUFub3RoZXIgd29yZD8gJ30KCiMg55S76Z2i6KGo56S644OG44Oz44OX44Os44O844OICnRlbXAgPSAnJycKICAgIHsyfQogICAgIHsxfSAgICB7M30KICAgICB7MX0gICAgezR9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgR3Vlc3NlZDogIHswfQogICAgIHsxfSAgIHs4fXs1fXs5fQogICAgIHsxfSAgICB7Nn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBXb3JkICM6ICAgICAgICAgICB7V29yZF9Ob30KICAgICB7MX0gICB7N30gezEwfSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ3VycmVudCBBdmVyYWdlOiAge0N1cnJlbnQ6LjNmfQogICBfX3sxfV9fX19fICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgT3ZlcmFsbCBBdmVyYWdlOiAge092ZXJhbGw6LjNmfQogICB8ICAgICAgfF9fXwogICB8X19fX19fX19ffAoKIFdvcmQ6ICB7V29yZH0KR3Vlc3M6IHttc2d9JycnCgojIOODj+ODs+OCsOODnuODs+ihqOekuumDqOWTgQpwYXJ0c190YWJsZSA9IHsxOiAoJ3wnLCAnICAgICAgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICAyOiAoJ3wnLCAnX19fX19fJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICAzOiAoJ3wnLCAnX19fX19fJywgJ3wnLCAnICcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICA0OiAoJ3wnLCAnX19fX19fJywgJ3wnLCAnMCcsICcgJywgJyAnLCAnICcsICcgJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICA1OiAoJ3wnLCAnX19fX19fJywgJ3wnLCAnMCcsICd8JywgJyAnLCAnICcsICcgJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICA2OiAoJ3wnLCAnX19fX19fJywgJ3wnLCAnMCcsICd8JywgJ3wnLCAnICcsICcgJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICA3OiAoJ3wnLCAnX19fX19fJywgJ3wnLCAnMCcsICd8JywgJ3wnLCAnLycsICcgJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICA4OiAoJ3wnLCAnX19fX19fJywgJ3wnLCAnMCcsICd8JywgJ3wnLCAnLycsICcvJywgJyAnLCAnICcpLAogICAgICAgICAgICAgICA5OiAoJ3wnLCAnX19fX19fJywgJ3wnLCAnMCcsICd8JywgJ3wnLCAnLycsICcvJywgJ1xcJywgJyAnKSwKICAgICAgICAgICAgICAgMTA6ICgnfCcsICdfX19fX18nLCAnfCcsICcwJywgJ3wnLCAnfCcsICcvJywgJy8nLCAnXFwnLCAnXFwnKX0KCiMg55Kw5aKDCmNsYXNzIEVudihvYmplY3QpOgogICAgZGVmIF9faW5pdF9fKHNlbGYsIHRoZVdvcmQsIFdvcmQsIGNvdW50ID0gMSwgR3Vlc3NlZCA9IFtdLCBXb3JkX05vID0gMSxcCiAgICAgICAgICAgICAgICAgQ3VycmVudCA9IDAsIE92ZXJhbGwgPSAwLCBtc2cgPSBtc2dbJyddKToKICAgICAgICBzZWxmLnRoZVdvcmQgPSB0aGVXb3JkCiAgICAgICAgc2VsZi5Xb3JkID0gV29yZAogICAgICAgIHNlbGYuY291bnQgPSBjb3VudAogICAgICAgIHNlbGYuR3Vlc3NlZCA9IEd1ZXNzZWQKICAgICAgICBzZWxmLldvcmRfTm8gPSBXb3JkX05vICMg5L2V5Zue55uu44Gu5oyR5oim44Gq44Gu44GLCiAgICAgICAgc2VsZi5DdXJyZW50ID0gQ3VycmVudCAjIOS9leWbnumWk+mBleOBiOOBpuOBjeOBn+OBiwogICAgICAgIHNlbGYuT3ZlcmFsbCA9IE92ZXJhbGwgIyDpgJrnrpfjgafkvZXlm57plpPpgZXjgYjjgabjgY3jgZ/jgYsoQ3VycmVudOOBruenu+WLleWFiCkKICAgICAgICBzZWxmLm1zZyA9IG1zZyAgICAgICAgICMg5Ye65Yqb55So44Oh44OD44K744O844K4CgogICAgIyDjg4fjg5Djg4PjgrDnlKgKICAgIGRlZiBfX3JlcHJfXyhzZWxmKToKICAgICAgICByZXR1cm4gZic8dGhlIFdvcmQ6IHtzZWxmLnRoZVdvcmR9LCBXb3JkOiB7c2VsZi5Xb3JkfSwgXApjb3VudDoge3NlbGYuY291bnR9LCBHdWVzc2VkOiB7c2VsZi5HdWVzc2VkfSwgV29yZCAjOiB7c2VsZi5Xb3JkX05vfSwgXApDdXJyZW50OiB7c2VsZi5DdXJyZW50fSwgT3ZlcmFsbDoge3NlbGYuT3ZlcmFsbH0sIG1zZzoge3NlbGYubXNnfT4nCgojIOWIneacn+WMlgpkZWYgaW5pdGlhbGl6ZSgpOgogICAgdGhlV29yZCA9IGNob2ljZShkaWN0aW9uYXJ5KQogICAgcmV0dXJuIEVudih0aGVXb3JkLCAnJy5qb2luKFsnLScgZm9yIGkgaW4gdGhlV29yZF0pKQoKIyBFdmFsCmRlZiBpbnRlcnAoeCwgZW52KToKICAgIHggPSB4Lmxvd2VyKClbMF0KICAgIGlmIGVudi5jb3VudCA9PSBjb3VudF9tYXggb3IgZW52LnRoZVdvcmQgPT0gZW52LldvcmQ6CiAgICAgICAgaWYgeCA9PSAneSc6CiAgICAgICAgICAgIHRoZVdvcmQgPSBjaG9pY2UoZGljdGlvbmFyeSkKICAgICAgICAgICAgcmV0dXJuIEVudih0aGVXb3JkLCAnJy5qb2luKFsnLScgZm9yIGkgaW4gdGhlV29yZF0pLAogICAgICAgICAgICAgICAgICAgICAgIDEsIFtdLCBlbnYuV29yZF9ObyArIDEsCiAgICAgICAgICAgICAgICAgICAgICAgZW52LkN1cnJlbnQsIGVudi5DdXJyZW50ICsgZW52Lk92ZXJhbGwsIG1zZ1snJ10pCiAgICAgICAgZWxpZiB4ID09ICduJzoKICAgICAgICAgICAgc3lzLmV4aXQoKQogICAgICAgIGVsc2U6CiAgICAgICAgICAgIHJldHVybiBFbnYoZW52LnRoZVdvcmQsIGVudi5Xb3JkLCBlbnYuY291bnQsIGVudi5HdWVzc2VkLFwKICAgICAgICAgICAgICAgICAgICAgICBlbnYuV29yZF9ObywgZW52LkN1cnJlbnQsIGVudi5PdmVyYWxsLCBtc2dbJ3AnXSkKICAgIGVsaWYgeC5pc2FscGhhKCk6CiAgICAgICAgaWYgeCBpbiBlbnYuR3Vlc3NlZDoKICAgICAgICAgICAgcmV0dXJuIEVudihlbnYudGhlV29yZCwgZW52LldvcmQsIGVudi5jb3VudCwgZW52Lkd1ZXNzZWQsXAogICAgICAgICAgICAgICAgICAgICAgIGVudi5Xb3JkX05vLCBlbnYuQ3VycmVudCwgZW52Lk92ZXJhbGwsIG1zZ1snYSddLmZvcm1hdCh4KSkKICAgICAgICBlbHNlOgogICAgICAgICAgICByZXR1cm4gRW52KGVudi50aGVXb3JkLAogICAgICAgICAgICAgICAgICAgICAgICcnLmpvaW4oW3ggaWYgeCA9PSBpWzBdIGVsc2UgaVsxXSBmb3IgaSBpblwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB6aXAoZW52LnRoZVdvcmQsIGVudi5Xb3JkKV0pIGlmIHhcCiAgICAgICAgICAgICAgICAgICAgICAgaW4gZW52LnRoZVdvcmQgZWxzZSBlbnYuV29yZCwKICAgICAgICAgICAgICAgICAgICAgICBlbnYuY291bnQgaWYgeCBpbiBlbnYudGhlV29yZFwKICAgICAgICAgICAgICAgICAgICAgICBlbHNlIGVudi5jb3VudCArIDEsCiAgICAgICAgICAgICAgICAgICAgICAgc29ydGVkKFt4XSArIGVudi5HdWVzc2VkKSwKICAgICAgICAgICAgICAgICAgICAgICBlbnYuV29yZF9ObywKICAgICAgICAgICAgICAgICAgICAgICBlbnYuQ3VycmVudCBpZiB4IGluIGVudi50aGVXb3JkXAogICAgICAgICAgICAgICAgICAgICAgIGVsc2UgZW52LkN1cnJlbnQgKyAxLAogICAgICAgICAgICAgICAgICAgICAgIGVudi5PdmVyYWxsLCBtc2dbJyddKQogICAgZWxzZToKICAgICAgICByZXR1cm4gRW52KGVudi50aGVXb3JkLCBlbnYuV29yZCwgZW52LmNvdW50LCBlbnYuR3Vlc3NlZCxcCiAgICAgICAgICAgICAgICAgICBlbnYuV29yZF9ObywgZW52LkN1cnJlbnQsIGVudi5PdmVyYWxsLCBtc2dbJ24nXS5mb3JtYXQoeCkpCiAgICAKIyBQcmludApkZWYgZGlzcGxheShlbnYpOgogICAgb3Muc3lzdGVtKCdjbHMnIGlmIG9zLm5hbWUgPT0gJ250JyBlbHNlICdjbGVhcicpCiAgICBwcmludCh0ZW1wLmZvcm1hdCgnJy5qb2luKGVudi5HdWVzc2VkKSwgKnBhcnRzX3RhYmxlW2Vudi5jb3VudF0sXAogICAgICAgICAgICAgICAgICAgICAgV29yZF9ObyA9IGVudi5Xb3JkX05vLFwKICAgICAgICAgICAgICAgICAgICAgIEN1cnJlbnQgPSBlbnYuQ3VycmVudCAvIGVudi5Xb3JkX05vLAogICAgICAgICAgICAgICAgICAgICAgT3ZlcmFsbCA9IGVudi5PdmVyYWxsIGlmIGVudi5Xb3JkX05vID09IDEgZWxzZVwKICAgICAgICAgICAgICAgICAgICAgIGVudi5PdmVyYWxsIC8gKGVudi5Xb3JkX05vIC0gMSkgLCBXb3JkID0gZW52LldvcmQsCiAgICAgICAgICAgICAgICAgICAgICBtc2cgPSAobXNnWydzJ10uZm9ybWF0KGVudi50aGVXb3JkKVwKICAgICAgICAgICAgICAgICAgICAgIGlmIGVudi5jb3VudCA9PSBjb3VudF9tYXhcCiAgICAgICAgICAgICAgICAgICAgICBlbHNlIG1zZ1sneSddIGlmIGVudi50aGVXb3JkID09IGVudi5Xb3JkXAogICAgICAgICAgICAgICAgICAgICAgICAgICBlbHNlICIiKSArIGVudi5tc2cpLFwKICAgICAgICAgIGVuZCA9ICcnKQogICAgcmV0dXJuIGVudgoKaWYgX19uYW1lX18gPT0gJ19fbWFpbl9fJzoKICAgIGVudiA9IGRpc3BsYXkoaW5pdGlhbGl6ZSgpKQogICAgd2hpbGUgVHJ1ZToKICAgICAgICBlbnYgPSBkaXNwbGF5KGludGVycChpbnB1dCgpLCBlbnYpKQo=