REV0 C ++ (Windows'ta Visual Studio) 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!");}}
Aşağıda, bir tehlikenin hemen yanında başlamamanız şartıyla) doğru oyunla her zaman kazanabileceğinizi gösteren bir oyundur. Müzikça bir meltem hissediyor, geri dönüyor ve saat yönünün tersine tam bir döngü yapıyor. Yine bir esinti hissetmesi için tam olarak 5 hamle yapmasıyla sağındaki deliği bilir ve mümkün olduğunca uzağa gider. Benzer şekilde, sağ ya da sol olup olmadığını bilmeden, wumpus kokladığında geri döner ve saat yönünde bir döngü yapar. Yine wumpusu koklamak için 5 hamle yapması gerekiyor, bu yüzden sola doğru olduğunu biliyor ve kesin bir şekilde vuruyor.
Eğer öbür tarafa ilmek etmiş olsaydı, wumpusu daha erken bulurdu ve döndüğü yönde olduğunu biliyordu.
REV1 C (Cygwin'deki GCC),% 431-35 bonus = 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!",)}}
Netlik için Newlines eklendi. Rev 0'dan gelen değişiklikler aşağıdaki gibidir:
Windows için Cygwin Linux emülatöründe GCC derleyicisini önerdiğiniz için @Dennis 'e teşekkür ederiz. Bu derleyici include
rev 0 programında s gerektirmez ve int
değişkenler için varsayılan tipe izin verir ve main.
bu hayat değiştiren bir golf ipucudur!
Ek olarak, Linux'ta çalıştırmak \f
, imlecin satır başı yapılmadan aşağı doğru hareket etmesine neden olduğu anlamına gelir (Windows'ta yalnızca basılabilir bir sembol ürettiği gibi).
Dennis'den yorumlarda birkaç ipucu ve kendi yorumlarımdan biri: ok wumpus'a çarpıp çarpmadığını kontrol ederken durum değişikliği: if(q==w)
> if(q-w)
(..else .. tersine döndü)
Oyuncunun bildiği bilgiyi gösteren grafik ekranın eklenmesi, bir wumpusun nerede koktuğunu / bir esinti hissettiğini,% 35 ikramiyeyi talep ettiğini hissediyor. (Bunun eski hata ayıklama sürümünü sildim, bu da wumpus ve hole'nin tam konumunu gösterdi. Düzenleme geçmişinde görülebilir.)
REV2C (Cygwin'deki GCC),% 389-35 bonus = 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");}
Kodumu yeniden düzenlemesi için Dennis'e tekrar teşekkürler:
Char sabiti m[]
değişmezlerle değiştirildi (değişmez dizini indeksleyebileceğinizi bilmiyordum.)
Yığın değişkeni ile rasgele sayıların tohumlanması (sisteme bağlı, bazı sistemler bellek tahsisini bir güvenlik önlemi olarak rastgele ayarlar.)
İleti, argümanların içine yerleştirildiğinde görüntülendiğinde çalıştırılması gereken puts
bir makro printf
ve ek kod ile değiştirilen makro printf
(format dizesinde yeterli format belirteci yoksa, printf'nin son birkaç argümanı yazdırmadığı avantajı.) if
ile ikame edilmiş||
Yeni makro içine yerleştirilen yeni oyuncu / wumpus pozisyonunun hesaplanması.
Dış while
döngüye yerleştirilen mesajları kazan / kaybet . if
koşullu operatör tarafından değiştirildi.
Ok atma için koşullu operatörün kullanılması. Müzikçalar özlüyorsa, bu hem mesaj yazdırmayı hem de wumpus konumunu ayarlamayı gerektirir. Dennis, birleştirme printf
ve wumpus pozisyonunun hesaplanmasını tek bir ifadeyle bir kaç yöntemle teklif etti , ancak ben kendimden biriyle gittim. 31 printf
olan basılan karakter sayısını döndürür Your arrow didn't hit anything\n
(11111 ikili) 31&Q(w)==Q(w)
.
Bu düzenlemeye diğer katkım, gereksiz parantezlerin ortadan kaldırılması olmuştur.
Çıktı
Burada oyuncu Wumpus'un nerede olduğunu çoktan buldu, ancak çukurun nerede olduğunu bulmak için kapsamlı bir keşif yapmayı seçti. Wumpus ve pit'in oyun boyunca nerede olduğunu gösteren eski hata ayıklama versiyonumun aksine, bu sadece oyuncunun ziyaret ettiği ve bir esinti hissettiği odaları (1) wumpusu (2) veya her ikisini (3) kokladığını gösteriyor. (Oynatıcı bir ok atar ve ıskalarsa, a
wumpus konum bilgisini içeren değişken sıfırlanır.)
ICOSAHEDRON TEMSİLİ
Not: Bu bölüm rev 1'e dayanmaktadır
Benim yıldız özelliğim! Kodumda grafik yok. Nasıl çalıştığını açıklamak için aşağıdaki dünya haritasına bakınız. İkosahedron üzerindeki herhangi bir nokta, 0-3 enlem ve boylam 0-4 (veya tek bir sayı long*4+lat
) ile temsil edilebilir . Sıfır enlemli yüzlerin merkezi.
Oyuncunun şu şekilde sembollerle temsil, 3 olası eksenlerde yönlendirilebilir: kuzey-güney -
kuzeydoğu-güneybatı \
, kuzeybatı-güneydoğu /
. Herhangi bir odada, kendisi için mevcut olan bu eksenlerin her birinde bir çıkışa sahiptir. Gösterilen ekranda oynatıcı tam bir saat yönünde döngü yapar. Nereden geldiğini ve dolayısıyla nereye gitmesine izin verildiğini belirten oyuncudan genel olarak anlaşılması kolaydır.
Başlatılmamış göz için biraz zor olan bir vaka dördüncü. Bu kutup sıralarından birinde bir eğik gördüğünüzde, oyuncu eğimin dış ucuna en yakın olan kutupsal hücreden gelmiş ve genel olarak ekvatora doğru bakmaktadır. Böylece oyuncu güneydoğuya bakar ve seçenekleri şunlardır: 15 (GÜNEY, sağdaki hücre) 25 (kuzeydoğu, üstteki hücre) veya 35 (kuzeybatı, aşağıdaki hücre).
Bu nedenle, temel olarak, icosahedron'u 5x4 ızgaraya eşlerim, 19 ila 0 numaralı hücreler basıldıkları sırada eşler. Hareket, oyuncunun enlemine ve yönüne bağlı olarak aşağıdaki tabloya göre mevcut konumdan toplama veya çıkarma yoluyla yapılır.
Eğer oyuncu tahtanın altından (batıdan) dışarı çıkarsa, üst (doğu) tarafa geri döner ve tam tersi olur, bu yüzden pozisyonu modulo 20'ye alınır. P
) Aşağıda gösterilen karakterleri veren ham değere, ancak prensibi işlemi etkilemeden 20 katından herhangi biri eklenebilir.
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
Oyuncunun girişi (ikinci basamağı çıkarmak için 10'a bölünmüş) geçerli yönüne eklenir ve yeni yönünü almak için modulo 3 alınır. Bu, çoğu durumda iyi çalışıyor. Ancak kutup odasındaki ve direğe doğru ilerlerken bir sorun var. Aşağıdaki haritayı katlarken, odayı "kuzeydoğuya" doğru bıraktığı takdirde, "güneydoğuya" bakan yeni kareye gireceği için bir düzeltme yapılması gerektiği açıktır. Bu satırda e=(d+i/10)*m[p%4]%3;
çarpma ile yapılır m[p%4]
. M [] nin ilk dört değeri, yukarıdaki fonksiyonlarına ek olarak, aynı zamanda karakteristik m[1]%3==m[2]%3==1
ve m[0]%3==m[3]%3==2
. Bu, ekvator odaları için tek başına yön bırakır ve kutup odaları için gerekli düzeltmeyi uygular.
Düzeltme yapmak için mantıksal zaman hamle sonrası olacaktır. Ancak karakterleri kaydetmek için hamle öncesi yapılır. Bu nedenle m [] cinsinden belirli değerler aktarılmalıdır. Bu nedenle, örneğin son 2 karakter yukarıdaki tablo başına LT
değil TL
.
UNUTMAYAN KOD
bu rev 1 kodudur, rev 2'den daha az karışıktır.
Bu GCC / Linux üzerinde çalışacak. Yorumlara Visual Studio / Windows'ta çalışması için gereken ekstra kodu ekledim. Bu büyük bir fark!
//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!",)
}
}
SORUNLAR VE CURIOISITIES
@Professorfish tarafından belirtilen noktadan yararlandım, eğer wumpus ve pit rastgele yerlerde başlarsa, oyuncunun rastgele bir yerde başlamasına gerek kalmaz. Oyuncu daima oda 19'da kuzeye bakacak şekilde başlar.
Wumpus'un “çukurdan etkilenmemiş” olması nedeniyle, wumpus'un başlayabileceğini veya çukurun bulunduğu odaya girebildiğini anlıyorum. Genel olarak bu, bir nokta dışındaki şeyleri basitleştirir. Oyunun bittiğini gösteren özel bir değişkenim yok; oyuncu wumpus veya pit ile çakıştığında biter. Bu yüzden oyuncu kazandığında, kazananı belirten mesajı görüntülerim, ancak çukuru oyuncunun dışına çıkarmak için çukuru oynatın! Wumpus orda olabileceği için oyuncuyı çukura koyamıyorum ve istemediğim wumpus hakkında bir mesaj alacağım.
Rev0program görsel stüdyosunda kusursuz bir şekilde çalıştı, ancak IDE çıkışta "i değişkeni etrafında bozuk yığılmış" dedi. Scanf bir koymak için çalışıyor olmasıdır int
bir içine char.
Dennis bu nedenle onun Linux makine yanlış davranışı bildirildi. Neyse, rev 1'de doğru tip kullanılarak sabitlenir.
Tahtayı rev 0'da gösterme çizgisi sakardır ve diğer platformlarda biraz farklı görünür. Gelen printf(" %c%c%c")
orta% c görüntülenen yazdırılabilir karakterdir. Son% c, ASCII 0 veya ASCII 10'dur (\ n, Windows'ta satır başı olan yeni satır.) Windows'ta, konsolda çalışan ve satır başı gelmeden satır aşağı gidecek bir karakter bulunmuyor. Olsaydı ilk c% 'ye (ASCII 0 ya da ASCII 9 sekmesi enlem 1 karakterinden önce ihtiyacım olmazdı. Sekmeler davranışlarında açıkça tanımsızdı.) Baştaki boşluk biçimlendirmeyi geliştirir (enlem 3 ve 2 karakterleri enlem 1 karakterine yaklaştırır) .) Rev 1, \ f formfeed karakteri kullanan ve bu nedenle printf'in başında herhangi bir format karakteri gerektirmeyen bu satırın bir revizyonuna sahiptir. Bu daha kısa yapar, ancak \ f Windows'ta çalışmaz.