Saltar al contenido

Caza al Wumpus

Este equipo de trabajo ha pasado horas investigando para darle soluciones a tus búsquedas, te regalamos la resolución de modo que deseamos que sea de mucha ayuda.

Solución:

GolfScript, 163

:n;:`"You shot the wumpus.
""The wumpus ate you.
""The pit swallowed you.
"19:2*0|[:,~,4%"ftvh"=.,+,@-]20%%:^;.^.+.3$?>"You feel a breeze.
"1$6"You smell a wumpus.
"4$8$?-1>*p2*'"#):"'++~3%/==3$=[email protected];if.[do])=

La puntuación se obtiene tomando el recuento de bytes (290), sumando el número de cadenas utilizadas para la interacción con el usuario (6) y restando la longitud combinada de esas cadenas (133). Los avances de línea son parte de las cadenas y contribuyen al recuento de bytes.

Hitos

  1. Portado la respuesta del profesorfish de Bash a GolfScript. Puntuación: 269

  2. Actuó de acuerdo con las sugerencias de Peter Taylor en los comentarios. Puntuación: 250

  3. Peter Taylor refactorizó todo mi código y me ayudó a comprimir la tabla de búsqueda. Puntuación: 202

  4. Se reemplazó la tabla de búsqueda de habitaciones adyacentes con un enfoque matemático. Puntuación: 182

  5. Entrada, salida refactorizada y la función que respalda el enfoque matemático. Puntuación: 163

¡Un gran gracias!” acude a Peter Taylor por toda su ayuda.

Cómo funciona

Las 20 habitaciones están representadas como los vértices de un dodecaedro, a los que se les han asignado números del 0 al 19 de la siguiente manera:

Gráfico dodecaédrico

Para encontrar las habitaciones adyacentes a la habitación norte y ordenarlos en sentido horario, tenemos que considerar cuatro casos:

  • Si N ≡ 0 mod 4 (vértices azules), la habitación adyacente es 19 – N, N + 2 mod 20 y N – 2 mod 20.

  • Si N ≡ 1 mod 4 (vértices verdes), la habitación adyacente es 19 – N, N – 4 mod 20 y N + 4 mod 20.

  • Si N ≡ 2 mod 4 (vértices amarillos), la habitación adyacente es 19 – N, N – 2 mod 20 y N + 2 mod 20.

  • Si N ≡ 3 mod 4 (vértices rojos), la habitación adyacente son, 19 – N, N + 4 mod 20 y N – 4 mod 20.

# The function “p” is implemented as “`print n print”. By storing an empty string in 
# “n” and nullifying “`”, “p” becomes an alias for “print”.

