Mastermind

Iniciado por N0body, 30 Abril 2010, 05:31 AM

0 Miembros y 1 Visitante están viendo este tema.

N0body

Bueno, luego de un gran descanso empezaré a postear nuevamente mis cosillas.

Aquí un jueguito que muchos quizás lo tengan en su casa con el nombre de "Mastermind"

El juego se base en adivinar un número de n dígitos elegido aleatoriamente por la máquina (el número de dígitos n es ingreso).

Pero se cuentan con una serie de pistas, lo que no indica que en el juego no influya la suerte obvio, pero lo hace un juego más para pensar que para "tirar números al azar".

Estas pistas consiste en dar al usuario el número de cifras en las que ha acertado. Y el número de cambios o conmutaciones que podrían hacer para hacer que una ficha que está incorrecta, lo esté.
Un ejemplo vale más que mil palabras:

Imaginemos que n vale 4 (osea, estamos operando con 4 dígitos)

El número elegido por la pc es: 3345

Nosotros ingresamos el: 5542

Cantidad de aciertos (o blancas): 1 (el 4 en la tercera posición)
Cantidad de rojas: 1 (ya que si bien tengo dos 5, osea, dos incorrectas, en la incógnita tengo sólo un 5. Así que el otro está de más)


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LIMPIAR_PANTALLA system("cls");




int esnumero (const char usuario[], int cant)
   {
       while (cant)
           if ( usuario[--cant]<'0' || usuario[cant]>'9' )
               return 1;
       return 0;
   }


int main(int argc, char *argv[])
{
 FILE *historial;
 char *incognita, *usuario, h;
 int cant, i, j, blancas, rojas;
 srand (time(NULL));

 do {
       printf ("Ingrese la cantidad de caracteres para jugar: ");
       scanf ("%i", &cant);
   } while (cant<1);

 do {
     printf ("\n\nDesea guardar el historial de la partida (ingrese 1 por si y 0 por no): ");
     scanf ("%i", &h);
   } while (h!=0&&h!=1);

 if (h)
   if (! (  historial = fopen ("historial.txt", "w")  )  )
       {
           do {
               printf ("\n\n\nHa surgido un error al crear el historial. Que desea hacer:\n1-Cerrar el programa\n2-Continuar sin guardar el historial\n\n\tOpcion: ");
               scanf ("%i", &h);
               } while (h!=0&&h!=1);
           if (h)
               return 0;
           else
               h=0;
       }

 usuario = (char *) malloc (cant);
 incognita = (char *) malloc (cant);

 for (i=0 ; i<cant ; i++)
   incognita[i] = rand ()%10+'0';
 incognita[cant] = '\0';

 if (h)
   fprintf (historial, "%s\n\n\n", incognita);

 for (i=0,j=0 ; i<cant ; i++)
   {
   j *= 10;
   j += 9;
   }
 // Programa propiamente dicho:
 LIMPIAR_PANTALLA
 printf ("A continuacion debe numeros entre 0 y %i hasta que adivine el numero\nLuego de cada numero le aparecera las pistas\n\nAprete una teclea para comenzar a jugar...", j);
 system ("PAUSE>>nul");
 LIMPIAR_PANTALLA

 do {
       do
           scanf ("%s", usuario);
             while (strlen (usuario) != cant || esnumero (usuario, cant) );

       if (h)
           fwrite (usuario, 1, cant, historial);

       blancas=0;
       rojas=0;

       for (i=0;i<cant;i++)
           if (incognita[i]==usuario[i])
               {
                   usuario[i] = 'b';
                   blancas++;
               }

       for (i=0;i<cant;i++)
           if (usuario[i]!='b')
               for (j=0;j<cant;j++)
                   if (usuario[j]!='b'&&usuario[j]!='r'&&incognita[i]==usuario[j])
                       {
                       usuario[j] = 'r';
                       rojas++;
                       break;
                       }

       if (h)
           fprintf (historial, "\nBlancas: %i Rojas: %i\n\n", blancas, rojas);

       printf ("Blancas: %i Rojas: %i\n\n", blancas, rojas);

   } while (blancas!=cant);

   LIMPIAR_PANTALLA

   printf ("\n\tFELICITACIONES!\n\n\nUsted ha adivinado el numero (%s)\n\n", incognita);

 free (usuario);
 free (incognita);
 system("PAUSE");
 return 0;
}


Bueno, es un juego muy popular también en mi escuela.

PD: También posee la opción de guardar el historial del juego

N0body

Bueno, ante la falta de comentarios creo que no entendieron de que va el juego.
Como no quiero privarlos de tal placer intelectual (sarcasmo).
Y quiero que comenten (verdadera intención).
He aquí un historial mío con los pensamientos deductivos que hice para adivinar el número a partir de las pistas. Vaya que tuve suerte, y me tocó un número fácil.
Capaz que tengo algún error de lógica porque mientras iba jugando una partida del juego anotaba mis deducciones y así como me quedo lo intercalé con el historial y lo pongo aquí.


---------------------------------------------------------
1233
Blancas: 0 Rojas: 0

...entonces no hay ni 1, ni 2 ni 3...


--------------------------------------------------------
4566
Blancas: 0 Rojas: 2

Hay un para rojo, puede ser:
4/5 5/6
4/6 6/6


------------------------------------------------------
6612
Blancas: 1 Rojas: 0

Con esto averigué que había un sólo 6 y que estaba en las posiciones 1 o 2
Por lo tanto el otro incorrecto debía ser un 4 o un 5 que podría ir en las posiciones 3 o 4 (para ambos) o 1 para el 5, o 2 para
el 4



------------------------------------------------------
6155
Blancas: 1 Rojas: 1

Esto puede significar que:
A) El 6 esté bien posicionado y que el 5 no va ni en 3, ni en 4, osea va en 2
B) O que el 6 vaya en 2 y el 5 esté bien en alguna de esas dos posiciones

Pero de cualquier modo nos asegura que el 5 está y por lo tanto el 4 queda descartado. Y que no hay más de un 5

***IMPORTANTE(vease abajo)

------------------------------------------------------
1651
Blancas: 2 Rojas: 0

Ahi me doy cuenta de que de las opciones A y B, la B es la correcta y además que el 5 va en la posicion 3.
Posibles (para las cifras sin adivinar): 7890



------------------------------------------------------
7891
Blancas: 1 Rojas: 0

Ahi sé que está bien el 7 y que ni el 8 ni el 9 están en el número, por lo que el dígito incógnita de la posición 4 es 0.



------------------------------------------------------
7650
Blancas: 4 Rojas: 0

Gané, me muestra el cartel que dice felicitaciones, que ustedes no verán nunca si no juegan! xD


***IMPORTANTE: no quiero hacer lío, pero soy un boludo importante. Cometí un error (igual gané, pero con un movimiento
inecesario). La opción A es inválida: ya que si el 6 está bien en la pos 1, el 5 tiene que estar en la 2. Pero como vimos
antes el 5 no puede estar en 2! Por lo que logicamente el incorrecto es el 6... :P