0

Je voudrais programmer un jeu-questionnaire avec multi-joueurs. La partie serveur choisit la question, puis l'envoie au client. Le client répond et envoie cette réponse au serveur. Le serveur vérifie ensuite s'il est correct ou non. Je voudrais le faire en boucle. Mais le problème est, il y a un problème de timing, parfois mon client ne reçoit pas la question avant de pouvoir répondre. Un autre problème est que le serveur ne reçoit pas la réponse lorsque le client l'envoie et je ne sais vraiment pas pourquoi.Quiz Jeu avec plusieurs joueurs, le serveur ne reçoit pas d'informations des clients

C'est la première fois que je fais de la programmation réseau et c'est difficile pour moi de comprendre le threading et tout ça. Merci pour votre aide =)

PS: Cette situation est liée à une autre question, je voudrais que ce code fonctionne avec une interface graphique simple ... Mais c'est l'étape suivante;)

Voici mon code client:

import socket 
import threading 
import time 

tLock = threading.Lock() 
shutdown = False 

def receving(name, sock): 
    while not shutdown: 
      try: 
       tLock.acquire() 
       while True: 
         data,addr = sock.recvfrom(1024) 
         print(str(data)) 
      except: 
        pass 
      finally: 
        tLock.release() 

#host = '192.168.26.86' 
host = '127.0.0.1' 
port = 0 #pick any free port currently on the computer 
server = (host, 5000) 

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind((host,port)) 
s.setblocking(0) 

#receiving thread 
rT = threading.Thread(target=receving, args=("RecvThread", s)) 
rT.start() 

alias = raw_input("Name: ") 

#PLAYER ENTERS DATA 
message = raw_input(alias + "First msg ->") 

while message != 'q': 
     tLock.acquire() 
     message = raw_input(alias + "What is your answer ? ->") 
     tLock.release() 


     if message != '': 
      s.sendto(alias + ": " + message, server) 

     time.sleep(0.2) 

shutdown = True 
rT.join() 
s.close() 

Voici mon code serveur:

import numpy as np 
from numpy.random import shuffle 
from random import randint 
import socket 
import time 

#LIST OF QUESTIONS AND ANSWERS 
question2 = ["What is the capital of France?","In which continent is Argentina?","Where is Big Ben?","What is the most densely populated country?","What language do they speak in Brazil?"] 
answer2 = [["Paris","London","Berlin","Madrid"], 
     ["South America","Africa","Europe","Asia"], 
     ["London","New York","Mexico","Jakarta"], 
     ["China","India","USA","Indonesia"], 
     ["Portuguese","Spanish","French","English"]] 
question_done=[0]*(len(question2)) 


#SCORE, stored as a list score[0]--> score of the player 1 
score=[0] 


#SHOW THE POSSIBLE ANSWERS 
def displayA(question,answer,i): 
    a = answer[i] 
    order = np.arange(4) 
    shuffle(order) #create list from 1 to 4 in different order --> to print the answers in random order 
    a_display = [[a[order[0]],a[order[1]]],[a[order[2]],a[order[3]]]] 
    print(a_display) 


#CHOOSE RANDOMLY A QUESTION IN THE LIST 
def chooseQuestion(question,answer): 
    k = randint(0,len(question)-1) 
    if (question_done[k]!=0): 
     while(question_done[k]!=0): 
      k = randint(0,len(question)-1) 
     question_done[k]=1 
    else : 
     question_done[k]=1 
    print(question[k]) 
    #displayA(question,answer,k) 
    return k 


#CHECK IF GOOD ANSWER OR NOT 
def checkAnswer(answer,agiven,qnb): 
    print("CHECK") 
    test = False 
    if(answer[qnb][0] in agiven): 
     test = True 
     score[0]=score[0]+1 
    print("ANSWER") 
    return test 



#END OF GAME, DISPLAY OF SCORES 
def final_score(score): 
    print("The scores are {}".format(score)) 

    maxi = max(score) 
    if(score.count(maxi)==1): 
     print("The winner is Player {}".format(score.index(max(score))+1)) 
    else : 
     winners = [] 
     for i in range(len(score)): 
      if(score[i]==maxi): 
       winners.append(i+1) 
     print("The winners are players {}".format(winners)) 


