Faisons une carte de donjon

9

Il y a longtemps, lorsque je passais plus de temps à jouer au RPG, l'un des problèmes de certains joueurs était de suivre les mouvements du groupe et de dessiner la bonne carte. Je viens donc avec une idée, pour vérifier comment vous en êtes arrivés à régler ce problème.

La tâche consiste à écrire une fonction, qui prend comme paramètre d'entrée la liste des directions (passées comme structure de votre choix) ^v<>, afficher la carte du donjon. Dans l'exemple pour l'entrée: la >>>vvv<<<^^^sortie sera:

+----+               +----+
|    |               |>>>v|
| ++ |               |^++v|
| ++ |  because      |^++v|
|    |               |^<<<|
+----+               +----+

Cas de test

>>>>>>vvvvv<<<<^^^>>v



 +-------+
 |       |
 +-+---+ |
   |   | |
   | + | |
   | +-+ |
   |     |
   +-----+


^^^^^vvv<<<^^vv>>>>>>>>vv>><<^^^^v>>>>v^<^

          +-+ 
       +-+| | +-++-+
       | || | | ++ ++
       | ++ +-+     |
       |        +-+ |
       +--+ +-+ +-+-+
          | | |   |
          +-+ +---+

Comme c'est un défi de code de golf, le code le plus court gagne.

Bon golf.

EDIT Désolé pour l'édition tardive, je n'ai pas eu beaucoup de temps récemment.

La carte est générée en fonction du mouvement. Il ne doit contenir que des couloirs visités lors de la marche. Par conséquent, la création d'une grande pièce ne sera pas une réponse valable.

Il y a trois symboles valides sur la carte:

  • | mur vertical
  • | mur horizontal
  • + intersection du mur vertical et horizontal.

La longueur maximale du chemin est de 255 caractères (mais si vous le pouvez, ne vous limitez pas).

Plus de cas de test:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

 +--+
 |  |
 |  |
 +--+

J'espère que maintenant tout est clair.

user902383
la source
3
Vous devez fournir une description de la tâche. Les deux cas de test ne sont même pas traités d'une manière qui semble cohérente - le premier ajoute une région déconnectée sans raison apparente.
feersum
3
Votre deuxième exemple a une pièce fermée, ce que je pensais initialement parce que la bordure extérieure devrait être rectangulaire, mais le troisième exemple réfute cette idée. Veuillez utiliser le bac à sable pour obtenir des commentaires sur un défi avant de publier.
El'endia Starman
2
Excellent. Je suggérerais toujours d'être explicite sur la façon dont le donjon est construit à partir des mouvements.
El'endia Starman
1
Qu'entendez-vous par «afficher la carte»? Le retour de la carte à partir d'une fonction est-il autorisé?
Paul Schmitz
3
Cela semble intéressant. Avez-vous une chance de le modifier pour le rouvrir? Choses à regarder en particulier: à partir des exemples, il semble que cela ne vous dérange pas d'espace supplémentaire autour de la sortie, mais il serait bon de clarifier. De plus, si vous décrivez explicitement l'apparence du mur et répondez à la question du lait, cela devrait la rendre suffisamment claire. Une chose que je pense que vous n'avez pas couverte est quelle sortie vvv>>^^^<<produirait (croix? Tuyaux?)
Dave

Réponses:

3

Javascript (ES6), 261 254 243 octets

s=>{v=Array(w=32);p=526;b=n=>v[n>>5]&(1<<(n&31));B=(n,i)=>b(p+n)|b(p-n)?i:0;[...0+s].map(c=>v[(p+=[0,1,-1,w,-w]['0><v^'.indexOf(c)])>>5]|=1<<(p&31));for(z='',p=0;p<w*w;z+=' |-+'[b(p)?0:B(1,1)|B(w,2)||B(31,3)|B(33,3)],p++%w||(z+=`
`));return z}

JSFiddle

Arnauld
la source
Vous pouvez supprimer le returnen remplaçant le ;par ,et le {}avec()
Cyoce
@Cyoce - Il y a une forboucle qui ne peut pas être intégrée de cette façon.
Arnauld
puis remplacez le {par eval("et }par ")pour supprimer le code de retourgolf.stackexchange.com/a/80967/41042
Cyoce
@Cyoce - Malheureusement, je pense que j'aurais besoin d'échapper au saut de ligne littéral comme '\\n'si je le faisais. Si je compte correctement, cela mène à +1 octet. Ou existe-t-il une meilleure façon d'intégrer le saut de ligne dans l'évaluation?
Arnauld
Vous n'en auriez besoin que \npuisque les chaînes de modèle prennent en charge les nouvelles lignes littérales, mais cela le laisserait toujours au même nombre d'octets.
Eh
3

C, 246 octets

n,y,*g,*p;main(c,v)char**v;{for(n=c*2+3,g=calloc(n*n,8),p=g+(n+1)*(c+1);c--;y=*v[c],p-=(y>70?n:1)*(y%5%4?-1:1))*p=1;for(y=n-1;--y;)for(c=n-1;c--;putchar(c?" |-++|-+"[*p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4]:10))p=g+y*n+c;}

Prend la saisie sous forme de caractères séparés, par exemple:

./mapper '>' '>' '>' 'v' 'v' 'v' '<' '<' '<' '^' '^' '^'

Ou plus commodément, ce format (intentionnellement non cité!):

./mapper $(echo '>>>vvv<<<^^^' | fold -w1)

Ou pour une entrée aléatoire (assez inefficace):

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 10 | fold -w1)

Et enfin, utiliser awkpour recadrer le résultat signifie que nous pouvons devenir beaucoup plus gros:

./mapper $(LC_CTYPE=C tr -dc '0-3' < /dev/urandom | tr '0123' '<>^v' | head -c 500 | fold -w1) | awk '/[^ ]/{l=match($0,"\\+");if(l&&(l<L||!L))L=l;v[i++]=$0}END{for(;j<i;){l=v[j++];print substr(l,L,match(l," *$")-L)}}'

 +-----+
 |     |
 |     +-+  +-----+
 |       |+-+     |
++       +|      ++
|         |      |
|         +      +-+
+--+               |
 +-+               +--+
 |     ++             |
 +-+  +-++           +-+
   ++   |+--+          |
    +-+ | |        ++  |
     ++ | ++   + +--+ ++
     |  |  +---|      |
     |  |     ++  +---+
     ++ |-+   |   |
      | | +--+-+  |
      | +    +    |
      |        +--+
      +--------+

Sorties vers sortie standard. Utilise le fait que le remplissage est autorisé autour de la carte (produit une carte qui a une longueur de bord 2 * n + 1, mettant la position finale au milieu).

Panne

Cela fonctionne en bouclant sur les arguments en sens inverse et en se déplaçant en sens inverse. Il utilise en fait le fait que arg 0 est le nom du programme; peu importe le nom, mais il nous permet de visiter à la fois la cellule initiale et la dernière (ainsi que toutes les cellules intermédiaires) sans avoir besoin d'une manipulation particulière.

n,                                  // Size of internal grid
y,                                  // Loop counter / current character
*g,                                 // Internal grid memory
*p;                                 // Current working pointer
main(c,v)char**v;{                  // K&R style function declaration
    for(                            // Step 1: identify visited cells
        n=c*2+3,                    //  Set output grid size
        g=calloc(n*n,8),            //  Allocate map storage space
        p=g+(n+1)*(c+1);            //  Start at centre
        c--;                        //  Loop over directions in reverse
        y=*v[c],                    //  Get current direction
        p-=(y>70?n:1)*(y%5%4?-1:1)  //  Move in reverse
    )*p=1;                          //  Mark cell visited
    for(y=n-1;--y;)                 // For each row (except edges)
        for(c=n-1;c--;              //   For each column (except edges, +1 for \n)
            putchar(c?" |-++|-+"[   //   Print wall using lookup table
                *p?0:p[1]|p[-1]|(p[n]|p[-n])*2|(p[1+n]|p[1-n]|p[n-1]|p[-n-1])*4
            ]:10)                   //   Or newline
        )p=g+y*n+c;                 //   Set current cell (happens first)
}
Dave
la source