REV0 C ++ (Visual Studio บน Windows) 405
#include"stdafx.h"
#include<stdlib.h>
#include<time.h>
int main(){srand(time(NULL));char i,h=rand()%19,w=rand()%19,p=19,d=0,q,e,m[]="e@LwQMQOSOLT";while(p-h&&p-w){for(i=3;i--;){q=(p+m[p%4*3+i])%20;if(q==w)puts("you smell a wumpus");if(q==h)puts("you feel a breeze");}scanf_s("%d",&i);e=(d+i/10)*m[p%4]%3;q=(p+m[p%4*3+e])%20;if(i%5){if(q==w){puts("YOU KILLED THE WUMPUS!");h=p;}else{puts("arrow missed");w=(w+m[w%4*3+rand()%3])%20;}}else{p=q;d=e;if(p==h)puts("YOU FELL IN A HOLE!");}if(p==w)puts("THE WUMPUS GOT YOU!");}}
ด้านล่างนี้คือ playthrough ซึ่งแสดงให้เห็นว่า (หากคุณไม่ได้เริ่มติดกับอันตราย) ด้วยการเล่นที่ถูกต้องคุณสามารถชนะได้เสมอ ผู้เล่นรู้สึกว่าสบายหันหลังกลับและหมุนวนทวนเข็มนาฬิกาจนจบ เมื่อเขาใช้เวลา 5 ก้าวในการรู้สึกถึงสายลมอีกครั้งเขาก็รู้รูไปทางขวาของเขาและออกไปให้ไกลที่สุด ในทำนองเดียวกันเมื่อเขาได้กลิ่นวุสปัสโดยไม่รู้ว่ามันถูกหรือซ้ายเขาก็หันหลังกลับและวนตามเข็มนาฬิกา เขาใช้เวลา 5 ครั้งในการดมกลิ่นวูมปัสอีกครั้งดังนั้นเขาจึงรู้ว่ามันอยู่ทางซ้ายและยิงด้วยความมั่นใจ
หากเขาวนลูปไปทางอื่นเขาจะพบว่าววัสเร็วขึ้นและรู้ว่ามันเป็นไปในทิศทางเดียวกันกับที่เขาหมุน
REV1 C (GCC สำหรับ Cygwin), 431-35% โบนัส = 280.15
#define u(t,s,c) if(t){puts(s);c;}
i,d,e,a,b;main(){srand(time(0));char q,p=19,h=rand()%p,w=rand()%p,*m="e@LwQMQOSOLT-\\/\n \v ";
while(p-h&&p-w){
for(i=3;i--;){q=(p+m[p%4*3+i])%20;u(q==w,"you smell a wumpus",a|=2<<p)u(q==h,"you feel a breeze",b|=1<<p)}
for(i=20;i--;)printf("%c%c",i==p?m[d+12]:48+(a>>i&2)+(b>>i&1),m[i%4+15]);
scanf("%d",&i);e=(d+i/10)*m[p%4]%3;q=(p+m[p%4*3+e])%20;
if(i%5){u(q-w,"arrow missed",w=(w+m[w%4*3+rand()%3])%20;a=0)else u(1,"YOU KILLED THE WUMPUS!",h=p)}
else{p=q;d=e;u(p==h,"YOU FELL IN A HOLE!",)}
u(p==w,"THE WUMPUS GOT YOU!",)}}
เพิ่มบรรทัดใหม่เพื่อความชัดเจน การเปลี่ยนแปลงจาก Rev 0 มีดังนี้:
ขอบคุณมากที่ @Dennis สำหรับการแนะนำคอมไพเลอร์ GCC บน Cygwin Linux emulator สำหรับ Windows คอมไพเลอร์นี้ไม่ต้องการinclude
s ในโปรแกรม rev 0 และอนุญาตint
ประเภทเริ่มต้นสำหรับตัวแปรและmain.
นี่คือเคล็ดลับการเล่นกอล์ฟที่เปลี่ยนแปลงชีวิต!
นอกจากนี้การรันใน Linux หมายความว่า\f
ทำให้เคอร์เซอร์เลื่อนลงโดยไม่ทำ carriage return (ต่างจากใน Windows ที่เพิ่งสร้างสัญลักษณ์ที่พิมพ์ได้) ซึ่งอนุญาตให้ย่อคำสั่ง printf ที่พิมพ์บนบอร์ดได้
เคล็ดลับเพิ่มเติมจากเดนนิสในความคิดเห็นและหนึ่งในตัวฉันเอง: เปลี่ยนเงื่อนไขเมื่อตรวจสอบว่าลูกศรกดปุ่ม wumus: if(q==w)
> if(q-w)
(..else .. is reverse)
เพิ่มเติมจากการแสดงกราฟิกที่แสดงข้อมูลที่ผู้เล่นรู้เกี่ยวกับตำแหน่งที่มีกลิ่นของ wumpus / สายลมรู้สึกว่ารับโบนัส 35% (ฉันลบ debug เวอร์ชั่นเก่าซึ่งแสดงตำแหน่งที่แน่นอนของ wumpus และ hole ซึ่งสามารถเห็นได้ในประวัติการแก้ไข)
REV2 C (GCC สำหรับ Cygwin) โบนัส 389-35% = 252.85
#define Q(N) (N+"QTLOQMQOSOLT"[N%4*3+e])%20
#define P printf(
i,d,e,a,b;main(){int p=19,q=srand(&p),h=rand()%p,w=rand()%p;
while(p-h&&p-w){
for(e=3;e--;){q=Q(p);q-w||P"You smell a wumpus\n",a|=2<<p);q-h||P"You feel a breeze\n",b|=1<<p);}
for(i=20;i--;)P"%c%c",i-p?48+(a>>i&2)+(b>>i&1):"-\\/"[d],"\n \v "[i%4]);
scanf("%d",&i);e=(d+i/9)*"edde"[p%4]%3;q=Q(p);
if(i%5){e=rand()%3;w=q-w?P"Your arrow didn't hit anything\n",a=0)&Q(w):(p=20);}
else p=q,d=e;
}
P p-20?p-w?"YOU FELL IN A HOLE!\n":"THE WUMPUS GOT YOU!\n":"YOU KILLED THE WUMPUS!\n");}
ขอขอบคุณเดนนิสอีกครั้งสำหรับการทำซ้ำรหัสของฉัน:
ค่าคงที่ของ Char m[]
ถูกแทนที่ด้วยตัวอักษร (ฉันไม่รู้ว่าคุณสามารถจัดทำดัชนีตามตัวอักษรได้)
การเพาะหมายเลขสุ่มด้วยตัวแปรสแต็ก (ขึ้นอยู่กับระบบบางระบบสุ่มการจัดสรรหน่วยความจำเป็นการวัดความปลอดภัย)
แมโครที่puts
ถูกแทนที่ด้วยแมโครด้วยprintf
และรหัสเพิ่มเติมซึ่งจะต้องดำเนินการเมื่อข้อความที่แสดงอยู่ภายในprintf
อาร์กิวเมนต์ (ประโยชน์ที่ได้จากใบหน้าที่ printf ไม่พิมพ์อาร์กิวเมนต์สองสามตัวสุดท้ายหากตัวระบุรูปแบบไม่เพียงพอในสตริงรูปแบบ) if
แทนที่ด้วย||
การคำนวณตำแหน่งใหม่ของผู้เล่น / wumpus วางไว้ในมาโครใหม่
รับ / วางข้อความที่อยู่นอกwhile
ลูป if
แทนที่ด้วยตัวดำเนินการตามเงื่อนไข
การใช้ตัวดำเนินการตามเงื่อนไขในสายการยิงลูกศร หากผู้เล่นพลาดสิ่งนี้จะต้องมีทั้งการพิมพ์ข้อความและปรับตำแหน่ง wumpus เดนนิสเสนอวิธีการรวมกันหลายวิธีprintf
และการคำนวณตำแหน่งของ wumpus ลงในนิพจน์เดียว แต่ฉันได้ไปกับหนึ่งในตัวของฉันเอง printf
ส่งกลับจำนวนของตัวอักษรที่พิมพ์ซึ่งYour arrow didn't hit anything\n
เป็น 31 (11111 ไบนารี.) 31&Q(w)==Q(w)
ดังนั้น
การมีส่วนร่วมอื่น ๆ ของฉันในการแก้ไขนี้ได้ทำการกำจัดวงเล็บเหลี่ยมที่ไม่จำเป็นออกไป
เอาท์พุต
ที่นี่ผู้เล่นพบว่า Wumpus อยู่ที่ไหน แต่เลือกที่จะสำรวจอย่างละเอียดเพื่อค้นหาว่าหลุมอยู่ที่ใดเช่นกัน ซึ่งแตกต่างจากรุ่น debug เก่าของฉันซึ่งแสดงให้เห็นว่า wumpus และหลุมอยู่ตลอดทั้งเกมนี้แสดงเฉพาะห้องที่ผู้เล่นเข้าเยี่ยมชมและรู้สึกถึงสายลม (1) หลอม wumpus (2) หรือทั้งสอง (3) (หากผู้เล่นยิงธนูและพลาดไปตัวแปรa
ที่บรรจุข้อมูลตำแหน่งของ wumpus จะถูกรีเซ็ต)
การเป็นตัวแทนของ ICOSAHEDRON
หมายเหตุ: ส่วนนี้อ้างอิงจาก rev 1
คุณสมบัติเด่นของฉัน! ไม่มีกราฟในรหัสของฉัน หากต้องการอธิบายวิธีการทำงานให้ดูแผนที่โลกด้านล่าง จุดใด ๆ บน icosahedron สามารถแสดงเป็นละติจูด 0-3 และลองจิจูด 0-4 (หรือหมายเลขเดียว, long*4+lat
.) เส้นลองจิจูดที่ทำเครื่องหมายไว้บนแผนที่จะผ่านใบหน้าเหล่านั้นที่มีศูนย์ลองจิจูดเท่านั้นและเส้นละติจูดผ่าน ศูนย์กลางของใบหน้าที่มีละติจูดเป็นศูนย์
ผู้เล่นสามารถมุ่งเน้นใน 3 แกนไปได้แทนด้วยสัญลักษณ์ดังนี้ทิศตะวันตกเฉียงใต้-
ทิศตะวันออกเฉียงเหนือทิศตะวันตกเฉียงใต้ทิศตะวันตกเฉียงเหนือตะวันออกเฉียงใต้\
/
ในห้องใดก็ตามเขามีทางออกเดียวให้กับเขาในแต่ละแกน ในจอแสดงผลแสดงว่าเครื่องเล่นทำลูปตามเข็มนาฬิกาจนจบ โดยทั่วไปจะง่ายต่อการระบุจากผู้เล่นที่ทำเครื่องหมายว่าเขามาจากไหนดังนั้นเขาจึงได้รับอนุญาตให้ไป
กรณีหนึ่งที่ยากเล็กน้อยสำหรับตาที่ไม่ได้ฝึกหัดคือตาที่สี่ เมื่อคุณเห็นการเอียงในหนึ่งในแถวขั้วโลกเหล่านี้ผู้เล่นมาจากเซลล์ขั้วโลกที่อยู่ใกล้ปลายด้านนอกสุดของเอียงและหันหน้าเข้าหาเส้นศูนย์สูตร ดังนั้นผู้เล่นจะหันหน้าไปทางทิศตะวันออกเฉียงใต้และทางเลือกของเขาคือ: 15 (SOUTH, เซลล์ทางด้านขวา) 25 (ทิศตะวันออกเฉียงเหนือ, เซลล์ด้านบน) หรือ 35 (ทิศตะวันตกเฉียงเหนือ, เซลล์ด้านล่าง)
โดยทั่วไปแล้วฉันจับคู่ icosahedron กับตาราง 5x4 โดยเซลล์มีหมายเลข 19 ถึง 0 ตามลำดับที่พิมพ์ การย้ายทำได้โดยการเพิ่มหรือลบออกจากตำแหน่งปัจจุบันขึ้นอยู่กับละติจูดและทิศทางของผู้เล่นตามตารางด้านล่าง
ถ้าผู้เล่นออกไปด้านล่าง (ตะวันตก) ของบอร์ดเขาจะกลับมาที่ด้านบน (ตะวันออก) และในทางกลับกันตำแหน่งของเขาจึงถูกนำไปเป็นโมดูโล 20 โดยทั่วไปการเคลื่อนไหวจะถูกเข้ารหัสเป็น m [] โดยเพิ่ม ascii 80 ( P
) ถึงค่า raw ที่แสดงตัวอักษรด้านล่าง แต่สามารถเพิ่มหลักการใดก็ได้จาก 20 รายการโดยไม่ส่งผลกระทบต่อการดำเนินการ
Table of addition values for moves
Direction Symbol Latitude 0 1 2 3 Latitude 0 1 2 3
0, N-S - 1 -1 1 -1 Q O Q O
1, NE-SW \ -4 1 -1 4 L Q O T
2, NW-SE / 4 -3 3 -4 T M S L
อินพุตของผู้เล่น (หารด้วย 10 เพื่อลบตัวเลขที่สอง) จะถูกเพิ่มไปยังทิศทางปัจจุบันของเขาและนำโมดุลโล 3 ไปสู่ทิศทางใหม่ของเขา วิธีนี้ใช้ได้ผลดีในกรณีส่วนใหญ่ อย่างไรก็ตามมีปัญหาเมื่อเขาอยู่ในห้องขั้วโลกและเดินไปทางเสา จะชัดเจนเมื่อพับแผนที่ด้านล่างว่าถ้าเขาออกจากห้องหันหน้าไปทางทิศตะวันออกเฉียงเหนือเขาจะเข้าสู่จตุรัสใหม่หันหน้าไปทางทิศตะวันออกเฉียงใต้ดังนั้นจึงต้องทำการแก้ไข นี้จะกระทำในบรรทัดโดยคูณด้วยe=(d+i/10)*m[p%4]%3;
m[p%4]
สี่ค่าแรกของม. [] ได้รับการคัดเลือกดังกล่าวว่านอกเหนือไปจากฟังก์ชั่นของพวกเขาเหนือพวกเขายังมีลักษณะ และm[1]%3==m[2]%3==1
m[0]%3==m[3]%3==2
สิ่งนี้ทำให้ทิศทางเดียวสำหรับห้องศูนย์สูตรและใช้การแก้ไขที่จำเป็นสำหรับห้องขั้วโลก
เวลาตรรกะที่จะทำการแก้ไขจะเป็นหลังการย้าย อย่างไรก็ตามในการบันทึกตัวละครมันจะทำก่อนที่จะย้าย ดังนั้นค่าบางค่าใน m [] ต้องถูกย้าย ดังนั้นอักขระ 2 ตัวสุดท้ายLT
แทนที่จะเป็นตัวอย่างของTL
ตารางข้างต้น
รหัสที่ไม่ได้แปล
นี่คือรหัส rev 1 ซึ่ง obfuscated น้อยกว่า rev 2
สิ่งนี้จะทำงานบน GCC / Linux ฉันได้รวมอยู่ในความคิดเห็นเกี่ยวกับรหัสพิเศษที่จำเป็นในการทำให้มันทำงานบน Visual studio / Windows มันแตกต่างกันมาก!
//Runs on gcc/linux. For visual studio / windows, change printf(...)
//to printf(" %c%c%c",9*(i%4==1),i==p?m[d+12]:48+(a>>i&2)+(b>>i&1),10*!(i%2)) and uncomment the following lines
//#include"stdafx.h"
//#include<stdlib.h>
//#include<time.h>
//#pragma warning(once:996;once:430) //allow the use of scanf instead of scanf_s, allow default type=int.
//Though rather than using the pragma, it is shorter to follow compiler recommendation and use scanf_s and int.
#define u(t,s,c) if(t){puts(s);c;} //if(test){puts(string);additional code;}
i, //player input, loop counter
d,e, //current and proposed direction
a,b; //bit flags for where wumpus smelt / breeze felt
main(){
srand(time(0));
char q,p=19,h=rand()%p,w=rand()%p, //Initialise player, hole and wumpus. q stores proposed player position.
*m="e@LwQMQOSOLT-\\/\n \f "; //Chars 0-11: movetable. Chars 12-14:symbol for player. Chars 15-18: graphics format.
while(p-h&&p-w){
// Print warnings
for(i=3;i--;){q=(p+m[p%4*3+i])%20;u(q==w,"you smell a wumpus",a|=2<<p)u(q==h,"you feel a breeze",b|=1<<p)}
// graphic display
for(i=20;i--;)printf("%c%c",i==p?m[d+12]:48+(a>>i&2)+(b>>i&1),m[i%4+15]);
// Get player input and work out direction and room
scanf("%d",&i);
e=(d+i/10)*m[p%4]%3;
q=(p+m[p%4*3+e])%20;
// i%5 is false if player inputs 5 (move player) otherwise true (shoot arrow)
if(i%5)
{u(q-w,"arrow missed",w=(w+m[w%4*3+rand()%3])%20;a=0)else u(1,"YOU KILLED THE WUMPUS!",h=p)}
else{p=q;d=e;u(p==h,"YOU FELL IN A HOLE!",)}
u(p==w,"THE WUMPUS GOT YOU!",)
}
}
ปัญหาและปัจจัยที่เกี่ยวข้อง
ฉันใช้ประโยชน์จากจุดที่เอ่ยถึง @professorfish ถ้าหาก wumpus และหลุมเริ่มต้นในสถานที่สุ่มไม่มีความจำเป็นสำหรับผู้เล่นที่จะเริ่มต้นในสถานที่สุ่ม ผู้เล่นเริ่มต้นในห้องที่ 19 ซึ่งหันหน้าไปทางทิศเหนือ
ฉันเข้าใจว่าเมื่อตั๊กแตนเป็น "ไม่ได้รับผลกระทบจากหลุม" ตั๊กแตนสามารถเริ่มต้นได้หรือเข้าไปในห้องที่หลุมอยู่ โดยทั่วไปสิ่งนี้ทำให้สิ่งต่าง ๆ ง่ายขึ้นยกเว้นเพียงจุดเดียว ฉันไม่มีตัวแปรเฉพาะที่ระบุว่าเกมจบลงแล้ว มันจบลงเมื่อผู้เล่นนั้นเกิดขึ้นพร้อมกับวุสตุสหรือหลุม ดังนั้นเมื่อผู้เล่นชนะฉันจะแสดงข้อความที่ชนะ แต่ย้ายหลุมไปยังผู้เล่นเพื่อควักออกจากวง! ฉันไม่สามารถวางผู้เล่นลงหลุมเนื่องจากวุดปัสอาจอยู่ที่นั่นและฉันจะได้รับข้อความเกี่ยวกับวู้ดปัสที่ฉันไม่ต้องการ
rev0program ทำงานได้อย่างสมบูรณ์แบบใน visual studio แต่ IDE กล่าวว่า "stack stack รอบ ๆ i เสียหาย" เมื่อออก นี่เป็นเพราะ scanf พยายามที่จะใส่int
ลงในchar.
เดนนิสรายงานพฤติกรรมที่ไม่ถูกต้องบนเครื่อง Linux ของเขาเพราะสิ่งนี้ อย่างไรก็ตามมันได้รับการแก้ไขโดยการใช้ประเภทที่ถูกต้องใน rev 1
บรรทัดสำหรับแสดงบอร์ดในรอบที่ 0 นั้นค่อนข้างงุ่มง่ามและแตกต่างกันเล็กน้อยบนแพลตฟอร์มอื่น ๆ ในprintf(" %c%c%c")
ตรงกลาง% c จะแสดงตัวอักษรที่พิมพ์ได้ % c สุดท้ายคือ ASCII 0 หรือ ASCII 10 (\ n, ขึ้นบรรทัดใหม่กับ carriage return ใน Windows) ดูเหมือนจะไม่มีอักขระใน Windows ที่ใช้งานได้ในคอนโซลที่จะลงบรรทัดโดยไม่ต้องคืนค่าขนส่ง หากฉันไม่ต้องการแท็บ c% แรก (ASCII 0 หรือ ASCII 9 ก่อนอักขระละติจูด 1 แท็บนั้นไม่ได้ระบุอย่างชัดเจนในพฤติกรรมของพวกเขา) พื้นที่ชั้นนำปรับปรุงการจัดรูปแบบ (ทำให้ละติจูด 3 และ 2 อักขระใกล้กับละติจูด 1 อักขระ .) Rev 1 มี revison ของบรรทัดนี้ซึ่งใช้อักขระ \ f formfeed ดังนั้นจึงไม่ต้องการอักขระรูปแบบที่จุดเริ่มต้นของ printf ทำให้สั้นลง แต่ \ f ไม่ทำงานใน Windows