Advertisement
Guest User

4.2

a guest
Dec 8th, 2019
184
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 15.59 KB | None | 0 0
  1. # import libraries
  2. from tkinter import *
  3. from socket import AF_INET, socket, SOCK_STREAM
  4. from threading import Thread
  5. from time import sleep
  6. import os
  7.  
  8. # opening and parsing dictioany file
  9. with open('dict', 'r', encoding='utf8') as f:
  10. dictionary = [line.replace('\n', '') for line in f.readlines()]
  11.  
  12. rules_and_author = """
  13. Правила очень простые - первый игрок назвает слово,
  14. второй игрок называет слово, первая буква которого
  15. совпадает с последней буквой слова, названного первым
  16. игроком. Далее снова первый игрок и т.д по очереди.
  17. Первый игрок, который отправит фразу 'я сдаюсь' -
  18. проиграл.
  19.  
  20. Автор: Tori, студентка группы P3273
  21. """
  22.  
  23. # client base class
  24. class Client:
  25. def __init__(self, name):
  26. self.response = None
  27. self.name = name
  28. self.used_words_index = 2
  29. self.window = Tk() # gui window
  30. self.window.title = 'Словечки'
  31. self.word_field = Entry(self.window, width=50) # field for entering words
  32. self.word_field.grid(row=1, column=0)
  33. self.submit = Button(self.window, text='Готово', command=self.process_turn) # submit button
  34. self.submit.grid(row=1, column=1)
  35. self.status_label = Label(self.window) # label that displays current game state
  36. self.status_label['text'] = 'Ожидаем ответа сервера...'
  37. self.status_label.grid(row=0, column=0)
  38. self.output_message = None # variable that stores messages for server
  39.  
  40. self.help_button = Button(self.window, text='Спрака', command=self.show_help)
  41. self.help_button.grid(row=0, column=1)
  42. self.help_label = Label(self.window)
  43. self.help_label['text'] = rules_and_author
  44.  
  45. def process_turn(self):
  46. if self.response is not None: # process message from server
  47. response_parts = self.response.split('\n')
  48. self.status_label['text'] = response_parts[0] # display current game status
  49. if len(response_parts) > 1:
  50. label = Label(self.window)
  51. if response_parts[1] == "__terminate__": # remove submit button on game end
  52. self.submit.grid_forget()
  53. return
  54. label['text'] = response_parts[1]
  55. label.grid(row=self.used_words_index, column=0) # update used words
  56. self.used_words_index += 1
  57. return
  58. self.output_message = self.word_field.get().lower() # process user input
  59. self.word_field.delete(0, 'end')
  60.  
  61.  
  62. def start_game(self): # main loop
  63. while True:
  64. if self.response is not None: # process server message
  65. self.process_turn()
  66. self.response = None
  67. try:
  68. self.window.update() # update gui
  69. except:
  70. os._exit(0) # kill all threads on gui termination
  71.  
  72. def show_help(self):
  73. self.help_button['text'] = 'Спрятать' # 'open help button' -> 'close help button'
  74. self.help_button['command'] = self.hide_help
  75. self.help_label.grid(row=0, column=2) # display rules and author
  76.  
  77. def hide_help(self):
  78. self.help_label.grid_forget() # hide rules and author
  79. self.help_button['text'] = 'Справка' # 'close help button' -> 'open help button'
  80. self.help_button['command'] = self.show_help
  81.  
  82. # server base class
  83. class Server:
  84. def __init__(self, p1_name, dictionary):
  85. self.last_letter = '' # last used letter
  86. self.used_words = [] # stores all used words
  87. self.bad_letters = ['ъ', 'ь', 'ы'] # we dont have words starts with this letter in Russian language
  88. self.used_words_index = 2 # gui offset
  89. self.dictionary = dictionary # setting game dictionary
  90. self.current_player_name = p1_name # init player name
  91. self.p1_name = p1_name
  92. self.window = Tk() # main window
  93. self.window.title = 'Словечки'
  94. self.word_field = Entry(self.window, width=50) # field for entering words
  95. self.word_field.grid(row=1, column=0)
  96. self.submit = Button(self.window, text='Готово', command=self.process_turn) # submit button
  97. self.submit.grid(row=1, column=1)
  98. self.status_label = Label(self.window) # game state label
  99. self.status_label['text'] = 'Ожидаем подключения второго игрока...'
  100. self.status_label.grid(row=0, column=0)
  101. self.response = None # variable that stores messages from client
  102. self.p2_name = None
  103. self.server_turn = False
  104. self.output_message = None # variable thta stores messages for client
  105.  
  106. self.help_button = Button(self.window, text='Спрака', command=self.show_help)
  107. self.help_button.grid(row=0, column=1)
  108. self.help_label = Label(self.window)
  109. self.help_label['text'] = rules_and_author
  110.  
  111. def start_game(self): # main loop
  112. while True:
  113. if self.response is not None: # process message from client
  114. self.process_turn()
  115. self.response = None
  116. try:
  117. self.window.update() # update gui
  118. except:
  119. os._exit(0) # kill all threads on giu termination
  120.  
  121. def show_help(self):
  122. self.help_button['text'] = 'Спрятать' # 'open help button' -> 'close help button'
  123. self.help_button['command'] = self.hide_help
  124. self.help_label.grid(row=0, column=2) # display rules and author
  125.  
  126. def hide_help(self):
  127. self.help_label.grid_forget() # hide rules and author
  128. self.help_button['text'] = 'Справка' # 'open help button' -> 'close help button'
  129. self.help_button['command'] = self.show_help
  130.  
  131. def process_turn(self):
  132. if self.response is None and not self.server_turn: # waiting for connection
  133. self.status_label['text'] = 'Ожидаем второго игрока...'
  134. return
  135.  
  136. if self.p2_name is None: # first turn
  137. self.p2_name = self.response
  138. self.status_label['text'] = f'{self.current_player_name}, назови первое слово!'
  139. self.server_turn = True
  140. return
  141. word = self.word_field.get().lower() if self.server_turn else self.response # current entered word (from server gui or client)
  142. self.word_field.delete(0, 'end') # clear words text fields
  143. if self.last_letter == '': # process first turn
  144. if word == '': # empty word
  145. if self.server_turn:
  146. self.status_label['text'] = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
  147. self.word_field.delete(0, 'end')
  148. else:
  149. self.output_message = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
  150. return
  151. elif word not in self.dictionary: # unknown word
  152. if self.server_turn:
  153. self.status_label['text'] = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
  154. self.word_field.delete(0, 'end')
  155. else:
  156. self.output_message = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
  157. return
  158. else: # update last letter
  159. for letter in reversed(word):
  160. if letter in self.bad_letters:
  161. continue
  162. self.last_letter = letter
  163. break
  164. self.used_words.append(word) # update used words
  165. else: # not first turn
  166. if word == 'я сдаюсь': # process surrender
  167. if self.current_player_name == self.p1_name:
  168. self.status_label['text'] = f'Поздравляю {self.p2_name} с победой!'
  169. self.output_message = f'Поздравляю {self.p2_name} с победой!\n__terminate__'
  170. else:
  171. self.status_label['text'] = f'Поздравляю {self.p1_name} с победой!'
  172. self.output_message = f'Поздравляю {self.p1_name} с победой!\n__terminate__'
  173. self.submit.grid_forget()
  174. return
  175.  
  176. if word == '': # empty word
  177. if self.server_turn:
  178. self.status_label['text'] = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
  179. self.word_field.delete(0, 'end')
  180. else:
  181. self.output_message = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
  182. return
  183. elif word not in self.dictionary: # unknown word
  184. if self.server_turn:
  185. self.status_label['text'] = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
  186. self.word_field.delete(0, 'end')
  187. else:
  188. self.output_message = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
  189. return
  190. elif word[0] != self.last_letter: # wrong first letter
  191. if self.server_turn:
  192. self.status_label['text'] = f'Слово должно начинаться с буквы \'{self.last_letter}\'! {self.current_player_name}, попробуй еще раз!'
  193. self.word_field.delete(0, 'end')
  194. else:
  195. self.output_message = f'Слово должно начинаться с буквы \'{self.last_letter}\'! {self.current_player_name}, попробуй еще раз!'
  196. return
  197. elif word in self.used_words: # word already userd in this game
  198. if self.server_turn:
  199. self.status_label['text'] = f'Такое слово уже было! {self.current_player_name}, попробуй еще раз!'
  200. self.word_field.delete(0, 'end')
  201. else:
  202. self.output_message = f'Такое слово уже было! {self.current_player_name}, попробуй еще раз!'
  203. return
  204. else: # update last letter
  205. for letter in reversed(word):
  206. if letter in self.bad_letters:
  207. continue
  208. self.last_letter = letter
  209. break
  210. self.used_words.append(word) # update used words
  211. if self.current_player_name == self.p1_name: # change current player
  212. self.current_player_name = self.p2_name
  213. else:
  214. self.current_player_name = self.p1_name
  215.  
  216. self.server_turn = not self.server_turn
  217.  
  218. if self.server_turn: # update game state, status label and send message to client
  219. self.status_label['text'] = f'Текущая буква - \'{self.last_letter}\'! {self.current_player_name} - назови слово на эту букву!'
  220. self.word_field.delete(0, 'end')
  221. label = Label(self.window)
  222. label['text'] = word
  223. label.grid(row=self.used_words_index, column=0)
  224. self.used_words_index += 1
  225. self.output_message = f'Ход игрока {self.p1_name}\n{word}'
  226. else:
  227. self.output_message = f'Текущая буква - \'{self.last_letter}\'! {self.current_player_name} - назови слово на эту букву!\n{word}'
  228. self.status_label['text'] = f'Ход игрока {self.p2_name}'
  229. label = Label(self.window)
  230. label['text'] = word
  231. label.grid(row=self.used_words_index, column=0)
  232. self.used_words_index += 1
  233.  
  234.  
  235. def accept_incoming_connections(SERVER, game_server):
  236. """Sets up handling for incoming clients."""
  237. while True:
  238. client, client_address = SERVER.accept()
  239. # run listener and speaker threads
  240. Thread(target=handle_client, args=(client, game_server)).start()
  241. Thread(target=speak, args=(client, game_server)).start()
  242.  
  243. def handle_client(client, game_server): # server-client communication
  244. name = client.recv(1024).decode("utf8")
  245. game_server.response = name # get second player name on first connection
  246. client.send(bytes(f'Ход игрока {game_server.p1_name}', 'utf8'))
  247.  
  248. while True:
  249. try:
  250. msg = client.recv(1024).decode('utf8') # receiving messages from client and pass it to server
  251. if msg != '':
  252. game_server.response = msg
  253. except:
  254. os._exit(0)
  255.  
  256. def speak(client, game_server): # sending messages
  257. while True:
  258. if game_server.output_message is not None:
  259. client.send(bytes(game_server.output_message, 'utf8'))
  260. game_server.output_message = None
  261.  
  262. def setup_server(): # setting up server
  263. port = int(port_entry.get())
  264. name = name_entry.get()
  265. game_mode_window.destroy()
  266.  
  267. HOST = ''
  268. PORT = port
  269. ADDR = (HOST, PORT)
  270.  
  271. SERVER = socket(AF_INET, SOCK_STREAM)
  272. SERVER.bind(ADDR)
  273.  
  274. SERVER.listen(5)
  275. game_server = Server(name, dictionary)
  276. # run thread for accepting client connection
  277. ACCEPT_THREAD = Thread(target=accept_incoming_connections, args=(SERVER, game_server))
  278. ACCEPT_THREAD.start()
  279.  
  280. game_server.start_game() # run gui thread
  281.  
  282. def receive(client_socket, client): # receiving messages
  283. while True:
  284. try:
  285. msg = client_socket.recv(1024).decode('utf8')
  286. if msg != '':
  287. client.response = msg
  288. except:
  289. os._exit(0)
  290.  
  291. def setup_client(): # setting up client
  292. port = int(port_entry.get())
  293. name = name_entry.get()
  294. game_mode_window.destroy()
  295.  
  296. HOST = '127.0.0.1'
  297. PORT = port
  298. ADDR = (HOST, PORT)
  299.  
  300. client_socket = socket(AF_INET, SOCK_STREAM)
  301. client_socket.connect(ADDR)
  302.  
  303. client = Client(name)
  304.  
  305. client_socket.send(bytes(name, 'utf8')) # sending player name to server
  306.  
  307. # run listerer and speaker threads
  308. receive_thread = Thread(target=receive, args=(client_socket, client)).start()
  309. speak_thread = Thread(target=speak, args=(client_socket, client)).start()
  310.  
  311. client.start_game() # run gui thread
  312.  
  313. # start window for setting up nickname, port and game mode (client/server)
  314. game_mode_window = Tk()
  315. name_label = Label(game_mode_window, text='Введите свой никнейм:', width=25)
  316. name_label.grid(row=1, column=1)
  317. name_entry = Entry(game_mode_window, width=25)
  318. name_entry.grid(row=1, column=2)
  319. port_label = Label(game_mode_window, text='Введите порт:', width=25)
  320. port_label.grid(row=2, column=1)
  321. port_entry = Entry(game_mode_window, width=25)
  322. port_entry.grid(row=2, column=2)
  323. server_button = Button(game_mode_window, text='Сервер', command=setup_server, width=25)
  324. server_button.grid(row=3, column=1)
  325. client_button = Button(game_mode_window, text='Клиент', command=setup_client, width=25)
  326. client_button.grid(row=3, column=2)
  327. game_mode_window.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement