로그 라이크 라이트


14

보드가 주어지면, 가장 짧은 프로그램이나 함수를 작성하여 플레이어에게 보이는 캐릭터를 표시하거나 반환하십시오. 시야를 막는 캐릭터를 가로 지르지 않고 캐릭터와 플레이어 사이에 선을 그릴 수 있다면 캐릭터가 시야에 들어옵니다.

입력:

  • @플레이어의 위치를 ​​나타냅니다. 입력에는이 중 하나만 있습니다.
  • 정규식과 일치하는 모든 문자는 [#A-Z]비전을 차단합니다.
  • 일치하는 모든 문자 [ a-z]는 비전을 허용합니다.
  • 유효하지 않은 문자가 없습니다
  • 당신은 직사각형 입력을 보장합니다

선은 다음과 같이 정의됩니다.

  • 벡터를 크기와 방향으로 정의
  • 방향은 N, NE, E, SE, S, SW, W, NW 중 하나입니다.
  • 크기는 그 방향을 따라 셀 수있는 문자 수입니다
  • 초기 벡터를 d 1 이라고하자 . 두 번째 벡터는 d 2 라고합니다
  • d 1 또는 d 2 중 하나의 크기는 1; 다른 하나는 크기에 관계없이
  • d 1 방향은 d 2 방향에 인접해야합니다 (예 : N 및 NE)

행은 d 1 , d 2 , d 1 , d 2 ... 를 적용하여 표시된 경로를 따라 모든 문자로 정의됩니다 .

샘플 라인 ( .s로 제공) :
d 1 = (크기 : 4, 방향 : E)
d 2 = (크기 : 1, 방향 NE)

               .....
          .....
     .....
@.... 

산출:

  • 올바른 위치에있는 각 보이는 문자는 .공백을 대체합니다.
  • 보이지 않는 각 문자를위한 공간입니다.

샘플 입력 :

@         
    K     
 J        

    L   




         o

해당 출력 :

@.........
....K.....
.J.....   
..........
.. .L.....
..  . ....
... .. ...
...  .. ..
...   .  .
....  ..  

샘플 입력 :

 B###M#  by 
 #Q   # Zmpq
 # # aaa    
@  m #      
# ##P#      
# ####      
# ####      
#M ###      
######      

해당 출력 :

.B  #M      
.# ..   Z pq
.#.#.aaa..  
@..m.#      
#.##P#      
 .#         
 .#         
 M.         
  #         

샘플 입력 :

  w                 

     O  l   gg  rT  
   QQL      Ag  #b  
   qqqqq         XqQ
 x     V# f@aa      
   Y        aaa     
   uU  E  l TaKK    
  e  dd  FF d opi   
   e       d        

해당 출력 :

   ..........  .....
    ......... ..... 
     O..l...gg..rT  
...QQL......Ag..#b..
...qqqqq.........XqQ
        #.f@aa......
   Y........aaa.....
...uU..E..l.TaKK....
      d..FF.d.op    
     .... .d. ...   

3
박쥐, 모든 종류의 곰팡이, 곰팡이, 뱀, 심지어는 망령이 시야를 가리지 만 거대한 모방, 언덕 오크, 마조 돈, 모든 종류의 다른 생물 또는 불 소용돌이도 그렇지 않습니까?
John Dvorak

@ JanDvorak 나는 게으르고 차단을 위해 대문자를 선택했습니다. 키가 큰 몬스터 대 짧은 몬스터의 종류; 어느 쪽을 볼 수 있을까요? 네
저스틴

1
나는 양자 역학에 대해 잘 모르지만 박쥐와 그놈 미라는 쉬운 거래일 수 있습니다. 그러나 모방은 상황을 더 복잡하게 할 수 있습니다. 또한,이 3 마리의 개미는 재미 있고 북동쪽에있는 여러 종류의 괴물들이 이미 당신에 대해 알고있을 것입니다. 네 ... 불쾌 할 수도 있습니다. # 3은 내 텔레포 레이션 스크롤은 어디에 있습니까? 죄송합니다. 갑옷을 파괴했습니다.
John Dvorak

3
호기심 많은 관찰이지만 "선"에 대한 정의를 이해 하면 장애물이 없어도 보이지 않는 사각형이있는 것처럼 보입니다 . 예를 들어, 플레이어가 (0, 0)에 있으면 (5, 12)의 정사각형에 도달 할 수 없습니다. 예를 들어, 두 점 사이에 선을 그리기 위해 Bresenham의 선 알고리즘의 정식 구현을 지정하고 그 선과 플레이어 사이의 선이 장애물과 교차하면 사각형을 가려진 것으로 정의하는 것이 더 합리적 일 수 있습니다.
Ilmari Karonen

1
@IlmariKaronen 당신은 절대적으로 정확합니다. 그게 내가 좋아하는 방법입니다. :-).
저스틴