:n;:`

# Push the messages corresponding to the three possible outcomes of the game.

"You shot the wumpus.n""The wumpus ate you.n""The pit swallowed you.n"

# Place the wumpus and the pit in randomly selected rooms different from room 19; place 
# the player in room 19, with his back to room 0.

19:2*0|

# Function “^” takes a single number as its argument and returns an array of all the
# adjacent rooms to the room that number corresponds to.

1:^

0do      

# Consolidate the entire stack into an array. And pop its last element: the index.
# Replace the array with the element corresponding to that index.

])=

# GolfScript will execute “print n print”.

REV0 C ++ (Visual Studio en Windows) 405

#include"stdafx.h"
#include
#include
int main()srand(time(NULL));char i,h=rand()%19,w=rand()%19,p=19,d=0,q,e,m[]="[email protected]
";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;elseputs("arrow missed");w=(w+m[w%4*3+rand()%3])%20;elsep=q;d=e;if(p==h)puts("YOU FELL IN A HOLE!");if(p==w)puts("THE WUMPUS GOT YOU!");

A continuación se muestra un recorrido que demuestra que (siempre que no comience justo al lado de un obstáculo) con el juego correcto siempre puede ganar. El jugador siente una brisa, se da la vuelta y hace un bucle completo en el sentido contrario a las agujas del reloj. Como le toma exactamente 5 movimientos volver a sentir la brisa, conoce el agujero a su derecha y se aleja lo más posible. Del mismo modo, cuando huele el wumpus, sin saber si es a la derecha o a la izquierda, se da la vuelta y hace un bucle en el sentido de las agujas del reloj. Le toma 5 movimientos volver a oler el wumpus, por lo que sabe que está a la izquierda y dispara con certeza.

Si hubiera girado en sentido contrario, habría encontrado el wumpus antes y habría sabido que estaba en la misma dirección en la que estaba girando.

ingrese la descripción de la imagen aquí

REV1 C (GCC en Cygwin), bonificación 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="[email protected]\/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
  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)
  elsep=q;d=e;u(p==h,"YOU FELL IN A HOLE!",)
  u(p==w,"THE WUMPUS GOT YOU!",)

Nuevas líneas agregadas para mayor claridad. Los cambios de Rev 0 son los siguientes:

Un gran agradecimiento a @Dennis por recomendar el compilador GCC en el emulador Cygwin Linux para Windows. Este compilador no requiere el includes en el programa rev 0, y permite int tipo para variables y main. ¡Este es un consejo de golf que cambia la vida!

Además, ejecutarse en Linux significa que f hace que el cursor se mueva hacia abajo sin hacer un retorno de carro (a diferencia de Windows, donde solo produce un símbolo imprimible). Esto ha permitido un acortamiento considerable de la declaración printf que imprime el tablero

Varios consejos adicionales de Dennis en los comentarios, y uno de los míos: cambio de condición al verificar si la flecha golpeó el wumpus: if(q==w)>if(q-w) (..else .. está al revés)

Se agregó una pantalla gráfica que muestra la información que el jugador sabe sobre dónde se huele un wumpus / se siente una brisa para reclamar el bono del 35%. (Eliminé la versión de depuración anterior que mostraba la posición exacta del wumpus y el agujero. Se puede ver en el historial de ediciones).

REV2 C (GCC en Cygwin), 389-35% de bonificación = 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--;)P"You feel a breezen",b
  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 anythingn",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");

Gracias de nuevo a Dennis por refactorizar mi código:

Char constante m[] reemplazado con literales (no sabía que podía indexar un literal).

Siembra de números aleatorios con variable de pila (depende del sistema, algunos sistemas aleatorizan la asignación de memoria como medida de seguridad).

Macro con puts reemplazado con una macro con printf y código adicional que debe ejecutarse cuando el mensaje que se muestra colocado dentro printf argumentos (aprovechando el aspecto de que printf no imprime los últimos argumentos si no hay suficientes especificadores de formato en la cadena de formato). if reemplazado por ||

Cálculo de la nueva posición del jugador / wumpus colocado dentro de la nueva macro.

Mensajes de ganar / perder colocados fuera while círculo. if reemplazado por operador condicional.

Uso de operador condicional en línea para disparar flechas. Si el jugador falla, esto requiere tanto imprimir un mensaje como ajustar la posición del wumpus. Dennis ofreció un par de formas de combinar printf y el cálculo de la posición de wumpus en una sola expresión, pero yo he elegido una propia. printf devuelve el número de caracteres impresos, que para Your arrow didn't hit anythingn es 31 (11111 binario.) Entonces, 31&Q(w)==Q(w).

Mi otra contribución a esta edición ha sido la eliminación de algunos corchetes innecesarios.

Producción

Aquí, el jugador ya ha encontrado dónde está el Wumpus, pero elige hacer una exploración exhaustiva para descubrir exactamente dónde está el pozo también. A diferencia de mi antigua versión de depuración que mostraba dónde estaban el wumpus y el pozo durante todo el juego, esto muestra solo las habitaciones donde el jugador ha visitado y sintió una brisa (1) olió el wumpus (2) o ambos (3). (Si el jugador dispara una flecha y falla, la variable a que contiene la información de la posición del wumpus se restablece).

ingrese la descripción de la imagen aquí

REPRESENTACIÓN DE ICOSAHEDRON

Nota: esta sección se basa en la rev 1

¡Mi característica estrella! No hay gráfico en mi código. Para explicar cómo funciona, consulte el mapa mundial a continuación. Cualquier punto del icosaedro se puede representar con una latitud 0-3 y una longitud 0-4 (o un solo número, long*4+lat.) La línea de longitud marcada en el mapa pasa solo por aquellas caras con longitud cero, y la línea de latitud pasa por el centro de las caras con latitud cero.

El jugador puede orientarse en 3 ejes posibles, representados por los símbolos de la siguiente manera: norte-sur- norte, este, Sur, Oeste noroeste-sureste /. En cualquier habitación, tiene a su disposición exactamente una salida en cada uno de estos ejes. En la pantalla que se muestra, el jugador realiza un bucle completo en el sentido de las agujas del reloj. En general, es fácil de identificar por el jugador que marca de dónde vino y, por lo tanto, a dónde se le permite ir.

El único caso que es un poco difícil para el ojo no iniciado es el cuarto. Cuando ve una inclinación en una de estas filas polares, el jugador proviene de la celda polar más cercana al extremo exterior de la inclinación y generalmente mira hacia el ecuador. Por lo tanto, el jugador mira hacia el sureste y sus opciones son: 15 (SUR, la celda de la derecha) 25 (noreste, la celda de arriba) o 35 (noroeste, la celda de abajo).

Entonces, básicamente mapeo el icosaedro en una cuadrícula de 5×4, con celdas numeradas del 19 al 0 en el orden en que se imprimen. El movimiento se realiza sumando o restando de la posición actual, según la latitud y dirección del jugador, según la tabla a continuación.

Si el jugador se sale de la parte inferior (oeste) del tablero, vuelve al lado superior (este) y viceversa, por lo que su posición se toma módulo 20. Generalmente los movimientos se codifican en m[] agregando ascii 80 (P) al valor bruto que proporciona los caracteres que se muestran a continuación, pero en principio se puede sumar cualquier múltiplo de 20 sin afectar la operación.

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

La entrada del jugador (dividida por 10 para eliminar el segundo dígito) se agrega a su dirección actual y se toma el módulo 3 para obtener su nueva dirección. Esto funciona bien en la mayoría de los casos. Sin embargo, hay un problema cuando está en una habitación polar y se mueve hacia el polo. Al doblar el mapa de abajo, quedará claro que si sale de la habitación mirando hacia el “noreste” entrará en el nuevo cuadrado mirando hacia el “sureste”, por lo que se debe hacer una corrección. Esto se hace en la linea e=(d+i/10)*m[p%4]%3; por la multiplicación por m[p%4]. Los primeros cuatro valores de m[] se seleccionan de modo que, además de su función anterior, también tengan la característica m[1]%3==m[2]%3==1 y m[0]%3==m[3]%3==2. Esto deja solo la dirección para las habitaciones ecuatoriales y aplica la corrección necesaria para las habitaciones polares.

El momento lógico para hacer la corrección sería después del movimiento. Sin embargo, para salvar personajes se hace antes de la mudanza. Por lo tanto, ciertos valores en m[] debe transponerse. Entonces los 2 últimos caracteres son LT en lugar de TL según la tabla anterior, por ejemplo.

ingrese la descripción de la imagen aquí

CÓDIGO SIN GOLF

este es el código rev 1, que está menos ofuscado que el rev 2.

Esto se ejecutará en GCC / Linux. He incluido en los comentarios el código adicional necesario para que se ejecute en Visual Studio / Windows. ¡Es una gran diferencia!

//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
//#include
//#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="[email protected]\/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--;)=1<>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)
        elsep=q;d=e;u(p==h,"YOU FELL IN A HOLE!",)
        u(p==w,"THE WUMPUS GOT YOU!",)
    


TEMAS Y CURIOISIDADES

He aprovechado el punto mencionado por @professorfish, si el wumpus y el pit comienzan en lugares aleatorios, no es necesario que el jugador comience en un lugar aleatorio. El jugador siempre comienza en la habitación 19 mirando al norte.

Entiendo que como el wumpus “no se ve afectado por el hoyo”, el wumpus puede comenzar o entrar en la habitación donde está el hoyo. En general, esto simplifica las cosas excepto por un punto. No tengo una variable específica para indicar que el juego terminó; se acaba cuando el jugador coincide con el wumpus o hoyo. Entonces, cuando el jugador gana, muestro el mensaje ganador, ¡pero muevo el hoyo al jugador para que se salga del circuito! No puedo poner al jugador en el foso porque el wumpus podría estar allí y recibiría un mensaje sobre el wumpus que no quiero.

El programa rev0 funcionó perfectamente en Visual Studio, pero el IDE dijo “pila corrupta alrededor de la variable i” al salir. Esto se debe a que scanf está intentando poner un int en un char. Dennis informó un comportamiento incorrecto en su máquina Linux debido a esto. De todos modos, se corrige mediante el uso del tipo correcto en la rev 1.

La línea para mostrar el tablero en la rev 0 es torpe y parece ligeramente diferente en otras plataformas. En printf(" %c%c%c") el% c del medio es el se muestra un carácter imprimible. El último% c es ASCII 0 o ASCII 10 ( n, nueva línea con retorno de carro en Windows). Parece que no hay ningún carácter en Windows que funcione en la consola, que bajará una línea sin dar un retorno de carro. Si lo hubiera, no necesitaría el primer c% (pestaña ASCII 0 o ASCII 9 antes del carácter de latitud 1. Las pestañas son notoriamente indefinidas en su comportamiento). El espacio inicial mejora el formato (coloca los caracteres de latitud 3 y 2 más cerca del carácter de latitud 1 .) Rev 1 tiene una revisión de esta línea que usa un carácter de alimentación de formulario f y, por lo tanto, no necesita ningún carácter de formato al comienzo de printf. Esto lo hace más corto, pero f no funciona en Windows.

GolfScript, 269 caracteres

puts:|;20,;9rand:r~$3<(:>"B:%d`w85>2n+Fup`y/>@D-=J7ldnx/W5XsLAb8~"32-%"`24"base/3/[.[[email protected]].[[email protected]]]%:A=3r=0=:F;~:W;:P;>A=0=F=?:^P&!!*^W&!!"You smell a wumpus"*'"#'9.?r';STDIN.gets()"'++~);(3%^=4`=W="Your arrow hit the wumpus"W A=0=3r=:W>=.!*if>:F;:>W=.!*>P=.!"You fell into the pit"*&ifdo

