ชุดก่อสร้าง Dungeon


19

เมื่อผมเป็นเด็กผมเล่นเกม Intellivision สูงดินและมังกร: สมบัติของ Tarmin กราฟิก 3 มิติทำให้คุณอยู่ในมุมมองของมุมมองบุคคลที่หนึ่งด้วยความสมจริงที่น่าตกใจ:

กราฟิก 3 มิติที่สมจริงอย่างน่าตกใจ

แต่ฉันได้รับ C-64 และฉันก็สามารถที่จะวาดภาพบนตาราง 40x25 ตัวอักษรโดย cursoring รอบ ๆ หน้าจอการตั้งค่าสีที่มีปุ่ม Ctrl และหลักและวางสัญลักษณ์ใดก็ได้ผมอยาก(ทำไมไม่bashให้ฉันทำอย่างนั้น?) ชุดตัวละครนั้นมีส่วนประกอบเป็นรูปสามเหลี่ยมและส่วนประกอบที่เป็นของแข็ง ดังนั้นฉันจึงสามารถให้เหตุผลว่าใครจะสร้างมุมมองของคน ๆ หนึ่งในกริดผ่านสื่อนั้น

ฉันพบสเป็คเก่าแก่เกือบสามทศวรรษในสมุดบันทึกที่มีเกลียวเป็นเกลียวเกี่ยวกับ "ชุดก่อสร้าง Dungeon" ในสัปดาห์นี้:

ป้อนคำอธิบายรูปภาพที่นี่

( อัปเดต : ผู้อ่านระวังจะสังเกตเห็นว่าสิ่งนี้ไม่ได้อยู่ด้วยกันในส่วนที่เอียง, หมายเลขที่ถูกต้องมีให้ด้านล่าง

แม้ว่า Treasure of Tarmin จะถูกเล่นบนกริด แต่กำแพงนั้นมีอยู่ที่ขอบสี่เหลี่ยมกริดเท่านั้น ฉันรู้ว่าถ้าฉันสร้างแผนที่จากไบต์ ... แต่ละสี่เหลี่ยมจัตุรัสบนแผนที่อาจมีสี่สถานะที่เป็นไปได้สำหรับแต่ละขอบ:

  1. ไม่มีอะไรขัดขวาง
  2. ผนัง
  3. ประตู
  4. อื่น ๆ อีก?

ฉันไม่เคยเขียนมันเลย (จนกระทั่งเมื่อคืน) ฉันคิดว่ามันน่าสนุกสำหรับคนอื่นที่จะลอง

ดังนั้นงานของคุณคือการใช้ตัวช่วยสร้างเขาวงกตโหมดตัวละครที่ใช้สเปค(แก้ไข !!)ของฉัน... แต่ใช้เทคโนโลยีของปี 2013

อินพุต

เนื่องจากสเป็คไม่ได้กำหนดการเรนเดอร์สำหรับประตูเราจะสมมติเพียงตัวเลือกเท่านั้นคือแบบ Wall-and-Not-Wall เพื่อความเรียบง่ายอินพุตของคุณคือแผนที่ที่ประกอบด้วยเส้นของสตริงที่มีลักษณะดังนี้:

WN.. .N.. .N.. .N.. .N.E
W... .... .... ..S. ...E
W... .N.E W... .N.. ...E
W... .... .... .... ...E
W.S. ..S. ..S. ..S. ..SE

นั่นจะเป็นแผนที่ 5x5 มุมซ้ายบน (1,1) มีชุดผนังWและNกระดูก มุมขวาล่าง (5,5) มีการตั้งค่าSouth และEast

มันสนุกน้อยกว่ามากหากไม่มีการนำทางแผนที่ อย่างน้อยที่สุดให้วางเครื่องเล่นของคุณที่ (1,1) หันหน้าไปทางทิศเหนือแล้วเสนอ:

[F]orward, [B]ackward, turn [L]eft, turn [R]ight or [Q]uit?

ในแต่ละขั้นตอนเอาต์พุตจอแสดงผลขนาด 16x15 ของมุมมองบุคคลที่หนึ่งตามที่กำหนดโดยข้อกำหนดกระดาษโน้ตบุ๊ก เพื่อป้องกันไม่ให้คุณต้องนับขนาดของผนังเรียบที่สามระยะทางคือ:

14x13  (directly in front of you; e.g. wall is in same cell)
8x7    (one step away)
6x5    (two steps away)

ขนาดขอบเขตของผนังแบบลาดเอียงคือ:

1x15   (your direct left or right; e.g. wall is in same cell)
3x13   (one step away)
1x7    (two steps away)

ชี้แจง

  • เซลล์ที่อยู่ติดกันอาจไม่เห็นด้วยกับผนังที่ใช้ร่วมกัน ดังนั้นขอบด้านใต้ของจตุรัสอาจเป็นกำแพงในขณะที่ขอบด้านเหนือของสี่เหลี่ยมจัตุรัสไปทางทิศใต้ของมันจะไม่มีสิ่งกีดขวาง ในการออกแบบดั้งเดิมฉันคิดว่านี่เป็นคุณสมบัติ: มันช่วยให้ความคิดที่น่าสนใจเช่นประตูทางเดียว ... หรือกำแพงที่มองไม่เห็นที่ปรากฏหลังจากคุณผ่านพวกเขาเท่านั้น สำหรับความเรียบง่ายนี้ให้ทำตามกฎเดียวกัน: สำหรับการนำทางและการให้ความสนใจจ่ายเพียงสถานะขอบบนมือถือใกล้เคียงกับคุณในทิศทางที่คุณกำลังเผชิญ

  • มุมมองดีขึ้นมากด้วย "การแรเงา" ดังนั้นสำหรับบล็อกเต็มของคุณให้เลือก Unicode 2593 ▓และ 2591 ░หรือใช้Xและ+ถ้าการใช้งานของคุณคือ ASCII

  • อักขระสามเหลี่ยม Unicode (25E2 ◢, 25E3 ◣, 25E4 ◤, 25E5 ◥) เป็นบิตที่อ่อนแอสำหรับการวาดภาพนี้ นอกจากนี้ยังไม่มีตัวแปรสีเทาพวกเขามักจะยืดเฉพาะความกว้างของตัวละครและไม่ใช่ความสูงเต็ม ... แม้ในแบบอักษรความกว้างคงที่ คุณสามารถวาดบล็อคเต็มหรืออักขระทับหรือสิ่งที่คุณเลือกในสถานที่ที่ฉันต้องการเส้นทแยงมุม โซลูชันสร้างสรรค์ที่น่าสนใจที่รวมสีและใช้อักขระเหล่านี้แทนที่จะเป็นที่นิยม

  • คุณอาจสันนิษฐานว่ากำแพงชั้นนอกสุดถูกตั้งค่าให้ผูกเข้ากับพื้นที่เล่นดังนั้นคุณไม่ต้องกังวลกับการทำอะไรนอกเขาวงกต กำแพงใด ๆ ที่อยู่ห่างจากคุณมากกว่าสเป็คจะถูกละเว้นและปล่อยพื้นที่ว่างเปล่า

  • เงาของผนังที่คุณเห็นตรงหน้าถ้าหันหน้าไปทางทิศเหนือที่ (1,1) ควรจะมืด การแรเงาทางเลือกบนผนังที่อยู่ติดกันในแผนที่เช่นถ้ามีกำแพงทุกห้องอยู่แล้วกำแพงไฟจะไม่ติดกับกำแพงมืด

  • การนำ C-64 มาใช้ทำสิ่งที่ฉันตั้งใจไว้จริง ๆ ... ด้วยตัวละครแนวทแยงและทุกคน ... จะต้องผ่านเกณฑ์อื่น ๆ :-)