답변:


5

GolfScript, 171 자

.n?):L)[n*.]*1/:I'@'?{\+[{1$+}*]..{I=26,{65+}%"#
"+\?)}??)<}+{[L~.).)1L)L.(-1L~]>2<`{[.[~\]]{1/~2$*+L*.-1%}%\;~}+L,%~}8,%%{|}*`{1$?)I@=.n=@|\.' '={;'.'}*' 'if}+I,,%''*n%n*

입력은 STDIN에 제공되어야합니다.

위에 주어진 예제의 출력은 약간 다릅니다. 나는 손으로 답변을 확인하고 그들이 맞다고 생각합니다.

예 1 :

@.........
....K.....
.J.....   
..........
.. .L.....
..  . ....
... .. ...
...  .. ..
...   .  .
....  ..  

예 2 :

.B  #M      
.# ..   Z pq
.#.#.aaa..  
@..m.#      
#.##P#      
 .#         
 .#         
 M.         
  #         

예 3 :

   ..........  .....
    ......... ..... 
     O..l...gg..rT  
...QQL......Ag..#b..
...qqqqq.........XqQ
        #.f@aa......
   Y........aaa.....
...uU..E..l.TaKK....
      d..FF.d.op    
     .... .d. ...   

한 줄 입력 (유효한 사각형)에는 작동하지 않는 것 같습니다.
Justin

@Quincunx이 코드는 줄 바꿈으로 입력을 마무리한다고 가정합니다. 또는 n+코드 앞에 추가 하십시오.
Howard

4

루비-510 자

꽤 매머드; 하지만 골프를 처음 시도한 것입니다.

m=$<.read;w,s,o,p=m.index(?\n)+1,m.size,m.dup.gsub(/[^@\n]/,' '),m.index(?@);d=[-w,1-w,1,w+1,w,w-1,-1,-1-w];0.upto(7){|i|x=d[i];[i-1,i+1].each{|j|y=d[j%8];[1,nil].each{|l|t=0;catch(:a){loop{c,f,r=p,1,nil;catch(:b){loop{(l||r)&&(1.upto(t){|u|c+=x;n=!(0...s).include?(c)||m[c]==?\n;n&&throw(f ?:a: :b);o[c]=m[c]==" "??.: m[c];a=m[c]=~/[#A-Z]/;a&&throw(f ?:a: :b)};f=nil);r=1;c+=y;n=!(0...s).include?(c)||m[c]==?\n;n&&throw(f ?:a: :b);o[c]=m[c]==" "??.: m[c];a=m[c]=~/[#A-Z]/;a&&throw(f ?:a: :b)}};t+=1}}}}};$><<o

입력은 인수로 지정된 파일을 기준으로합니다. 입력 파일은 직사각형 문자 블록으로 구성되며 (마침표 포함) 후행 줄 바꿈이 있다고 가정합니다.

이 버전은 catch-throw딥 루프를 종료하기 위해 광범위하게 사용 됩니다. 대신 경계 검사 루프로 문제를 개선 할 수 있습니다.

명확하지 않은 코드 :

# Read the map in
map = $<.read

# Determine its width and size
width = map.index("\n")+1
size = map.size

# Create a blank copy of the map to fill in with visible stuff
output = map.dup.gsub /[^@\n]/,' '

# Locate the player
player = map.index('@')

dirs = [
  -width,   # N
  1-width,  # NE
  1,        # E
  width+1,  # SE
  width,    # S
  width-1,  # SW
  -1,       # W
  -1-width  # NW
]

0.upto(7) do |i1|
  d1 = dirs[i1]
  [i1-1, i1+1].each do |i2|
    d2 = dirs[i2%8]

    # Stepping by 0,1,2... in d1, work along the line.
    # Write the cell value into the duplicate map, then break if it's
    # a "solid" character.
    #
    # Extensive use of catch-throw lets us exit deep loops.

    # For convenience of notation, instead of having either d1 or d2
    # be magnitude 1, and always doing d1,d2,d1... - I have d2 always
    # being magnitude 1, and doing either d1,d2,d1 or d2,d1,d2...

    # Loop twice - first with d1,d2,d1... second with d2,d1,d2...
    [true,false].each do |long_first|
      step = 0

      catch(:all_done) do
        # This loop increments step each iteration, being the magnitude of d1
        loop do
          cell = player
          first = true  # True until we've done the first d1
          later = false # True once we've done the first d2

          catch(:done) do
            # This loop repeatedly applies d1 and d2
            loop do
              if long_first || later  # Don't apply d1 first if starting with d2
                1.upto(step) do |dd1|
                  cell += d1 # Move one cell in d1
                  invalid = !(0...size).include?(cell) || map[cell]=="\n" # Out of range
                  throw :all_done if first && invalid # No point trying a longer step if the
                                                      # first application of d1 is out of range
                  throw :done if invalid # No point continuing with this step length

                  output[cell]=map[cell] == " " ? '.' : map[cell] # Transfer visble character
                  wall = map[cell]=~/[#A-Z]/  # Hit a wall?
                  throw :all_done if first && wall # Drop out as before
                  throw :done if wall
                end
                first = false
              end
              later=true

              # Now repeat above for the single d2 step
              cell += d2
              invalid = !(0...size).include?(cell) || map[cell]=="\n"
              throw :all_done if first && invalid
              throw :done if invalid
              output[cell]=map[cell] == " " ? '.' : map[cell]
              wall = map[cell]=~/[#A-Z]/
              throw :all_done if first && wall
              throw :done if wall
            end
          end
          step += 1
        end
      end
    end
  end
end

puts output

편집하다

질문에 Ilmari Karonen은 주어진 비전 알고리즘이 장애물이 없어도 모든 사각형을 볼 수는 없다고 말합니다. 다음은 플레이어로부터 (40,40) 떨어져있는 데모입니다.

@.......................................
........................................
........................................
........................................
........................................
............ ...........................
..............  ........................
............ ...   ..... ...............
.............. ...    .....  ...........
...............  ...     .....   .......
.................  ...      .....    ...
..................   ...       .....
..... . ............   ...        .....
.....................    ...         ...
...... . ..............    ...
...... .. ..............     ...
....... . ................     ...
....... .. ............. ..      ...
.......  .  .................      ...
........ .. ............... ..       ...
........  .  ............... ...       .
........  ..  ................ ..
.........  .  ................. ...
.........  ..  .................  ..
....... .   .   . ................ ...
..........  ..  ...................  ..
..........   .   ...................  ..
........ .   ..   . ..................
........ ..   .   .. ..................
...........   ..   .....................
......... .    .    . ..................
......... ..   ..   .. .................
......... ..    .    .. ................
.......... .    ..    . ................
.......... ..    .    .. ...............
.......... ..    ..    .. ..............
..........  .     .     .  .............
........... ..    ..    .. .............
........... ..     .     .. ............
...........  .     ..     .  ...........

흠. 테스트 3이 실패합니다. 디버깅이 필요합니다.
Chowlett

확실합니까? 실수를했을 수도 있습니다.
Justin

확실합니다-벽 뒤의 V를 볼 수 있습니다! 이전 줄 이후 줄 바꿈을 감지하지 못하는 것 같습니다.
Chowlett

분명히 그것을 보지 말아야한다…
Justin

아, 내 입력에 문제가있었습니다. 나는 후에 여분의 공간이 있었다 XqQ. 즉, 3에 대한 주어진 대답은 테스트 케이스와 전혀 일치하지 않습니다. 적어도 맨 위에 여분의 줄이 있고 O와 사이에 하나의 공백 만 l있습니다.
Chowlett
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.