SHARE
TWEET

4.2

a guest Dec 8th, 2019 109 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  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()
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top