ตัวอย่าง

สำหรับแผนที่ตัวอย่างที่ระบุด้านบน ...

ที่ (1,3) หันหน้าไปทางทิศใต้:

               /
              /+
             /X+
            /XX+
           /XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
           \XXX+
            \XX+
             \X+
              \+
               \

ที่ (3,2) หันหน้าไปทางทิศใต้:

                      /* blank line */        
X             /
X            /+
X           /++
X           +++
X           +++
X           +++
X           +++
X           +++
X           +++
X           +++
X           \++
X            \+
X             \
                      /* blank line */

ที่ (3,2) หันหน้าไปทางทิศตะวันออก:

                      /* blank line */        
              / 
             /X 
            /XX 
            XXX 
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
            XXX 
            \XX 
             \X 
              \ 
                      /* blank line */        

ที่ (2,3) หันหน้าไปทางทิศเหนือ:

               /
 ++++++++++++++X
 ++++++++++++++X
 ++++++++++++++X
 ++++++++++++++X
X++++++++++++++X
X++++++++++++++X
X++++++++++++++X
X++++++++++++++X
X++++++++++++++X
 ++++++++++++++X
 ++++++++++++++X
 ++++++++++++++X
 ++++++++++++++X
               \

1
ฉันขอแนะนำให้ทำสิ่งนี้ให้ท้าทายรหัส - กอล์ฟจะอ่านไม่ออกและยากเกินไป: P
Doorknob

1
@Doorknob อย่าปล่อยให้มันหลอกคุณ ... จริงๆแล้วมันไม่ได้ยากขนาดนั้นทั้งหมด มีคำใบ้ที่ค่อนข้างดีสำหรับรายการขนาด 3 ขอบเขต และสนามกอล์ฟคืออะไร แต่เป็นความท้าทายที่แก้ไขแล้วลงเอย :-) แต่ฉันจะให้คนเลือกว่าพวกเขาต้องการแก้ปัญหาอย่างไร ... NP
Dr. Rebmu

คุณช่วยอธิบายคอลัมน์สองคอลัมน์Xในมุมมองของคุณที่3, 2หันหน้าไปทางทิศใต้ได้ไหม
jazzpi

โดยเฉพาะที่อยู่ทางด้านขวามือ ฉันเห็นว่าทำไมคนที่เหลืออยู่ที่นั่น แต่ดูเหมือนว่าสิ่งที่ถูกต้องจะละเมิดการชี้แจง # 1
jazzpi

@jazzpi โอ๊ะคุณพูดถูกแผนที่ที่วางไว้ไม่จำเป็นต้องเชื่อฟังคำชี้แจง 1! ทำได้ดี. แก้ไขแล้ว. (ฉันจะใส่กำแพงด้านทิศใต้ที่หายไปในรุ่นของฉันในบางจุด ... แต่ดีที่จะมีกรณีทดสอบในตัวอย่าง ... ดังนั้นปล่อยให้ผนังด้านทิศใต้ออกมา!)
ดร. Rebmu

คำตอบ:


10

พลเรือจัตวา 64 พื้นฐาน

ชายนั่นสนุก และยาก C64 Basic นั้นแทบจะไม่สามารถบั๊กได้คุณไม่สามารถแม้แต่จะทำการprintดีบั๊กเพราะหน้าจอนั้นถูกใช้สำหรับการแสดงดันเจี้ยนแล้ว 55250 goto 55110คุณรู้ว่าคุณกำลังมีความสนุกสนานเมื่อคุณเขียนโค้ดเช่น Dijkstra จะฆ่าฉัน

โปรแกรมใช้สองสีและตัวละครแนวทแยง

ไม่จำเป็นต้องบอกว่าฉันไม่ได้เล่นกอล์ฟ มันบอกว่าท้าทายรหัสตอนนี้หลังจากทั้งหมด มันคือ7183ไบต์ถ้าคุณสนใจ

มันช้า - ที่ความเร็วเริ่มต้นมันใช้เวลาหลายวินาทีเพื่อให้ฉาก ขนาดแผนที่สูงสุดคือ 10 คูณ 10 แต่สามารถเปลี่ยนแปลงได้โดยแก้ไขบรรทัด 120

ฉันได้พัฒนาและทดสอบสิ่งนี้โดยใช้ตัวจำลองVICE รหัสด้านล่างแสดงเป็น ASCII ดังนั้นนั่นหมายความว่าPETSCII ที่ถูกเลื่อน อย่างไรก็ตามเมื่อป้อนแผนที่คุณควรใช้unshifted PETSCII

ภาพหน้าจอ: ภาพหน้าจอ

รหัส:

10 rem c64 dungeon construction set.
20 rem enter using lowercase mode
99 rem DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD
100 rem initialisation
110 poke 53272,21
115 poke 53280,0
120 dim m%(10,10)
121 dim di$(3),wa$(1),ma%(2,2)
122 di$(0)="north"
123 di$(1)="east "
124 di$(2)="south"
125 di$(3)="west "
126 wa$(1)="-wall"
127 wa$(0)="     "

130 x=0:y=0:di=0:xs=0:ys=0:wa=0
134 rem read map
135 print "input map"
140 l$="":input l$
150 if len(l$)=0 goto 250
160 cz=0
170 for i=1 to len(l$)
180   c$=mid$(l$,i,1)
190   if c$="n" then cz=cz or 8
200   if c$="e" then cz=cz or 4
205   if c$="s" then cz=cz or 2
210   if c$="w" then cz=cz or 1
215   if c$=" " then m%(x,y)=cz:cz=0:x=x+1
220   if x>=xs then xs=x
225 next
230 m%(x,y)=cz:x=0:y=y+1
240 goto 140
250 rem come from 150
260 print chr$(147)
265 ys=y:xs=xs+1
270 x=0:y=0

500 rem loop
510 gosub 1000: rem status
515 gosub 2000: rem render
520 gosub 55000: rem input
530 goto 500

1000 rem display current (x,y) value
1010 sx=5
1020 sy=17
1030 sl$="    "
1035 sw=14
1040 gosub 63900
1050 cz=m%(x,y)
1060 sx=5:sl$=".":if cz and 8 then sl$="n"
1065 gosub 63900
1070 sx=6:sl$=".":if cz and 4 then sl$="e"
1075 gosub 63900
1080 sx=7:sl$=".":if cz and 2 then sl$="s"
1085 gosub 63900
1090 sx=8:sl$=".":if cz and 1 then sl$="w"
1095 gosub 63900
1100 return

2000 rem render dungeon
2010 rem DDDDDDDDDDDDDD
2020 rem clear area
2030 sw=14:sz=32
2040 for sy=0 to 15
2050   for sx=0 to 16
2060      gosub 63950
2070   next
2080 next
2090 rem find cells / reorient sw
2100 rem store in ma% - we're at (0,1)
2110 sx=x:sy=y
2113 co=di+x+y and 1
2115 for ty=0 to 2
2120    gosub 59800:rem left/right sx/sy
2125    ma%(1,ty)=0
2126    if sx>=0 and sy>=0 and sx<xs and sy<ys then ma%(1,ty)=m%(sx,sy)
2130    ma%(0,ty)=rl
2140    ma%(2,ty)=rr
2150    gosub 59900:rem advance
2160 next
2170 rem draw back walls
2180 sa=ma%(1,2):gosub 59700
2190 if rf=0 goto 2245
2195 sw=14-11*co:sz=160
2200 for sy=5 to 9
2210    for sx=5 to 10
2220       gosub 63950
2230    next
2240 next
2245 sw=3:if co=1 then sw=14
2250 for de=0 to 2 step 2 
2260    sa=ma%(de,2):gosub 59700
2270    if rf=0 goto 2350
2280    for sx=de*5.5 to 4+de*5.5
2290       for sy=5 to 9
2300          gosub 63950
2310       next
2340    next 
2350 next
2360 rem 1,2 left wall
2370 sa=ma%(1,2):gosub 59700
2380 if rl=0 goto 2430
2390 sx=4:sz=160
2400 for sy=5 to 9:gosub 63950:next
2410 sy=4:sz=223:gosub 63950
2420 sy=10:sz=105:gosub 63950
2430 rem 1,2 right wall
2440 if rr=0 goto 2490
2450 sx=11:sz=160
2460 for sy=5 to 9:gosub 63950:next
2470 sy=4:sz=233:gosub 63950
2480 sy=10:sz=95:gosub 63950
2490 rem 1,1 back wall
2500 sa=ma%(1,1):gosub 59700
2510 sz=160
2520 sw=14:if co=1 then sw=3
2520 if rf=0 goto 2580
2530 for sy=4 to 10
2540    for sx=4 to 11
2550       gosub 63950
2560    next
2570 next
2580 rem (0-2),1 back walls
2590 sw=14:if co=1 then sw=3
2600 for de=0 to 2 step 2
2610    sa=ma%(de,1):gosub 59700
2620    if rf=0 goto 2680
2630    for sx=de*6 to 3+de*6
2640       for sy=4 to 10
2650          gosub 63950
2660       next
2670    next
2680 next 
2690 rem 1,1 left side wall
2700 sw=14:if co=1 then sw=3
2710 sa=ma%(1,1):gosub 59700
2720 if rl=0 goto 2760
2730 for sx=1 to 3
2735   sy=sx:sz=223:gosub 63950
2736   sy=14-sx:sz=105:gosub 63950
2737   sz=160
2740   for sy=1+sx to 13-sx:gosub 63950:next
2750 next
2760 rem 1,1 right side wall
2770 if rr=0 goto 2850
2780 for qx=1 to 3
2790   sx=15-qx
2800   sy=qx:sz=233:gosub 63950
2810   sy=14-qx:sz=95:gosub 63950
2820   sz=160
2830   for sy=1+qx to 13-qx:gosub 63950:next
2840 next
2850 rem 0,1 back wall
2860 sa=ma%(1,0):gosub 59700
2870 if rf=0 goto 2930
2880 for sy=1 to 13
2890   for sx=1 to 14
2900     gosub 63950
2910   next
2920 next
2930 rem (0,2)-0 back walls
2940 sw=3:if co=1 then sw=14
2950 for de=0 to 2 step 2
2960   sa=ma%(de,0):gosub 59700
2970   if rf=0 goto 3000
2980   sx=de*7.5
2990   for sy=1 to 13:gosub 63950:next
3000 next
3010 rem (1,0) left side wall
3020 sa=ma%(1,0):gosub 59700
3030 if rl=0 goto 3080
3040 sx=0:sy=0:sz=223:gosub 63950
3050 sy=14:sz=105:gosub 63950
3060 sz=160
3070 for sy=1 to 13:gosub 63950:next
3080 rem (1,0) right side wall
3085 if rr=0 goto 3130
3090 sx=15:sy=0:sz=233:gosub 63950
3100 sy=14:sz=95:gosub 63950
3110 sz=160
3120 for sy=1 to 13:gosub 63950:next
3130 rem done
3140 return

