Hadi bir zindan haritası yapalım


9

Uzun zaman önce, RPG oynamak için daha fazla zaman harcadığımda, bazı oyuncuların sahip olduğu sorunlardan biri parti hareketini izlemek ve uygun harita çizmekti. Bu yüzden, bu konuyla nasıl başa çıkacağınızı kontrol etmek için bir fikrim var.

Görev, yönlerin giriş parametresi listesini (seçtiğiniz yapı olarak geçti) alan ^v<>, zindanın haritasını gösteren bir işlev yazmaktır . Örneğin giriş için: >>>vvv<<<^^^çıkış:

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

testcases

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



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


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

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

Golf kod mücadelesi olduğu için en kısa kod kazanır.

Mutlu golf.

EDIT Geç düzenleme için özür dilerim, son zamanlarda fazla zamanım olmadı.

Harita harekete göre oluşturulur. Sadece yürüyüş sırasında ziyaret edilen koridorları içermelidir. Dolayısıyla büyük bir oda yaratmak geçerli bir cevap olmayacaktır.

Haritada üç geçerli sembol vardır:

  • | dikey duvar
  • | yatay duvar
  • + dikey ve yatay duvar kesişimi.

Yolun maksimum uzunluğu 255 karakterdir (ancak mümkünse kendinizi sınırlamayın).

Daha fazla test örneği:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

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

Umarım şimdi her şey açıktır.


3
Görevin bir tanımını vermeniz gerekir. İki test vakası tutarlı görünen bir şekilde ele alınmıyor - ilki belirgin bir sebep olmadan bağlantısı kesilmiş bir bölge ekliyor.
feersum

3
İkinci örneğinizde, başlangıçta dış kenarlığın dikdörtgen olması gerektiği düşünülen kapalı bir oda var, ancak üçüncü örnek bu fikri çürütüyor. Göndermeden önce bir meydan okuma hakkında geri bildirim almak için lütfen Sandbox'ı kullanın.
El'endia Starman

2
Mükemmel. Hâlâ zindanın hareketlerden nasıl kurulduğu konusunda açık olmayı öneririm.
El'endia Starman

1
"Haritayı görüntüle" ile ne demek istiyorsun? Bir işlevden haritanın döndürülmesine izin veriliyor mu?
Paul Schmitz

3
Bu ilginç görünüyor. Yeniden açmak için düzenleme şansınız var mı? Özellikle bakılması gerekenler: örneklerden, çıktı çevresinde fazladan boşluk bırakmamanız gibi görünüyor, ancak açıklığa kavuşturmak iyi olacaktır. Ayrıca, duvarın görünümünü açık bir şekilde tanımlar ve sütün sorusunu cevaplarsanız, soruyu yeterince açıklığa kavuşturmalıdır. Kapsamayacağınızı düşündüğüm bir şey, çıktının vvv>>^^^<<ne üreteceğidir (haçlar? Borular?)
Dave

Yanıtlar:


3

JavaScript (ES6), 261 254 243 bayt

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


Sen kaldırabilir returndeğiştirerek ;ile ,ve {}ile()
Cyoce

@Cyoce - İçeride bu şekilde gömülemeyen bir fordöngü var.
Arnauld

Daha sonra yerini {ile eval("ve }ile ")dönüş kaldırmak için codegolf.stackexchange.com/a/80967/41042
Cyoce

@Cyoce - Ne yazık ki, '\\n'sanki tam anlamıyla satır sonu kaçmak zorundayım sanırım. Doğru sayarsam, bu aslında +1 bayta yol açar. Yoksa satır sonu değerlendirmesine gömmek için daha iyi bir yolu var mı?
Arnauld

Yalnızca \nşablon dizeleri gerçek yeni satırları desteklediğinden gerekir , ancak yine de aynı bayt sayısında kalır. Oh iyi
Cyoce

3

C, 246 bayt

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;}

Girişi ayrı karakterler olarak alır, örneğin:

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

Veya daha kolay, bu (kasıtlı olarak alıntı yapılmadı!) Biçimi:

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

Veya (oldukça verimsiz) rastgele giriş için:

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

Son olarak, awksonucu kırpmak için kullanmak çok daha büyük olabileceğimiz anlamına gelir:

./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)}}'

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

Stdout'a çıkışlar. Haritanın etrafında dolguya izin verildiğini kullanır (son konumu ortaya koyarak, 2 * n + 1 kenar uzunluğuna sahip bir harita üretir).

Yıkmak

Bu, argümanları tersine çevirerek ve tersine hareket ettirerek çalışır. Aslında arg 0'ın program adı olduğu gerçeğini kullanır; adın ne olduğu önemli değil, ancak özel işleme gerek kalmadan hem ilk hem de son hücreyi (ve aradaki tüm hücreleri) ziyaret etmemizi sağlıyor.

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)
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.