REV0 C ++ (Visual Studio pada 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!");}}
Di bawah ini adalah permainan, menunjukkan bahwa (asalkan Anda tidak memulai tepat di sebelah bahaya) dengan permainan yang benar Anda selalu bisa menang. Pemain merasa mudah, berbalik dan melakukan putaran berlawanan arah jarum jam yang lengkap. Saat ia membutuhkan tepat 5 gerakan untuk merasakan angin sepoi-sepoi lagi, ia tahu lubang di sebelah kanannya, dan berada sejauh mungkin. Demikian pula, ketika dia mencium wumpus, tidak tahu apakah itu benar atau kiri, dia berbalik dan melakukan putaran searah jarum jam. Dibutuhkan 5 langkah untuk mencium wumpus lagi, jadi dia tahu itu ke kiri dan menembak dengan pasti.
Jika dia memutar ke arah lain, dia akan menemukan wumpus lebih cepat dan tahu itu ke arah yang sama dengan yang dia putar.
REV1 C (GCC di Cygwin), 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!",)}}
Baris baru ditambahkan untuk kejelasan. Perubahan dari Rev 0 adalah sebagai berikut:
Terima kasih banyak kepada @Dennis karena merekomendasikan kompiler GCC pada emulator Cygwin Linux untuk Windows. Kompiler ini tidak memerlukan include
s dalam program rev 0, dan memungkinkan defaultint
tipe untuk variabel dan main.
Ini adalah tip golf yang mengubah hidup!
Selain itu berjalan di Linux berarti itu \f
menyebabkan kursor bergerak ke bawah tanpa melakukan carriage return (tidak seperti di Windows di mana ia hanya menghasilkan simbol yang dapat dicetak.) Ini telah memungkinkan pemendekan pernyataan printf yang mencetak papan.
Beberapa tips tambahan dari Dennis di komentar, dan salah satu dari saya: perubahan kondisi saat memeriksa apakah panah mengenai wumpus: if(q==w)
> if(q-w)
(..else .. dibalik)
Penambahan tampilan grafis menunjukkan informasi yang pemain ketahui tentang di mana wumpus dilebur / angin sepoi-sepoi terasa untuk mengklaim bonus 35%. (Saya menghapus versi debug yang lama ini yang menunjukkan posisi persis wumpus dan lubang. Hal ini dapat dilihat pada riwayat edit.)
REV2 C (GCC di Cygwin), bonus 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");}
Sekali lagi terima kasih kepada Dennis untuk refactoring kode saya:
Konstanta Char m[]
diganti dengan literal (saya tidak tahu Anda bisa mengindeks literal.)
Pembibitan angka acak dengan variabel tumpukan (ketergantungan sistem, beberapa sistem mengacak alokasi memori sebagai ukuran keamanan.)
Makro dengan puts
diganti dengan makro dengan printf
dan kode tambahan yang harus dijalankan ketika pesan yang ditampilkan ditempatkan di dalam printf
argumen (keuntungan diambil dari wajah bahwa printf tidak mencetak beberapa argumen terakhir jika tidak ada cukup penentu format dalam string format.) if
digantikan oleh||
Perhitungan posisi baru pemain / wumpus ditempatkan di dalam makro baru.
Menang / kalah pesan yang ditempatkan di luar while
lingkaran. if
diganti oleh operator kondisional.
Gunakan operator bersyarat untuk menembakkan panah. Jika pemain absen, ini membutuhkan baik mencetak pesan dan menyesuaikan posisi wumpus. Dennis menawarkan beberapa cara untuk menggabungkan printf
dan menghitung posisi wumpus menjadi satu ekspresi, tetapi saya telah menggunakan salah satu dari cara saya sendiri. printf
mengembalikan jumlah karakter yang dicetak, yang Your arrow didn't hit anything\n
adalah 31 (11111 biner.) Jadi 31&Q(w)==Q(w)
,.
Kontribusi saya yang lain untuk pengeditan ini adalah menghilangkan beberapa tanda kurung yang tidak perlu.
Keluaran
Di sini pemain telah menemukan di mana Wumpus berada, tetapi memilih untuk melakukan penjelajahan menyeluruh untuk mencari tahu persis di mana lubang itu juga. Tidak seperti versi debug lama saya yang menunjukkan di mana wumpus dan lubang berada di sepanjang permainan, ini hanya menunjukkan kamar di mana pemain telah mengunjungi dan merasakan angin sepoi-sepoi (1) mencium wumpus (2) atau keduanya (3). (Jika pemain menembak panah dan meleset, variabel yang a
berisi info posisi wumpus diatur ulang.)
REPRESENTASI ICOSAHEDRON
Catatan: bagian ini didasarkan pada rev 1
Fitur bintang saya! Tidak ada grafik dalam kode saya. Untuk menjelaskan cara kerjanya, lihat peta dunia di bawah ini. Setiap titik pada icosahedron dapat diwakili oleh garis lintang 0-3 dan garis bujur 0-4 (atau satu angka long*4+lat
,.) Garis bujur yang ditandai pada peta hanya melewati wajah-wajah dengan garis bujur nol, dan garis garis lintang melewati pusat wajah dengan garis lintang nol.
Pemain dapat berorientasi pada 3 kemungkinan sumbu, diwakili oleh simbol-simbol sebagai berikut: utara-selatan -
-timur laut-barat daya \
-tenggara /
. Di setiap ruangan tertentu ia memiliki tepat satu pintu keluar pada masing-masing kapak yang tersedia untuknya. Pada layar yang ditampilkan, pemain membuat putaran searah jarum jam lengkap. Secara umum mudah untuk mengidentifikasi dari pemain yang menandai dari mana ia berasal, dan oleh karena itu ia boleh pergi ke mana.
Satu kasus yang agak sulit bagi mata yang belum diinisiasi adalah yang keempat. Ketika Anda melihat kemiringan pada salah satu baris kutub ini, pemain telah datang dari sel kutub terdekat ujung luar kemiringan dan umumnya menghadap ke arah khatulistiwa. Dengan demikian pemain menghadap tenggara dan opsinya adalah: 15 (SELATAN, sel ke kanan) 25 (northEAST, sel di atas) atau 35 (northWEST, sel di bawah.)
Jadi, pada dasarnya saya memetakan icosahedron ke kisi 5x4, dengan sel-sel bernomor 19 hingga 0 dalam urutan dicetak. Langkah ini dilakukan dengan menambah atau mengurangi dari posisi saat ini, tergantung pada garis lintang dan arah pemain, per tabel di bawah ini.
Jika pemain keluar dari bawah (barat) papan, ia kembali ke sisi atas (timur) dan sebaliknya, sehingga posisinya diambil modulo 20. Secara umum gerakan dikodekan ke dalam m [] dengan menambahkan ascii 80 ( P
) ke nilai mentah memberikan karakter yang ditunjukkan di bawah ini, tetapi prinsip kelipatan 20 dapat ditambahkan tanpa mempengaruhi operasi.
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
Input pemain (dibagi 10 untuk menghapus digit kedua) ditambahkan ke arah saat ini dan diambil modulo 3 untuk mendapatkan arah baru. Ini berfungsi dengan baik di sebagian besar kasus. Namun ada masalah ketika dia berada di ruang kutub dan bergerak menuju kutub. Ini akan menjadi jelas ketika melipat peta di bawah ini bahwa jika dia meninggalkan ruangan menghadap "timur laut" dia akan memasuki alun-alun baru yang menghadap "tenggara" sehingga koreksi harus dilakukan. Ini dilakukan di baris e=(d+i/10)*m[p%4]%3;
dengan perkalian dengan m[p%4]
. Empat nilai pertama m [] dipilih sedemikian rupa sehingga, selain fungsinya di atas, mereka juga memiliki karakteristik m[1]%3==m[2]%3==1
dan m[0]%3==m[3]%3==2
. Ini meninggalkan arah sendirian untuk kamar khatulistiwa dan menerapkan koreksi yang diperlukan untuk kamar kutub.
Waktu logis untuk melakukan koreksi adalah setelah pindah. Namun untuk menyimpan karakter itu dilakukan sebelum pindah. Karenanya nilai-nilai tertentu dalam m [] harus ditransformasikan. Jadi 2 karakter terakhir LT
bukan TL
per tabel di atas misalnya.
KODE TIDAK TERGERAK
ini adalah kode rev 1, yang kurang dikaburkan daripada rev 2.
Ini akan berjalan di GCC / Linux. Saya telah memasukkan dalam komentar kode tambahan yang diperlukan untuk membuatnya berjalan di Visual studio / Windows. Itu perbedaan besar!
//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!",)
}
}
ISU DAN KURIOISITAS
Saya telah mengambil keuntungan dari poin yang disebutkan oleh @professorfish, jika wumpus dan pit mulai di tempat acak, tidak ada kebutuhan bagi pemain untuk memulai di tempat acak. Pemain selalu mulai di kamar 19 menghadap ke utara.
Saya mengerti bahwa ketika wumpus "tidak terpengaruh oleh lubang", wumpus dapat mulai masuk, atau memasuki ruangan di mana lubang itu berada. Secara umum ini menyederhanakan hal-hal kecuali satu poin. Saya tidak memiliki variabel khusus untuk menunjukkan bahwa permainan telah berakhir; itu berakhir ketika pemain bertepatan dengan wumpus atau lubang. Jadi, ketika pemain menang, saya menampilkan pesan yang menang tetapi memindahkan lubang ke pemain untuk keluar dari lingkaran! Saya tidak bisa menempatkan pemain di lubang karena wumpus mungkin ada di sana dan saya akan mendapatkan pesan tentang wumpus yang tidak saya inginkan.
Program rev0 bekerja dengan sempurna di studio visual, tetapi IDE mengatakan "tumpukan rusak di sekitar variabel i" saat keluar. Hal ini karena scanf sedang mencoba untuk menempatkan int
ke dalam char.
Dennis melaporkan perilaku yang salah pada mesin Linux nya karena hal ini. Pokoknya itu diperbaiki dengan menggunakan tipe yang benar di rev 1.
Garis untuk menampilkan papan di rev 0 adalah canggung dan muncul sedikit berbeda pada platform lain. Di printf(" %c%c%c")
tengah% c adalah karakter yang dapat dicetak ditampilkan. % C terakhir adalah ASCII 0 atau ASCII 10 (\ n, baris baru dengan carriage return di Windows.) Tampaknya tidak ada karakter di Windows yang bekerja di konsol, yang akan turun baris tanpa memberikan carriage return. Jika ada, saya tidak memerlukan tab c% pertama (ASCII 0, atau ASCII 9 sebelum karakter lintang 1. Tab terkenal tidak terdefinisi dalam perilakunya.) Ruang terdepan meningkatkan pemformatan (menempatkan karakter 3 & 2 lebih dekat dengan karakter lintang 1 lebih dekat dengan karakter 1 .) Rev 1 memiliki revisi garis ini yang menggunakan karakter formfeed dan karenanya tidak memerlukan karakter format pada awal printf. Ini membuatnya lebih pendek, tetapi \ f tidak berfungsi di Windows.