実現したいこと
Python初心者です。
現在、Pythonでクライアントサーバー型の対戦タイピングゲームを作成しています。1台のPCでサーバーをバックグラウンドで起動し、複数のクライアントが接続してゲームを行う構成です。
発生している問題・分からないこと
1回目の単語は正常に送受信・入力が表示され、結果が表示がされるんですが、
2回目以降の単語では入力プロンプトがクライアントに表示されず、ゲームが途中で止まってしまいます。
サーバー側では次の単語を正しく送信しており、クライアントも受信ログで確認済みです。
しかし、クライアントのinput()が呼び出されずに止まったままです。
この問題の原因や解決方法についてアドバイスをいただきたいです。
現在の主要なコード(簡略版)も下記に記載します。
つたないコードで見にくいと思いますが、アプローチ方法をご教授いただければ幸いです。
該当のソースコード
#サーバー側 import socket import typing_game_func as tgf class TypingServer: def __init__(self, host='0.0.0.0', port=65432): self.server_address = (host, port) self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.server_socket.bind(self.server_address) self.server_socket.listen() self.client_sockets = [] self.player_names = [] self.num_players = 0 print("サーバーが起動しました...") def send_message(self, socket, message): socket.sendall(message.encode('utf-8')) def recv_message(self, socket): return socket.recv(1024).decode('utf-8').strip() def start(self): first_client_socket, _ = self.server_socket.accept() self.client_sockets.append(first_client_socket) print("最初のクライアントが接続しました") self.send_message(self.client_sockets[0], "num_players") self.num_players = int(self.recv_message(self.client_sockets[0])) print(f"あと{self.num_players - 1}人待っています...") for i in range(self.num_players - 1): client_socket, _ = self.server_socket.accept() self.client_sockets.append(client_socket) print(f"クライアント{i+2}が接続しました") game = tgf.TypingGame(self.server_socket, self.client_sockets) game.start_game() for client_socket in self.client_sockets: client_socket.close() self.server_socket.close() if __name__ == "__main__": server = TypingServer() server.start()
#クライアント側 import socket import time class TypingClinet: def __init__(self, host='127.0.0.1', port=65432): self.server_address = (host, port) self.client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.client_socket.connect(self.server_address) print("サーバーに接続しました。") def send_message(self, socket, message): socket.sendall(message.encode('utf-8')) def recv_message(self, socket): return socket.recv(1024).decode('utf-8').strip() def start(self): try: while True: message = self.recv_message(self.client_socket) if message == "num_players": num_plyaers = input("プレイヤー人数の入力>> ") self.send_message(self.client_socket, num_plyaers) elif message == "name": name = input("名前を入力>> ") self.send_message(self.client_socket, name) elif "ゲーム開始" in message: print(message) break while True: # サーバーから単語を受け取る word = self.recv_message(self.client_socket) print("word_recv", flush=True) if word == "end": break # ゲーム終了時 elif "単語" in word: print(word) start_time = time.time() player_input = input("入力: ") #ここが上手くいきません。 player_time = time.time() - start_time # 入力結果とタイムをサーバーに送信 self.send_message(self.client_socket, f"{player_input}, {player_time:.2f}") result = self.recv_message(self.client_socket) print(result) result = self.recv_message(self.client_socket) print(result) except Exception as e: print(f"エラー: {e}") finally: self.client_socket.close()
#ゲーム内容 import random import time class TypingGame: def __init__(self, server_socket, client_sockets): self.server_socket = server_socket self.client_sockets = client_sockets self.score_limit = 5 self.words = [] self.player_scores = [0] * (len(client_sockets)) self.player_names = [] def send_message(self, socket, message): socket.sendall(message.encode('utf-8')) def recv_message(self, socket): return socket.recv(1024).decode('utf-8').strip() def broadcast(self, message): #全プレイヤーにメッセージを送信 for client_socket in self.client_sockets: self.send_message(client_socket, message) def load_words(file): with open(file, 'r') as f: return [line.strip() for line in f] def collect_inputs(self): #全プレイヤーの入力を集めて、結果を返す player_times = [] player_inputs = [] # クライアントの入力を受信 for client_socket in self.client_sockets: client_input, client_time = self.recv_message(client_socket).split(',') player_inputs.append(client_input) player_times.append(float(client_time)) return player_inputs, player_times def send_results_to_clients(self, player_times, player_scores, player_names): results = "\ntime :" for i in range(len(player_times)): if i != 0: results += " - " results += f"[{player_names[i]}] {player_times[i]:.2f}sec" results += "\nscore:" for i in range(len(player_scores)): if i != 0: results += " - " results += f"[{player_names[i]}] {player_scores[i]}" self.broadcast(results) def start_game(self): #ニックネーム設定 for client_socket in self.client_sockets: self.send_message(client_socket, "name") client_name = self.recv_message(client_socket) self.player_names.append(client_name) self.words = self.load_words('words.txt') self.broadcast("ゲーム開始まで2秒...") time.sleep(2) # ゲーム進行 while max(self.player_scores) < self.score_limit: word = random.choice(self.words) self.words.remove(word) self.broadcast(f"\n単語: {word}") # 全プレイヤーの入力を集める player_inputs, player_times = self.collect_inputs() # 正誤判定 correct_inputs = [] for i in player_inputs: if i == word: correct_inputs.append(True) else: correct_inputs.append(False) #タイム判定 correct_times = [] for i, t in zip(correct_inputs, player_times): if i: correct_times.append(t) if correct_times: min_time = min(correct_times) else: min_time = None # スコアを更新 for i, correct in enumerate(correct_inputs): if min_time != None and correct and player_times[i] == min_time: self.player_scores[i] += 1 #結果を表示 self.send_results_to_clients(player_times, self.player_scores, self.player_names) self.broadcast("end") # 勝敗の決定 winner = self.player_scores.index(max(self.player_scores)) self.broadcast(f"{self.player_names[winner]}が勝利しました!")
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
以下のコードで"word_recv"というデバックを用意しましたが、なぜか二個目の単語の際はこのprintが表示されず、print(word)だけ表示されます。しかし、input("入力:")はでてきません。
# サーバーから単語を受け取る word = self.recv_message(self.client_socket) print("word_recv", flush=True)#デバック if word == "end": break # ゲーム終了時 elif "単語" in word: print(word) start_time = time.time() player_input = input("入力: ") #ここが上手くいきません。 player_time = time.time() - start_time
補足
何か私のコードでわからない部分があればいつでも聞いてください。

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2024/12/16 18:23
2024/12/16 19:48