""" 

#Number of choosen questions, random order : GIVE THE QUESTION TO THE PLAYER 
nb = 3 

for k in range(nb): 
    nbq = chooseQuestion(question2,answer2) 
    agiven = raw_input("What is your answer? ") 
    result = checkAnswer(answer2,agiven,nbq) 
    print("Your answer is {}".format(result)) 



#Say who the winner is 
final_score(score) 



""" 
#START THE NETWORK CODE 
#host = '192.168.26.86' 
host = '127.0.0.1' 

port = 5000 

#list for all the players 
players = [] 

#creation of socket object UDP and bind 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind((host, port)) 
#socket non blocking --> will always try to grab datas from the stream 
#not block it 
s.setblocking(0) 


quitting = False 
print "Server Started." 

#NUMBER OF QUESTIONS 
nb = 3 


while (not quitting and nb>0): 
    try: 
      data, addr = s.recvfrom(1024) 
      print("FIRST RECV {}".format(data)) 
      if "Quit" in str(data): 
       quitting = True 
      if addr not in players: 
       players.append(addr) 
       print("liste players {}".format(players)) 
       s.sendto("the game is starting ",players[len(players)-1]) 

      print time.ctime(time.time()) + ":" + str(data) 

      #GAME 

      #for k in range(nb): 
      print("question nb {}".format(nb)) 
      nbq = chooseQuestion(question2,answer2) 


      for i in range(len(players)): 
       print("ENTER FOR") 
       #s.sendto(question2[nbq], players[i]) 
       try: 
        s.sendto(question2[nbq], players[i]) 
        print("BEFORE GET ANSWER") 
        agiven, addr = s.recvfrom(1024) 
        print("GOT ANSWER") 

        print("agiven is : {}".format(agiven)) 
        checkAnswer(answer2,agiven,nbq) 

        if "Quit" in str(agiven): 
         quitting = True 
        if addr not in players: 
         s.sendto("You cannot enter the game now ",addr) 
        else: 
         players[i] = addr 
       except: 
        pass 

      nb=nb-1 

    except: 
      pass 



for i in range(len(players)): 
    try: 
     s.sendto("The game is finished, write q to quit",players[i]) 

    except: 
     pass 

final_score(score) 
s.close() 

Répondre

0

Votre code contient la logique correcte pour les questions et les réponses, mais le dat un transfert entre le client et le serveur était fragile et cela ne fonctionnait que si le timing était parfait.

J'ai modifié votre code pour aider à contrôler le timing et empêcher les choses de se dégrader. J'ai utilisé l'appel système select() pour gérer les délais, et dans le client j'ai changé le thread de lecture pour notifier la boucle principale lorsque des questions arrivent du serveur.

Ce code est loin d'être parfait mais il fonctionne et devrait vous aider à construire quelque chose de final qui fonctionne comme vous le préférez. NB: J'ai enlevé le code "tu ne peux pas rejoindre le jeu maintenant" pour m'aider à déboguer le code original, donc tu pourrais probablement le remettre maintenant. J'espère que c'est utile.

Code client:

import socket 
import threading 
import time 

tEv = threading.Event() 
tShutdown = threading.Event() 

def receving(name, sock): 
    shutdown = False 
    while not shutdown: 
     try: 
      data,addr = sock.recvfrom(1024) 
      print(str(data)) 
      if '?' in data: 
       tEv.set() 
      if data == "The game is finished": # message from server to stop 
       tShutdown.set() 
       shutdown = True 
     except: 
      pass 
     finally: 
      pass 

#host = '192.168.26.86' 
host = '127.0.0.1' 
port = 0 #pick any free port currently on the computer 
server = (host, 5000) 

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind((host,port)) 
s.setblocking(0) 

# Start listener 
rT = threading.Thread(target=receving, args=("RecvThread", s)) 
rT.start() 

# Join the game 
alias = raw_input("Name: ") 
s.sendto(alias, server) 

running = True 
while running: 
    if tEv.wait(1.0): 
     tEv.clear() 
     message = raw_input(alias + ", what is your answer ? -> ") 
     if message != '': 
      s.sendto(alias + ": " + message, server) 
    if tShutdown.is_set(): 
     running = False 

rT.join() 
s.close() 

Code Serveur:

import numpy as np 
from numpy.random import shuffle 
from random import randint 
import socket 
import time 
import select 