55000 rem ask for prompt & handle input
55010 sx=0:sy=20:gosub 63850
55013 print "at";x+1;y+1;"going ";di$(di);" size";xs;ys;wa$(wa)
55020 print "{f}rwd {b}kwd {l}eft {r}ight {q}uit"
55030 input c$
55040 if c$="q" goto 63999
55050 if c$="f" then dm=1:goto 55100
55060 if c$="b" then dm=-1:goto 55100
55070 if c$="l" then di=(di-1)and 3
55080 if c$="r" then di=(di+1)and 3
55090 return
55100 goto 55200:rem check walls
55110 if di=0 then y=y-dm
55120 if di=1 then x=x+dm
55130 if di=2 then y=y+dm
55140 if di=3 then x=x-dm
55145 wa=0
55146 if y>=ys then y=0
55147 if y<0   then y=ys-1
55148 if x>=xs then x=0
55149 if x<0   then x=xs-1
55150 return
55200 rem check walls
55205 cz=m%(x,y)
55207 if dm=-1 goto 55280
55210 if (di=0) and (cz and 8) goto 55260
55220 if (di=1) and (cz and 4) goto 55260
55230 if (di=2) and (cz and 2) goto 55260
55240 if (di=3) and (cz and 1) goto 55260
55250 goto 55110
55260 wa=1
55270 return : rem wall in the way
55280 rem backward
55290 if (di=2) and (cz and 8) goto 55260
55300 if (di=3) and (cz and 4) goto 55260
55310 if (di=0) and (cz and 2) goto 55260
55320 if (di=1) and (cz and 1) goto 55260
55330 goto 55110

59700 rem return front/back/left/right
59710 rem given sa and d
59720 sn=0:if sa and 8 then sn=1
59725 se=0:if sa and 4 then se=1
59730 ss=0:if sa and 2 then ss=1
59735 zw=0:if sa and 1 then zw=1
59740 if di=0 then rf=sn:rr=se:rb=ss:rl=zw
59745 if di=1 then rf=se:rr=ss:rb=zw:rl=sn
59750 if di=2 then rf=ss:rr=zw:rb=sn:rl=se
59755 if di=3 then rf=zw:rr=sn:rb=se:rl=ss
59760 return

59800 rem return left/right from sx/sy/d
59810 if di=0 then ly=sy:ry=sy:lx=sx-1:rx=sx+1
59820 if di=1 then lx=sx:rx=sx:ly=sy-1:ry=sy+1
59830 if di=2 then ly=sy:ry=sy:lx=sx+1:rx=sx-1
59840 if di=3 then lx=sx:rx=sx:ly=sy+1:ry=sy-1
59850 rl=0:rr=0
59860 if lx<0 or lx>=xs or ly<0 or ly>=ys goto 59880
59870 rl=m%(lx,ly)
59880 if rx<0 or rx>=xs or ry<0 or ry>=ys goto 59895
59890 rr=m%(rx,ry)
59895 return

59900 rem step forward
59910 if di=0 then sy=sy-1:rem N
59920 if di=1 then sx=sx+1:rem E
59930 if di=2 then sy=sy+1:rem S
59940 if di=3 then sx=sx-1:rem W
59950 return

63850 rem set cursor position
63851 rem sx=x sy=y
63860 poke 781,sy
63870 poke 782,sx
63880 poke 783,0
63890 sys 65520
63895 return

63900 rem write str to screen
63901 rem sl$ = string
63910 gosub 63850
63920 print sl$;
63930 return

63950 rem write chr to screen
63951 rem sx = x coordinate
63952 rem sy = y coordinate
63953 rem sz = character code
63954 rem sw = color
63950 sv=sx+sy*40
63960 poke 1024+sv,sz
63970 poke 55296+sv,sw
63980 return

63998 rem quit program
63999 print chr$(147):end

ภาพเทป: ดาวน์โหลดได้ที่นี่

ตัวอย่าง:

ตัวอย่าง


1
พระเจ้าช่วย. ถ้าคนอื่นต้องการแก้ปัญหานี้เพื่อความหายนะมันเยี่ยมมาก ... แต่คุณได้รับรางวัลโดยคำจำกัดความของทรัมป์ในการท้าทาย ฉันถูกล่อลวงให้ดึงอีมูเลเตอร์ออกมาและทำมันด้วยเหตุผลที่คิดถึง แต่คิดว่ามันมีประโยชน์มากกว่าที่จะเขียนเป็นสีแดงเพื่อดูว่าคอมไพเลอร์ไขว้คอมไพเลอร์สามารถเก็บได้ดีแค่ไหน แหล่งที่มา ฉันจะRebmu-ifyและโพสต์ไว้ในบางจุด ... แต่ความโปรดปรานนั้นเป็นของคุณ! ปรบมือใหญ่
ดร. Rebmu

1
นอกจากนี้ RE: Dijkstra เขามีคำพูดตลก ๆ เกี่ยวกับความเป็นอมตะ : "ฉันหมายความว่าถ้า 10 ปีต่อจากนี้เมื่อคุณกำลังทำอะไรที่รวดเร็วและสกปรกคุณก็นึกภาพว่าฉันมองไหล่ของคุณและพูดกับตัวเองว่า 'Dijkstra ไม่ชอบสิ่งนี้ 'ดีนั่นคงเป็นอมตะสำหรับฉัน " ดังนั้นฉันคิดว่าเขาได้รับความปรารถนาของเขา! :-)
Dr. Rebmu

@ Dr.Rebmu: ขอบคุณสำหรับความโปรดปราน! ฉันใช้เวลาทั้งวันอย่างแท้จริงในการเขียน :)
marinus

10

(ทำไมไม่bashให้ฉันทำอย่างนั้น?)

ฉันต้องทำตอนนี้

Bash, 12743 ตัวอักษร

