Ayuda con programa

Iniciado por HectorSersi, 22 Noviembre 2018, 20:37 PM

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

HectorSersi

Cita de: YreX-DwX en  7 Diciembre 2018, 13:32 PM
Para eso tienes varias alternativas:
- Una sería usar ficheros de acceso aleatorio mediante funciones como <seekp()> y <seekg()>. Puedes buscar más información buscando "ficheros de acceso aleatorio c++" o buscando directamente las funciones que te he comentado y ver cómo funcionan.

Si no tienes ni idea de trabajar con ficheros de acceso aleatorio, yo te recomendaría usar la segunda opción que consistiría en aplicar lo que ya sabes para conseguir una lectura aleatoria:
- Yo generaría un número aleatorio pequeño para no irme al final del fichero y saltaría esos números. Así no coges siempre los n-primeros.
Código (cpp) [Seleccionar]

int cartasASaltar = generarAleatorio(0,5);
int cartasSaltadas = 0;
int carta;
while(!fichero.eof() && cartasSaltadas <= cartasASaltar){
    fichero >> carta;
    cartasSaltadas++;
}
cout << "Tu carta es: " << carta << endl;


Ahí tienes un trozo de prueba para que veas a lo que me refiero. Con la función que te comenté hace un tiempo para generar números aleatorios le pasas el mínimo y el máximo (como coges como mucho 5 cartas, saltando un máximo de 5 cartas en cada vuelta es seguro que no te sales del fichero, podrías saltarte más eso ya te dejo que lo calcules tú si quieres) Para hacerlo más aleatorio puedes generar un número aleatorio distinto en cada vuelta para que no siga el mismo patrón. Suerte. :-X

Mientras escribía esto me he dado cuenta de que también puedes empezar con un fichero vacío y el propio programa genere el fichero (simulando que se está barajando). Creas números aleatorios entre [1,10] y los escribes en el archivo. Así la baraja no empezaría ordenada. En este caso tendrías que controlar que no se repitan más de 4 veces cada valor ya que en la baraja cada valor numérico se repite hasta 4 veces. Mi recomendación si lo haces así que la verdad me parece bastante interesante es que hagas un array y cada vez que generes un número, compruebes que no has generado ya 4 veces ese número y  le sumes 1 al (i-1)-elemento. Me explico por si no se entiende:
- Tienes un array <maximos[10] = {0,0,0,0,0,0,0,0,0,0}> que indica cuantas veces has generado cada valor.
- Generas x valor (imagina un 1).
- Compruebas que (maximos[x-1] < 4) Si no es menor que 4 generas otro número distinto.
- Si es menor que 4, lo agregas al fichero y haces <maximos[x-1] += 1>, es decir le sumas 1 en la posición correspondiente.

Suerte y espero que te animes a intentar el último método que te he comentado. O incluso puedes mezclarlos, eso ya depende de la imaginación del programador. Personalmente creo que es mejor que resuelvas un problema con las herramientas que conoces hasta que estudies otras y no que uses herramientas que no sabes como funcionan para salir del paso. La decisión final es tuya. Suerte. :-X :-X


Okey gracias, por ultimo, me gustaría hacer que al pasarse de 7.5 tanto la maquina como el humano, pierdan la partida automáticamente con un cout<<"Has perdido la partida", para ello habia creado esto, pero no me funciona.

Código (cpp) [Seleccionar]
int determinaGanador(double puntosHumano, double puntosMaquina)
{
int ganador;

while (puntosHumano || puntosMaquina < 7.5)
{
if (puntosHumano > puntosMaquina)
{
ganador = HUMANO;
}
else if (puntosHumano < puntosMaquina)
{
ganador = MAQUINA;
}

else if (puntosHumano == puntosMaquina)
{
ganador = HUMANO + rand() % +(MAQUINA - HUMANO);
}
}

while (puntosHumano || puntosMaquina > 7.5)
{
if (puntosHumano > 7.5)
{
cout << "Has perdido ";
}
if (puntosMaquina > 7.5)
{
cout << "La maquina ha perdido ";
}
}
return ganador;
}



