Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # import libraries
- from tkinter import *
- from socket import AF_INET, socket, SOCK_STREAM
- from threading import Thread
- from time import sleep
- import os
- # opening and parsing dictioany file
- with open('dict', 'r', encoding='utf8') as f:
- dictionary = [line.replace('\n', '') for line in f.readlines()]
- rules_and_author = """
- Правила очень простые - первый игрок назвает слово,
- второй игрок называет слово, первая буква которого
- совпадает с последней буквой слова, названного первым
- игроком. Далее снова первый игрок и т.д по очереди.
- Первый игрок, который отправит фразу 'я сдаюсь' -
- проиграл.
- Автор: Tori, студентка группы P3273
- """
- # client base class
- class Client:
- def __init__(self, name):
- self.response = None
- self.name = name
- self.used_words_index = 2
- self.window = Tk() # gui window
- self.window.title = 'Словечки'
- self.word_field = Entry(self.window, width=50) # field for entering words
- self.word_field.grid(row=1, column=0)
- self.submit = Button(self.window, text='Готово', command=self.process_turn) # submit button
- self.submit.grid(row=1, column=1)
- self.status_label = Label(self.window) # label that displays current game state
- self.status_label['text'] = 'Ожидаем ответа сервера...'
- self.status_label.grid(row=0, column=0)
- self.output_message = None # variable that stores messages for server
- self.help_button = Button(self.window, text='Спрака', command=self.show_help)
- self.help_button.grid(row=0, column=1)
- self.help_label = Label(self.window)
- self.help_label['text'] = rules_and_author
- def process_turn(self):
- if self.response is not None: # process message from server
- response_parts = self.response.split('\n')
- self.status_label['text'] = response_parts[0] # display current game status
- if len(response_parts) > 1:
- label = Label(self.window)
- if response_parts[1] == "__terminate__": # remove submit button on game end
- self.submit.grid_forget()
- return
- label['text'] = response_parts[1]
- label.grid(row=self.used_words_index, column=0) # update used words
- self.used_words_index += 1
- return
- self.output_message = self.word_field.get().lower() # process user input
- self.word_field.delete(0, 'end')
- def start_game(self): # main loop
- while True:
- if self.response is not None: # process server message
- self.process_turn()
- self.response = None
- try:
- self.window.update() # update gui
- except:
- os._exit(0) # kill all threads on gui termination
- def show_help(self):
- self.help_button['text'] = 'Спрятать' # 'open help button' -> 'close help button'
- self.help_button['command'] = self.hide_help
- self.help_label.grid(row=0, column=2) # display rules and author
- def hide_help(self):
- self.help_label.grid_forget() # hide rules and author
- self.help_button['text'] = 'Справка' # 'close help button' -> 'open help button'
- self.help_button['command'] = self.show_help
- # server base class
- class Server:
- def __init__(self, p1_name, dictionary):
- self.last_letter = '' # last used letter
- self.used_words = [] # stores all used words
- self.bad_letters = ['ъ', 'ь', 'ы'] # we dont have words starts with this letter in Russian language
- self.used_words_index = 2 # gui offset
- self.dictionary = dictionary # setting game dictionary
- self.current_player_name = p1_name # init player name
- self.p1_name = p1_name
- self.window = Tk() # main window
- self.window.title = 'Словечки'
- self.word_field = Entry(self.window, width=50) # field for entering words
- self.word_field.grid(row=1, column=0)
- self.submit = Button(self.window, text='Готово', command=self.process_turn) # submit button
- self.submit.grid(row=1, column=1)
- self.status_label = Label(self.window) # game state label
- self.status_label['text'] = 'Ожидаем подключения второго игрока...'
- self.status_label.grid(row=0, column=0)
- self.response = None # variable that stores messages from client
- self.p2_name = None
- self.server_turn = False
- self.output_message = None # variable thta stores messages for client
- self.help_button = Button(self.window, text='Спрака', command=self.show_help)
- self.help_button.grid(row=0, column=1)
- self.help_label = Label(self.window)
- self.help_label['text'] = rules_and_author
- def start_game(self): # main loop
- while True:
- if self.response is not None: # process message from client
- self.process_turn()
- self.response = None
- try:
- self.window.update() # update gui
- except:
- os._exit(0) # kill all threads on giu termination
- def show_help(self):
- self.help_button['text'] = 'Спрятать' # 'open help button' -> 'close help button'
- self.help_button['command'] = self.hide_help
- self.help_label.grid(row=0, column=2) # display rules and author
- def hide_help(self):
- self.help_label.grid_forget() # hide rules and author
- self.help_button['text'] = 'Справка' # 'open help button' -> 'close help button'
- self.help_button['command'] = self.show_help
- def process_turn(self):
- if self.response is None and not self.server_turn: # waiting for connection
- self.status_label['text'] = 'Ожидаем второго игрока...'
- return
- if self.p2_name is None: # first turn
- self.p2_name = self.response
- self.status_label['text'] = f'{self.current_player_name}, назови первое слово!'
- self.server_turn = True
- return
- word = self.word_field.get().lower() if self.server_turn else self.response # current entered word (from server gui or client)
- self.word_field.delete(0, 'end') # clear words text fields
- if self.last_letter == '': # process first turn
- if word == '': # empty word
- if self.server_turn:
- self.status_label['text'] = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
- self.word_field.delete(0, 'end')
- else:
- self.output_message = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
- return
- elif word not in self.dictionary: # unknown word
- if self.server_turn:
- self.status_label['text'] = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
- self.word_field.delete(0, 'end')
- else:
- self.output_message = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
- return
- else: # update last letter
- for letter in reversed(word):
- if letter in self.bad_letters:
- continue
- self.last_letter = letter
- break
- self.used_words.append(word) # update used words
- else: # not first turn
- if word == 'я сдаюсь': # process surrender
- if self.current_player_name == self.p1_name:
- self.status_label['text'] = f'Поздравляю {self.p2_name} с победой!'
- self.output_message = f'Поздравляю {self.p2_name} с победой!\n__terminate__'
- else:
- self.status_label['text'] = f'Поздравляю {self.p1_name} с победой!'
- self.output_message = f'Поздравляю {self.p1_name} с победой!\n__terminate__'
- self.submit.grid_forget()
- return
- if word == '': # empty word
- if self.server_turn:
- self.status_label['text'] = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
- self.word_field.delete(0, 'end')
- else:
- self.output_message = f'Нельзя задать пустое слово! {self.current_player_name}, попробуй еще раз!'
- return
- elif word not in self.dictionary: # unknown word
- if self.server_turn:
- self.status_label['text'] = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
- self.word_field.delete(0, 'end')
- else:
- self.output_message = f'Я не знаю такого слова... {self.current_player_name}, попробуй еще раз!'
- return
- elif word[0] != self.last_letter: # wrong first letter
- if self.server_turn:
- self.status_label['text'] = f'Слово должно начинаться с буквы \'{self.last_letter}\'! {self.current_player_name}, попробуй еще раз!'
- self.word_field.delete(0, 'end')
- else:
- self.output_message = f'Слово должно начинаться с буквы \'{self.last_letter}\'! {self.current_player_name}, попробуй еще раз!'
- return
- elif word in self.used_words: # word already userd in this game
- if self.server_turn:
- self.status_label['text'] = f'Такое слово уже было! {self.current_player_name}, попробуй еще раз!'
- self.word_field.delete(0, 'end')
- else:
- self.output_message = f'Такое слово уже было! {self.current_player_name}, попробуй еще раз!'
- return
- else: # update last letter
- for letter in reversed(word):
- if letter in self.bad_letters:
- continue
- self.last_letter = letter
- break
- self.used_words.append(word) # update used words
- if self.current_player_name == self.p1_name: # change current player
- self.current_player_name = self.p2_name
- else:
- self.current_player_name = self.p1_name
- self.server_turn = not self.server_turn
- if self.server_turn: # update game state, status label and send message to client
- self.status_label['text'] = f'Текущая буква - \'{self.last_letter}\'! {self.current_player_name} - назови слово на эту букву!'
- self.word_field.delete(0, 'end')
- label = Label(self.window)
- label['text'] = word
- label.grid(row=self.used_words_index, column=0)
- self.used_words_index += 1
- self.output_message = f'Ход игрока {self.p1_name}\n{word}'
- else:
- self.output_message = f'Текущая буква - \'{self.last_letter}\'! {self.current_player_name} - назови слово на эту букву!\n{word}'
- self.status_label['text'] = f'Ход игрока {self.p2_name}'
- label = Label(self.window)
- label['text'] = word
- label.grid(row=self.used_words_index, column=0)
- self.used_words_index += 1
- def accept_incoming_connections(SERVER, game_server):
- """Sets up handling for incoming clients."""
- while True:
- client, client_address = SERVER.accept()
- # run listener and speaker threads
- Thread(target=handle_client, args=(client, game_server)).start()
- Thread(target=speak, args=(client, game_server)).start()
- def handle_client(client, game_server): # server-client communication
- name = client.recv(1024).decode("utf8")
- game_server.response = name # get second player name on first connection
- client.send(bytes(f'Ход игрока {game_server.p1_name}', 'utf8'))
- while True:
- try:
- msg = client.recv(1024).decode('utf8') # receiving messages from client and pass it to server
- if msg != '':
- game_server.response = msg
- except:
- os._exit(0)
- def speak(client, game_server): # sending messages
- while True:
- if game_server.output_message is not None:
- client.send(bytes(game_server.output_message, 'utf8'))
- game_server.output_message = None
- def setup_server(): # setting up server
- port = int(port_entry.get())
- name = name_entry.get()
- game_mode_window.destroy()
- HOST = ''
- PORT = port
- ADDR = (HOST, PORT)
- SERVER = socket(AF_INET, SOCK_STREAM)
- SERVER.bind(ADDR)
- SERVER.listen(5)
- game_server = Server(name, dictionary)
- # run thread for accepting client connection
- ACCEPT_THREAD = Thread(target=accept_incoming_connections, args=(SERVER, game_server))
- ACCEPT_THREAD.start()
- game_server.start_game() # run gui thread
- def receive(client_socket, client): # receiving messages
- while True:
- try:
- msg = client_socket.recv(1024).decode('utf8')
- if msg != '':
- client.response = msg
- except:
- os._exit(0)
- def setup_client(): # setting up client
- port = int(port_entry.get())
- name = name_entry.get()
- game_mode_window.destroy()
- HOST = '127.0.0.1'
- PORT = port
- ADDR = (HOST, PORT)
- client_socket = socket(AF_INET, SOCK_STREAM)
- client_socket.connect(ADDR)
- client = Client(name)
- client_socket.send(bytes(name, 'utf8')) # sending player name to server
- # run listerer and speaker threads
- receive_thread = Thread(target=receive, args=(client_socket, client)).start()
- speak_thread = Thread(target=speak, args=(client_socket, client)).start()
- client.start_game() # run gui thread
- # start window for setting up nickname, port and game mode (client/server)
- game_mode_window = Tk()
- name_label = Label(game_mode_window, text='Введите свой никнейм:', width=25)
- name_label.grid(row=1, column=1)
- name_entry = Entry(game_mode_window, width=25)
- name_entry.grid(row=1, column=2)
- port_label = Label(game_mode_window, text='Введите порт:', width=25)
- port_label.grid(row=2, column=1)
- port_entry = Entry(game_mode_window, width=25)
- port_entry.grid(row=2, column=2)
- server_button = Button(game_mode_window, text='Сервер', command=setup_server, width=25)
- server_button.grid(row=3, column=1)
- client_button = Button(game_mode_window, text='Клиент', command=setup_client, width=25)
- client_button.grid(row=3, column=2)
- game_mode_window.mainloop()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement