Construisez un générateur de puzzle de glace + solveur

13

Dans Twitch Plays Pokémon , l'un des obstacles les plus ennuyeux que l'on puisse rencontrer est un puzzle de glace, où vous devez vous déplacer d'un endroit à un autre en glissant tout le long dans une direction jusqu'à ce que vous heurtiez un mur ou un rocher.

Votre tâche consiste à créer un programme qui générera un casse-tête de glace difficile et aléatoire.

Votre programme acceptera trois numéros, M, Net P, en entrée (avec 10 <= M <= 30, 15 <= N <= 40et 0 <= P < 65536):

12 18

et affichera:

  • Un Mde Ngrille consistant en .et Oreprésentant respectivement la glace et un rocher.
  • Un marqueur de position représentant d'où le puzzle est entré. Ce marqueur de position est constitué d'une lettre L, R, T, ou B, soit à gauche, droite, haut, et en bas, suivi d'un nombre représentatif de la position (à gauche ou en haut) sur le côté devant être entré à partir.
  • Un marqueur de position similaire représentant la sortie du puzzle.
  • La plus courte solution du puzzle, consistant en une séquence de L, R, U, et , Drespectivement.

Exemple de sortie:

..O...O...........
............O.....
..O...............
.......O..........
..................
...........O......
O..O...........O..
..........O.......
..O..........O....
........O.........
O....O.........O..
............O.....
R 4
B 5
LDLDRULD
(Note that this output is actually invalid because it is not actually long enough.)

Pour une entrée Met N, la solution du puzzle doit avoir au moins des min(M, N)étapes et déplacer au moins un 2 (M + N)total d'espaces. (Pour référence, le puzzle ci - dessus se déplace un total de 12 étapes, le déplacement 69 des espaces.) Votre générateur de puzzle doit générer un autre Mpar Npuzzle avec une voie de solution différente ( par exemple une séquence différente d'étapes pour chaque solution) pour chaque graine P.

  • Notez que l'exigence d'un chemin de solution différent est d'éviter les solutions qui tentent de générer systématiquement des chemins de roche, comme la solution de Claudiu ici . S'il y a deux ou trois paires de solutions identiques en raison des caprices de l'aléatoire, ce sera correct, tant que le programme n'essaie pas intentionnellement de générer systématiquement des puzzles avec la même séquence de mouvements.

Le code le plus court pour effectuer les gains ci-dessus.