Tenga en cuenta que 163 se restó del recuento de caracteres para las cadenas codificadas de forma rígida. Si desea una salida de depuración que indique los números de habitación, agregue la siguiente línea justo después de la primera aparición de ^:

'  YOU 'F'->'>+++puts'  DIRECTIONS [BRL] '^`+puts'  PIT 'P+puts'  WUMPUS 'W+puts 

Una sesión de ejemplo (con salida de depuración adicional):

  YOU 6->11
  DIRECTIONS [BRL] [6 7 16]
  PIT 7
  WUMPUS 5
You feel a breeze
25
  YOU 11->16
  DIRECTIONS [BRL] [11 17 15]
  PIT 7
  WUMPUS 5
35
  YOU 16->11
  DIRECTIONS [BRL] [16 6 7]
  PIT 7
  WUMPUS 5
You feel a breeze
15
  YOU 11->6
  DIRECTIONS [BRL] [11 10 1]
  PIT 7
  WUMPUS 5
15
  YOU 6->10
  DIRECTIONS [BRL] [6 15 5]
  PIT 7
  WUMPUS 5
You smell a wumpus
14
Your arrow didn't hit anything
  YOU 6->10
  DIRECTIONS [BRL] [6 15 5]
  PIT 7
  WUMPUS 0
25
  YOU 10->5
  DIRECTIONS [BRL] [10 14 0]
  PIT 7
  WUMPUS 0
You smell a wumpus
24
Your arrow hit the wumpus

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *