IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

[EXERCICE] Serveur et Client


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Candidat au Club
    Homme Profil pro
    Hobbyiste
    Inscrit en
    Mars 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Hobbyiste

    Informations forums :
    Inscription : Mars 2018
    Messages : 4
    Par défaut [EXERCICE] Serveur et Client
    Bonjour à toutes et à tous

    Je poste aujourd'hui sur ce forum car cela fait plusieurs jours que je bloque sur le même problème et je désespère vraiment.

    J'apprends Python en ligne et j'arrive à un exercice où on nous demande de développer un petit jeu de labyrinthe appelé Roboc en 2 temps.

    1) Développer le jeu qui doit fonctionner en console en mode solo

    2) Étendre le code réalisé en développant 2 scripts serveur.py et client.py qui doivent permettre à plusieurs joueurs de jouer dans le même labyrinthe à tour de rôle

    J'ai réussi la première partie sans aucun souci, j'obtiens un code fonctionnel, propre et modulaire que voici, vous êtes libres de le recopier rapidement pour voir ce qu'il fait, respectez bien l'arborescence cependant :

    roboc.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Jeu import *
     
    # FONCTIONS
     
    # Fonction principale #
     
    def main():
    	jeu = Jeu()
     
    	jeu.bienvenue()
     
    	while not jeu.termine:
    		jeu.continuer()
     
    	jeu.aurevoir()
     
    # PROGRAMME
     
    if __name__ == "__main__":
    	main()
    cartes/facile.txt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    OOOOOOUOOOOOO
    O           O
    O           O
    O     .     O
    O           O
    O           O
    U  .  x  .  U
    O           O
    O           O
    O     .     O
    O           O
    O           O
    OOOOOOUOOOOOO
    cartes/prison.txt

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    OOOOOOOOOOOOOOOOO
    O   O   .   O   U
    O x O   O   O   O
    O   O   O   O   O
    O   O   O   O   O
    O   .   O   .   O
    OOOOOOOOOOOOOOOOO
    classes/Jeu.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Carte import *
    from classes.Partie import *
     
    # CLASSE
     
    class Jeu:
    	def __init__(self):
    		self.nom = "ROBOC v1_1"
    		self.cartes = []
    		self.termine = False
     
    	def initialiser(self):
    		self.cartes = chargerCartes()
     
    	def bienvenue(self):
    		print("#"*(len(self.nom)+4))
    		print("# {nomJeu} #".format(nomJeu=self.nom))
    		print("#"*(len(self.nom)+4))
    		print("Bienvenue dans le jeu du labyrinthe ! Vous pensez pouvoir en sortir ? C'est ce qu'on va voir !")
     
    	def aurevoir(self):
    		print("Au revoir !")
     
    	def continuer(self):
    		# Étape 1 : Charger les cartes
    		self.initialiser()
     
    		# Étape 2 : Demander au joueur d'en choisir une et lui confirmer son choix
    		afficherCartes(self.cartes)
    		carteChoisie = choisirCarte(self.cartes)
    		confirmerCarteChoisie(carteChoisie)
     
    		# Étape 4 : Démarrer une nouvelle partie sur la carte choisie
    		# qui se poursuit tant qu'elle n'est pas gagnée
    		# ou qu'on a pas saisi la commande pour quitter la partie et le jeu
    		partie = Partie(carteChoisie)
     
    		partie.labyrinthe.afficher()
     
    		while not partie.terminee:
    			partie.continuer()
     
    		# Étape 5 : La partie est terminée, soit elle a été gagnée soit elle a été interrompue.
    		if partie.gagnee:
    			if partie.nombreCoups == 1:
    				print("Bravo ! Vous avez trouvé la sortie en 1 coup !")
    			else:
    				print("Bravo ! Vous avez trouvé la sortie en {nombreCoups} coups !".format(nombreCoups=partie.nombreCoups))
     
    			self.rejouer()
    		else:
    			self.termine = True
     
    	def rejouer(self):
    		oui = ['o', 'oui']
    		non = ['n', 'non']
    		rejouerEnAttente = True
    		while rejouerEnAttente:
    			rejouer = input("Voulez-vous rejouer (o/n) ? ")
    			rejouer = rejouer.lower()
    			if rejouer in oui or rejouer in non:
    				rejouerEnAttente = False
    			else:
    				print("ERREUR - Vous devez répondre par oui ou par non.")
    		if rejouer in non:
    			self.termine = True
    classes/Partie.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    # -*-coding:utf-8 -*
    # CLASSE
     
    class Partie:
    	def __init__(self, carteChoisie):
    		self.carte = carteChoisie
    		self.labyrinthe = carteChoisie.labyrinthe
    		self.nombreCoups = 0
    		self.gagnee = False
    		self.terminee = False
     
    	def continuer(self):
    		commande, direction, nombrePas = self.saisirCommande()
    		if commande != "q": # dans ce cas on sait qu'on a demandé un déplacement
    			self.labyrinthe.deplacer_robot(self, direction, nombrePas)
    			self.nombreCoups += 1
     
    	def saisirCommande(self):
    		commandesPossibles = ["q", "n", "s", "o", "e"]
    		direction = ""
    		nombrePas = 0
    		messageErreur = "ERREUR - Vous devez saisir une commande reconnue.\nQ : sauvegarder et quitter\nN : 1 pas vers le Nord\nS : 1 pas vers le Sud\nO : 1 pas vers l'Ouest\nE : 1 pas vers l'Est\nExemple : N2 : 2 pas vers le Nord"
    		commandeEnAttente = True
     
    		while commandeEnAttente:
    			commande = input("> ")
    			commande = commande.lower()
    			longueurCommande = len(commande)
     
    			if longueurCommande == 0:
    				print(messageErreur)
    			elif longueurCommande == 1:
    				if commande in commandesPossibles:
    					if commande in "nsoe":
    						direction = commande
    						nombrePas = 1
    					else:
    						self.terminee = True
    					commandeEnAttente = False
    				else:
    					print(messageErreur)
    			else:
    				if commande[0] in commandesPossibles:
    					if commande[0] in "nsoe":
    						direction = commande[0]
    						try:
    							nombrePas = int(commande[1:])
    						except ValueError:
    							print(messageErreur)
    						else:
    							commandeEnAttente = False
    					else:
    						print(messageErreur)
    				else:
    					print(messageErreur)
     
    		return commande, direction, nombrePas
    classes/Carte.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    import os
    from classes.Labyrinthe import *
     
    # FONCTIONS
     
    def chargerCartes():
    	cartes = []
    	nomsFichiers = os.listdir("cartes")
    	for nomFichier in nomsFichiers:
    		if nomFichier.endswith(".txt"):
    			cheminFichier = os.path.join("cartes", nomFichier)
    			with open(cheminFichier, "r") as fichierCarte:
    				contenuFichier = fichierCarte.read()
    				carte = Carte(nomFichier, contenuFichier)
    				cartes.append(carte)
    	return cartes
     
    def afficherCartes(cartes):
    	print("Cartes disponibles :")
    	for indiceCarte, carte in enumerate(cartes):
    		print("{numeroCarte} - {nomCarte}".format(numeroCarte=indiceCarte+1, nomCarte=carte.nom))
     
    def choisirCarte(cartes):
    	numerosCartes = [indiceCarte+1 for indiceCarte, carte in enumerate(cartes)]
    	numeroCarteEnAttente = True
     
    	while numeroCarteEnAttente:
    		numeroCarte = input("Saisissez le numéro de la carte dont vous souhaitez vous munir : ")
    		try:
    			numeroCarte = int(numeroCarte)
    			assert numeroCarte in numerosCartes
    		except ValueError:
    			print("ERREUR - Vous devez saisir un nombre.")
    		except AssertionError:
    			print("ERREUR - Vous devez saisir un nombre correspondant à une carte disponible.")
    		else:
    			numeroCarteEnAttente = False
     
    	return cartes[numeroCarte-1]
     
    def confirmerCarteChoisie(carteChoisie):
    	print("Vous vous munissez de la carte : {nomCarteChoisie}".format(nomCarteChoisie=carteChoisie.nom))
     
    # CLASSE
     
    class Carte:
    	def __init__(self, nomFichier, contenuFichier):
    		self.nom = nomFichier[:-4]
    		self.labyrinthe = creerLabyrintheDepuisContenuFichier(contenuFichier)
     
    	def __repr__(self):
    		return "<Carte: {nomCarte}>".format(nomCarte=self.nom)
    classes/Labyrinthe.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Robot import *
    from classes.Obstacle import *
    from classes.Mur import *
    from classes.Porte import *
    from classes.Sortie import *
     
    # FONCTIONS
     
    def creerLabyrintheDepuisContenuFichier(contenuFichier):
    	x = 0
    	y = 0
    	robot = None
    	obstacles = []
     
    	symboles = {
    		"o": Mur,
    		".": Porte,
    		"u": Sortie,
    		"x": Robot
    	}
     
    	for caractere in contenuFichier:
    		if caractere == "\n":
    			x = 0
    			y += 1
    			continue
    		elif caractere == " ":
    			pass
    		elif caractere.lower() in symboles:
    			classe = symboles[caractere.lower()]
    			objet = classe(x, y)
    			if type(objet) is Robot:
    				if robot is None:
    					robot = objet
    				else:
    					raise ValueError("ERREUR - Vous essayez d'insérer un nouveau robot en (x={xRobotAInserer}, y={yRobotAInserer}) alors qu'il y en a déjà un en (x={xRobotDejaPresent}, y={yRobotDejaPresent}).".format(xRobotAInserer=x, yRobotAInserer=y, xRobotDejaPresent=robot.x, yRobotDejaPresent=robot.y))
    			else:
    				obstacles.append(objet)
    		else:
    			raise ValueError("ERREUR - Symbole inconnu en (x={xSymboleInconnu}, y={ySymboleInconnu}) : {symboleInconnu}".format(xSymboleInconnu=x, ySymboleInconnu=y, symboleInconnu=caractere))
     
    		x += 1
     
    	nombreColonnes = x
    	nombreLignes = y+1
    	labyrinthe = Labyrinthe(nombreColonnes, nombreLignes, robot, obstacles)
     
    	return labyrinthe
     
    # CLASSE
     
    class Labyrinthe:
    	def __init__(self, nombreColonnes, nombreLignes, robot, obstacles):
    		self.grille = {}
    		self.invisibles = []
     
    		# Étape 1 : On vérifie les paramètres 'nombreColonnes' et 'nombreLignes' qui correspondent aux dimensions du labyrinthe
    		if type(nombreColonnes) is int and nombreColonnes > 0:
    			self.nombreColonnes = nombreColonnes
    		else:
    			raise ValueError("ERREUR - Vous essayez de créer un labyrinthe avec un nombre de colonnes incorrect.")
     
    		if type(nombreLignes) is int and nombreLignes > 0:
    			self.nombreLignes = nombreLignes
    		else:
    			raise ValueError("ERREUR - Vous essayez de créer un labyrinthe avec un nombre de lignes incorrect.")
     
    		# Étape 2 : On vérifie que le paramètre 'robot' a reçu un objet de la classe Robot avec des coordonnées valides
    		if type(robot) is Robot:
    			if robot.x >= 0 and robot.x < self.nombreColonnes and robot.y >= 0 and robot.y < self.nombreLignes:
    				self.robot = robot
    				self.grille[(robot.x, robot.y)] = robot
    			else:
    				raise ValueError("ERREUR - Vous essayez d'insérer un Robot en (x={xRobotAInserer}, y={yRobotAInserer}), soit en dehors des limites de la grille (xMin=0, yMin=0, xMax={xMax}, yMax={yMax}).".format(xRobotAInserer=robot.x, yRobotAInserer=robot.y, xMax=self.nombreColonnes-1, yMax=self.nombreLignes-1))
    		else:
    			raise ValueError("ERREUR - Vous essayez de passer un objet qui n'est pas issu de la classe Robot au paramètre 'robot'.")
     
    		# Étape 3 : On vérifie que le paramètre 'obstacles' a reçu une liste d'objets issus de classes héritées de la classe Obstacle avec des coordonnées valides et non occupées par un autre objet
    		for obstacle in obstacles:
    			if isinstance(obstacle, Obstacle):
    				if obstacle.x >= 0 and obstacle.x < self.nombreColonnes and obstacle.y >= 0 and obstacle.y < self.nombreLignes:
    					if (obstacle.x, obstacle.y) not in self.grille:
    						self.grille[(obstacle.x, obstacle.y)] = obstacle
    					else:
    						raise ValueError("ERREUR - Vous essayez d'insérer un obstacle en (x={xObstacleAInserer}, y={yObstacleAInserer}), où se trouve déjà un autre objet ({nomObjetDejaPresent}).".format(xObstacleAInserer=obstacle.x, yObstacleAInserer=obstacle.y, nomObjetDejaPresent=self.grille[(obstacle.x, obstacle.y)].nom))
    				else:
    					raise ValueError("ERREUR - Vous essayez d'insérer un obstacle en (x={xObstacleAInserer}, y={yObstacleAInserer}), soit en dehors des limites de la grille (xMin=0, yMin=0, xMax={xMax}, yMax={yMax}).".format(xObstacleAInserer=obstacle.x, yObstacleAInserer=obstacle.y, xMax=self.nombreColonnes-1, yMax=self.nombreLignes-1))
    			else:
    				raise ValueError("ERREUR - Vous essayez de passer une liste d'objets qui ne sont pas tous issus de classes héritées de la classe Obstacle au paramètre 'obstacles'.")
     
    	def afficher(self):
    		representation = ""
    		premiereLigne = True
    		for y in range(self.nombreLignes):
    			if not premiereLigne:
    				representation += "\n"
    			else:
    				premiereLigne = False
    			for x in range(self.nombreColonnes):
    				if (x, y) in self.grille:
    					representation += self.grille[(x, y)].symbole#.upper()
    				else:
    					representation += " "
    		print(representation)
     
    	def valider_deplacement(self, direction, nombrePas):
    		robot = self.robot
    		coords = [robot.x, robot.y]
    		nombrePasRestants = nombrePas
    		deplacementValide = True
     
    		while nombrePasRestants > 0:
    			if direction == "n":
    				coords[1] -= 1
    			elif direction == "s":
    				coords[1] += 1
    			elif direction == "o":
    				coords[0] -= 1
    			elif direction == "e":
    				coords[0] += 1
    			else:
    				deplacementValide = False
    				nombrePas = 0
     
    			x, y = coords
    			if x >= 0 and x < self.nombreColonnes and y >= 0 and y < self.nombreLignes:
    				if (x, y) in self.grille and not self.grille[(x, y)].franchissable:
    					deplacementValide = False
    					nombrePas = 0
    			else:
    				deplacementValide = False
    				nombrePas = 0
     
    			nombrePasRestants -= 1
     
    		return deplacementValide
     
    	def actualiser_invisibles(self):
    		for obstacle in list(self.invisibles):
    			if (obstacle.x, obstacle.y) not in self.grille:
    				self.grille[(obstacle.x, obstacle.y)] = obstacle
    				self.invisibles.remove(obstacle)
     
    	def deplacer_robot(self, partie, direction, nombrePas):
    		deplacementValide = self.valider_deplacement(direction, nombrePas)
     
    		if deplacementValide:
    			robot = self.robot
    			coords = [robot.x, robot.y]
    			nombrePasRestants = nombrePas
     
    			while nombrePasRestants > 0:
    				if direction == "n":
    					coords[1] -= 1
    				elif direction == "s":
    					coords[1] += 1
    				elif direction == "o":
    					coords[0] -= 1
    				elif direction == "e":
    					coords[0] += 1
     
    				nombrePasRestants -= 1
     
    			x, y = coords
     
    			obstacle = self.grille.get((x, y))
    			if obstacle is None or obstacle.franchissable:
    				if obstacle:
    					self.invisibles.append(obstacle)
     
    				del self.grille[(robot.x, robot.y)]
     
    				self.grille[(x, y)] = robot
    				robot.x = x
    				robot.y = y
    				self.actualiser_invisibles()
    				self.afficher()
     
    				if obstacle:
    					obstacle.arriver(partie)
    		else:
    			print("ERREUR - Déplacement invalide !")
    classes/Obstacle.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # -*-coding:utf-8 -*
    # CLASSE
     
    class Obstacle:
    	nom = "obstacle"
    	symbole = ""
    	franchissable = True
     
    	def __init__(self, x, y):
    		self.x = x
    		self.y = y
     
    	def __repr__(self):
    		return "<{nomObstacle}: {xObstacle},{yObstacle}>".format(nomObstacle=self.nom.capitalize(), x=self.x, y=self.y)
     
    	def arriver(self, partie):
    		pass
    classes/Mur.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Obstacle import *
     
    # CLASSE
     
    class Mur(Obstacle):
    	nom = "mur"
    	symbole = "O"
    	franchissable = False
    classes/Porte.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Obstacle import *
     
    # CLASSE
     
    class Porte(Obstacle):
    	nom = "porte"
    	symbole = "."
    classes/Sortie.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Obstacle import *
     
    # CLASSE
     
    class Sortie(Obstacle):
    	nom = "sortie"
    	symbole = "U"
     
    	def arriver(self, partie):
    		partie.gagnee = True
    		partie.terminee = True
    classes/Robot.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # -*-coding:utf-8 -*
    # CLASSE
     
    class Robot:
    	nom = "robot"
    	symbole = "x"
     
    	def __init__(self, x, y):
    		self.x = x
    		self.y = y
     
    	def __repr__(self):
    		return "<Robot: {xRobot},{yRobot}>".format(xRobot=self.x, yRobot=self.y)
    J'arrive maintenant à la deuxième partie, où je dois développer les 2 nouveaux scripts : serveur.py et client.py en respectant de nouvelles consignes :

    - il faut que le serveur attende au moins 2 joueurs avant d'autoriser le lancement du jeu lorsqu'un client saisit la commande "C"
    - les robots des joueurs seront placés aléatoirement dans le labyrinthe au lancement du jeu (pour l'instant je passe carrément la dessus...)
    - les joueurs pourront également saisir 2 nouvelles commandes : M<direction> pour créer un mur à un pas de distance de leur robot dans la direction indiquée (MN : Murer Nord) , P<direction> pour percer un mur à un pas de leur robot (PE : Percer Est) (pour l'instant je passe aussi carrément la dessus)

    J'ai donc commencé à rédiger les deux scripts que voici, mais je bloque sur la façon dont intégrer mon travail précédent dans ces deux nouveaux scripts :

    serveur.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Serveur import *
     
    # FONCTIONS
     
    # Fonction principale #
     
    def main():
    	serveur = Serveur()
     
    	serveur.demarrer()
     
    	if serveur.actif:
    		serveur.bienvenue()
     
    		while serveur.actif:
    			serveur.continuer()
     
    		serveur.aurevoir()
     
    # PROGRAMME
     
    if __name__ == "__main__":
    	main()
    classes/Serveur.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    import socket
    import select
    import time
     
    # CLASSE
     
    class Serveur:
    	def __init__(self):
    		self.hote 					= ""
    		self.portMin 				= 1024
    		self.portMax 				= 65535
    		self.port 					= 0
    		self.socketServeur 			= None
    		self.actif 					= False
    		self.socketsClients 		= []
     
    	def choisirHote(self):
    		hote = input("Hôte : ")
    		if len(hote) == 0:
    			hote = "localhost"
    		return hote
     
    	def choisirPort(self):
    		messageErreur = "ERREUR - Vous devez saisir un numéro de port compris entre {portMin} et*{portMax}.".format(portMin=self.portMin, portMax=self.portMax)
    		portEnAttente = True
     
    		while portEnAttente:
    			port = input("Port (entre {portMin} et {portMax}) : ".format(portMin=self.portMin, portMax=self.portMax))
    			try:
    				port = int(port)
    				assert port >= self.portMin and port <= self.portMax
    			except ValueError:
    				print(messageErreur)
    			except AssertionError:
    				print(messageErreur)
    			else:
    				portEnAttente = False
     
    		return port
     
    	def demarrer(self):
    		nombreEssaisRestantsCreationSocketServeur = 3
    		socketServeurCree = False
     
    		while not socketServeurCree and nombreEssaisRestantsCreationSocketServeur > 0:
    			self.hote = self.choisirHote()
    			self.port = self.choisirPort()
    			try:
    				self.socketServeur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    				self.socketServeur.bind((self.hote, self.port))
    				self.socketServeur.listen(2)
    			except Exception:
    				nombreEssaisRestantsCreationSocketServeur -= 1
    				if nombreEssaisRestantsCreationSocketServeur > 1:
    					messageErreur = "ERREUR - Ouverture du serveur de jeu sur le port {port} de l'hôte {hote} échouée... {nombreEssaisRestantsCreationSocketServeur} essais restants...".format(port=self.port, hote=self.hote, nombreEssaisRestantsCreationSocketServeur=nombreEssaisRestantsCreationSocketServeur)
    				else:
    					messageErreur = "ERREUR - Ouverture du serveur de jeu sur le port {port} de l'hôte {hote} échouée... {nombreEssaisRestantsCreationSocketServeur} essai restant...".format(port=self.port, hote=self.hote, nombreEssaisRestantsCreationSocketServeur=nombreEssaisRestantsCreationSocketServeur)
    				print(messageErreur)
    			else:
    				socketServeurCree = True
     
    		if socketServeurCree:
    			self.actif = True
     
    	def bienvenue(self):
    		nomProgramme = "SERVEUR"
    		print("#"*(len(nomProgramme)+4))
    		print("# {nomProgramme} #".format(nomProgramme=nomProgramme))
    		print("#"*(len(nomProgramme)+4))
    		print("Bienvenue !")
     
    	def aurevoir(self):
    		print("Au revoir !")
     
    	def accepterSocketsClients(self):
    		if self.jeuEnCours:
    			return False
    		else:
    			return True
     
    	def continuer(self):
    		print("Serveur actif...")
     
    		# ÉTAPE 1 : Accepter les connexions de clients
    		socketsClientsDemandes, wlist, xlist = select.select([self.socketServeur], [], [], 0)
     
    		for socketClientDemande in socketsClientsDemandes:
    			socketClientAcceptee, infosSocketClientAcceptee = socketClientDemande.accept()
    			print(socketClientAcceptee)
    			print(infosSocketClientAcceptee)
    			self.socketsClients.append(socketClientAcceptee)
     
    		# ÉTAPE 2 : ...
     
    		# C'EST ICI QUE JE DOIS INTÉGRER MON TRAVAIL PRÉCÉDENT
    		# ...
    		# ...
    		# ...
     
    		time.sleep(3)
    client.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    from classes.Client import *
     
    # FONCTIONS
     
    # Fonction principale #
     
    def main():
    	client = Client()
     
    	client.demarrer()
     
    	if client.actif:
    		client.bienvenue()
     
    		while client.actif:
    			client.continuer()
     
    		client.aurevoir()
     
    # PROGRAMME
     
    if __name__ == "__main__":
    	main()
    classes/Client.py

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    # -*-coding:utf-8 -*
    # IMPORTATIONS
     
    import socket
    import time
     
    # CLASSE
     
    class Client:
    	def __init__(self):
    		self.hote = ""
    		self.portMin = 1024
    		self.portMax = 65535
    		self.port = 0
    		self.socketServeur = None
    		self.actif = True
     
    	def choisirHote(self):
    		hote = input("Hôte : ")
    		if len(hote) == 0:
    			hote = "localhost"
    		return hote
     
    	def choisirPort(self):
    		messageErreur = "ERREUR - Vous devez saisir un numéro de port compris entre {portMin} et*{portMax}.".format(portMin=self.portMin, portMax=self.portMax)
    		portEnAttente = True
     
    		while portEnAttente:
    			port = input("Port (entre {portMin} et {portMax}) : ".format(portMin=self.portMin, portMax=self.portMax))
    			try:
    				port = int(port)
    				assert port >= self.portMin and port <= self.portMax
    			except ValueError:
    				print(messageErreur)
    			except AssertionError:
    				print(messageErreur)
    			else:
    				portEnAttente = False
     
    		return port
     
    	def demarrer(self):
    		nombreEssaisRestantsCreationSocketServeur = 3
    		socketServeurCree = False
     
    		while not socketServeurCree and nombreEssaisRestantsCreationSocketServeur > 0:
    			self.hote = self.choisirHote()
    			self.port = self.choisirPort()
    			try:
    				self.socketServeur = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    				self.socketServeur.connect((self.hote, self.port))
    			except Exception:
    				nombreEssaisRestantsCreationSocketServeur -= 1
    				if nombreEssaisRestantsCreationSocketServeur > 1:
    					messageErreur = "ERREUR - Ouverture du serveur de jeu sur le port {port} de l'hôte {hote} échouée... {nombreEssaisRestantsCreationSocketServeur} essais restants...".format(port=self.port, hote=self.hote, nombreEssaisRestantsCreationSocketServeur=nombreEssaisRestantsCreationSocketServeur)
    				else:
    					messageErreur = "ERREUR - Ouverture du serveur de jeu sur le port {port} de l'hôte {hote} échouée... {nombreEssaisRestantsCreationSocketServeur} essai restant...".format(port=self.port, hote=self.hote, nombreEssaisRestantsCreationSocketServeur=nombreEssaisRestantsCreationSocketServeur)
    				print(messageErreur)
    			else:
    				socketServeurCree = True
     
    		if socketServeurCree:
    			self.actif = True
     
    	def bienvenue(self):
    		nomProgramme = "CLIENT"
    		print("#"*(len(nomProgramme)+4))
    		print("# {nomProgramme} #".format(nomProgramme=nomProgramme))
    		print("#"*(len(nomProgramme)+4))
    		print("Bienvenue !")
     
    	def aurevoir(self):
    		print("Au revoir !")
     
    	def continuer(self):
    		print("Client actif...")
     
    		# ÉTAPE 2 : ...
     
    		# C'EST ICI QUE JE DOIS INTÉGRER MON TRAVAIL PRÉCÉDENT
    		# ...
    		# ...
    		# ...
     
    		time.sleep(3)
    Si vous avez lu jusque là, je vous remercie infiniment !

    Si vous avez des suggestions / conseils, je vous serais éternellement reconnaissant !

    Merci d'avance de vos réponses !

  2. #2
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Salut,

    Pour ma part, je vois pas comment tu pourrais intégrer ton code précédent sans devoir tout réécrire, car quand on regarde ce que fais ta classe Jeu, c'est prévu pour un seul joueur, input, print, etc.

    Puis de toute façon un jeu en solo ne se gère pas de la même façon qu'un jeu avec plusieurs joueurs, bref, va falloir que tu schématises tout ça pour déterminer quelles sont les tâches que le serveur devra faire et celles côtés clients

  3. #3
    Candidat au Club
    Homme Profil pro
    Hobbyiste
    Inscrit en
    Mars 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Hobbyiste

    Informations forums :
    Inscription : Mars 2018
    Messages : 4
    Par défaut
    Mon véritable problème je crois c'est que lorsque je développe, j'ai pris cette habitude de :

    - réfléchir au déroulement supposé du programme et les différentes erreurs qui peuvent survenir à chaque étape
    - développer chaque étape dans l'ordre avec la gestion des exceptions
    - une fois TOUT le code fini, tester

    Je me disais que programmer en orienté objet simplifierait la maintenance mais pas toujours clairement... car dès qu'on change ne serait-ce qu'un minimum ce que doit faire telle ou telle partie d'un programme, toutes les parties liées s'en retrouvent impactées...

    Autrement dit ici je devrais selon toi :

    - modifier mes fichiers .txt du dossier cartes/ pour supprimer les symboles "x" (histoire de générer le placement aléatoire d'un joueur au début du jeu)
    - créer une fonction dans ma classe Partie qui place le robot d'un joueur parmi les emplacements vides dans ou les emplacement sur lesquels se trouvent des objets franchissables
    - recréer ma classe Jeu pour qu'une de ses instances possède en plus un attribut : joueurs = [] qui recevra une liste d'objets issus de la classe Joueur et qui dans la méthode continuer contiendrait une boucle qui parcourrait chaque joueur de la liste et vérifierait qu'il saisisse une commande valide puis passerait au suivant tant que la partie n'est ni finie ni gagnée par un joueur
    - créer une classe Joueur qui représenterait un joueur avec 2 attributs : pseudo = "" et socketClient = ... (le socket côté serveur qui lui permet de communiquer avec le client/joueur en question)
    - recréer ma classe labyrinthe

    La question qui me vient du coup c'est comment détecter lorsqu'un client fait Ctrl + C pour quitter le script client.py que le socket client en question est fermé et donc qu'on ne doit plus attendre de réponse de la part de ce joueur, puisqu'elle n'arrivera jamais ? :S

    Merci pour tes conseils !

  4. #4
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 741
    Par défaut
    Citation Envoyé par pynoobie Voir le message
    Je me disais que programmer en orienté objet simplifierait la maintenance mais pas toujours clairement... car dès qu'on change ne serait-ce qu'un minimum ce que doit faire telle ou telle partie d'un programme, toutes les parties liées s'en retrouvent impactées...
    La POO aide à construire plus facilement ce genre de solution mais si vous n'avez pas pensé "client serveur" dès le début et à ce que vous allez pouvoir préserver ou pas....

    Citation Envoyé par pynoobie Voir le message
    - modifier mes fichiers .txt du dossier cartes/ pour supprimer les symboles "x" (histoire de générer le placement aléatoire d'un joueur au début du jeu)
    - créer une fonction dans ma classe Partie qui place le robot d'un joueur parmi les emplacements vides dans ou les emplacement sur lesquels se trouvent des objets franchissables
    - recréer ma classe Jeu pour qu'une de ses instances possède en plus un attribut : joueurs = [] qui recevra une liste d'objets issus de la classe Joueur et qui dans la méthode continuer contiendrait une boucle qui parcourrait chaque joueur de la liste et vérifierait qu'il saisisse une commande valide puis passerait au suivant tant que la partie n'est ni finie ni gagnée par un joueur
    - créer une classe Joueur qui représenterait un joueur avec 2 attributs : pseudo = "" et socketClient = ... (le socket côté serveur qui lui permet de communiquer avec le client/joueur en question)
    - recréer ma classe labyrinthe
    Hu?!? Vous pensez déjà au code alors que vous devriez penser rôles et responsabilités
    des côtés client et serveur. Quelque part les clients et le serveur doivent voir le même Jeu. Le serveur prendra en charge les coups joués par les robots mais que se passe-t-il lorsque le Joueur A joue? Il va expédier un message au serveur qui valide le coup et propage l'information aux autres joueurs. Si le serveur a une petite idée de qui va jouer le coup suivant, comment çà va se traduire côté joueurs?

    Citation Envoyé par pynoobie Voir le message
    La question qui me vient du coup c'est comment détecter lorsqu'un client fait Ctrl + C pour quitter le script client.py que le socket client en question est fermé et donc qu'on ne doit plus attendre de réponse de la part de ce joueur, puisqu'elle n'arrivera jamais ? :S
    Ca c'est de la programmation sockets qu'il va vous falloir découvrir avant de penser à votre Jeu car tout ne sera pas "permis", "possible" ou facile.
    Pour vous rendre compte du nombre de marches et de leur hauteur, peut être que vous pourriez jeter un oeil au Jeu de Bombardes du Swinnen. Il présente la construction d'une version multijoueur sur le même écran puis un peu plus loi vous avez la version réseau.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Candidat au Club
    Homme Profil pro
    Hobbyiste
    Inscrit en
    Mars 2018
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Hobbyiste

    Informations forums :
    Inscription : Mars 2018
    Messages : 4
    Par défaut
    J'ai adoré votre réaction :

    Hu?!? Vous pensez déjà au code alors que vous devriez penser rôles et responsabilités
    Ça a toujours été mon problème, on ne nous apprend jamais à nous poser les questions pour développer une solution sur le papier avant de penser au code... On nous pousse toujours à penser code, résultat, je ne suis pas fichu de résoudre cet exercice. J'essaye toujours mais sans les bonnes questions à se poser autant dire, qu'il est plus facile de penser code qu'architecture...

  6. #6
    Membre très actif

    Homme Profil pro
    Bidouilleur
    Inscrit en
    Avril 2016
    Messages
    721
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Bidouilleur

    Informations forums :
    Inscription : Avril 2016
    Messages : 721
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par pynoobie Voir le message
    Ça a toujours été mon problème, on ne nous apprend jamais à nous poser les questions pour développer une solution sur le papier avant de penser au code...
    Ce n'est pas spécifique à toi, rassure-toi

    Sinon, si n'est pas trop indiscret, c'est sur quel site que l'on te demande de faire ce genre d'exercices ?
    Parce que bon, ce genre de choses demandent comme tu dis un minimum de réflexion sur la modélisation de l'application sans pour autant y aller à coup de diagrammes complexes, et je trouve étonnant que tu ne sois pas un petit peu aiguillé dans sa conception, au moins dans les grandes lignes.

Discussions similaires

  1. Perl uniquement serveur ou Client/Serveur?
    Par alexandred dans le forum Web
    Réponses: 4
    Dernier message: 18/02/2006, 00h06
  2. Réponses: 4
    Dernier message: 16/08/2004, 17h03
  3. Client-Serveur Dcom = Client+Serveur lancés sur la machine ?
    Par Jilam dans le forum Bases de données
    Réponses: 6
    Dernier message: 27/07/2004, 14h55
  4. Serveur Multi-clients
    Par darsky dans le forum C++Builder
    Réponses: 5
    Dernier message: 16/04/2004, 09h53
  5. Création d'un Serveur Multi Client
    Par N*E*R*D dans le forum Autres éditeurs
    Réponses: 5
    Dernier message: 16/03/2004, 17h13

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo