Les jeux

# Chapitre 16 Les jeux

## 16.1 Un jeu

On considère le jeu suivant :

- Le joueur tire au hasard un nombre entre 1 et 10. Ce nombre est son gain, il peut le garder et la partie est finie.
- Le joueur peut choisir d’abandonner ce gain et de recommencer. Il lui est permis de tirer ainsi au plus 5 fois et son gain est le résultat du dernier tirage lorsqu’il a abandonné les gains des 4 tirages précédents.

1. Écrire un programme qui réalise ce jeu,
2. Le joueur choisit 4 nombres n1,n2,n3,n4 compris entre 1 et 10 et choisit comme stratégie de garder son gain du jième essai si celui-ci est supérieur ou égal à nj sinon il recommence (si n1=9, n2=8, n3=6, n4=5 avec le tirage 2,7,8, le gain est 8 mais avec le tirage 8,7,5,4,2 le gain est 2).
   Il joue 100 parties selon cette stratégie avec les mêmes nj. Écrire un programme donnant la moyenne des gains obtenus. A vous de jouer !.

    jeu1():={
     //repondre o pour dire oui
     local j,g,rep;
     pour j de 1 jusque 4 faire
       g:=alea(10)+1;afficher(g);
       lis_phrase(rep);
       si rep=="o" alors retourne g; fsi;
     fpour;
     retourne alea(10)+1;
    }:;

`jeu2` a comme paramètre `L` qui est la séquence n1,n2,n3,n4 puis LL est la suite n1,n2,n3,n4,0 de façon à ce que LL[j] soit définie pour j=0..4 (LL[0]=n1).
`jeu102` est la moyenne des gains de 100 parties faites avec `jeu2`.

    jeu2(L):={
     local j,g,LL;
     LL:=L,0;
     pour j de 0 jusque 4 faire
       g:=alea(10)+1;afficher(g);
       si g>=LL[j] alors break fsi;
     fpour;
     retourne g;
    }:;
    jeu102(L):={
     local g,j;
     g:=0;
     pour j de 1 jusque 100 faire
       g:=g+jeu2(L);
     fpour;
     retourne evalf(g/100);
    }:;

À vous de trouver la meilleure stratégie !

## 16.2 Le Master-Mind

### 16.2.1 La règle du jeu

L’ordinateur sera ici le codificateur : il choisit une combinaison de 4 couleurs, différentes ou non, parmi les 6 disponibles numérotées de 0 à 5 (noir, rouge, vert, jaune, bleu, magenta). Par exemple (0,5,2,5)
Le joueur doit essayer de deviner la combinaison choisit en donnant une proposition. Par exemple (5,4,2,1).
Le codificateur donne alors son verdict en donnant 1 marqueur noir par couleur se trouvant à la bonne place et un marqueur blanc par couleur trouvée mais ne se trouvant pas à la bonne place. Avec l’exemple il répond 1N et 1B.
Le joueur peut faire au plus nc propositions (en général nc=10).
Variante On peut permettre une septième couleur de numéro 6 (cyan) mais le codificateur ne peut pas choisir la combinaison (6,6,6,6).

### 16.2.2 Le programme du Master-Mind

    masterm(nc):={
    local L,R,R0,n,j,N,B,a;
    L:=[alea(6)$(j=1..4)];
    n:=0;
    while (n<nc) {
    saisir(R);
    R:=[R];n:=n+1;R0:=R;
    N:=0;B:=0;j:=0;
    pour j de 0 jusque 3 faire
    a:=R[j];si a==L[j] alors N:=N+1; fsi;
    fpour;
    if (N==4) alors return "gagne en "+n+" coups";fsi;
    while (0<=size(R)-1){
    a:=R[0];B:=B+min(count_eq(a,R),count_eq(a,L));
    R:=remove(a,R);j:=j+1;
    };
    afficher(R0+", "+N+" N, "+(B-N)+" B");
    }
    return ("perdu " , L);
    }:;

### 16.2.3 Le programme de la variante du Master-Mind

Il faut vérifier que la liste choisie n’est pas (6,6,6,6) avec la fonction :
`nonconst(L,6)` ci dessous :

    nonconst(L,a):={
    local j,n:=size(L);
    pour j de 0 jusque n-1 faire
    si L[j]!=a alors return 1 fsi;
    fpour;
    return 0;
    }
    :;
    mastervariante(nc):={
    local L,R,R0,n,j,N,B,a;
    repeter L:=[alea(7)$(j=1..4)]; jusqua nonconst(L,6);
    n:=0;
    while (n<nc) {
    saisir(R);
    R:=[R];n:=n+1;R0:=R;
    N:=0;B:=0;j:=0;
    pour j de 0 jusque 3 faire
    a:=R[j];si a==L[j] alors N:=N+1; fsi;
    fpour;
    if (N==4) alors return "gagne en "+n+" coups";fsi;
    while (0<=size(R)-1){
    a:=R[0];B:=B+min(count_eq(a,R),count_eq(a,L));
    R:=remove(a,R);j:=j+1;
    };
    afficher(R0+", "+N+" N, "+(B-N)+" B");
    }
    return ("perdu " , L);
    }
    :;

### 16.2.4 Le mastermind avec les couleurs

Le joueur devra maintenant taper les couleurs (ou juste sa première lettre) qu’il choisit (entourée de ‘`"`). On tape pour transformer la liste des couleurs en la liste de leur code.

    conv(L):={
      local d,j,R;
      d:=size(L);
      R:=makelist(0,1,d);
      pour j de 0 jusque d-1 faire
       if L[j][0]=="n" or L[j][0]=="N" alors R[j]:=0;elif
        L[j][0]=="r" or L[j][0]=="R" alors R[j]:=1;elif
         L[j][0]=="v" or L[j][0]=="V" alors R[j]:=2;elif
          L[j][0]=="j" or L[j][0]=="J" alors R[j]:=3;elif
           L[j][0]=="b" or L[j][0]=="B" alors R[j]:=4;elif
            L[j][0]=="m" or L[j][0]=="M" alors R[j]:=5;end;
      fpour;
      return R;
    }:;

On tape pour transformer une liste de code couleur en des carrés de couleur, suivi de disques noir ou blanc qui donnent le résultat de l’essai.

    L2C(l,n,N,B):={
    local d,j,C;
    C:=NULL;
    d:=size(l);
    pour j de 0 jusque d-1 faire
    C:=C,affichage(carre(-5+j/4+(5-n/4)*i,-5+(j+1)/4+(5-n/4)*i),
                                                   l[j]+rempli);
    fpour;
    pour j de 1 jusque N faire
    C:=C,affichage(cercle(-5+(d)/4+j/4+(5-n/4+1/8)*i,0.1),rempli);
    fpour;
    pour j de 1 jusque B faire
    C:=C,cercle(-5+(d+N+j)/4+(5-n/4+1/8)*i,0.08);
    fpour;
    return C;
    }
    :;

Dans le programme `mastermind(nc)`, le joueur devra taper une chaine de 4 lettres sans les guillemets (`"`) qui sont les initiales des noms des couleurs par exemple `rvnn` si vous péférez taper une liste de caractères par exemple `"r","v","n","n"` il faut décommenter `saisir(R); R:=conv([R]);` et commenter la ligne suivante. Le programme remplacera une lettre non valide par `"n"`. On tape si Le joueur peut faire au plus nc propositions :

    mastermind(nc):={
    local L,R,R0,n,j,N,B,a;
    print("jeu du mastermind");
    print("taper 4 couleurs parmi NRVJBM par ex RVNB");
    gl_x=-5.3.2;
    gl_y=-2..5.3;
    ClrGraph();DispG();
    L:=[alea(6)$(j=1..4)];
    n:=0;
    while (n<nc) {
    //saisir(R); R:=conv([R]);
    repeter saisir_chaine("4 couleurs parmi NRJVBM, ex. RRBJ",R); jusqua size(R)==4;
    R:=conv(R);
    n:=n+1;R0:=R;
    N:=0;B:=0;j:=0;
    pour j de 0 jusque 3 faire
    a:=R[j];si a==L[j] alors N:=N+1; fsi;
    fpour;
    si (N==4) alors
    L2C(R0,n,4,0),L2C(L,n+2,0,0);DispG();
    return afficher("gagne en "+n+" coups");
    fsi;
    while (0<=size(R)-1){
    a:=R[0];B:=B+min(count_eq(a,R),count_eq(a,L));
    R:=remove(a,R);j:=j+1;
    };
    B:=B-N;
    L2C(R0,n,N,B);DispG();
    }
    L2C(L,n+2,0,0);
    return afficher(("perdu " , L));
    }:;

A vous de programmer la variante avec les couleurs !

## 16.3 Les 4 dés du jeu de Win

On considère les 4 dés suivants :

- les faces du dé `A` ont comme points : `0,0,4,4,4,4`,
- les faces du dé `B` ont comme points : `1,1,1,5,5,5`,
- les faces du dé `C` ont comme points : `2,2,2,2,6,6`,
- les faces du dé `D` ont comme points : `3,3,3,3,3,3`,

La partie se compose de 12 lancers.
Pour une partie, chacun des joueurs choisit un dé. À chaque lancer, celui qui a le meilleur score marque 1 point. La partie se compose de 12 lancers.
On veut simuler ce jeu pour que l’on puisse jouer contre l’ordinateur. L’ordinateur tire au hasard un dé, vous donne son choix, puis vous choisisez un dé parmi les 3 dés qui restent. Puis vous jouez....
Quel dé faut-il choisir pour gagner contre l’ordinateur ?
On se reportera à la section 9.3 pour voir l’analyse du jeu.
On utilise les listes A,B,C,D pour representer chaque dé, et pour jouer, on tape :

    jeuwin():={
    local deo,dem,po,pm,scoro,j,A,B,C,D;
    deo:=char(rand(4)+65);
    print("j'ai choisi le de "+ deo);
    A:=[0,0,4,4,4,4];
    B:=[1,1,1,5,5,5];
    C:=[2,2,2,2,6,6];
    D:=[3,3,3,3,3,3];
    deo:=expr(deo);
    repeter saisir("votre choix",dem);
    jusqua dem!=deo;
    scoro:=0;
    for (j:=0;j<12;j++){
    po:=deo[rand(6)];
    pm:=dem[rand(6)];
    print(po,pm);
    if (po>pm) scoro:=scoro+1;
    }
    return [scoro,12-scoro];
    }
    :;

Ma stratégie :
Si l’ordinateur choisit le dé A, je choisis le dé B,
Si l’ordinateur choisit le dé B, je choisis le dé C,
Si l’ordinateur choisit le dé C, je choisis le dé D,
Si l’ordinateur choisit le dé D, je choisis le dé A,
on tape `jeuwins()` qui joue selon cette stratégie.
Pour connaitre le score de n parties selon cette stratégie, on tape `jeuxwin(n)` :

    jeuwins():={
    local deo,dem,po,pm,scoro,j,A,B,C,D;
    A:=[0,0,4,4,4,4];
    B:=[1,1,1,5,5,5];
    C:=[2,2,2,2,6,6];
    D:=[3,3,3,3,3,3];
    deo:=rand(4);
    dem:=irem(deo+1,4);
    scoro:=0;
    deo:=expr(char(deo+65));
    dem:=expr(char(dem+65));
    for (j:=0;j<12;j++){
    po:=deo[rand(6)];
    pm:=dem[rand(6)];
    if (po>pm) scoro:=scoro+1;
    }
    return [scoro,12-scoro];
    }
    :;
    jeuxwin(n):={
    local scoro,j;
    scoro:=0;
    pour j de 1 jusque n faire
    scoro:=scoro+jeuwins()[0];
    fpour;
    return [scoro,12*n-scoro];
    }:;

On tape :
`jeuxwin(200)`
On obtient :
`[836,1564]`
0n a 836/2400.,1564/2400.∼ 0.348333333333,0.651666666667 soit environ 1/3,2/3.

## 16.4 Un jeu de cartes

Un joueur reçoit 4 cartes d’un jeu de 32 cartes.

- si il a un carré il reçoit 5082 euros
- si il a un brelan (3 cartes de même hauteur) il reçoit 50 euros
- si il a deux paires il reçoit 45 euros
- si il a une paire il reçoit 5082 euros
- sinon il doit payer 10 euros

Ce jeu est-il équitable ?
Faire un programme qui permet de faire n parties de ce jeu.

Il y a `comb(32,4)=35960` mains possibles.

- IL y a `comb(8,1)=8` possibilités d’avoir un carré.
  La probabilité d’avoir un carré est donc : `8/35960=1/4495`
- IL y a `comb(8,1)*comb(4,3)*comb(28,1)=896` possibilités d’avoir un brelan.
  La probabilité d’avoir un brelan est donc : `896/35960=112/4495`
- IL y a `comb(8,1)*comb(4,2)*comb(7,1)*comb(4,2)/2=1008` possibilités d’avoir deux paires.
  La probabilité d’avoir deux paires est donc :`1008/35960=126/4495`
- IL y a `comb(8,1)*comb(4,2)*comb(28,1)*comb(24,1)/2=16128` (ou encore `comb(8,1)*comb(4,2)*(comb(28,2)-comb(7,1)*comb(4,2))=16128`) possibilités d’avoir une paire.
  La probabilité d’avoir une paire est donc :`16128/35960=2016/4495`
- On utilise la probabilité complémentaire de ne pas avoir ni carré, ni brelan, ni paires : `1-(1+112+126+2016)/4495=448/899`

Le jeu est équitable si l’espérance de gain est nulle.
On tape :
`(5082+112*50+126*45+3*2016)/4495-10*448/899`
On obtient `0`
Le jeu est donc équitable.
On tape le programme en representant une carte par un nombre de 0 à 31 0..7 pour les trèfles, 8..15 pour les carreaux, 16..23 pour les cœurs et 24..31 pour les piques. On tire au hasard 4 nombres a,b,c,d différents parmi 0..31 (`hasard(4,0..31)`), on aura un carré si :
`irem(a,8)==irem(b,8)==irem(c,8)==irem(d,8)`

    cartes(n):={
      local j,s,a,b,c,d,na,nb,nc,L;
      s:=0;
      pour j de 1 jusque n faire
        a,b,c,d:= irem(hasard(4,0,31),8);
        L:=[a,b,c,d];
        //print(L);
        na:=count(x->x==a,L);
        nb:=count(x->x==b,L);
        nc:=count(x->x==c,L);
        if na==4 alors s:=s+5082; elif
          na==3 or nb==3 alors s:=s+50; elif
            na==2 and nb==2 and nc==2 alors s:=s+45; elif
              na==1 and nb==1 and nc==1 alors s:=s-10;
               else
                s:=s+3;
              end;
            fpour;
            return s;}
          :;

On fait le graphe des gains pour p parties de n tirages.

    gain(p,n):={
    local G,k,s,c;
    G:=NULL;
    s:=0
    pour k de 1 jusque p faire
    c:=cartes(n);
    //print(c);
    G:=G,point(k,c);
    s:=s+c;
    fpour;
    print (evalf(s/(p*n)));
    return G;
    }:;