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

Free Pascal Discussion :

Conditions de victoire d'un Morpion [Free Pascal]


Sujet :

Free Pascal

  1. #1
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Octobre 2011
    Messages : 72
    Points : 38
    Points
    38
    Par défaut Conditions de victoire d'un Morpion
    Hello à toutes et à tous !
    J'ai un petit exo à faire, j'ai presque terminé. IL s'agit d'un Morpion en mode Console (hé oui, on en est encore là ).
    Seulement voilà, il me manque la partie où je vérifie les conditions de victoire.
    Je pensais créer une fonction de type char où j'aurais stocké le nom du gagnant : la fonction renverrait donc 'X' ou 'O', voire 'r' lorsqu'il y aurait égalité. ( 'r' pour 'rien' ).
    Voilà le code que j'ai déjà écrit, avec un essai que j'ai réalisé sur les conditions de victoire qui n'est pas satisfaisant :

    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
    program morpion;
    const Nmax = 7;
    type jeu = array [1..Nmax,1..Nmax] of char;
     
    procedure init (var T : jeu);
    var x,y : integer;
    begin
    	for x := 1 to Nmax do
    		for y := 1 to Nmax do
    			T[x,y] := '_'
    end;
     
    procedure aff(T : jeu);
    var x,y : integer;
    begin
    	for x := 1 to Nmax do
    	begin
    		for y:= 1 to Nmax do
    			write(' | ',T[x,y]);
    		writeln
    	end
    end;
     
    procedure change (var j : char);
    begin
    	if j = 'X' then j := 'O'
    	else j := 'X'
    end;
     
    procedure valide (var T : jeu; j : char);
    var x,y : integer;
    	verif : boolean;
    begin
    	verif := false;
    	repeat
    		write('No ligne et colonne :');
    		readln(x,y);
    		if T[x,y] = '_' then
    		begin
    			T[x,y] := j;
    			verif := true
    		end
    		else writeln('Coup non valide !')
    	until (verif)
    end;
     
    function rempli (T : jeu) : boolean;  // Savoir si la partie est terminée parce que la grille est remplie (en grille 7*7 c'est pourtant peu probable :D)
    var i,j : integer;
    begin
    	rempli := true;
    	for i := 1 to Nmax do
    		for j := 1 to Nmax do
    			if T[i,j] = '_' then rempli := false
    end;
     
    function gagnant (T : jeu) : char;   // Ne fonctionne apparemment pas, pas d'erreur à l'exécution pourtant :S
    var i,j : integer;
    begin
    	gagnant:= 'r';
    	i := 1;
    	while (i <= Nmax) and (gagnant = 'r') do
    	begin
    		gagnant := T[i,1];
    		for j := 1 to 4 do
    			if T[i,j] = T[i,j+1] then gagnant := 'r'; // En fait à chaque début de ligne il va vérifier si 5 pions se suivent
    		i := i + 1;
    	end;
    	j := 1;
    	while (j <= Nmax) and (gagnant = 'r') do
    	begin
    		gagnant := T[1,j];
    		for i := 1 to 4 do
    			if T[i,j] = T[i+1,j] then gagnant := 'r'; // Pareil pour les colonnes :)
    		j := j + 1
    	end
    end;
     
    var T : jeu; j : char;
    begin
    	init(T);
    	j := 'O';
    	aff(T);
    	while (gagnant(T) = 'r') and not(rempli(T)) do
    	begin
    		change(j);
    		valide(T,j);
    		aff(T)
    	end;
    	if rempli(T) then writeln('Egalite !') else writeln('Gagnant : ',gagnant(T));
    	readln
    end.
    C'est un peu plus délicat qu'une grille 3*3 parce qu'ici c'est 7*7 et il suffit de 5 pions alignés pour gagner. Et comme vous le voyez dans ma fonction gagnant, je n'ai même pas encore testé pour les diagonales vu que j'ai déjà ce problème sur mes conditions de victoire. Mon code ici passe inaperçu à l'exécution, en fait quand il y a un gagnant le programme ne réagit même pas et continue à demander un pion à placer
    Merci d'avance de votre aide

  2. #2
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if T[i,j] <> T[i,j+1] then gagnant := 'r';
    non ?
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  3. #3
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Octobre 2011
    Messages : 72
    Points : 38
    Points
    38
    Par défaut
    J'y ai pensé après, merci ^^,
    Mais il y a toujours un problème, le programme m'affiche 'Gagnant : _ ' dès l'exécution et le jeu n'est pas jouable :/
    Un idée ? Parce que moi ça me passe au-dessus de la tête là

    J'ai réécrit ma fonction autrement :

    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
    function gagnant (T : jeu) : char;
    var i,j,x,compt : integer;
    begin
    	compt := 0; i := 1; j := 1; gagnant := 'r';
    	if T[i,j] <> '_' then
    		while (i <= Nmax) and (gagnant = 'r') do
    		begin
    			j := 1;
    			while (j <= 3) and (gagnant = 'r') do
    			begin
    				for x := 1 to 4 do
    					if T[i,j] = T[i,j+x] then compt := compt + 1;
    				if compt = 4 then
    					gagnant := T[i,j]
    				else
    					compt := 0;
    				j := j + 1
    			end;
    			i := i + 1
    		end
    end;
    Seulement, toujours le même problème, lorsque je rentre (1,1) le programme m'affiche que le gagnant est '_' ce qui est absurde, et il ne détecte pas quand les pions sont effectivement alignés :S
    Là, c'est seulement le code pour vérifier les horizontales du coup

  4. #4
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Kei,

    Donc, retour aux sources : papier + crayon !

    Tu notes l'évolution de toutes les variables pas à pas, en suivant ton programme ligne à ligne (le VRAI programme, celui que tu as écrit, pas celui que tu penses avoir fait ).
    Si les cons volaient, il ferait nuit à midi.

  5. #5
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    ton test "if T[i,j] <> '_' then" est en dehors de la boucle, donc dès la seconde itération "_" est donné gagnant

    ton code gagnerait en lisibilité avec des "continue", "break" ou "exit"
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  6. #6
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Octobre 2011
    Messages : 72
    Points : 38
    Points
    38
    Par défaut
    Merci !
    J'avais remarqué un truc dans ce genre mais finalement j'étais à des lieues de m'imaginer que c'était un truc dans ce genre qui n'allait pas _ _'
    Finalement, j'ai aussi fait le cas des verticales et un peu modifié le truc, pour le coup. Voilà le code :

    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
    function gagnant (T : jeu) : char;  
    var i,j,x,y,compt : integer;
    begin
    	// Cas horizontal
    	compt := 0; i := 1; gagnant := 'r';
    	while (i <= Nmax) and (gagnant = 'r') do
    	begin
    		j := 1;
    		while (j <= 3) and (gagnant = 'r') do
    		begin
    			if T[i,j] <> '_' then
    			begin
    				compt := 0;
    				for x := 1 to 4 do
    					if T[i,j] = T[i,j+x] then compt := compt + 1;
    				if compt = 4 then gagnant := T[i,j]
    			end;
    			j := j + 1
    		end;
    		i := i + 1
    	end;
    	// Cas vertical
    	compt := 0; j := 1;
    	while (j <= Nmax) and (gagnant = 'r') do
    	begin
    		i := 1;
    		while (i <= 3) and (gagnant = 'r') do
    		begin
    			if T[i,j] <> '_' then
    			begin
    				compt := 0;
    				for y := 1 to 4 do
    					if T[i,j] = T[i+y,j] then compt := compt + 1;
    				if compt = 4 then gagnant := T[i,j]
    			end;
    			i := i + 1
    		end;
    		j := j + 1
    	end;
    	// Cas diagonal
     
    end;
    On n'a pas encore vu les break, exit et tout ça donc je n'ai rien modifié en ce sens ^^
    J'ai laissé le cas des diagonales vide à la fin parce que je sais pas encore comment trop m'y prendre, la question que je me pose surtout maintenant c'est comment optimiser ce bazar, j'ai deux bouts de programme qui sont quasiment similaires (horizontal et vertical), j'ai essayé d'en faire une procédure pour raccourcir de moitié mais il paraît qu'appeler une procédure depuis une fonction c'est pas terrible :S, et en plus ça marchait pas ^^
    Donc je vais peut-être laisser ça comme ça...
    En tous cas merci beaucoup

  7. #7
    Expert confirmé

    Inscrit en
    Août 2006
    Messages
    3 942
    Détails du profil
    Informations forums :
    Inscription : Août 2006
    Messages : 3 942
    Points : 5 654
    Points
    5 654
    Par défaut
    Qia,

    Petite remarque : ton code est indenté, c'est bien. MAIS, une tabulation de 8 caractères d'indentation à chaque niveau de bloc, c'est trop, dans le sens où ça étale le texte à l'écran, et le rend du coup moins lisible.
    Si les cons volaient, il ferait nuit à midi.

  8. #8
    Expert éminent sénior
    Avatar de Paul TOTH
    Homme Profil pro
    Freelance
    Inscrit en
    Novembre 2002
    Messages
    8 964
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Freelance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2002
    Messages : 8 964
    Points : 28 445
    Points
    28 445
    Par défaut
    une piste pour n'avoir qu'une fonction

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
      for k := 1 to 4 do
        if T[i,j] = T[i + k * dx,j + k * dy] then compt := compt + 1;
    quelles valeurs pourraient prendre dx et dy ?

    (je présuppose que la multiplication est acquise dans ton programme ^^)
    Developpez.com: Mes articles, forum FlashPascal
    Entreprise: Execute SARL
    Le Store Excute Store

  9. #9
    Membre chevronné

    Homme Profil pro
    Étudiant
    Inscrit en
    Juin 2009
    Messages
    935
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Aveyron (Midi Pyrénées)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Juin 2009
    Messages : 935
    Points : 1 765
    Points
    1 765
    Par défaut
    Salut

    J'aimerais ajouter

    Citation Envoyé par eldoir Voir le message
    ... j'ai deux bouts de programme qui sont quasiment similaires (horizontal et vertical), j'ai essayé d'en faire une procédure pour raccourcir de moitié mais il paraît qu'appeler une procédure depuis une fonction c'est pas terrible :S
    Ah bon ? Non, cela n'est pas déconseillé d'appeler une procédure depuis une fonction (ni l'inverse)...

    Au contraire, tu as eu la bonne démarche, a savoir : "Tiens, un bout de code se répete, je vais le regrouper dans une procedure/fonction" ...

  10. #10
    Nouveau membre du Club
    Homme Profil pro
    Inscrit en
    Octobre 2011
    Messages
    72
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Maine et Loire (Pays de la Loire)

    Informations forums :
    Inscription : Octobre 2011
    Messages : 72
    Points : 38
    Points
    38
    Par défaut
    @ Paul Toth : j'avais pensé à ça, en appelant une autre fonction depuis celle-ci. J'avais remarqué que T[i,j+x] T[i+x,j] et T[i+x,j+x] ( pour la diagonale ) s'écrivaient finalement tous de la même façon et que je pouvais donc factoriser en T[i+x,j+y] où pour le cas horizontal x serait égal 0 et y serait égal à 0 pour le cas vertical.
    Donc si je ne me trompe pas dans mon raisonnement, dx et dy peuvent toutes les deux prendre les valeurs 0 ou 1
    Mon prof de TP me dit toujours qu'il vaut mieux éviter d'appeler une procédure depuis une fonction parce qu'à terme on peut s'embrouiller dans les paramètres, d'ailleurs il me l'a encore dit aujourd'hui ^^
    Du coup je pense que je vais utiliser la méthode dx dy

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Morpion - Problème conditions de boucles
    Par max1012 dans le forum Débuter
    Réponses: 2
    Dernier message: 07/03/2013, 15h47
  2. [LG]Un jeu du morpion
    Par yffick dans le forum Langage
    Réponses: 10
    Dernier message: 23/12/2003, 18h52
  3. Condition et contenu TImage
    Par Detlev_linux dans le forum Langage
    Réponses: 6
    Dernier message: 23/12/2003, 01h00
  4. [Morpion] Faire jouer l'ordinateur intelligement
    Par Invité dans le forum Intelligence artificielle
    Réponses: 8
    Dernier message: 18/09/2003, 11h05
  5. boucle avec condition d'arret changeante
    Par NicoH dans le forum Langage
    Réponses: 3
    Dernier message: 10/06/2003, 11h48

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