K-YreX

Primero para la función que tienes no se usa un <while> sino un <if>. Es muy común traducir una sentencia como "mientras..." pero en realidad es "si...".Un <while> se usa si vas a repetir un trozo de código hasta que se cumpla una condición, por lo tanto los valores de la condición tienen que ir cambiando dentro del <while>, por ejemplo:
Código (cpp) [Seleccionar]

while(puntosMaquina < puntosHumano && puntosMaquina < 7.5)
    puntosMaquina += carta;

Eso sería un <while>. Mientras los puntos de la máquina no superen al humano ni el 7.5 entonces le sumamos otra carta. No digo que lo tengas que hacer así ya que tienes tus propias funciones para robar cartas. Es sólo para que veas el uso del <while>.

En tu caso si es para determinar un ganador es con un <if>. Además en programación lo que se suele hacer para dar menos vueltas es asumir un caso y si la condición es la opuesta, modificar el resultado, tu caso:
Código (cpp) [Seleccionar]

int determinaGanador(int puntosHumano, int puntosMaquina){
    int ganador = HUMANO;
    if(puntosHumano > 7.5 || (puntosMaquina < 7.5 && puntosHumano < puntosMaquina))
        ganador = MAQUINA;
    else if(puntosHumano == puntosMaquina)
        ganador += rand() % 2;
    return ganador;
}

Esa es tu función que una vez tiene los puntos de ambos, te dice quien es el ganador. No contempla el caso de que los dos jugadores se hayan pasado del 7.5. Eso ya te lo dejo a ti.  :rolleyes:

Si lo que quieres es interrumpir el programa en cuanto uno de los dos pasa de 7.5. Entonces la modificación la tienes que hacer al momento en que van robando cartas. He mirado un poco tu programa por encima y en cada función del modo de juego ya compruebas que no se haya pasado de 7.5, eso está bien. Lo que puedes hacer en el <main> sería algo así:
Código (cpp) [Seleccionar]

puntosHumano = modoA(archivo, numeroAleatorio);
if(puntosHumano < 7.5)
    puntosMaquina = modoA(archivo, numeroAleatorio);
//...

Así si el humano se pasa de 7.5 tal y como te he hecho la función anterior ganaría la máquina sin necesidad de robar cartas. Esto tendrías que implementarlo para cada uno de los modos. Además te recomiendo no usar números mágicos, es decir, números que aparecen literalmente por ahí y no se sabe lo que son. Dale un nombre a 7.5 y sustitúyelo en el programa por ejemplo:
Código (cpp) [Seleccionar]

const int PUNTUACION_LIMITE = 7.5;
// y en el resto del programa poner PUNTUACION_LIMITE donde ponga 7.5

Así cambiando sólo ese número puedes cambiar el límite del juego sin tener que ir cambiando todo el programa. Suerte. :-X
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

CalgaryCorpus

Sugiero hacer un cambio en esta parte

if(puntosHumano == puntosMaquina)
        ganador += rand() % 2;


pues depende mucho del valor de las constantes, y que valor tiene "ganador" antes de llegar aqui, y si una de las constantes esta separada exactamente en 1 de la otra.

Cambiando ligeramente el codigo todas estas dependencias ya no estaran.

Ejemplo:

if(puntosHumano == puntosMaquina) {
       if( rand() % 2 ) {
          ganador = MAQUINA;
       }
}


Con esta modificacion, no importa el valor de las constantes, o que esten separadas en 1 una de otra, podrian ser otros valores y estar separadas en mas de 1 sus valores.
Aqui mi perfil en LinkedIn, invitame un cafe aqui

K-YreX

Es cierto, pero si no recuerdo mal, él había declarado lo siguiente:
Código (cpp) [Seleccionar]

const int HUMANO = 1;
const int MAQUINA = 2;

