Ayuda con vectores.

Iniciado por elkiedis, 8 Octubre 2012, 05:10 AM

0 Miembros y 2 Visitantes están viendo este tema.

elkiedis

Hola a todos! Hace rato que no visitaba el foro pero volví a retomar el lenguaje C y ahora estoy teniendo un inconveniente con una función que debo desarrollar.

El tema es el siguiente. En mi programa tengo un vector Cartas de 10 posiciones. Lo inicializo del 0 al 9. Es decir... Cartas[1] es igual a 1, Cartas[2] es igual a 2, y así... El cero no interesa en este caso porque solo se utilizan las cartas del 1 al 9.
A medida que el juego avanza, algunas cartas del vector se cambian por el valor 0 (quedando estas "tapadas") y necesito validar si dentro del vector existe una carta que equivalga a una tirada de Dados realizada por el jugador, o si al menos, existe la posibilidad de sumar 2 cartas del Vector para obtener el resultado de la tirada de Dados.
La tirada de Dados consta de 2 dados de 6 caras c/u. Siendo la tirada mas baja posible 2, y la mas alta 12.


int validaJugada ()
{
    int i, j, p, suma;
    for (i=1; i<10; i++)
    {
        for (j=1; j<10; j++)
        {
            suma = Cartas[i] + Cartas[j];
            if (suma == Dados)
            {
               p = 1;
               break;
            }
            else
            {
               p = 0;
            }
        }
    }   
return p;
}


En este código solo comparo las sumas de Cartas[1] con Cartas[1], Cartas[1] con Cartas[2], Cartas[1] con Cartas[3]... Así hasta Cartas[9].
Luego comparo las sumas de Cartas[2] con Cartas[1], Cartas[2] con Cartas[2], Cartas[2] con Cartas[3]... Así hasta Cartas[9].
y sucesivamente... hasta que termine el ciclo..
Ahora... el problema está en que no debería sumar cartas de la misma posición... es decir Cartas[1] con Cartas[1], o Cartas[2] con Cartas[2]... y no sé como obviar o exceptuar esto..

Tendría que dejar una posicion del vector fija como pivot y sumarla con todas las otras una por una hasta la ultima posicion, y luego comenzar a hacer lo mismo pero desde la segunda posición, pero realmente se me complica...

Desde ya muchas gracias por su ayuda..



xiruko

if (i != j) {
     suma = Cartas[i] + Cartas[j];
     //...
}


de manera que solo sume y haga esas cosas si los indices son distintos.

un saludo!

elkiedis