Joe Z.
la source
2
Je ne peux pas comprendre l'objectif: "vous devez voyager d'un endroit à un autre en glissant complètement dans une direction jusqu'à ce que vous heurtiez un mur ou un rocher". Est-il bon de frapper des murs ou des rochers? Où avez-vous l'intention d'aller dès le départ? Si vous frappez un rocher, le jeu se termine-t-il? Que se passe-t-il lorsque vous heurtez un mur? Est-ce juste moi ou les directions ne sont-elles pas claires?
DavidC
3
Oh, de vieux souvenirs de Pokémon Gold et Silver ici. Trouvez la sortie, prenez HM07 et allez à Blackthorn City.
Victor Stafusa
3
Cela me rappelle les niveaux de glace dans Chip's Challenge .
luser droog
1
Pourquoi ne pas utiliser >et <(ou n'importe quel caractère) pour l'entrée et la sortie? Les puzzles seront plus faciles à lire.
AL
1
En fait, votre sortie d'échantillon n'est pas valide - le chemin le plus court est celui LDLDRULDqui ne fait que 8 étapes
Claudiu

Réponses:

5

Python, 672 548 caractères, des puzzles plus intéressants

Bien que respectant strictement les règles, mon autre programme Python bat celui-ci, j'ai décidé d'en écrire un qui générerait de toute façon des puzzles plus intéressants. C'est ici:

R=range;import random as J;X=J.randint
x=(0,1,-1,0);y=x[2:]+x
g=lambda r,c:(0<=r<H)+(0<=c<W)>1and f[r][c]or x[(r,c)in(A,E)]
l=lambda r,c:g(r+y[d],c+x[d])<1and(r,c)or l(r+y[d],c+x[d])
H,W,P=input();J.seed(P)
while 1:
 A=(-1,X(0,W));E=(H,X(0,W));f=[[X(0,7)for _ in R(W)]for _ in R(H)]
 q=[(A,'')];n=z={}
 while q and n!=E:
    n,O=q.pop()
    for d in R(4):
     N=l(*n)
     if g(n[0]+y[d],n[1]+x[d])and N not in z:q[:0]=[(N,O+"URLD"[d])];z[N]=1
 if(n==E)*len(O)>min(H,W):print"\n".join(''.join('O.'[c>0]for c in T)for T in f),"\nT",A[1],"\nB",E[1],"\n",O;break

Les niveaux d'indentation sont espace, tabulation, tabulation + espace.

Échantillons :

$ echo [10,15,0] | python ice2.py
.....OO........
...............
...O....O.OO..O
...........O...
..O....O.......
.......O....O..
....O..........
.............O.
..............O
...............
T 1
B 10
DLURDRURULDRD

Il utilise Pcomme graine, donc chacun Pgénérera le même puzzle, et chaque différent Pest extrêmement susceptible d'être différent:

$ echo [10,15,1] | python ice2.py
.OOO.O.........
...O......O.O.O
.......O.......
..O..........OO
.....O.........
.............O.
.O.............
.O............O
O....O.........
......O........
T 14
B 8
DLDRDLURULD

Il fonctionne assez rapidement jusqu'à des tailles de M=25,N=40mais au-delà, il devient vraiment lent. Il devrait théoriquement fonctionner M=30, N=40si vous le laissez fonctionner suffisamment longtemps. J'ai écrit manuellement dans le sentier ici car il est difficile à suivre - le programme sort juste le puzzle.

$ echo [25,40,0] | python ice2.py
                   *
...................dO....urrrO..O..O....
....O.....O........dO....u..dO..........
..........O.....O..d....Ou.Odrrrrrrrrrrr
...........O.......d.O..Ou..O.....OOllld
.O....O.OO.........drrrrrrO....Olllud..O
O......O...O.O.....O............dO.ud...
O........OO..........O.........Od..ud..O
.........O......................d..ud...
....O.....O.O....O.....O........d..ud.O.
.....O..O...................O...d..udO..
.........O.........O..O.........d..ud...
.......O.O...O..O.OO....O...OOlldOOld...
........Olllllllllu....OO.OO..dOO...O...
.O.O....Od........u......O....d..O...O..
..O....O.d........u..O........d..O..O...
....O....d..O.....uO.....O....d.........
.........d........u...........d.........
.........d....O...u.O..O.....Od.O.......
........Od...O....u...........d.........
.O.....OuxrrrrO...u...OOOO..O.d.........
........udO..dO.O.u...........d.........
O..O.O..ud...d..urrO..........d.O...O...
........ud...d..u.O.O........Od..O...O..
..OO....ud..Od..u......OllllludO.....O..
..O....OldO..dOOlllllllld...Old...O..O..
             *
T 19
B 13
DRURDRDLDLULDLDLULDLURULDLURD

Explication :

Le programme boucle, générant une position de départ aléatoire en haut, une position de fin aléatoire en bas et une grille aléatoire avec une 12.5%chance pour un rocher à n'importe quel endroit donné. Il résout ensuite le casse-tête avec une recherche en premier et si la solution existe et est plus grande min(H,W), elle s'imprime et se ferme.

Claudiu
la source
4

Java - 2632

Alors que j'admire la pureté technique de la réponse de Claudiu , j'ai décidé de m'essayer à faire des puzzles un peu plus difficiles;)

Étapes de base (assez simples):

Randomize entry location
Step forward
For min(m,n)-1 steps:
    Rotate left or right
    Slide until I hit something or go a random distance
    Place a rock in front of stopping location
If I can slide straight to any wall:
    Slide to exit
Else
    Create another step and try again

If at any step I get trapped, start over
If BFS finds shorter path, start over

Je marque également chaque place comme «nogo» lorsque je glisse. Si je me retrouve sur un spot de nogo (ou juste en face de celui qui signifierait qu'un rocher y allait), c'est une étape invalide.

Donc, fondamentalement, l'idée est de générer au hasard un grand nombre de cartes et de conserver la première qui est valide. Je prévois de rendre cela plus intelligent (retour en arrière, etc.), mais cela fonctionne bien en ce moment. Cela pourrait également réduire le code redondant, nous verrons.

En l'état, il génère presque instantanément de petites cartes (15 x 10), des cartes moyennes (30 x 20) en quelques secondes et de grandes (40 x 30) en un temps aléatoire compris entre 20 secondes et 20 minutes, selon la graine. Il teste entre 300k-500k maps / seconde sur ma machine, selon la taille.

Note latérale: Parfois, les cartes ne sont pas trop dures, simplement parce qu'il n'y a que autant de roches que de marches, et à moins que la marche ne vous mène à un mur, la plupart du temps, il n'y a qu'une seule option si vous voulez frapper une vraie pierre. Je corrigerai cela plus tard en plaçant des roches "aléatoires" dans des endroits sûrs une fois toutes les étapes tracées. Étant donné que les taches nogo sont déjà marquées, cela devrait être assez simple. Pour l'instant, profitez simplement de ces exemples:

Sortie montrant différentes tailles / graines:

$ java I 30 20 6851              $ java I 15 10 1     $ java I 15 10 65513  

............................O.      .......O.......     ....O..........     
..............................      ...............     ...............     
..............................      .........O.....     .........O.....     
..........O......O............      .............O.     ..............O     
...............O...........O..      ...............     ...............     
..............................      .......O.......     .....O.O.......     
..............................      O..............     ...............     
........................O.....      ...............     ..........O....     
..............................      ...............     O..............     
...O.......................O..      ......O........     ...............     
O...............O.OO..........          
..............O..........O....          
...........O..................      T 14                R 6         
....O.........................      T 7                 T 14            
..............................      DLDLULURU           LULDLDRURU
..............................
..............................
.................O............
.O............................
..............................


B 28
R 9
ULURDLDLDRURDLDRURUR

Taille max 40x30:

$ java I 40 30 2

........................................
........................................
........................................
........................................
................O.......................
..........O.............................
........................................
.......O................................
.....................O..........O.......
......................O.................
.................................O......
......................................O.
........................................
........................................
..............................O.........
...........O............................
........................................
.......................................O
.........O...................O..........
....................O...................
...............................O........
............O..O......................O.
......O...........O.....................
..................O....O................
..................................O.....
........................................
..............................O.........
.....................................O..
...........O............................
...................O....................

B 19
B 11
URURDLULULDRDRDLULDLDLULURDLD

Golfé:

import java.util.*;import java.awt.*;class I{int m,n,p,g,a[][],b[][];Random r;Point s,e,c;ArrayList<Integer>z;void Q(String q,int l){if(l>0)System.out.println(q);else System.out.print(q);}void G(String[]y){m=Integer.valueOf(y[0]);n=Integer.valueOf(y[1]);p=Integer.valueOf(y[2]);r=new Random(p);Q("",1);int o=0,i,j,u=0;char t,f[]={85,76,68,82};while(o<3){if(++u%20000==0)Q("\r#"+u,0);a=new int[m+2][n+2];b=new int[m+2][n+2];for(i=0;i<m+2;i++)for(j=0;j<n+2;j++)if(i==0||i==m+1||j==0||j==n+1)a[i][j]=2;s=new Point();int e=r.nextInt(m*2+n*2);if(e<m*2){s.x=e%m+1;s.y=e<m?0:n+1;}else{s.y=(e-m*2)%n+1;s.x=(e-m*2)<n?0:m+1;}if(s.x<1)g=3;else if(s.x>m)g=1;else if(s.y<1)g=2;else if(s.y>n)g=0;a[s.x][s.y]=0;c=new Point(s);z=new ArrayList<Integer>();z.add(g);for(i=0;i++<Math.min(m,n)-1;)if(N()<1&&N()<1)break;o=((z.size()>=Math.min(m,n)-1)?1:0)+F()+((V()==z.size())?1:0);}Q("\r",0);for(j=1;j<n+1;j++){for(i=1;i<m+1;i++)Q(String.valueOf(a[i][j]>0?'O':'.'),0);Q("",1);}Q("\n\n",0);if(s.x<1||s.x>m){t=s.x<1?'L':'R';u=s.y;}else{t=s.y<1?'T':'B';u=s.x;}Q(t+" "+u,1);if(e.x<1||e.x>m){t=e.x<1?'L':'R';u=e.y;}else{t=e.y<1?'T':'B';u=e.x;}Q(t+" "+u,1);for(i=0;i<z.size();)Q(String.valueOf(f[z.get(i++)]),0);Q("",1);}public static void main(String[]a){new I().G(a);}int F(){int c=0;while(C()<1&&c++<10)if(N()<1)return 0;return e==null?0:1;}int C(){int d=g<2?-1:1;if(g%2<1){int y=c.y;while(y>0&&y<n+1){y+=d;if(a[c.x][y]==1)return 0;}e=new Point(c.x,y);}else{int x=c.x;while(x>0&&x<m+1){x+=d;if(a[x][c.y]==1)return 0;}e=new Point(x,c.y);}a[e.x][e.y]=0;return 1;}int V(){if((s.x-e.x)+(s.y-e.y)<2)return 0;Queue<Point>q=new ArrayDeque<Point>();Queue<Integer>d=new ArrayDeque<Integer>();a[s.x][s.y]=-2;q.add(s);d.add(0);while(q.size()>0){Point t=q.poll();int h=d.poll(),i=0;if(t.equals(e))return h;for(;i<4;i++){Point n=S(a,t,i<2?0:1,i%2<1?-1:1,99,1);if(a[n.x][n.y]==-2)continue;a[n.x][n.y]=-2;q.add(n);d.add(h+1);}}return 0;}int N(){Point q;int d=g<2?-1:1,x,y;System.arraycopy(a,0,b,0,a.length);q=S(b,c,g,d,r.nextInt((g%2<1?n:m)/2)+2,0);if(q.x<1||q.y<1||q.x>m||q.y>n||q.equals(c)||b[q.x][q.y]!=0)return 0;x=q.x;y=q.y;if(g%2<1)y+=d;else x+=d;if(b[x][y]<0)return 0;b[q.x][q.y]=-1;b[x][y]=1;int f=r.nextInt(2)<1?-1:1;g=g%2<1?(f<0?1:3):(g=f<0?0:2);c=q;System.arraycopy(b,0,a,0,a.length);z.add(g);return 1;}Point S(int[][]u,Point f,int w,int d,int q,int s){int i=1,x=f.x,y=f.y;for(;i<=q;i++){if(w%2<1)y=f.y+i*d;else x=f.x+i*d;if(e!=null&&e.x==x&&e.y==y)return e;if(y<0||y>n+1||x<0||x>m+1)return f;if(s<1&&u[x][y]<1)u[x][y]=-1;if(u[x][y]>0){if(w%2<1)y-=d;else x-=d;return new Point(x,y);}}if(w%2<1)return new Point(f.x,f.y+i*d);else return new Point(f.x+i*d,f.y);}}

Avec des sauts de ligne:

import java.util.*;
import java.awt.*;

class I{
    int m,n,p,g,a[][],b[][];
    Random r;
    Point s,e,c;
    ArrayList<Integer>z;

    void Q(String q,int l){if(l>0)System.out.println(q);else System.out.print(q);}

    void G(String[]y){
        m=Integer.valueOf(y[0]);
        n=Integer.valueOf(y[1]);
        p=Integer.valueOf(y[2]);
        r=new Random(p);
        Q("",1);

        int o=0,i,j,u=0;
        char t,f[]={85,76,68,82};
        while(o<3){
            if(++u%20000==0)
                Q("\r#"+u,0);

            a=new int[m+2][n+2];
            b=new int[m+2][n+2];
            for(i=0;i<m+2;i++)
                for(j=0;j<n+2;j++)
                    if(i==0||i==m+1||j==0||j==n+1)
                        a[i][j]=2;

            s=new Point(); 
            int e=r.nextInt(m*2+n*2);
            if(e<m*2){
                s.x=e%m+1;
                s.y=e<m?0:n+1;
            }else{
                s.y=(e-m*2)%n+1;
                s.x=(e-m*2)<n?0:m+1;
            }
            if(s.x<1)g=3;
            else if(s.x>m)g=1;
            else if(s.y<1)g=2;
            else if(s.y>n)g=0;

            a[s.x][s.y]=0;
            c=new Point(s);
            z=new ArrayList<Integer>();
            z.add(g);

            for(i=0;i++<Math.min(m,n)-1;)
                if(N()<1&&N()<1)
                        break;
            o=((z.size()>=Math.min(m,n)-1)?1:0)+F()+((V()==z.size())?1:0);
        }

        Q("\r",0);
        for(j=1;j<n+1;j++){
            for(i=1;i<m+1;i++)
                Q(String.valueOf(a[i][j]>0?'O':'.'),0);
            Q("",1);
        }
        Q("\n\n",0);
        if(s.x<1||s.x>m){
            t=s.x<1?'L':'R';
            u=s.y;
        }else{
            t=s.y<1?'T':'B';
            u=s.x;
        }
        Q(t+" "+u,1);
        if(e.x<1||e.x>m){
            t=e.x<1?'L':'R';
            u=e.y;
        } else {
            t=e.y<1?'T':'B';
            u=e.x;
        }
        Q(t+" "+u,1);
        for(i=0;i<z.size();)
            Q(String.valueOf(f[z.get(i++)]),0);
        Q("",1);
    }

    public static void main(String[]a){
        new I().G(a);
    }

    int F(){
        int c=0;
        while(C()<1&&c++<10)
            if(N()<1)
                return 0;
        return e==null?0:1;
    }

    int C(){
        int d=g<2?-1:1;
        if(g%2<1){
            int y=c.y;
            while(y>0&&y<n+1){
                y+=d;
                if(a[c.x][y]==1)
                    return 0;
            }
            e=new Point(c.x,y);
        }else{
            int x=c.x;
            while(x>0&&x<m+1){
                x+=d;
                if(a[x][c.y]==1)
                    return 0;
            }
            e=new Point(x,c.y);
        }
        a[e.x][e.y]=0;
        return 1;
    }


    int V(){
        if((s.x-e.x)+(s.y-e.y)<2)
            return 0;
        Queue<Point>q=new ArrayDeque<Point>();
        Queue<Integer>d=new ArrayDeque<Integer>();
        a[s.x][s.y]=-2;

        q.add(s);
        d.add(0);
        while(q.size()>0){
            Point t=q.poll();
            int h=d.poll(),i=0;
            if(t.equals(e))
                return h;
            for(;i<4;i++){
                Point n=S(a,t,i<2?0:1,i%2<1?-1:1,99,1);
                if(a[n.x][n.y]==-2)
                    continue;
                a[n.x][n.y]=-2;
                q.add(n);d.add(h+1);
            }
        }
        return 0;
    }


    int N(){
        Point q;
        int d=g<2?-1:1,x,y;
        System.arraycopy(a,0,b,0,a.length);
        q=S(b,c,g,d,r.nextInt((g%2<1?n:m)/2)+2,0);      
        if(q.x<1||q.y<1||q.x>m||q.y>n||q.equals(c)||b[q.x][q.y]!=0)
            return 0;
        x=q.x;
        y=q.y;
        if(g%2<1)
            y+=d;
        else
            x+=d;
        if(b[x][y]<0)
            return 0;
        b[q.x][q.y]=-1;
        b[x][y]=1;
        int f=r.nextInt(2)<1?-1:1;          
        g=g%2<1?(f<0?1:3):(g=f<0?0:2);
        c=q;
        System.arraycopy(b,0,a,0,a.length);
        z.add(g);
        return 1;
    }

    Point S(int[][]u,Point f,int w,int d,int q,int s){
        int i=1,x=f.x,y=f.y;
        for(;i<=q;i++){
            if(w%2<1)
                y=f.y+i*d;
            else
                x=f.x+i*d;
            if(e!=null&&e.x==x&&e.y==y)
                return e;
            if(y<0||y>n+1||x<0||x>m+1)
                return f;
            if(s<1&&u[x][y]<1)
                u[x][y]=-1;
            if(u[x][y]>0){
                if(w%2<1)
                    y-=d;
                else
                    x-=d;
                return new Point(x,y);
            }
        }
        if(w%2<1)
            return new Point(f.x,f.y+i*d);
        else
            return new Point(f.x+i*d,f.y);              
    }
}
Géobits
la source
Impossible while(o<3){...;o=...;}être for(;o<3;o=...){...;}, sauver un octet?
Jonathan Frech
if(w%2<1)return new Point(f.x,f.y+i*d);else return new Point(f.x+i*d,f.y);-> return new Point(f.x+(w%2<1?0:i*d),f.y+(w%2<1?f.y:0));.
Jonathan Frech
3

Python, 235 206 185 185 176 caractères

H,W,P=input()
t=''
for x in range(16):t+=".O"[(P>>x)%2]
for n in[t[1:],t[0],"O","...O"]+["."]*(H-5)+[".O.."]:print(n*W)[:W]
print"B 1\nR",(H,3)[-W%4/2],"\n",("URDR"*W)[:W+W%2]

Utilisation :

L'entrée se fait via stdin du formulaire [M, N, P].

$ echo [14, 17, 2] | python ice.py
O..............O.
.................
OOOOOOOOOOOOOOOOO
...O...O...O...O.
.................
.................
.................
.................
.................
.................
.................
.................
.................
.O...O...O...O...
B 1
R 3
URDRURDRURDRURDRUR

Vous avez dit que les cartes devaient être différentes pour chaque graine P... et elles sont:

$ echo [14, 17, 233] | python ice.py
..O.OOO..........
OOOOOOOOOOOOOOOOO
OOOOOOOOOOOOOOOOO
...O...O...O...O.
.................
.................
.................
.................
.................
.................
.................
.................
.................
.O...O...O...O...
B 1
R 3
URDRURDRURDRURDRUR
$ echo [14, 17, 65133] | python ice.py
.OO.OO..OOOOOOO.O
OOOOOOOOOOOOOOOOO
OOOOOOOOOOOOOOOOO
...O...O...O...O.
.................
.................
.................
.................
.................
.................
.................
.................
.................
.O...O...O...O...
B 1
R 3
URDRURDRURDRURDRUR

Et un exemple avec une taille différente:

$ echo [10, 15, 65133] | python ice.py
.OO.OO..OOOOOOO
OOOOOOOOOOOOOOO
OOOOOOOOOOOOOOO
...O...O...O...
...............
...............
...............
...............
...............
.O...O...O...O.
B 1
R 10
URDRURDRURDRURDR

Répond à tous les critères objectifs fournis:

  • Chacun Pmène à un puzzle différent
  • Il n'y a qu'une seule solution, c'est donc la plus courte
  • La solution prend des N + N%2mesures, ce qui est au moinsN
  • La solution prend toujours plus que 2 (M + N)l'espace total

Explication :

Chaque ligne est construite en répétant un certain Wtemps d' élément de chaîne et en limitant la longueur à W(j'utilise Het Wau lieu de Met N).

Les deux premières lignes dépendent Ppour rendre chaque puzzle unique. Fondamentalement, notez que cela Ptient dans un entier non signé 16 bits. Je convertis Pen binaire, en utilisant .pour 0 et Opour 1:

t=''
for x in range(16):t+=".O"[(P>>x)%2]

Le premier élément de ligne est 15 derniers bits, t[1:]tandis que le deuxième élément de ligne est le premier bit, t[0]. Je ne pouvais pas tout mettre sur une seule ligne car la largeur minimale est de 15, ce qui ne conviendrait pas aux 16 bits si P> 32767. Ainsi, les deux premières lignes représentent de manière unique chacune des valeurs possibles de P.

La troisième ligne est un mur plein afin que la valeur de Pn'affecte pas la solution.

Suivez ensuite les éléments réels du labyrinthe. Cette ligne les imprime tous, en les répétant jusqu'à la casquette. Le résultat est comme vous le voyez ci-dessus:

for n in[t[1:],t[0],"O","O..."]+["."]*(H-5)+["..O."]:print(n*W)[:W]

Le reste cherchait juste à résoudre le labyrinthe généré dynamiquement. Cela dépend uniquement de la largeur du labyrinthe. J'ai noté que les solutions, pour une largeur donnée, étaient:

  W  | solution 
-----+---------
  1  | UR
  2  | UR
  3  | UR DR
  4  | UR DR 
  5  | UR DR UR
  6  | UR DR UR
  7  | UR DR UR DR
  8  | UR DR UR DR

etc. Par conséquent, il est simplement URDRrépété et coupé au bon endroit W+W%2,.

print"B 1\nR",(H,3,3,H)[W%4],"\n",("URDR"*W)[:W+W%2]
Claudiu
la source
1
comment au 33e bit d'un entier cela fonctionne-t-il?
masterX244
@ masterX244: Beaucoup, beaucoup de golf ... exploitant essentiellement la nature répétitive de la sortie et faisant quelques calculs pour s'assurer que tout s'aligne correctement
Claudiu
se demandant surtout comment se fait le "hasard" (PS le downvote ne vient pas de moi)
masterX244
@ masterX244: ah gotcha. J'ajouterai une explication
Claudiu
1
Je ne le pensais pas de manière négative. C'est intelligent à coup sûr, j'espère juste que les développeurs de jeux en herbe n'utilisent pas cela pour des puzzles réels: p
Geobits