Por eso lo he hecho así, sin embargo, tu idea es mejor por el tema que dices de que el valor no se diferencie en 1.
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

CalgaryCorpus

Las enumeraciones parecen calzar mejor aquí
Aqui mi perfil en LinkedIn, invitame un cafe aqui

HectorSersi

#25
Cita de: YreX-DwX en  8 Diciembre 2018, 15:24 PM
Primero para la función que tienes no se usa un <while> sino un <if>. Es muy común traducir una sentencia como "mientras..." pero en realidad es "si...".Un <while> se usa si vas a repetir un trozo de código hasta que se cumpla una condición, por lo tanto los valores de la condición tienen que ir cambiando dentro del <while>, por ejemplo:
Código (cpp) [Seleccionar]

while(puntosMaquina < puntosHumano && puntosMaquina < 7.5)
   puntosMaquina += carta;

Eso sería un <while>. Mientras los puntos de la máquina no superen al humano ni el 7.5 entonces le sumamos otra carta. No digo que lo tengas que hacer así ya que tienes tus propias funciones para robar cartas. Es sólo para que veas el uso del <while>.

En tu caso si es para determinar un ganador es con un <if>. Además en programación lo que se suele hacer para dar menos vueltas es asumir un caso y si la condición es la opuesta, modificar el resultado, tu caso:
Código (cpp) [Seleccionar]

int determinaGanador(int puntosHumano, int puntosMaquina){
   int ganador = HUMANO;
   if(puntosHumano > 7.5 || (puntosMaquina < 7.5 && puntosHumano < puntosMaquina))
       ganador = MAQUINA;
   else if(puntosHumano == puntosMaquina)
       ganador += rand() % 2;
   return ganador;
}

Esa es tu función que una vez tiene los puntos de ambos, te dice quien es el ganador. No contempla el caso de que los dos jugadores se hayan pasado del 7.5. Eso ya te lo dejo a ti.  :rolleyes:

Si lo que quieres es interrumpir el programa en cuanto uno de los dos pasa de 7.5. Entonces la modificación la tienes que hacer al momento en que van robando cartas. He mirado un poco tu programa por encima y en cada función del modo de juego ya compruebas que no se haya pasado de 7.5, eso está bien. Lo que puedes hacer en el <main> sería algo así:
Código (cpp) [Seleccionar]

puntosHumano = modoA(archivo, numeroAleatorio);
if(puntosHumano < 7.5)
   puntosMaquina = modoA(archivo, numeroAleatorio);
//...

Así si el humano se pasa de 7.5 tal y como te he hecho la función anterior ganaría la máquina sin necesidad de robar cartas. Esto tendrías que implementarlo para cada uno de los modos. Además te recomiendo no usar números mágicos, es decir, números que aparecen literalmente por ahí y no se sabe lo que son. Dale un nombre a 7.5 y sustitúyelo en el programa por ejemplo:
Código (cpp) [Seleccionar]

const int PUNTUACION_LIMITE = 7.5;
// y en el resto del programa poner PUNTUACION_LIMITE donde ponga 7.5

Así cambiando sólo ese número puedes cambiar el límite del juego sin tener que ir cambiando todo el programa. Suerte. :-X



K-YreX

No es que la puntuación de la máquina salga al final, simplemente al ser un bucle en el que el usuario no tiene que hacer nada el programa se ejecuta muy rápido y por eso se muestra la puntuación y de seguido el ganador. Si quieres ver la puntuación en cada iteración lo que puedes hacer es meter una pausa por ejemplo con <cin.get()>. Así se va a parar en cada vuelta hasta que pulses enter.
Código (cpp) [Seleccionar]

double modoBmaquina(ifstream & archivo, int numeroAleatorio, double puntosHumano){
int final = 0, aux;
double puntos = 0;

while (final < numeroAleatorio && puntosHumano < puntos && puntos < PUNTUACION_LIMITE){
archivo >> aux;
if (aux > 7)
puntos += 0.5;
else
puntos += aux;
cout << "La maquina ha robado : " << aux << endl;
cout << "La puntuacion de la maquina es : " << puntos << endl;
                cin.get();
        }
return puntos;
}