#!/bin/bash
IFS=
declare -a term
typeset -i term[0] term[1]
IFS=' ' read -a term <<< `stty size`
front[0]='\e[2;2H██████████████
\e[3;2H██████████████
\e[4;2H██████████████
\e[5;2H██████████████
\e[6;2H██████████████
\e[7;2H██████████████
\e[8;2H██████████████
\e[9;2H██████████████
\e[10;2H██████████████
\e[11;2H██████████████
\e[12;2H██████████████
\e[13;2H██████████████
\e[14;2H██████████████'
front[1]='\e[5;5H████████
\e[6;5H████████
\e[7;5H████████
\e[8;5H████████
\e[9;5H████████
\e[10;5H████████
\e[11;5H████████'
front[2]='\e[6;6H██████
\e[7;6H██████
\e[8;6H██████
\e[9;6H██████
\e[10;6H██████'
lfront[0]='\e[2;1H█
\e[3;1H█
\e[4;1H█
\e[5;1H█
\e[6;1H█
\e[7;1H█
\e[8;1H█
\e[9;1H█
\e[10;1H█
\e[11;1H█
\e[12;1H█
\e[13;1H█
\e[14;1H█'
lfront[1]='\e[5;1H████
\e[6;1H████
\e[7;1H████
\e[8;1H████
\e[9;1H████
\e[10;1H████
\e[11;1H████'
lfront[2]='\e[6;1H█████
\e[7;1H█████
\e[8;1H█████
\e[9;1H█████
\e[10;1H█████'
rfront[0]='\e[2;16H█
\e[3;16H█
\e[4;16H█
\e[5;16H█
\e[6;16H█
\e[7;16H█
\e[8;16H█
\e[9;16H█
\e[10;16H█
\e[11;16H█
\e[12;16H█
\e[13;16H█
\e[14;16H█'
rfront[1]='\e[5;13H████
\e[6;13H████
\e[7;13H████
\e[8;13H████
\e[9;13H████
\e[10;13H████
\e[11;13H████'
rfront[2]='\e[6;12H█████
\e[7;12H█████
\e[8;12H█████
\e[9;12H█████
\e[10;12H█████'
left[0]='\e[1;1H▙
\e[2;1H█
\e[3;1H█
\e[4;1H█
\e[5;1H█
\e[6;1H█
\e[7;1H█
\e[8;1H█
\e[9;1H█
\e[10;1H█
\e[11;1H█
\e[12;1H█
\e[13;1H█
\e[14;1H█
\e[15;1H▛'
left[1]='\e[2;2H▙
\e[3;2H█▙
\e[4;2H██▙
\e[5;2H███
\e[6;2H███
\e[7;2H███
\e[8;2H███
\e[9;2H███
\e[10;2H███
\e[11;2H███
\e[12;2H██▛
\e[13;2H█▛
\e[14;2H▛'
left[2]='\e[5;5H▙
\e[6;5H█
\e[7;5H█
\e[8;5H█
\e[9;5H█
\e[10;5H█
\e[11;5H▛'
right[0]='\e[1;16H▟
\e[2;16H█
\e[3;16H█
\e[4;16H█
\e[5;16H█
\e[6;16H█
\e[7;16H█
\e[8;16H█
\e[9;16H█
\e[10;16H█
\e[11;16H█
\e[12;16H█
\e[13;16H█
\e[14;16H█
\e[15;16H▜'
right[1]='\e[2;13H  ▟
\e[3;13H ▟█
\e[4;13H▟██
\e[5;13H███
\e[6;13H███
\e[7;13H███
\e[8;13H███
\e[9;13H███
\e[10;13H███
\e[11;13H███
\e[12;13H▜██
\e[13;13H ▜█
\e[14;13H  ▜'
right[2]='\e[5;12H▟
\e[6;12H█
\e[7;12H█
\e[8;12H█
\e[9;12H█
\e[10;12H█
\e[11;12H▜'

echo -e "\e[2J"

# Read map
typeset -i cout
cout=0
echo "Please input your map!"
echo "Please input the next row (or leave it blank if you're finished!)"
read input

declare -A map

typeset -i xlen ylen
ylen=0

until [ -z $input ]
do
    IFS=' ' read -a inputmap <<< "$input"
    xlen=${#inputmap[*]}
    let ylen++
    for index in "${!inputmap[@]}"
    do
        typeset -i map[$index,$cout]
        map[$index,$cout]=0
        el=${inputmap[index]}
        if [[ $el == W??? ]]
        then
            let "map[$index,$cout]|=1"
        fi
        if [[ $el == ?N?? ]]
        then
            let "map[$index,$cout]|=2"
        fi
        if [[ $el == ??S? ]]
        then
            let "map[$index,$cout]|=4"
        fi
        if [[ $el == ???E ]]
        then
            let "map[$index,$cout]|=8"
        fi
    done
    echo "Please input the next row (or leave it blank if you're finished!)"
    read input
    cout+=1
done

echo -ne "\e[2J"

typeset -i dir x y
dir=0
x=0
y=0

move() {
    if ((dir == 0)) && ( ((${map[$x,$y]} & 2)) || ((y == 0)) )
    then
        return 1
    elif ((dir == 1)) && ( ((${map[$x,$y]} & 8)) || (($x == $xlen)) )
    then
        return 1
    elif ((dir == 2)) && ( ((${map[$x,$y]} & 4)) || ((y == $ylen)) )
    then
        return 1
    elif ((dir == 3)) && ( ((${map[$x,$y]} & 1)) || ((x == 0)) )
    then
        return 1
    fi
    x=$1
    y=$2
}

input=

until [[ $input == [qQ] ]]
do
    if [[ $input == [DlL] ]]
    then
        let dir-=1
        if (( dir == -1 ))
        then
            dir=3
        fi
    elif [[ $input == [CrR] ]]
    then
        let dir+=1
        if (( dir == 4 ))
        then
            dir=0
        fi
    elif [[ $input == [AfF] ]]
    then
        if (( dir == 0 ))
        then
            move $x $(( y-1 ))
        elif (( dir == 1 ))
        then
            move $(( x+1 )) $y
        elif (( dir == 2 ))
        then
            move $x $(( y+1 ))
        elif (( dir == 3 ))
        then
            move $(( x-1 )) $y
        fi
    elif [[ $input == [bB] ]]
    then
        if (( dir == 0 ))
        then
            dir=2
            move $x $(( y+1 ))
            dir=0
        elif (( dir == 1 ))
        then
            dir=3
            move $(( x-1 )) $y
            dir=1
        elif (( dir == 2 ))
        then
            dir=0
            move $x $(( y-1 ))
            dir=2
        elif (( dir == 3 ))
        then
            dir=1
            move $(( x+1 )) $y
            dir=3
        fi
    fi
    echo -ne "\e[2J"
    echo -ne "\e[16;1Hd=$dir; x=$x; y=$y\e[48;5;29m"
    for (( y2=1; y2 <= 15; y2++ ))
    do
        echo -ne "\e[$y2;16H\e[1K"
    done
    if (( dir == 0 ))
    then
        for (( y2=(y-2); y2 <= y; y2++ ))
        do
            if (( y2 < 0 )); then continue; fi
            let i=y-y2
            if (( x > 0 )) && (( ${map[$((x-1)),$y2]} & 2 ))
            then
                if (( ((x-1) + y2) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${lfront[$i]}
            fi
            if (( (x+1) < xlen )) && (( ${map[$((x+1)),$y2]} & 2 ))
            then
                if (( ((x-1) + y2) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${rfront[$i]}
            fi
            if (( ${map[$x,$y2]} & 1 ))
            then
                if (( (x + y2) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${left[$i]}
            fi
            if (( ${map[$x,$y2]} & 8 ))
            then
                if (( (x + y2) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${right[$i]}
            fi
            if (( ${map[$x,$y2]} & 2 ))
            then
                if (( (x + y2) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${front[$i]}
            fi
        done
    elif (( dir == 1 ))
    then
        for (( x2=x+2; x2 >= x; x2-- ))
        do
            if (( x2 > 16 )) || (( x2 >= xlen )); then continue; fi
            let i=x2-x
            if (( y > 0 )) && (( ${map[$x2,$((y-1))]} & 8 ))
            then
                if (( (x2 + (y-1)) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${lfront[$i]}
            fi
            if (( (y+1) < ylen )) && (( ${map[$x2,$((y+1))]} & 8 ))
            then
                if (( (x2 + (y-1)) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${rfront[$i]}
            fi
            if (( ${map[$x2,$y]} & 2 ))
            then
                if (( (x2 + y) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${left[$i]}
            fi
            if (( ${map[$x2,$y]} & 4 ))
            then
                if (( (x2 + y) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${right[$i]}
            fi
            if (( ${map[$x2,$y]} & 8 ))
            then
                if (( (x2 + y) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${front[$i]}
            fi
        done
    elif (( dir == 2 ))
    then
        for (( y2=(y+2); y2 >= y; y2-- ))
        do
            if (( y2 > 15 )) || (( y2 >= ylen )); then continue; fi
            let i=y2-y
            if (( x > 0 )) && (( ${map[$((x-1)),$y2]} & 4 ))
            then
                if (( ((x-1) + y2) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${rfront[$i]}
            fi
            if (( (x+1) < xlen )) && (( ${map[$((x+1)),$y2]} & 4 ))
            then
                if (( ((x+1) + y2) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${lfront[$i]}
            fi
            if (( ${map[$x,$y2]} & 8 ))
            then
                if (( (x + y2) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${left[$i]}
            fi
            if (( ${map[$x,$y2]} & 1 ))
            then
                if (( (x + y2) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${right[$i]}
            fi
            if (( ${map[$x,$y2]} & 4 ))
            then
                if (( (x + y2) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${front[$i]}
            fi
        done
    elif (( dir == 3 ))
    then
        for (( x2=(x-2); x2 <= x; x2++ ))
        do
            if (( x2 < 0 )); then continue; fi
            let i=x-x2
            if (( y > 0 )) && (( ${map[$x2,$((y-1))]} & 1 ))
            then
                if (( (x2 + (y-1)) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${rfront[$i]}
            fi
            if (( (y+1) < ylen )) && (( ${map[$x2,$((y+1))]} & 1 ))
            then
                if (( (x2 + (y+1)) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${lfront[$i]}
            fi
            if (( ${map[$x2,$y]} & 4 ))
            then
                if (( (x2 + y) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${left[$i]}
            fi
            if (( ${map[$x2,$y]} & 2 ))
            then
                if (( (x2 + y) & 1 ))
                then
                    echo -ne "\e[38;5;40m"
                else
                    echo -ne "\e[38;5;28m"
                fi
                echo -ne ${right[$i]}
            fi
            if (( ${map[$x2,$y]} & 1 ))
            then
                if (( (x2 + y) & 1 ))
                then
                    echo -ne "\e[38;5;28m"
                else
                    echo -ne "\e[38;5;40m"
                fi
                echo -ne ${front[$i]}
            fi
        done
    fi
    echo -ne "\e[0m"
    echo -ne "\e[${term[0]};0H[F]orward, [B]ackward, turn [L]eft, turn [R]ight or [Q]uit?"
    read -n 1 input
done

echo

โปรดจำไว้ว่านี่เป็นสิ่งแรกที่ฉันทำกับbashมันมากกว่าแค่ใช้คำสั่งสองสามคำพร้อมกัน มันอาจจะถูกลดทอนลงได้มากถ้าฉันไม่ได้ hardcode กำแพงทั้งหมด แต่มันดูง่ายขึ้น มันไม่มีความสอดคล้องอะไรเลย รูปแบบไบต์ของแต่ละตารางจะถูกเลือกด้วยวิธีที่น่ากลัว แต่มันได้ผล

ฉันยังเพิ่มการรองรับการเคลื่อนไหวผ่านปุ่มลูกศร :)

นี่เป็นภาพหน้าจอสำหรับใส่ตัวอย่าง (โปรดทราบว่าแผนที่ของฉันเริ่มต้นที่ (0 | 0)):

0 | 0 หันหน้าไปทางทิศเหนือ 0 | 2 หันหน้าไปทางทิศใต้ 2 | 1 หันหน้าไปทางทิศตะวันออก 2 | 1 หันหน้าไปทางทิศใต้ 1 | 2 หันหน้าไปทางทิศเหนือ

นอกเหนือจากอันที่สี่พวกเขาทั้งหมดก็ดูเหมือนตัวอย่างด้วย (ดูความคิดเห็นของฉันที่ OP)

ภาพหน้าจอเหล่านี้ถ่ายใน urxvt v9.15 พร้อมการรองรับ 256 สีมันอาจจะดูค่อนข้างอึใน 88 terminal สีและเทอร์มินัลที่ไม่มีการสนับสนุน Unicode จะไม่ทำงานเลย ตัวอักษรที่ฉันใช้คือSource Code Proโดย Adobe


1
ฮ่าฮ่าทุบตีและสีด้วย! ดี คุณพูดถูกเกี่ยวกับกำแพงนั้นโดยสิ้นเชิงฉันเห็นว่าในบางจุด "แก้ไขมัน" ในโปรแกรมของฉัน ดังนั้นฉันยกเลิกการแก้ไข :-) ขอบคุณสำหรับการจับ!
ดร. Rebmu

3

นี่คือเวอร์ชั่นของฉันใน Python 3 มันเหมือนกับตัวละคร 3k และอาจจะเล็กลงเล็กน้อยด้วยความพยายามเล็กน้อย (มีพื้นที่สีขาวจำนวนมากที่สามารถลบออกได้เพื่อเริ่มต้นด้วย)

ปัจจุบันใช้+X/\เป็นอักขระวาดรูป แต่ถูกตั้งค่าให้วาดด้วยอักขระ Unicode ถ้าคุณมีแบบอักษรความกว้างคงที่ที่จะแสดงอย่างถูกต้อง มันรองรับการใช้กระเบื้องแยกต่างหากสำหรับส่วนมุมของผนังที่มีการชนต่างกันแม้ว่าฉันจะไม่ได้ใช้คุณสมบัตินั้น นอกจากนี้ยังช่วยให้คุณสามารถจัดวางกระเบื้องเพดานพื้นและ "ระยะทางไกล" และคุณสามารถใช้ตัวเลือกที่แตกต่างกันเมื่อผู้เล่นหันหน้าไปทางทิศตะวันออกหรือทิศตะวันตกเฉียงเหนือหรือทางเหนือ อนิจจาสิ่งนี้ไม่เคยดูดีนักดังนั้นสิ่งเหล่านี้น่าจะว่างเปล่า (หรืออะไรทำนองนั้น)

อนิจจาในระบบ Windows 7 ของฉันฉันมีช่วงเวลาที่น่ากลัวในการพยายามหาแบบอักษรที่มีช่องว่างที่เต็มไปด้วยชุดอักขระเต็มชุด (เช่นและ) สิ่งที่ฉันพบส่วนใหญ่ไม่สามารถให้บริการในcmdคอนโซลด้วยเหตุผลบางอย่าง (อาจเป็นเพราะพวกเขาไม่ได้จำเจอย่างสมบูรณ์?) หากคุณคิดว่าคอนโซลของคุณทำงานได้ดีขึ้นลองใช้ชุดอักขระทางเลือกที่ฉันได้คอมเม้นต์ไว้ใกล้ด้านบนของไฟล์ซึ่งไม่ได้ดูแย่เกินไปแม้ว่าจะมีเพียงสองสี มันเต็มไปด้วยเพดานและพื้นและผนังส่วนใหญ่โปร่งใส

รหัส:

from itertools import product as p
r=range
cs=r"+X//\\//\\      " #" ░▛▛▜▜▟▟▙▙██████"
shapes=[(1,[(x,y,0)for x,y in p(r(5),r(5,10))]),
        (0,[(x,y,0)for x,y in p(r(5,11),r(5,10))]),
        (1,[(x,y,0)for x,y in p(r(11,16),r(5,10))]),
        (1,[(4,4,4),(4,10,6)]+[(4,y,0)for y in r(5,10)]),
        (1,[(11,4,2),(11,10,8)]+[(11,y,0)for y in r(5,10)]),
        (0,[(x,y,0)for x,y in p(r(4),r(4,11))]),
        (1,[(x,y,0)for x,y in p(r(4,12),r(4,11))]),
        (0,[(x,y,0)for x,y in p(r(12,16),r(4,11))]),
        (0,[(1,1,4),(2,2,4),(3,3,4),(1,13,6),(2,12,6),(3,11,6)]+
           [(x,y,0)for x,y in p(r(1,4),r(2,14)) if x<y<14-x]),
        (0,[(14,1,2),(13,2,2),(12,3,2),(14,13,8),(13,12,8),(12,11,8)]+
           [(x,y,0)for x,y in p(r(12,15),r(2,14)) if 15-x<y<x-1]),
        (1,[(0,y,0) for y in r(1,14)]),
        (0,[(x,y,0) for x,y in p(r(1,15),r(1,14))]),
        (1,[(15,y,0) for y in r(1,14)]),
        (1,[(0,0,4),(0,14,6)]+[(0,y,0)for y in r(1,14)]),
        (1,[(15,0,2),(15,14,8)]+[(15,y,0) for y in r(1,14)])]
def rr(s):
    for r in s:print("".join(r))
def dw(s,a,p,d):
    for i,r in enumerate(s):r[:]=cs[10+i//5*2+d%2]*16
    for w,(pl,sh) in zip(a,shapes):
        if w:
            for x,y,c in sh:
                s[y][x]=cs[c+(p+d+pl)%2]
dx=[1,0,-1,0]
def ga(x,y,d,m):
    fx=dx[d];fy=lx=dx[d-1];ly=dx[d-2]
    return [m[y+2*fy+ly][x+2*fx+lx][d],m[y+2*fy][x+2*fx][d],
            m[y+2*fy-ly][x+2*fx-lx][d],m[y+2*fy][x+2*fx][d-1],
            m[y+2*fy][x+2*fx][d-3],m[y+fy+ly][x+fx+lx][d],
            m[y+fy][x+fx][d],m[y+fy-ly][x+fx-lx][d],
            m[y+fy][x+fx][d-1],m[y+fy][x+fx][d-3],
            m[y+ly][x+lx][d],m[y][x][d],
            m[y-ly][x-lx][d],m[y][x][d-1],m[y][x][d-3]]
def rd():
    l=input();
    while l!="":
        if "\n" in l:yield from l.split("\n")
        else:yield l
        l=input()
def rm():
    m=[[[d in s for d in"ESWN"]for s in r.strip().split()]+[[1]*4]*2
       for r in rd()]
    return m+[[[1]*4 for _ in m[0]]]*2
def cl():print("\n"*30)
def gl():
    print("Enter map, followed by a blank line.")
    x=y=0;d=3;m=rm();mv="";s=[[""]*16 for _ in r(15)]
    while True:
        cl();dw(s,ga(x,y,d,m),x+y,d);rr(s)
        print("X:",x+1,"Y:",y+1,"Facing:","ESWN"[d])
        if mv:print("Last move:",mv)
        mv=input("[FBLRQ]? ").upper()
        if mv=="F":
            if not m[y][x][d]:x+=dx[d];y+=dx[d-1]
            else:mv+=" (Blocked)"
        elif mv=="B":
            if not m[y][x][d-2]:x+=dx[d-2];y+=dx[d-3]
            else:mv+=" (Blocked)"
        elif mv=="L":d=(d-1)%4
        elif mv=="R":d=(d+1)%4
        elif mv=="Q":break
        else:mv="I didn't understand %r."%mv
gl()

ชุดอักขระถูกระบุไว้ใกล้ด้านบนของไฟล์ ลำดับของตัวละครคือ:

  1. แม้แต่กำแพงที่เท่าเทียมกัน
  2. ผนังพาริตี้คี่
  3. เท่าเทียมกันมุมผนังด้านบนขวาเท่าเทียมกัน (เช่น/กับผนังด้านล่าง)
  4. มุมคี่มุมขวาบน
  5. แม้กระทั่งมุมผนังซ้ายบน
  6. มุมคี่ซ้ายบนซ้าย
  7. แม้มุมผนังด้านล่างขวาเท่าเทียมกัน
  8. มุมล่างขวาล่างของพาริตี้คี่
  9. แม้กระทั่งมุมกำแพงล่างซ้ายเสมอกัน
  10. มุมล่างซ้ายผนังคี่แปลก
  11. หันหน้าไปทางเพดาน E / W
  12. หันหน้าไปทางเพดาน N / S
  13. ขอบฟ้าหันหน้าไปทาง E / W (ตรงกลางของหน้าจอหากไม่มีกำแพง)
  14. ขอบฟ้าหันหน้าไปทาง N / S
  15. หันหน้าไปทางพื้น E / W
  16. หันหน้าไปทางพื้น N / S

มีกำแพง 15 หลังที่อาจจำเป็นต้องแสดงผลโดยเกมในรูปแบบเช่นนี้ (โดยVระบุตำแหน่งของผู้เล่นและมุมมองที่โค้ง):

_ _ _
_|_|_ 
_|_|_
 |V|

กระเบื้องที่ใช้โดยกำแพงทั้ง 15 แผ่นถูกกำหนดไว้ในshapesรายการ มันคือรายการของ 2-tuples ค่าแรกของ tuple บ่งชี้ "parity" ของกำแพงพร้อมกับ0ระบุว่าควรวาดด้วยอักขระเดียวกันกับผนังด้านหน้าอักขระโดยตรงและเป็นการ1บ่งชี้ว่าควรเป็นรูปแบบทางเลือก (เช่น+vs X) ค่าที่สองคือรายการของx,y,ttuples ที่ระบุพิกัดหน้าจอและดัชนีย่อยของพิกเซลหนึ่งพิกเซล (กำแพงที่แสดงผลด้วยพาริตีคี่จะ1เพิ่มเข้าไปในแต่ละดัชนีเหล่านี้) รูปร่างเรียงตามระยะทางดังนั้นสามคนแรกจึงเป็นตัวแทนของผนังที่ตั้งฉากสองแผ่นก่อนหน้าของตัวอักษรตามด้วยผนังสองขนานสองแผ่นสองข้างหน้าและอื่น ๆ

ฟังก์ชั่นคือ:

  • rr: "เรนเดอร์" หน้าจอ (โดยการพิมพ์ไทล์ในบัฟเฟอร์หน้าจอ)
  • dw: "Draw กำแพง" ไปยังบัฟเฟอร์หน้าจอที่จัดเตรียมไว้ วิธีนี้ใช้อัลกอริธึมของจิตรกรดังนั้นกำแพงที่อยู่ไกลที่สุดจะถูกวาดขึ้นมาก่อน
  • ga: "get area" ส่งคืนรายการค่าบูลีนที่ระบุว่ากำแพงใดทึบแสงสำหรับตำแหน่งแผนที่ที่กำหนดและหันหน้าไปทาง
  • rd: "read" ซึ่งเป็นตัวสร้างที่อ่านแผนที่และยอมให้เส้น สิ่งนี้จำเป็นเพียงเพราะคอนโซลของ IDLE ทำสิ่งแปลก ๆ เมื่อคุณวางอินพุตหลายบรรทัดแทนที่จะป้อนทีละบรรทัด
  • rm: "read map" แยกวิเคราะห์แผนที่เป็นรายการบูลีนที่ซ้อนกันจัดทำดัชนีโดยm[y][x][d](โดยd=0เป็นทิศตะวันออกและd=1ทิศใต้) นอกจากนี้ยังเพิ่มสองแถวและสองคอลัมน์ของช่องว่างภายในเพื่อหลีกเลี่ยงข้อผิดพลาดดัชนีในรหัสอื่น ๆ
  • cl: "ล้าง" ผลลัพธ์ (โดยการเขียนบรรทัดใหม่เพื่อเลื่อนมุมมองเก่าออกไปด้านบนสุดของคอนโซลส่วนใหญ่)
  • gl: "game loop" ซึ่งมีการรวบรวมอินพุตและสิ่งต่าง ๆ ข้างต้นจะถูกเรียก

ภาพหน้าจอบางส่วน:

ตำแหน่งเริ่มต้น:

\               
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
+XXXXXXXXXXXXXX+
/               
X: 1 Y: 1 Facing: N
[FBLRQ]? 

มองไปตามผนังด้านทิศเหนือ:

\               
X\              
X+\             
X++\            
X+++\           
X+++X           
X+++X           
X+++X           
X+++X           
X+++X           
X+++/           
X++/            
X+/             
X/              
/               
X: 1 Y: 1 Facing: E
Last move: R
[FBLRQ]? 

สองสามช็อตที่ตรงกับตัวอย่างของคุณ (หมายเหตุบรรทัดแรกที่ว่างเปล่าถูกตัดออกโดย Stack Overflow ซึ่งอยู่ในผลลัพธ์ของโปรแกรม):

X             / 
X            /+ 
X           /++ 
X           +++ 
X           +++ 
X           +++ 
X           +++ 
X           +++ 
X           +++ 
X           +++ 
X           \++ 
X            \+ 
X             \ 

X: 3 Y: 2 Facing: S
Last move: F
[FBLRQ]? 

และ:

              / 
             /X 
            /XX 
            XXX 
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
+++++XXXXXX+XXX+
            XXX 
            \XX 
             \X 
              \ 

X: 3 Y: 2 Facing: E
Last move: L
[FBLRQ]? 

นี่คือหนึ่งในมุมมองของคนแปลกหน้าในแผนที่ที่ให้มาเนื่องจากผนังขนานกับมุมมองของเรามีสีเดียวกับผนังแนวตั้งฉากยื่นออกมาด้านหลัง:

 \              
 +\             
 ++\            
++++        ++++
++++        ++++
++++        ++++
++++        ++++
++++        ++++
++++        ++++
++++        ++++
 ++/            
 +/             
 /              

X: 3 Y: 4 Facing: N
Last move: R
[FBLRQ]? 

นี่คือลักษณะของภาพสุดท้ายจากด้านบน:

_   _
 |
  V

เพิ่มการวิเคราะห์และไดอะแกรมที่ดี! หืมกำแพงเหล่านั้นจบลงด้วยสีที่เหมือนกันในอันสุดท้ายในการดำเนินการของฉันด้วย จุดที่ดีเกี่ยวกับกรณีขอบ ฉันไม่คิดว่ามันจะเกิดขึ้น แต่มันต้องเป็นเช่นนั้น เดาว่ามันเหมือนกับการระบายสีแผนที่และสองสีก็ไม่เพียงพอ ... : - /
Dr. Rebmu
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.