wordle.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. import time
  2. from pywebio import start_server, config
  3. from pywebio.output import *
  4. from pywebio.session import run_js, local as session_local
  5. TODAY_WORD = 'PYWEBIO' # need to be uppercase
  6. MAX_TRY = 6
  7. WORD_LEN = len(TODAY_WORD)
  8. CSS = """
  9. .pywebio {padding-top: 0} .markdown-body table {display:table; width:250px; margin:10px auto;}
  10. .markdown-body table th, .markdown-body table td {font-weight:bold; padding:0; line-height:50px;}
  11. th>div,td>div {width:50px; height:50px}.btn-light {background-color:#d3d6da;}
  12. @media (max-width: 435px) {.btn{padding:0.375rem 0.5rem;}}
  13. @media (max-width: 355px) {.btn{padding:0.375rem 0.4rem;}}
  14. """
  15. # To check if a user's input word is actually a legit word
  16. # We just implement a placeholder function in this example
  17. # If a guess word is UNHAPPY, toast a message
  18. def is_word(s):
  19. return 'UNHAPPY' not in s
  20. def on_key_press(char):
  21. if session_local.curr_row >= MAX_TRY or session_local.game_pass:
  22. return
  23. if char == '◀':
  24. session_local.curr_word = session_local.curr_word[:-1]
  25. return clear(f's-{session_local.curr_row}-{len(session_local.curr_word)}')
  26. # show the char in grid
  27. with use_scope(f's-{session_local.curr_row}-{len(session_local.curr_word)}', clear=True):
  28. put_text(char)
  29. session_local.curr_word += char
  30. if len(session_local.curr_word) == WORD_LEN: # submit a word guess
  31. if not is_word(session_local.curr_word):
  32. toast('Not in word list!', color='error')
  33. session_local.curr_word = ''
  34. for i in range(WORD_LEN):
  35. clear(f's-{session_local.curr_row}-{i}')
  36. else:
  37. for idx, c in enumerate(session_local.curr_word):
  38. time.sleep(0.2)
  39. if TODAY_WORD[idx] == c:
  40. session_local.green_chars.add(c)
  41. run_js('$("button:contains(%s)").css({"background-color":"#6aaa64", "color":"white"})' % c)
  42. text_bg = '#6aaa64'
  43. session_local.game_result += '🟩'
  44. elif c in TODAY_WORD:
  45. text_bg = '#c9b458'
  46. session_local.game_result += '🟨'
  47. if c not in session_local.green_chars:
  48. run_js('$("button:contains(%s)").css({"background-color":"#c9b458", "color":"white"})' % c)
  49. else:
  50. text_bg = '#787c7e'
  51. session_local.game_result += '⬜'
  52. run_js('$("button:contains(%s)").css({"background-color":"#787c7e", "color":"white"})' % c)
  53. with use_scope(f's-{session_local.curr_row}-{idx}', clear=True):
  54. put_text(c).style(f'color:white;background:{text_bg}')
  55. session_local.game_result += '\n'
  56. if session_local.curr_word == TODAY_WORD:
  57. toast('Genius', color='success')
  58. session_local.game_pass = True
  59. session_local.curr_row += 1
  60. session_local.curr_word = ''
  61. if session_local.game_pass:
  62. message = f'Wordle {session_local.curr_row}/{MAX_TRY}\n' + session_local.game_result
  63. with popup("Game Result", size='small'):
  64. put_text(message).style('text-align: center')
  65. put_button('Share', color='success', onclick=lambda: toast('Copied to clipboard') or run_js("""navigator.clipboard.write([new ClipboardItem({"text/plain":new Blob([text],{type:"text/plain"})})]);""", text=message)).style('text-align: center')
  66. @config(title="WORDLE with PyWebIO", description="A wordle-like game implemented with PyWebIO", css_style=CSS)
  67. def main():
  68. put_markdown(
  69. '# WORDLE \n A pure python implementation of a [Wordle-like game](https://en.wikipedia.org/wiki/Wordle), using PyWebIO library. '
  70. '[Source code](https://github.com/pywebio/PyWebIO/blob/dev/demos/wordle.py)'
  71. ).style('text-align:center')
  72. grid = [
  73. [put_scope(f's-{x}-{y}', content=put_text(' ')) for y in range(WORD_LEN)]
  74. for x in range(MAX_TRY)
  75. ]
  76. put_table(grid).style('text-align: center')
  77. keyboard = [
  78. put_buttons([dict(label=c, value=c, color='light') for c in keys], on_key_press, serial_mode=True)
  79. for keys in ['QWERTYUIOP', 'ASDFGHJKL', 'ZXCVBNM◀']
  80. ]
  81. put_column(keyboard).style('text-align: center')
  82. session_local.curr_row = 0
  83. session_local.curr_word = ''
  84. session_local.green_chars = set()
  85. session_local.game_pass = False
  86. session_local.game_result = ''
  87. if __name__ == '__main__':
  88. start_server(main, port=8080, cdn=False)