El tema de la <PUNTUACION_LIMITE> si lo único que has hecho ha sido declarar la variable y sustituir en cada <7.5> por <PUNTUACION_LIMITE> el programa no tiene que cambiar. Puede que sea que si usas números aleatorios para la cantidad de cartas que se roban y has aplicado alguno de los métodos que te comenté para robar cartas desordenadas haya coincidido que el humano haya tenido 7 puntos con las cartas que ha robado y la máquina se haya pasado en la última iteración a 8.
Prueba a quitar los trozos de código aleatorios para que las cartas que se cogen siempre sean las mismas y así poder controlar los resultados.

Un par de consejos más:
Código (cpp) [Seleccionar]

if (determinaGanador(puntosHumano, puntosMaquina) == HUMANO) {
cout << "Ha ganado el HUMANO" << endl;
cin.get();
}
else{
cout<<"El ganador es la maquina"<<endl;
cin.get();
}

Si tienes un <if> que ejecuta una instrucción y un <else> que ejecuta la misma instrucción, esa instrucción se ejecutará siempre. Entonces se pone después del <else> y así sólo se pone una vez.
Código (cpp) [Seleccionar]

if (determinaGanador(puntosHumano, puntosMaquina) == HUMANO)
cout << "Ha ganado el HUMANO" << endl;
else
cout<<"El ganador es la maquina"<<endl;
cin.get();


Y esto:
Código (cpp) [Seleccionar]

while (responder < 1 || responder > 2)

Sería más correcto usar el operador "distinto" <!=>.
Código (cpp) [Seleccionar]

while(responder != 1 && responder != 2)
Código (cpp) [Seleccionar]

cout << "Todos tenemos un defecto, un error en nuestro código" << endl;

CalgaryCorpus

Estas instrucciones

                archivo >> aux;
if (aux > 7)
puntos += 0.5;
else
puntos += aux;


Podrían ser una función, parecen repetirse varias veces en el código enviado.

Si nadie se tienta a hacerlo por ti, sugiero que crees una función que convierta lo anterior en


     puntos += puntosAdicionales(archivo);
Aqui mi perfil en LinkedIn, invitame un cafe aqui

HectorSersi

#28
[quote author=YreX-DwX link=topic=489919.msg2180460#msg2180460 date=1544368262]
No es que la puntuación de la máquina salga al final, simplemente al ser un bucle en el que el usuario no tiene que hacer nada el programa se ejecuta muy rápido y por eso se muestra la puntuación y de seguido el ganador. Si quieres ver la puntuación en cada iteración lo que puedes hacer es meter una pausa por ejemplo con <cin.get()>. Así se va a parar en cada vuelta hasta que pulses enter.
[code=cpp]
double modoBmaquina(ifstream & archivo, int numeroAleatorio, double puntosHumano){
int final = 0, aux;
double puntos = 0;

while (final < numeroAleatorio && puntosHumano < puntos && puntos < PUNTUACION_LIMITE){
archivo >> aux;
if (aux > 7)
puntos += 0.5;
else
puntos += aux;
cout << "La maquina ha robado : " << aux << endl;
cout << "La puntuacion de la maquina es : " << puntos << endl;
               cin.get();
       }
return puntos;
}


El tema de la <PUNTUACION_LIMITE> si lo único que has hecho ha sido declarar la variable y sustituir en cada <7.5> por <PUNTUACION_LIMITE> el programa no tiene que cambiar. Puede que sea que si usas números aleatorios para la cantidad de cartas que se roban y has aplicado alguno de los métodos que te comenté para robar cartas desordenadas haya coincidido que el humano haya tenido 7 puntos con las cartas que ha robado y la máquina se haya pasado en la última iteración a 8.
Prueba a quitar los trozos de código aleatorios para que las cartas que se cogen siempre sean las mismas y así poder controlar los resultados.

Un par de consejos más:
Código (cpp) [Seleccionar]

if (determinaGanador(puntosHumano, puntosMaquina) == HUMANO) {
cout << "Ha ganado el HUMANO" << endl;
cin.get();
}
else{
cout<<"El ganador es la maquina"<<endl;
cin.get();
}

Si tienes un <if> que ejecuta una instrucción y un <else> que ejecuta la misma instrucción, esa instrucción se ejecutará siempre. Entonces se pone después del <else> y así sólo se pone una vez.
Código (cpp) [Seleccionar]

if (determinaGanador(puntosHumano, puntosMaquina) == HUMANO)
cout << "Ha ganado el HUMANO" << endl;
else
cout<<"El ganador es la maquina"<<endl;
cin.get();


Y esto:
Código (cpp) [Seleccionar]

while (responder < 1 || responder > 2)

Sería más correcto usar el operador "distinto" <!=>.
Código (cpp) [Seleccionar]

while(responder != 1 && responder != 2)

[/quote]


   srand(time(NULL));
   numeroAleatorio = 3 + rand() % 5 - 3 + 1;

   return numeroAleatorio;
}[/code]

