Hãy tạo một bản đồ của ngục tối


9

Từ lâu, khi tôi dành nhiều thời gian chơi RPG, một trong những vấn đề mà một số người chơi gặp phải, là theo dõi chuyển động của nhóm và vẽ bản đồ phù hợp. Vì vậy, tôi có ý tưởng, để kiểm tra xem các bạn đã giải quyết vấn đề này như thế nào.

Nhiệm vụ là viết một hàm, lấy danh sách tham số đầu vào của các hướng (được truyền dưới dạng cấu trúc bạn chọn) ^v<>, hiển thị bản đồ của ngục tối. Trong ví dụ cho đầu vào: >>>vvv<<<^^^đầu ra sẽ là:

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

Tủ thử

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



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


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

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

Vì đây là thử thách mã golf, mã ngắn nhất sẽ thắng.

Chúc bạn chơi golf vui vẻ.

EDIT Xin lỗi vì chỉnh sửa muộn, gần đây tôi không có nhiều thời gian.

Bản đồ được tạo ra dựa trên sự di chuyển. Nó chỉ nên chứa hành lang đã được truy cập trong khi đi bộ. Do đó tạo ra một phòng lớn sẽ không phải là một câu trả lời hợp lệ.

Có ba biểu tượng hợp lệ trên bản đồ:

  • | tường dọc
  • | tường ngang
  • + giao nhau của tường dọc và ngang.

Độ dài tối đa của đường dẫn là 255 ký tự (nhưng nếu bạn có thể, đừng tự giới hạn).

Nhiều trường hợp thử nghiệm:

 ><><><><

 +--+
 |  |
 +--+

 >^<v

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

Tôi hy vọng bây giờ mọi thứ đã rõ ràng.


3
Bạn cần cung cấp một mô tả về nhiệm vụ. Hai trường hợp thử nghiệm thậm chí không được xử lý theo cách có vẻ nhất quán - trường hợp đầu tiên thêm một khu vực bị ngắt kết nối mà không có lý do rõ ràng.
frageum

3
Ví dụ thứ hai của bạn có một phòng kín, mà ban đầu tôi nghĩ là bởi vì đường viền bên ngoài phải là hình chữ nhật, nhưng sau đó ví dụ thứ ba từ chối ý tưởng đó. Vui lòng sử dụng Hộp cát để nhận phản hồi về thử thách trước khi đăng.
El'endia Starman

2
Thông minh. Tôi vẫn đề nghị rõ ràng về cách ngục tối được xây dựng từ các phong trào.
El'endia Starman

1
Bạn có ý nghĩa gì bởi "hiển thị bản đồ"? Là trả lại bản đồ từ một chức năng được phép?
Paul Schmitz

3
Điều này có vẻ thú vị. Bất kỳ cơ hội chỉnh sửa để mở lại? Những điều cần xem xét cụ thể: từ các ví dụ, có vẻ như bạn không bận tâm thêm khoảng trắng xung quanh đầu ra nhưng sẽ rất tốt để làm rõ. Ngoài ra, nếu bạn mô tả rõ ràng sự xuất hiện của bức tường và trả lời câu hỏi của sữa, nó sẽ làm cho câu hỏi đủ rõ ràng. Một điều tôi nghĩ rằng bạn chưa được bảo hiểm là sản lượng vvv>>^^^<<nào sẽ tạo ra (đường ống? Đường ống?)
Dave

Câu trả lời:


3

Javascript (ES6), 261 254 243 byte

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}

Câu đố


Bạn có thể xóa returnbằng cách thay thế ;bằng ,{}bằng()
Cyoce

@Cyoce - Có một forvòng lặp trong đó không thể được nhúng theo cách đó.
Arnauld

sau đó thay thế { bằng eval("}bằng ")để loại bỏ codegolf.stackexchange.com/a/80967/41042
Cyoce

@Cyoce - Thật không may, tôi nghĩ rằng tôi cần phải thoát khỏi sự phá vỡ theo nghĩa đen như '\\n'thể tôi làm như vậy. Nếu tôi đếm chính xác, điều đó thực sự dẫn đến byte 1. Hoặc có cách nào tốt hơn để nhúng linebreak trong eval?
Arnauld

Bạn sẽ chỉ cần \nvì các chuỗi mẫu hỗ trợ các dòng mới theo nghĩa đen, nhưng điều đó vẫn để nó ở cùng một số byte. Oh well
Cyoce

3

C, 246 byte

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

Lấy đầu vào là các ký tự riêng biệt, ví dụ:

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

Hoặc thuận tiện hơn, định dạng này (cố ý không trích dẫn!):

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

Hoặc cho đầu vào ngẫu nhiên (khá không hiệu quả):

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

Và cuối cùng, sử dụng awkđể cắt kết quả có nghĩa là chúng ta có thể lớn hơn nhiều:

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

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

Đầu ra cho thiết bị xuất chuẩn. Sử dụng thực tế là phần đệm được cho phép trên bản đồ (tạo ra bản đồ có độ dài cạnh 2 * n + 1, đặt vị trí cuối cùng ở giữa).

Phá vỡ

Điều này hoạt động bằng cách lặp qua các đối số ngược và di chuyển ngược lại. Nó thực sự sử dụng thực tế rằng arg 0 là tên chương trình; nó không quan trọng tên là gì, nhưng nó cho phép chúng ta truy cập vào cả ô ban đầu và ô cuối cùng (cũng như tất cả các ô ở giữa) mà không cần xử lý đặc biệt.

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)
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.