#2
Genial! tan sencillo como eso y no se me había ocurrido :(

Ahora he corrido una prueba de la validación y no sé por qué motivo no funciona como lo esperado.
Aquí les dejo el código de ejemplo.


#include <stdio.h>
#include <stdlib.h>

void mostrarCartas (void);
int validaJugada (void);

int Cartas[10], Dados;

int main (){
   
   int i, Posible;
 
   Dados = 6;  /* ejemplo de tirada cualquiera */
 
   for(i=0; i<10; i++)
   {
      Cartas[i]=i;
   }
   
   Cartas[6]=0;   /* fijamos la carta 6 en 0 */
   Cartas[5]=0;   /* fijamos la carta 5 en 0 */

   Posible = validaJugada();
   
   mostrarCartas();
   printf("\nPosible: %d", Posible);
   
   
system("pause");
return EXIT_SUCCESS;
   }

/* ----- Funcion que muestra las cartas ----- */
void mostrarCartas ()
{
  printf("\n-%d-%d-%d-%d-%d-%d-%d-%d-%d-\n\n", Cartas[1],Cartas[2],Cartas[3],Cartas[4],Cartas[5],Cartas[6],Cartas[7],Cartas[8],Cartas[9]);    
}

/* ----- Funcion que valida la jugada ----- */
int validaJugada ()
{
   int i, j, p;
    int suma = 0;
   for (i=1; i<10; i++)
   {
       for (j=1; j<10; j++)
       {
           if (i != j)
           {
           suma = Cartas[i] + Cartas[j];
           }
           if (suma == Dados)
           {
              p = 1;
              break;
           }
           else
           {
              p = 0;
           }
       }
   }    

   return p;
}



Los Dados (valor 6), pueden ser igualados sumando el 2 con el 4, y sin embargo el resultado de la variable Posible termina siendo 0 cuando debería ser 1... Alguno puede ayudarme? No encuentro donde está el error...

Muchas gracias xiruko por la ayuda!

elkiedis

Alguien podría por favor tratar de ayudarme? Necesito saber en qué me estoy equivocando porque ese código no hace lo esperado..

Gracias!

xiruko

#4
he mirado el codigo, y a pesar de que no soy partidario de las variables globales (puedes hacer lo mismo pasando las variables como parametros a funciones) creo que el problema esta en el break de la funcion validajugada(). este break hara que salgas del for, pero en tu caso al tener 2 for, el break hara que salgas del primero (el de indice j) pero luego seguiras dentro por el otro for (el de indice i), por lo que pasaran cosas raras que no creo que quieras que pasen (entre otras, que p tome el valor 0 de nuevo).

para arreglar esto sin alterarte mucho el codigo, seria de la siguiente manera:

int validaJugada () {

   int i, j;
   int suma = 0;

   for (i=1; i<10; i++)
   {
       for (j=1; j<10; j++)
{
if (i != j)
{
suma = Cartas[i] + Cartas[j];
if (suma == Dados) return 1;
}
}
  }    

   return 0;
}


ahora bien, no se por que haces que tu funcion solo pueda devolver un 1 o un 0. y si la tirada de dados es un 8? habria dos posibles soluciones, 2+6 y 3+5, por lo que esta funcion deberia devolver 2 no? si es asi, a la que encuentres 1 posible, deberias hacer esos valores 0, y seguir buscando hasta recorrer todo el array por si acaso hay otra posible. se me ocurre hacerlo asi:

int validaJugada () {

   int i, j, p=0; // p inicialmente vale 0, y si se encuentra alguna posibilidad, se cambia el valor
   int suma = 0;

   for (i=1; i<10; i++)
   {
       for (j=1; j<10; j++)
{
if (i != j)
{
suma = Cartas[i] + Cartas[j];
if (suma == Dados) {
                            p++;
                            Cartas[i]=0;
                            Cartas[j]=0;
                             break;
                       }
}
}
  }    

   return p;
}


espero que alguna de las dos soluciones te sirva, un saludo!

rir3760

Cita de: elkiedis en  8 Octubre 2012, 05:10 AMnecesito validar si dentro del vector existe una carta que equivalga a una tirada de Dados realizada por el jugador
Para esto solo tienes que verificar el valor de "Dados" sea menor que 10 y que el valor de "Cartas[ Dados ]" sea diferente de cero.


Cita de: elkiedis en  8 Octubre 2012, 05:10 AMo si al menos, existe la posibilidad de sumar 2 cartas del Vector para obtener el resultado de la tirada de Dados.
La tirada de Dados consta de 2 dados de 6 caras c/u. Siendo la tirada mas baja posible 2, y la mas alta 12.
Para esto solo necesitas de un bucle. La función con los cambios:
int validaJugada(void)
{
   int i;
   int j;
   
   if (Dados > 9){
      i = Dados - 9;
      j = 9;
   }else {
      i = 1;
      j = Dados - 1;
   }
   
   while (i < j && (!Cartas[i] || !Cartas[j])){
      i++;
      j--;
   }
   
   return i < j;
}


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

elkiedis

Cita de: rir3760 en  9 Octubre 2012, 03:06 AM
Para esto solo tienes que verificar el valor de "Dados" sea menor que 10 y que el valor de "Cartas[ Dados ]" sea diferente de cero.

Para esto solo necesitas de un bucle. La función con los cambios:
int validaJugada(void)
{
   int i;
   int j;
   
   if (Dados > 9){
      i = Dados - 9;
      j = 9;
   }else {
      i = 1;
      j = Dados - 1;
   }
   
   while (i < j && (!Cartas[i] || !Cartas[j])){
      i++;
      j--;
   }
   
   return i < j;
}


Un saludo

rir3760 , muchas gracias por tu ayuda! Pero el codigo que propones no tiene en cuenta si las cartas ya ha sido previamente tapadas o no...

elkiedis

Cita de: xiruko en  8 Octubre 2012, 22:13 PM
he mirado el codigo, y a pesar de que no soy partidario de las variables globales (puedes hacer lo mismo pasando las variables como parametros a funciones) creo que el problema esta en el break de la funcion validajugada(). este break hara que salgas del for, pero en tu caso al tener 2 for, el break hara que salgas del primero (el de indice j) pero luego seguiras dentro por el otro for (el de indice i), por lo que pasaran cosas raras que no creo que quieras que pasen (entre otras, que p tome el valor 0 de nuevo).

para arreglar esto sin alterarte mucho el codigo, seria de la siguiente manera:

int validaJugada () {

   int i, j;
   int suma = 0;

   for (i=1; i<10; i++)
   {
       for (j=1; j<10; j++)
{
if (i != j)
{
suma = Cartas[i] + Cartas[j];
if (suma == Dados) return 1;
}
}
  }    

   return 0;
}


ahora bien, no se por que haces que tu funcion solo pueda devolver un 1 o un 0. y si la tirada de dados es un 8? habria dos posibles soluciones, 2+6 y 3+5, por lo que esta funcion deberia devolver 2 no? si es asi, a la que encuentres 1 posible, deberias hacer esos valores 0, y seguir buscando hasta recorrer todo el array por si acaso hay otra posible. se me ocurre hacerlo asi:

int validaJugada () {

   int i, j, p=0; // p inicialmente vale 0, y si se encuentra alguna posibilidad, se cambia el valor
   int suma = 0;

   for (i=1; i<10; i++)
   {
       for (j=1; j<10; j++)
{
if (i != j)
{
suma = Cartas[i] + Cartas[j];
if (suma == Dados) {
                            p++;
                            Cartas[i]=0;
                            Cartas[j]=0;
                             break;
                       }
}
}
  }    

   return p;
}


espero que alguna de las dos soluciones te sirva, un saludo!

Me ha servido tu codigo colega! Muchas gracias un abrazo grande!!!

rir3760

Cita de: elkiedis en  9 Octubre 2012, 04:04 AMgracias por tu ayuda! Pero el codigo que propones no tiene en cuenta si las cartas ya ha sido previamente tapadas o no...
Si toma en cuenta las cartas que ya han sido marcadas con el valor cero. Ello se realiza con la segunda condición:
(!carta[i] || !carta[j])
Si alguna de las cartas es igual a cero se pasa a revisar el siguiente par.


Si extendemos para crear un programa sencillo terminamos con:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int validar_jugada(int carta[], int tirada, int *a, int *b);

int main (void)
{
   int carta[11] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   int tirada;
   int a;
   int b;
   int i;
   int j;
   
   srand((unsigned) time(NULL));
   
   /* Cinco tiradas, solo se revisan pares de cartas */
   for (i = 0; i < 5; i++){
      for (j = 1; j < 11; j++)
         if (carta[j])
            printf(" %d", carta[j]);
         else
            printf(" X");
      putchar('\n');
     
      tirada = 2 + rand() % 11;
      printf("La tirada es %d, es una ", tirada);
      if (validar_jugada(carta, tirada, &a, &b)){
         puts("jugada valida\n");
         carta[a] = carta[b] = 0;
      }else
         puts("jugada NO valida\n");
   }
   
   return EXIT_SUCCESS;
}

int validar_jugada(int carta[], int tirada, int *a, int *b)
{
   int i;
   int j;
   
   if (tirada > 9){
      i = tirada - 9;
      j = 9;
   }else {
      i = 1;
      j = tirada - 1;
   }

   while (i < j && (!carta[i] || !carta[j])){
      i++;
      j--;
   }
   if (i < j){
      *a = i;
      *b = j;
   }
   
   return i < j;
}



Y un ejemplo de su salida:
1 2 3 4 5 6 7 8 9 10
La tirada es 7, es una jugada valida

X 2 3 4 5 X 7 8 9 10
La tirada es 9, es una jugada valida

X X 3 4 5 X X 8 9 10
La tirada es 5, es una jugada NO valida

X X 3 4 5 X X 8 9 10
La tirada es 3, es una jugada NO valida

X X 3 4 5 X X 8 9 10
La tirada es 12, es una jugada valida


Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

elkiedis

Gracias nuevamente por tu ayuda! ya pude resolver el problema. De todos modos rir3760, fijate que no está validando bien las sumas ni las jugadas...

Fijate en tu ejemplo:

1 2 3 4 5 6 7 8 9 10
La tirada es 7, es una jugada valida

X 2 3 4 5 X 7 8 9 10
La tirada es 9, es una jugada valida

X X 3 4 5 X X 8 9 10  // Aquí se podría tomar el 5, no necesariamente se debían sumar 2 cartas.
La tirada es 5, es una jugada NO valida

X X 3 4 5 X X 8 9 10  // Aquí se podría tomar el 3, no necesariamente se debían sumar 2 cartas.
La tirada es 3, es una jugada NO valida

X X 3 4 5 X X 8 9 10  // Aquí se podía dar una jugada valida sumando el 8 con el 4.
La tirada es 12, es una jugada valida