HectorSersi

Cita de: YreX-DwX en  9 Diciembre 2018, 16:11 PM
No es que la puntuación de la máquina salga al final, simplemente al ser un bucle en el que el usuario no tiene que hacer nada el programa se ejecuta muy rápido y por eso se muestra la puntuación y de seguido el ganador. Si quieres ver la puntuación en cada iteración lo que puedes hacer es meter una pausa por ejemplo con <cin.get()>. Así se va a parar en cada vuelta hasta que pulses enter.
Código (cpp) [Seleccionar]

double modoBmaquina(ifstream & archivo, int numeroAleatorio, double puntosHumano){
int final = 0, aux;
double puntos = 0;

while (final < numeroAleatorio && puntosHumano < puntos && puntos < PUNTUACION_LIMITE){
archivo >> aux;
if (aux > 7)
puntos += 0.5;
else
puntos += aux;
cout << "La maquina ha robado : " << aux << endl;
cout << "La puntuacion de la maquina es : " << puntos << endl;
                cin.get();
        }
return puntos;
}


El tema de la <PUNTUACION_LIMITE> si lo único que has hecho ha sido declarar la variable y sustituir en cada <7.5> por <PUNTUACION_LIMITE> el programa no tiene que cambiar. Puede que sea que si usas números aleatorios para la cantidad de cartas que se roban y has aplicado alguno de los métodos que te comenté para robar cartas desordenadas haya coincidido que el humano haya tenido 7 puntos con las cartas que ha robado y la máquina se haya pasado en la última iteración a 8.
Prueba a quitar los trozos de código aleatorios para que las cartas que se cogen siempre sean las mismas y así poder controlar los resultados.

Un par de consejos más:
Código (cpp) [Seleccionar]

if (determinaGanador(puntosHumano, puntosMaquina) == HUMANO) {
cout << "Ha ganado el HUMANO" << endl;
cin.get();
}
else{
cout<<"El ganador es la maquina"<<endl;
cin.get();
}

Si tienes un <if> que ejecuta una instrucción y un <else> que ejecuta la misma instrucción, esa instrucción se ejecutará siempre. Entonces se pone después del <else> y así sólo se pone una vez.
Código (cpp) [Seleccionar]

if (determinaGanador(puntosHumano, puntosMaquina) == HUMANO)
cout << "Ha ganado el HUMANO" << endl;
else
cout<<"El ganador es la maquina"<<endl;
cin.get();


Y esto:
Código (cpp) [Seleccionar]

while (responder < 1 || responder > 2)

Sería más correcto usar el operador "distinto" <!=>.
Código (cpp) [Seleccionar]

while(responder != 1 && responder != 2)


Por lo menos dime por que me da error en tCartasPorAparecer (error de sintaxis) y en "cartas"(en las primeras lineas)

Agradeceria mucho la ayuda.