#LIST OF QUESTIONS AND ANSWERS 
question2 = ["What is the capital of France?","In which continent is Argentina?","Where is Big Ben?","What is the most densely populated country?","What language do they speak in Brazil?"] 
answer2 = [["Paris","London","Berlin","Madrid"], 
     ["South America","Africa","Europe","Asia"], 
     ["London","New York","Mexico","Jakarta"], 
     ["China","India","USA","Indonesia"], 
     ["Portuguese","Spanish","French","English"]] 
question_done=[0]*(len(question2)) 


#SCORE, stored as a list score[0]--> score of the player 1 
score=[0] 


#SHOW THE POSSIBLE ANSWERS 
def displayA(question,answer,i): 
    a = answer[i] 
    order = np.arange(4) 
    shuffle(order) #create list from 1 to 4 in different order --> to print the answers in random order 
    a_display = [[a[order[0]],a[order[1]]],[a[order[2]],a[order[3]]]] 
    print(a_display) 


#CHOOSE RANDOMLY A QUESTION IN THE LIST 
def chooseQuestion(question,answer): 
    k = randint(0,len(question)-1) 
    if (question_done[k]!=0): 
     while(question_done[k]!=0): 
      k = randint(0,len(question)-1) 
     question_done[k]=1 
    else : 
     question_done[k]=1 
    print(question[k]) 
    #displayA(question,answer,k) 
    return k 


#CHECK IF GOOD ANSWER OR NOT 
def checkAnswer(answer,agiven,qnb): 
    #print("CHECK") 
    test = False 
    if(answer[qnb][0] in agiven): 
     test = True 
     score[0]=score[0]+1 
    #print("ANSWER") 
    return test 



#END OF GAME, DISPLAY OF SCORES 
def final_score(score): 
    print("The scores are {}".format(score)) 

    maxi = max(score) 
    if(score.count(maxi)==1): 
     print("The winner is Player {}".format(score.index(max(score))+1)) 
    else : 
     winners = [] 
     for i in range(len(score)): 
      if(score[i]==maxi): 
       winners.append(i+1) 
     print("The winners are players {}".format(winners)) 


""" 
#Number of choosen questions, random order : GIVE THE QUESTION TO THE PLAYER 
nb = 3 

for k in range(nb): 
    nbq = chooseQuestion(question2,answer2) 
    agiven = raw_input("What is your answer? ") 
    result = checkAnswer(answer2,agiven,nbq) 
    print("Your answer is {}".format(result)) 

#Say who the winner is 
final_score(score) 
""" 
#START THE NETWORK CODE 
#host = '192.168.26.86' 
host = '127.0.0.1' 

port = 5000 

#list for all the players 
players = [] 

#creation of socket object UDP and bind 
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 
s.bind((host, port)) 
#socket non blocking --> will always try to grab datas from the stream 
#not block it 
s.setblocking(0) 

print "Server Started." 

#INITIAL SETUP PERIOD 
secs = 20 
max_players = 5 

# WAIT FOR PLAYERS TO JOIN 
while ((secs > 0) and (len(players) < max_players)): 
    ready = select.select([s], [], [], 1) 
    if ready[0]: 
     data, addr = s.recvfrom(1024) 
     print("FIRST RECV {}".format(data)) 
     if addr not in players: 
      players.append(addr) 
      print("liste players {}".format(players)) 
      s.sendto("Wait for game to start... ",players[len(players)-1]) 
     print time.ctime(time.time()) + ":" + str(data) 
    secs = secs - 1 

#START GAME 
print("Game starting") 
for i in range(len(players)): 
    try: 
     s.sendto("Game starting", players[i]) 
    except: 
     pass 

#ASK QUESTIONS 
nb = 3 
for k in range(nb): 
    print("question nb {}".format(k)) 
    nbq = chooseQuestion(question2,answer2) 
    #print("ENTER FOR") 
    for i in range(len(players)): 
     try: 
      s.sendto(str(question2[nbq]), players[i]) 
      #print("BEFORE GET ANSWER") 
      agiven = "" 
      ready = select.select([s], [], [], 10) 
      if ready[0]: 
       agiven, addr = s.recvfrom(1024) 
       #print("GOT ANSWER") 
      print("agiven is : {}".format(agiven)) 
      checkAnswer(answer2,agiven,nbq) 
     except: 
      pass 

for i in range(len(players)): 
    try: 
     s.sendto("The game is finished", players[i]) 
    except: 
     pass 

final_score(score) 
s.close() 
+0

Merci beaucoup! C'est exactement ce dont j'avais besoin. Je ne connaissais pas le select et c'est vraiment intéressant pour moi =) –