Foros del Web » Programación para mayores de 30 ;) » C/C++ »

problema con juego de palabras

Estas en el tema de problema con juego de palabras en el foro de C/C++ en Foros del Web. Hola amigos, he estado trasteando un poco porque vi en el movil un juego muy chulo que te muestra una palabra de 4 letras desordenada ...
  #1 (permalink)  
Antiguo 16/11/2015, 13:20
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
problema con juego de palabras

Hola amigos, he estado trasteando un poco porque vi en el movil un juego muy chulo que te muestra una palabra de 4 letras desordenada y tienes que adivinarla y al hacerlo usa esas letras para una palabra nueva que tienes que adivinar pero esta con 5 letras y te muestra la nueva letra y los huecos y asi hasta nueve letras. Lo he estado meditando mucho la forma de afrontar esto para hacerlo yo en C y aprender un poco y despues de mucho marearme conseguí esto:
Código C++:
Ver original
  1. /******************************************************************************
  2. * Este juego busca una palabra de 4 letras, te la muestra desordenada y te    *
  3. * pide que la adivines.                                                       *
  4. * Una vez que la adivines busca una palabra en otro archivo que tenga una     *
  5. * letra mas y que contenga todas las letras de la anterior.                   *
  6. * El juego sigue igual hasta que adivines la palabra de 9 caracteres y en ese *
  7. * momento empieza de nuevo con otra palabra de 4 que escogera al azar del     *
  8. * archivo.                                                                    *
  9. *******************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14.  
  15. #define MIN_LEVEL 4
  16. #define MAX_LEVEL 9
  17. #define SIZE 10
  18. //-----------------------------------------------------------------------------
  19.  
  20. int SearchFirstWord(char *word);
  21. int SearchNextWord(char *word,int length,char *siguiente,int *posCharExtra);
  22. int ShowFirst(char *word);
  23. void ShowMask(char *word,int length,int posCharExtra);
  24. void RandomCharsOfWord(char *word,char *result,int length);
  25. //-----------------------------------------------------------------------------
  26.  
  27. int main ()
  28. {
  29.    char palabra[SIZE];
  30.    char entrada[SIZE];
  31.    int posCaracterExtra;
  32.    int largo;
  33.  
  34.    srand(time(NULL));
  35.    SearchFirstWord(palabra);
  36.    ShowFirst(palabra);
  37.    largo=strlen(palabra);
  38.  
  39.    while(largo <= MAX_LEVEL){
  40.       printf("Adivina la palabra: ");
  41.       scanf("%s",entrada);
  42.       if(strcmp(entrada,"0")==0)
  43.          break;
  44.       if(strcmp(palabra,entrada) !=0){
  45.          printf("Nooop\n");
  46.       }else{
  47.          printf("Correcto!\n");
  48.          if(largo==MAX_LEVEL){
  49.             system("PAUSE");
  50.             system("CLS");
  51.             largo=MIN_LEVEL;
  52.             if(SearchFirstWord(palabra)==1){
  53.                ShowFirst(palabra);
  54.             }else{
  55.                printf("Huvo un error al obtener la siguiente palabra. El programa finalizara.\n");
  56.                break;
  57.             }
  58.          }else{
  59.             if(SearchNextWord(palabra,largo,palabra,&posCaracterExtra)==1){
  60.                largo++;
  61.                printf("La siguiente es: ");
  62.                ShowMask(palabra,largo,posCaracterExtra);
  63.             }else{
  64.                printf("Huvo un error al obtener la siguiente palabra. El programa finalizara.\n");
  65.                break;
  66.             }
  67.          }
  68.       }
  69.    }
  70.    return 0;
  71. }
  72. //-----------------------------------------------------------------------------
  73.  
  74. int ShowFirst(char *word)
  75. {
  76.    char cadena[MIN_LEVEL+1];
  77.  
  78.    printf("Juega a 'Adivina la palabra'\n");
  79.    printf("Introduce '0' y pulsa intro para salir del juego en cualquier momento.\n");
  80.    printf("======================================================================\n\n");
  81.  
  82.    do{
  83.       RandomCharsOfWord(word,cadena,MIN_LEVEL);
  84.    }while(strcmp(cadena,word)==0);
  85.  
  86.    printf ("La palabra desordenada es: %s\n",cadena);
  87.    return 0;
  88. }
  89. //-----------------------------------------------------------------------------
  90.  
  91. void ShowMask(char *word,int length,int posCharExtra)
  92. {
  93.    int i;
  94.    for(i=0;i<length;i++)
  95.       if(i==posCharExtra)
  96.          printf("%c ",word[i]);
  97.       else
  98.          printf("_ ");
  99.    printf("\n");
  100. }
  101. //-----------------------------------------------------------------------------
  102.  
  103. void RandomCharsOfWord(char *word,char *result,int length)
  104. {
  105.    int a,i,posRand;
  106.    char aux;
  107.  
  108.    strcpy(result,word);
  109.    for(a=0;a<length;a++){
  110.       for(i=0;i<length-(1+a);i++){
  111.          posRand=rand()%length;
  112.          aux=result[i];
  113.          result[i]=result[posRand];
  114.          result[posRand]=aux;
  115.       }
  116.    }
  117. }
  118. //-----------------------------------------------------------------------------
  119.  
  120. int SearchNextWord(char *word,int length,char *siguiente,int *posCharExtra)
  121. {
  122.    char cadena[SIZE],salida[SIZE];
  123.    char nameFile[13]={0};
  124.    char aux;
  125.    int a,i,contador,retval;
  126.    FILE *archivo;
  127.  
  128.    sprintf(nameFile,"%i_Letras.txt",length+1);
  129.    archivo=fopen(nameFile,"r");
  130.  
  131.    if(archivo != NULL){
  132.       do{
  133.          retval=fread(cadena,SIZE,1,archivo);
  134.          strcpy(salida,cadena);
  135.          contador=length;
  136.          for(a=0;a<length;a++){
  137.             for(i=0;i<=contador;i++){
  138.                if(word[a]==cadena[i])
  139.                {
  140.                   aux=cadena[i];
  141.                   cadena[i]=cadena[contador];
  142.                   cadena[contador]=aux;
  143.                   contador--;
  144.                   break;
  145.                }
  146.             }
  147.          }
  148.          if(contador==0){
  149.             strcpy(siguiente,salida);
  150.             *posCharExtra=(int)strchr(siguiente,cadena[0])-(int)siguiente;
  151.             retval=1;
  152.          }
  153.       }while(contador !=0 && !feof(archivo));
  154.       fclose(archivo);
  155.    }else{
  156.       retval=-1;
  157.    }
  158.    return retval;
  159. }
  160. //-----------------------------------------------------------------------------
  161.  
  162. int SearchFirstWord(char *word)
  163. {
  164.    int retval,nPalabras,posPalabra;
  165.    FILE *archivo;
  166.    char nameFile[13]={0};
  167.    char palabra[SIZE];
  168.  
  169.    sprintf(nameFile,"%i_Letras.txt",MIN_LEVEL);
  170.    archivo=fopen(nameFile,"r");
  171.    if(archivo != NULL){
  172.       fseek(archivo,0,SEEK_END);
  173.       nPalabras=ftell(archivo)/SIZE;
  174.       posPalabra=rand()%nPalabras;
  175.       fseek(archivo,posPalabra*SIZE,SEEK_SET);
  176.       retval=fread(palabra,SIZE,1,archivo);
  177.       if(retval==1)
  178.          strcpy(word,palabra);
  179.       fclose(archivo);
  180.    }else{
  181.       retval=-1;
  182.    }
  183.    return retval;
  184. }
  185. //-----------------------------------------------------------------------------

El juego funciona aunque hay cosas que no las controlo porque aun no lo tengo del todo controlado y estoy haciendo pruebas pero funcionar funciona.
El problema que tengo es que a veces se da el caso de que no encuentra una palabra que contenga todas las letras de la anterior pero con una letra mas, no se si me explico. Cuando eso pasa el juego se acaba porque yo hago que sea asi pero me gustaria que eso no pasara y que siempre encontrara una valida para cada tamaño de palabra. La unica manera que se me ocurre es rellenar un array con todas las palabras que usará en la mano actual y asegurarme que se obtienen todas pero no se me ocurre un modo eficiente de conseguirlo. ¿alguien puede ayudarme?
Edito: Lo he estado pensando y creo que la manera más eficiente es ir desde las más largas a las más cortas comprobando que haya alguna palabra que sirva para ella y si no es asi desecharlo del archivo y luego hacer lo mismo pero empezando desde la más corta a la más larga y así me aseguro que todas las que hayan sean válidas.

Última edición por aguml; 16/11/2015 a las 16:36
  #2 (permalink)  
Antiguo 17/11/2015, 03:25
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

¿Y si precalculas toda la secuencia de palabras antes de empezar la partida? Así si llegas a un callejón sin salida puedes desechar la última palabra y probar una combinación nueva... o empezar desde el principio... y el usuario no se enteraría de nada.

A poco malo que sea tu ordenador el programa debería ser capaz de verificar varios miles de combinaciones en un par de segundos.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #3 (permalink)  
Antiguo 17/11/2015, 07:52
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Bueno creo que lo mas eficiente es crear listas de palabras que sean todas validas y en eso me hallo y he creado este codigo para quitar todas las que no valgan:
Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define MIN_LEVEL 4
  6. #define MAX_LEVEL 9
  7. #define SIZE 10
  8. //-----------------------------------------------------------------------------
  9.  
  10. int DelInvalidWordsDesc(char *nameFile,int size,int *nEliminadas);
  11. int DelInvalidWordsAsc(char *nameFile,int size,int *nEliminadas);
  12. int SearchBackWord(char *word,int length,char *anterior,int pos);
  13. int SearchNextWord(char *word,int length,char *siguiente,int pos);
  14. int SearchRepe(FILE *archivo,char *palabra);
  15.  
  16. int main(int argc, char* argv[])
  17. {
  18.    int retval,palabrasDesechadas;
  19.    int contador=MIN_LEVEL;
  20.    char nameFileOrigen[25],nameFileDestino[25],nameFileSig[25];
  21.  
  22.    //Limpio los archivos de palabras con 4,5,6,7,y 8 letras
  23.    do{
  24.       sprintf(nameFileOrigen,"%i_Letras.txt",contador);
  25.       sprintf(nameFileSig,"%i_Letras.txt",contador+1);
  26.       sprintf(nameFileDestino,"%i_Letras_res.txt",contador);
  27.       retval=DelInvalidWordsAsc(nameFileOrigen,contador,&palabrasDesechadas);
  28.       switch(retval){
  29.          case -3:
  30.             printf("El archivo %s no se pudo limpiar. %s no se pudo abrir.",nameFileOrigen,nameFileSig);
  31.             remove(nameFileDestino);
  32.          break;
  33.          case -2:
  34.             printf("El archivo %s no se pudo limpiar. %s no se pudo crear.",nameFileOrigen,nameFileDestino);
  35.          break;
  36.          case -1:
  37.             printf("%s no se pudo limpiar porque no pudo abrirse.\n",nameFileOrigen);
  38.          break;
  39.          case 0:
  40.             printf("%s se pudo limpiar. %s creado exitosamente. Se eliminaron %i palabras.\n",nameFileOrigen,nameFileDestino,palabrasDesechadas);
  41.             remove(nameFileOrigen);
  42.             rename(nameFileDestino,nameFileOrigen);
  43.          break;
  44.       }
  45.       contador++;
  46.    }while(contador < MAX_LEVEL);
  47.  
  48.    
  49.    //Limpio el archivo de palabras de 9 letras
  50.  
  51.    sprintf(nameFileOrigen,"%i_Letras.txt",contador);
  52.    sprintf(nameFileSig,"%i_Letras.txt",contador-1);
  53.    sprintf(nameFileDestino,"%i_Letras_res.txt",contador);
  54.    retval=DelInvalidWordsDesc(nameFileOrigen,MAX_LEVEL,&palabrasDesechadas);
  55.    switch(retval){
  56.       case -3:
  57.          printf("El archivo %s no se pudo limpiar. %s no se pudo abrir.",nameFileOrigen,nameFileSig);
  58.          remove(nameFileDestino);
  59.       break;
  60.       case -2:
  61.          printf("El archivo %s no se pudo limpiar. %s no se pudo crear.",nameFileOrigen,nameFileDestino);
  62.       break;
  63.       case -1:
  64.          printf("%s no se pudo limpiar porque no pudo abrirse.\n",nameFileOrigen);
  65.       break;
  66.       case 0:
  67.          printf("%s se pudo limpiar. %s creado exitosamente. Se eliminaron %i palabras.\n",nameFileOrigen,nameFileDestino,palabrasDesechadas);
  68.          remove(nameFileOrigen);
  69.          rename(nameFileDestino,nameFileOrigen);
  70.       break;
  71.    }
  72.    system("PAUSE");
  73.    return 0;
  74. }
  75. //---------------------------------------------------------------------------
  76.  
  77. int SearchNextWord(char *word,int length,char *siguiente,int pos)
  78. {
  79.    char cadena[SIZE],salida[SIZE];
  80.    char nameFile[13]={0};
  81.    char aux;
  82.    int a,i,contador,retval;
  83.    FILE *archivo;
  84.  
  85.    sprintf(nameFile,"%i_Letras.txt",length+1);
  86.    archivo=fopen(nameFile,"r");
  87.  
  88.    if(archivo != NULL){
  89.       fseek(archivo,pos,SEEK_SET);
  90.       do{
  91.          retval=fread(cadena,SIZE,1,archivo);
  92.          strncpy(salida,cadena,SIZE);
  93.          contador=length;
  94.          for(a=0;a<length;a++){
  95.             for(i=0;i<=contador;i++){
  96.                if(word[a]==cadena[i])
  97.                {
  98.                   aux=cadena[i];
  99.                   cadena[i]=cadena[contador];
  100.                   cadena[contador]=aux;
  101.                   contador--;
  102.                   break;
  103.                }
  104.             }
  105.          }
  106.          if(contador==0){
  107.             memset(siguiente,'\0',SIZE);
  108.             strncpy(siguiente,salida,SIZE);
  109.             retval=ftell(archivo);
  110.          }else{
  111.             retval=-1;
  112.          }
  113.       }while(contador !=0 && !feof(archivo));
  114.       fclose(archivo);
  115.    }else{
  116.       retval=-2;
  117.    }
  118.    return retval;
  119. }
  120. //-----------------------------------------------------------------------------
  121.  
  122. int SearchBackWord(char *word,int length,char *anterior,int pos)
  123. {
  124.    char cadena[SIZE],salida[SIZE];
  125.    char nameFile[13]={0};
  126.    char aux;
  127.    int a,i,contador,retval;
  128.    FILE *archivo;
  129.  
  130.    sprintf(nameFile,"%i_Letras.txt",length-1);
  131.    archivo=fopen(nameFile,"r");
  132.  
  133.    if(archivo != NULL){
  134.       fseek(archivo,pos,SEEK_SET);
  135.       do{
  136.          retval=fread(cadena,SIZE,1,archivo);
  137.          strncpy(salida,cadena,10);
  138.          contador=length-1;
  139.          for(a=0;a<length;a++){
  140.             for(i=0;i<contador;i++){
  141.                if(word[a]==cadena[i])
  142.                {
  143.                   aux=cadena[i];
  144.                   cadena[i]=cadena[contador-1];
  145.                   cadena[contador-1]=aux;
  146.                   contador--;
  147.                   break;
  148.                }
  149.             }
  150.          }
  151.          if(contador==0){
  152.             memset(anterior,'\0',SIZE);
  153.             strncpy(anterior,salida,SIZE);
  154.             retval=ftell(archivo);
  155.          }else{
  156.             retval=-1;
  157.          }
  158.       }while(contador !=0 && !feof(archivo));
  159.       fclose(archivo);
  160.    }else{
  161.       retval=-2;
  162.    }
  163.    return retval;
  164. }
  165. //-----------------------------------------------------------------------------
  166.  
  167. int DelInvalidWordsDesc(char *nameFile,int size,int *nEliminadas)
  168. {
  169.    int encontrada,nPalabras,posPalabra,pos=0;
  170.    FILE *archivo,*salida;
  171.    char palabra[SIZE],siguiente[SIZE],pathSalida[25];
  172.  
  173.    *nEliminadas=0;
  174.    archivo=fopen(nameFile,"r");
  175.    if(archivo != NULL){
  176.       sprintf(pathSalida,"%i_Letras_res.txt",size);
  177.       salida=fopen(pathSalida,"w+");
  178.  
  179.       if(salida != NULL){
  180.          do{
  181.             encontrada=fread(palabra,SIZE,1,archivo);
  182.             if(encontrada==1){
  183.                pos=SearchBackWord(palabra,size,siguiente,pos);
  184.                if(pos > -1){
  185.                   if(SearchRepe(salida,siguiente)==0){
  186.                      fwrite(palabra,sizeof(palabra),1,salida);
  187.                   }
  188.                }else if(pos==-2){
  189.                   encontrada=-3;
  190.                   break;
  191.                }else{
  192.                   *nEliminadas +=1;
  193.                }
  194.             }
  195.          }while(!feof(archivo));
  196.          fclose(salida);
  197.       }else{
  198.          encontrada=-2;
  199.       }
  200.       fclose(archivo);
  201.    }else{
  202.       encontrada=-1;
  203.    }
  204.    return encontrada;
  205. }
  206.  
  207. int DelInvalidWordsAsc(char *nameFile,int size,int *nEliminadas)
  208. {
  209.    int encontrada,nPalabras,posPalabra,pos=0;
  210.    FILE *archivo,*salida;
  211.    char palabra[SIZE],siguiente[SIZE],pathSalida[25];
  212.  
  213.    *nEliminadas=0;
  214.    archivo=fopen(nameFile,"r");
  215.    if(archivo != NULL){
  216.       sprintf(pathSalida,"%i_Letras_res.txt",size);
  217.       salida=fopen(pathSalida,"w+");
  218.  
  219.       if(salida != NULL){
  220.          do{
  221.             encontrada=fread(palabra,SIZE,1,archivo);
  222.             if(encontrada==1){
  223.                pos=SearchNextWord(palabra,size,siguiente,pos);
  224.                if(pos > -1){
  225.                   if(SearchRepe(salida,siguiente)==0){
  226.                      fwrite(palabra,sizeof(palabra),1,salida);
  227.                   }
  228.                }else if(pos==-2){
  229.                   encontrada=-3;
  230.                   break;
  231.                }else{
  232.                   *nEliminadas +=1;
  233.                }
  234.             }
  235.          }while(!feof(archivo));
  236.          fclose(salida);
  237.       }else{
  238.          encontrada=-2;
  239.       }
  240.       fclose(archivo);
  241.    }else{
  242.       encontrada=-1;
  243.    }
  244.    return encontrada;
  245. }
  246. //-----------------------------------------------------------------------------
  247.  
  248. int SearchRepe(FILE *archivo,char *palabra)
  249. {
  250.    int encontrada=0,retval;
  251.    char leida[SIZE];
  252.  
  253.    fseek(archivo,0,SEEK_SET);
  254.    do{
  255.       retval=fread(leida,sizeof(leida),1,archivo);
  256.       if(retval==1 && strcmp(leida,palabra)==0){
  257.          encontrada=1;
  258.          break;
  259.       }
  260.    }while(!feof(archivo) && encontrada==0);
  261.    fseek(archivo,0,SEEK_END);
  262.    return encontrada;
  263. }
La verdad es que si creo los archivos y a su archivo correspondiente le meto una cadena que se que valdrá funciona mi codigo aunque tengo que ir ejecutandolo varias veces hasta obtener que no se borro nada de ningun archivo.
Por ejemplo:
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi

Si pongo cada una de estas en su correspondiente archivo me borra todas las que no se puedan combinar pero estas no las borra porque si que se pueden combinar pero si no meto estas cadenas acaba borrandome todo o casi todo y algunos archivos acaban vacios pero sin embargo al jugar en el juego veo que hay combinaciones validas asi que no deberia borrarlas pero no se que hago mal.
  #4 (permalink)  
Antiguo 17/11/2015, 08:08
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

Código C:
Ver original
  1. for(a=0;a<length;a++){
  2.             for(i=0;i<=contador;i++){
  3.                if(word[a]==cadena[i])
  4.                {
  5.                   aux=cadena[i];
  6.                   cadena[i]=cadena[contador];
  7.                   cadena[contador]=aux;
  8.                   contador--;
  9.                   break;
  10.                }
  11.             }
  12.          }

Ahí, si no me equivoco, estás intentando dos cosas a la vez:
  • Comprobar si la palabra es válida
  • Desordenar sus caracteres

Al final no estás comprobando si la palabra es 100% válida. Primero porque solo recorres cadena con i, que depende de contador, no de la longitud de la palabra y segundo porque según vas verificando la letra la reubicas... lo que puede dar lugar a que compruebes dos veces la misma letra y a que haya letras sin verificar.

¿No sería mejor hacerlo en dos pasos? Primero chequear la palabra y luego, si la palabra es válida, descolocar sus componentes?

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #5 (permalink)  
Antiguo 17/11/2015, 10:30
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Realmente no hago lo que dices. Lo que hago es que contador vale tanto como el largo de la palabra con la que quiero comparar y si coincide el carácter pongo ese carácter en el lugar que apunta contador intercambiando los caracteres y decremento el contador para que el caracter que puse en el lugar que apuntaba contador no se vuelva a comprobar. Nunca se podrá examinar doblemente ese caracter porque quedará fuera del rango al decrementar contador. Si es válida saldrá con contador valiendo 0. Si no es válida contador será mayor que 0. El que la palabra acabe desordenada es un daño colateral jejeje. Por eso la pongo antes la palabra a buen recaudo, para poder saber cual era.
  #6 (permalink)  
Antiguo 17/11/2015, 11:58
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

La verdad es que yo no me preocuparía tanto por las palabras sin secuencia completa... como te dije un ordenador mínimanete decente debería ser capaz de probar miles de rutas en un segundo. Si no consigues ese objetivo prueba a paralelizar la búsqueda usando tantos hilos como núcleos tenga el pc... usar un pool de hilos puede ser una buena idea para realizar esa tarea.

Yo me centraría más en pulir el motor de búsqueda para que garantice siempre una secuencia válida.

¿Por qué no soy partidario de borrar palabras? Porque según te vayas animando y añadiendo nuevas palabras a la lista, las palabras que ahora están huerfanas podrán pasar a formar parte de secuencias completas... de otra forma pierdes parte del trabajo invertido.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #7 (permalink)  
Antiguo 17/11/2015, 16:41
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Mmmm pues si es buena idea aunque en realidad esto era una simple prueba y no tengo pensado continuar más allá. Lo haré como dices pero ya por cabezonería quiero ver si mi código de quitar palabras funciona. Después de pensarlo mucho estoy pensando que quizás alguno de los archivos tiene un formato invalido y por eso este pasando esto, o sea que como cada elemento son 10 bytes pues que algún elemento no tenga ese tamaño o algo y descoloque todo. Quiero hacerme un pequeño código que lea elemento por elemento y compruebe el tamaño de la palabra y si no es correcto me indique donde es y a ver si con eso resuelvo algo. Ya cuento lo que sea.
  #8 (permalink)  
Antiguo 18/11/2015, 14:26
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Bueno, ya di con la tecla para borrar las palabras que no sirven. Quedó asi:
Código C++:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define MIN_LEVEL 4
  6. #define MAX_LEVEL 9
  7. #define SIZE 10
  8. //-----------------------------------------------------------------------------
  9.  
  10. int DelInvalidWordsDesc(char *nameFile,int size,int *nEliminadas);
  11. int DelInvalidWordsAsc(char *nameFile,int size,int *nEliminadas);
  12. int SearchBackWord(char *word,int length,char *anterior,int pos);
  13. int SearchNextWord(char *word,int length,char *siguiente,int pos);
  14. int SearchRepe(FILE *archivo,char *palabra);
  15.  
  16. int main(int argc, char* argv[])
  17. {
  18.    int retval,palabrasDesechadas;
  19.    int contador=MAX_LEVEL-1;
  20.    char nameFileOrigen[25],nameFileDestino[25],nameFileSig[25];
  21.  
  22.    //Limpio los archivos de palabras con 4,5,6,7,y 8 letras
  23.    do{
  24.       sprintf(nameFileOrigen,"%i_Letras.txt",contador);
  25.       sprintf(nameFileSig,"%i_Letras.txt",contador+1);
  26.       sprintf(nameFileDestino,"%i_Letras_res.txt",contador);
  27.       retval=DelInvalidWordsAsc(nameFileOrigen,contador,&palabrasDesechadas);
  28.       switch(retval){
  29.          case -3:
  30.             printf("El archivo %s no se pudo limpiar. %s no se pudo abrir.",nameFileOrigen,nameFileSig);
  31.             remove(nameFileDestino);
  32.          break;
  33.          case -2:
  34.             printf("El archivo %s no se pudo limpiar. %s no se pudo crear.",nameFileOrigen,nameFileDestino);
  35.          break;
  36.          case -1:
  37.             printf("%s no se pudo limpiar porque no pudo abrirse.\n",nameFileOrigen);
  38.          break;
  39.          case 0:
  40.             printf("%s se pudo limpiar. %s creado exitosamente. Se eliminaron %i palabras.\n",nameFileOrigen,nameFileDestino,palabrasDesechadas);
  41.             remove(nameFileOrigen);
  42.             rename(nameFileDestino,nameFileOrigen);
  43.          break;
  44.       }
  45.       contador--;
  46.    }while(contador >= MIN_LEVEL);
  47.  
  48.    contador=MAX_LEVEL;
  49.    //Limpio el archivo de palabras de 9 letras
  50.  
  51.    sprintf(nameFileOrigen,"%i_Letras.txt",contador);
  52.    sprintf(nameFileSig,"%i_Letras.txt",contador-1);
  53.    sprintf(nameFileDestino,"%i_Letras_res.txt",contador);
  54.    retval=DelInvalidWordsDesc(nameFileOrigen,MAX_LEVEL,&palabrasDesechadas);
  55.    switch(retval){
  56.       case -3:
  57.          printf("El archivo %s no se pudo limpiar. %s no se pudo abrir.",nameFileOrigen,nameFileSig);
  58.          remove(nameFileDestino);
  59.       break;
  60.       case -2:
  61.          printf("El archivo %s no se pudo limpiar. %s no se pudo crear.",nameFileOrigen,nameFileDestino);
  62.       break;
  63.       case -1:
  64.          printf("%s no se pudo limpiar porque no pudo abrirse.\n",nameFileOrigen);
  65.       break;
  66.       case 0:
  67.          printf("%s se pudo limpiar. %s creado exitosamente. Se eliminaron %i palabras.\n",nameFileOrigen,nameFileDestino,palabrasDesechadas);
  68.          remove(nameFileOrigen);
  69.          rename(nameFileDestino,nameFileOrigen);
  70.       break;
  71.    }
  72.    system("PAUSE");
  73.    return 0;
  74. }
  75. //---------------------------------------------------------------------------
  76.  
  77. int SearchNextWord(char *word,int length,char *siguiente,int pos)
  78. {
  79.    char cadena[SIZE],salida[SIZE];
  80.    char nameFile[13]={0};
  81.    int a,i,largoCadena,retval;
  82.    FILE *archivo;
  83.  
  84.    sprintf(nameFile,"%i_Letras.txt",length+1);
  85.    archivo=fopen(nameFile,"r");
  86.  
  87.    if(archivo != NULL){
  88.       fseek(archivo,pos,SEEK_SET);
  89.       do{
  90.          retval=fread(cadena,SIZE,1,archivo);
  91.          strncpy(salida,cadena,SIZE);
  92.          largoCadena=strlen(cadena);
  93.          for(a=0;a<length;a++){
  94.             for(i=0;i<largoCadena;i++){
  95.                if(word[a]==cadena[i])
  96.                {
  97.                   cadena[i]=cadena[largoCadena-1];
  98.                   cadena[largoCadena-1]='\0';
  99.                   largoCadena--;
  100.                   break;
  101.                }
  102.             }
  103.          }
  104.          if(largoCadena==1){
  105.             memset(siguiente,'\0',SIZE);
  106.             strncpy(siguiente,salida,SIZE);
  107.             retval=ftell(archivo);
  108.          }else{
  109.             retval=-1;
  110.          }
  111.       }while(largoCadena > 1 && !feof(archivo));
  112.       fclose(archivo);
  113.    }else{
  114.       retval=-2;
  115.    }
  116.    if(retval < 0)
  117.       memset(siguiente,'\0',SIZE);
  118.    return retval;
  119. }
  120. //-----------------------------------------------------------------------------
  121.  
  122. int SearchBackWord(char *word,int length,char *anterior,int pos)
  123. {
  124.    char cadena[SIZE],salida[SIZE];
  125.    char nameFile[13]={0};
  126.    int a,i,largoCadena,retval;
  127.    FILE *archivo;
  128.  
  129.    sprintf(nameFile,"%i_Letras.txt",length-1);
  130.    archivo=fopen(nameFile,"r");
  131.  
  132.    if(archivo != NULL){
  133.       fseek(archivo,pos,SEEK_SET);
  134.       do{
  135.          retval=fread(cadena,SIZE,1,archivo);
  136.          strncpy(salida,cadena,10);
  137.          largoCadena=strlen(cadena);
  138.          for(a=0;a<length;a++){
  139.             for(i=0;i<largoCadena;i++){
  140.                if(word[a]==cadena[i])
  141.                {
  142.                   cadena[i]=cadena[largoCadena-1];
  143.                   cadena[largoCadena-1]='\0';
  144.                   largoCadena--;
  145.                   break;
  146.                }
  147.             }
  148.          }
  149.          if(largoCadena==0){
  150.             memset(anterior,'\0',SIZE);
  151.             strncpy(anterior,salida,SIZE);
  152.             retval=ftell(archivo);
  153.          }else{
  154.             retval=-1;
  155.          }
  156.       }while(largoCadena > 0 && !feof(archivo));
  157.       fclose(archivo);
  158.    }else{
  159.       retval=-2;
  160.    }
  161.    if(retval < 0)
  162.       memset(anterior,'\0',SIZE);
  163.    return retval;
  164. }
  165. //-----------------------------------------------------------------------------
  166.  
  167. int DelInvalidWordsDesc(char *nameFile,int size,int *nEliminadas)
  168. {
  169.    int encontrada,nPalabras,posPalabra,pos=0;
  170.    FILE *archivo,*salida;
  171.    char palabra[SIZE],anterior[SIZE],pathSalida[25];
  172.  
  173.    *nEliminadas=0;
  174.    archivo=fopen(nameFile,"r");
  175.    if(archivo != NULL){
  176.       sprintf(pathSalida,"%i_Letras_res.txt",size);
  177.       salida=fopen(pathSalida,"w+");
  178.  
  179.       if(salida != NULL){
  180.          do{
  181.             encontrada=fread(palabra,SIZE,1,archivo);
  182.             if(encontrada==1){
  183.                pos=SearchBackWord(palabra,size,anterior,pos);
  184.                if(pos > -1){
  185.                   if(SearchRepe(salida,anterior)==0){
  186.                      fwrite(palabra,sizeof(palabra),1,salida);
  187.                   }
  188.                }else if(pos==-2){
  189.                   encontrada=-3;
  190.                   break;
  191.                }else{
  192.                   *nEliminadas +=1;
  193.                }
  194.                pos=0;
  195.             }
  196.          }while(!feof(archivo));
  197.          fclose(salida);
  198.       }else{
  199.          encontrada=-2;
  200.       }
  201.       fclose(archivo);
  202.    }else{
  203.       encontrada=-1;
  204.    }
  205.    return encontrada;
  206. }
  207.  
  208. int DelInvalidWordsAsc(char *nameFile,int size,int *nEliminadas)
  209. {
  210.    int encontrada,nPalabras,posPalabra,pos=0;
  211.    FILE *archivo,*salida;
  212.    char palabra[SIZE],siguiente[SIZE],pathSalida[25];
  213.  
  214.    *nEliminadas=0;
  215.    archivo=fopen(nameFile,"r");
  216.    if(archivo != NULL){
  217.       sprintf(pathSalida,"%i_Letras_res.txt",size);
  218.       salida=fopen(pathSalida,"w+");
  219.  
  220.       if(salida != NULL){
  221.          do{
  222.             encontrada=fread(palabra,SIZE,1,archivo);
  223.             if(encontrada==1){
  224.                pos=SearchNextWord(palabra,size,siguiente,pos);
  225.                if(pos > -1){
  226.                   if(SearchRepe(salida,siguiente)==0){
  227.                      fwrite(palabra,sizeof(palabra),1,salida);
  228.                   }
  229.                }else if(pos==-2){
  230.                   encontrada=-3;
  231.                   break;
  232.                }else{
  233.                   *nEliminadas +=1;
  234.                }
  235.                pos=0;
  236.             }
  237.          }while(!feof(archivo));
  238.          fclose(salida);
  239.       }else{
  240.          encontrada=-2;
  241.       }
  242.       fclose(archivo);
  243.    }else{
  244.       encontrada=-1;
  245.    }
  246.    return encontrada;
  247. }
  248. //-----------------------------------------------------------------------------
  249.  
  250. int SearchRepe(FILE *archivo,char *palabra)
  251. {
  252.    int encontrada=0,retval;
  253.    char leida[SIZE];
  254.  
  255.    fseek(archivo,0,SEEK_SET);
  256.    do{
  257.       retval=fread(leida,sizeof(leida),1,archivo);
  258.       if(retval==1 && strcmp(leida,palabra)==0){
  259.          encontrada=1;
  260.          break;
  261.       }
  262.    }while(!feof(archivo) && encontrada==0);
  263.    fseek(archivo,0,SEEK_END);
  264.    return encontrada;
  265. }
Funcionar funciona. Que se pueda mejorar, pues seguro pero este funciona jajaja.
Ahora me quiero liar con el juego para hacerlo como me dijiste sin quitar las palabras que sobran y, aun mas, que busque todas las palabras validas para una palabra y escoja una aleatoriamente y asi hasta completar una combinacion valida. Actualmente coge solo la primera palabra válida y puede haber otras combinaciones y no las uso nunca. Con lo que quiero hacer la cosa mejorará mucho. Supongo que la forma mas correcta es crear una estructura con un puntero para cada lista de palabras validas y con realloc voy reservando memoria para cada palabra encontrada y si una palabra no vale la borro y asi hasta conseguir un listado valido. Aun no tengo muy claro como lo haré pero creo que podré. De todos modos escucho sugerencias.
Cuando tenga el codigo del juego terminado lo pondré aqui.
  #9 (permalink)  
Antiguo 19/11/2015, 01:59
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

Lo suyo sería, yo creo, leer todas las palabras al arrancar el programa y después hacer los cálculos con todo en memoria... ganarás mucha velocidad y el consumo de memoria no va a ser para nada alto.

Puedes usar una lista enlazada circular para almacenar la lista de palabras de N letras. De esa forma generas un número aleatorio, avanzas ese número de posiciones sin preocuparte por si se te acaba la lista y desde ahí a localizar la primera palabra válida... también puedes usar ese número aleatorio para descartar las N primeras palabras válidas. Si tienes todo en memoria, descartar una palabra no debería significar borrarla de la memoria.

Para almacenar la secuencia podrías utilizar o un arreglo de tamaño fijo o una lista enlazada. El algoritmo rellena la secuencia copiando la palabra correspondiente en la posición que le toque. Finalmente coges el listado que te genera el algoritmo y a jugar :)

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #10 (permalink)  
Antiguo 19/11/2015, 07:38
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Estoy haciendo una prueba como dije pero a veces funciona bien y retrocede para cambiar de palabra y buscar la siguiente y a veces falla al reallocar la memoria. La verdad es que me tiene loco y no se donde puede estar el fallo. Como lo tengo, cuando funciona, obtengo la combinacion rapidisimo, vamos al instante. El caso es que, a veces, da una excepcion al reallocar memoria y dice algo asi como que intento escribir en una direccion no valida. ¿puedes indicarme donde esta el fallo? Lo de lista circulares... bueno, no se ni por donde empezar ya que primero supongo que tendria que funcionar mi codigo, luego crear una lista enlazada en la que voy añadiendo todas las combinaciones validas, y por ultimo simplemente obtener un puntero al azar de esa lista pero si no funciona primero mi codigo no se por donde seguir. Esto es lo que tengo:

Código C:
Ver original
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <ctype.h>
  5.  
  6. #define MIN_LEVEL 4
  7. #define MAX_LEVEL 9
  8. #define SIZE 10
  9. //-----------------------------------------------------------------------------
  10.  
  11. typedef struct PRIMERA{
  12.    char Palabra[SIZE];
  13. }Primera;
  14.  
  15. typedef struct PALABRA{
  16.    char Palabra[SIZE];
  17.    int PosCaracterExtra;
  18. }Palabra;
  19.  
  20. typedef struct LISTA_PALABRAS{
  21.    Palabra *Palabras;
  22.    int nEncontradas;
  23. }ListaPalabras;
  24.  
  25. typedef struct COMBINACION{
  26.    Primera cuatroLetras;
  27.    ListaPalabras cincoLetras;
  28.    ListaPalabras seisLetras;
  29.    ListaPalabras sieteLetras;
  30.    ListaPalabras ochoLetras;
  31.    ListaPalabras nueveLetras;
  32. }Combinacion;
  33. //-----------------------------------------------------------------------------
  34.  
  35. int SearchFirstWord(char *word);
  36. int SearchNextWords(char *word,int length,ListaPalabras *Lista);
  37. int ShowFirst(char *word);
  38. void ShowMask(char *word,int length,int posCharExtra,int nCaracteresAMostrar);
  39. void RandomCharsOfWord(char *word,char *result,int length);
  40. void EliminarPalabra(ListaPalabras *Lista,int pos);
  41. //-----------------------------------------------------------------------------
  42.  
  43. int main ()
  44. {
  45.    char entrada[SIZE];
  46.    int posCaracterExtra;
  47.    int i,largo,encontrada,salir=0;
  48.    int selCincoLetras,selSeisLetras,selSieteLetras,selOchoLetras,selNueveLetras;
  49.    Combinacion combinacion;
  50.  
  51.    srand(time(NULL));
  52.  
  53.    do{
  54.       SearchFirstWord(combinacion.cuatroLetras.Palabra);
  55.       combinacion.cincoLetras.nEncontradas=0;
  56.       combinacion.cincoLetras.Palabras=NULL;
  57.       combinacion.seisLetras.nEncontradas=0;
  58.       combinacion.seisLetras.Palabras=NULL;
  59.       combinacion.sieteLetras.nEncontradas=0;
  60.       combinacion.sieteLetras.Palabras=NULL;
  61.       combinacion.ochoLetras.nEncontradas=0;
  62.       combinacion.ochoLetras.Palabras=NULL;
  63.       combinacion.nueveLetras.nEncontradas=0;
  64.       combinacion.nueveLetras.Palabras=NULL;
  65.       largo=4;
  66.       if(SearchNextWords(combinacion.cuatroLetras.Palabra,largo,&combinacion.cincoLetras) > 0){
  67.          ShowFirst(combinacion.cuatroLetras.Palabra);
  68.          do{
  69.             printf("Palabras siguientes validas: ");
  70.             for(i=0;i<combinacion.cincoLetras.nEncontradas;i++)
  71.                printf("%s ",combinacion.cincoLetras.Palabras[i].Palabra);
  72.             selCincoLetras=rand()%combinacion.cincoLetras.nEncontradas;
  73.             printf("\nPalabra seleccionada al azar: %s\n",combinacion.cincoLetras.Palabras[selCincoLetras].Palabra);
  74.             largo=5;
  75.             if(SearchNextWords(combinacion.cincoLetras.Palabras[selCincoLetras].Palabra,largo,&combinacion.seisLetras) > 0){
  76.                do{
  77.                   printf("Palabras siguientes validas para la seleccionada: ");
  78.                   for(i=0;i<combinacion.seisLetras.nEncontradas;i++)
  79.                      printf("%s ",combinacion.seisLetras.Palabras[i].Palabra);
  80.                   selSeisLetras=rand()%combinacion.seisLetras.nEncontradas;
  81.                   printf("\nPalabra seleccionada al azar: %s\n",combinacion.seisLetras.Palabras[selSeisLetras].Palabra);
  82.                   largo=6;
  83.                   if(SearchNextWords(combinacion.seisLetras.Palabras[selSeisLetras].Palabra,largo,&combinacion.sieteLetras) > 0){
  84.                      do{
  85.                         printf("Palabras siguientes validas para la seleccionada: ");
  86.                         for(i=0;i<combinacion.sieteLetras.nEncontradas;i++)
  87.                            printf("%s ",combinacion.sieteLetras.Palabras[i].Palabra);
  88.                         selSieteLetras=rand()%combinacion.sieteLetras.nEncontradas;
  89.                         printf("\nPalabra seleccionada al azar: %s\n",combinacion.sieteLetras.Palabras[selSieteLetras].Palabra);
  90.                         largo=7;
  91.                         if(SearchNextWords(combinacion.sieteLetras.Palabras[selSieteLetras].Palabra,largo,&combinacion.ochoLetras) > 0){
  92.                            do{
  93.                               printf("Palabras siguientes validas para la seleccionada: ");
  94.                               for(i=0;i<combinacion.ochoLetras.nEncontradas;i++)
  95.                                  printf("%s ",combinacion.ochoLetras.Palabras[i].Palabra);
  96.                               selOchoLetras=rand()%combinacion.ochoLetras.nEncontradas;
  97.                               printf("\nPalabra seleccionada al azar: %s\n",combinacion.ochoLetras.Palabras[selOchoLetras].Palabra);
  98.                               largo=8;
  99.                               if(SearchNextWords(combinacion.ochoLetras.Palabras[selOchoLetras].Palabra,largo,&combinacion.nueveLetras) > 0){
  100.                                  printf("Palabras siguientes validas para la seleccionada: ");
  101.                                  for(i=0;i<combinacion.nueveLetras.nEncontradas;i++)
  102.                                     printf("%s ",combinacion.nueveLetras.Palabras[i].Palabra);
  103.                                  selNueveLetras=rand()%combinacion.nueveLetras.nEncontradas;
  104.                                  printf("\nPalabra seleccionada al azar: %s\n",combinacion.nueveLetras.Palabras[selNueveLetras].Palabra);
  105.                                  encontrada=1;
  106.                                  free(combinacion.nueveLetras.Palabras);
  107.                                  combinacion.nueveLetras.nEncontradas=0;
  108.                                  salir=1;
  109.                               }else{
  110.                                  printf("No se encontro una palabra valida de 9 letras\n");
  111.                                  EliminarPalabra(&combinacion.ochoLetras,selOchoLetras);
  112.                               }
  113.                            }while(salir == 0 &&combinacion.nueveLetras.nEncontradas < 1 && combinacion.ochoLetras.nEncontradas > 0);
  114.                            free(combinacion.ochoLetras.Palabras);
  115.                            combinacion.ochoLetras.nEncontradas=0;
  116.                            if(salir==0)
  117.                               EliminarPalabra(&combinacion.sieteLetras,selSieteLetras);
  118.                         }else{
  119.                            printf("No se encontro una palabra valida de 8 letras\n");
  120.                            EliminarPalabra(&combinacion.sieteLetras,selSieteLetras);
  121.                         }
  122.                      }while(salir == 0 && combinacion.ochoLetras.nEncontradas < 1 && combinacion.sieteLetras.nEncontradas > 0);
  123.                      free(combinacion.sieteLetras.Palabras);
  124.                      combinacion.sieteLetras.nEncontradas=0;
  125.                      if(salir==0)
  126.                         EliminarPalabra(&combinacion.seisLetras,selSeisLetras);
  127.                   }else{
  128.                      printf("No se encontro una palabra valida de 7 letras\n");
  129.                      EliminarPalabra(&combinacion.seisLetras,selSeisLetras);
  130.                   }
  131.                }while(salir == 0 && combinacion.sieteLetras.nEncontradas < 1 && combinacion.seisLetras.nEncontradas > 0);
  132.                free(combinacion.seisLetras.Palabras);
  133.                combinacion.seisLetras.nEncontradas=0;
  134.                if(salir==0)
  135.                   EliminarPalabra(&combinacion.cincoLetras,selCincoLetras);
  136.             }else{
  137.                printf("No se encontro una palabra valida de 6 letras\n");
  138.                EliminarPalabra(&combinacion.cincoLetras,selCincoLetras);
  139.             }
  140.          }while(salir == 0 && combinacion.seisLetras.nEncontradas < 1 && combinacion.cincoLetras.nEncontradas > 0);
  141.          free(combinacion.cincoLetras.Palabras);
  142.          combinacion.cincoLetras.nEncontradas=0;
  143.       }else{
  144.          printf("No se encontro una palabra valida de 5 letras\n");
  145.       }
  146.    }while(salir == 0 && combinacion.cincoLetras.nEncontradas < 1);
  147.    system("PAUSE");
  148.    return 0;
  149. }
  150. //-----------------------------------------------------------------------------
  #11 (permalink)  
Antiguo 19/11/2015, 07:39
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Y las funciones:
Código C:
Ver original
  1. void EliminarPalabra(ListaPalabras *Lista,int pos)
  2. {
  3.    int i;
  4.    if(pos < Lista->nEncontradas-1 && pos > 0)
  5.       for(i=Lista->nEncontradas-1;i>pos;i--)
  6.          memcpy(&Lista->Palabras[i-1],&Lista->Palabras[i],sizeof(Palabra));
  7.    Lista->nEncontradas--;
  8. }
  9. //-----------------------------------------------------------------------------
  10.  
  11. int ShowFirst(char *word)
  12. {
  13.    char cadena[MIN_LEVEL+1];
  14.  
  15.    printf("Juega a 'Adivina la palabra'\n");
  16.    printf("Introduce '0' y pulsa intro para salir del juego en cualquier momento.\n");
  17.    printf("======================================================================\n\n");
  18.  
  19.    do{
  20.       RandomCharsOfWord(word,cadena,MIN_LEVEL);
  21.    }while(strcmp(cadena,word)==0);
  22.  
  23.    printf ("La palabra desordenada es: %s\n",cadena);
  24.    return 0;
  25. }
  26. //-----------------------------------------------------------------------------
  27.  
  28. void ShowMask(char *word,int length,int posCharExtra,int nCaracteresAMostrar)
  29. {
  30.    int i;
  31.    for(i=0;i<length;i++)
  32.       if(i==posCharExtra)
  33.          printf("%c ",word[i]);
  34.       else if(nCaracteresAMostrar > 0){
  35.          printf("%c ",word[i]);
  36.          nCaracteresAMostrar--;
  37.       }else
  38.          printf("_ ");
  39.    printf("\n");
  40. }
  41. //-----------------------------------------------------------------------------
  42.  
  43. void RandomCharsOfWord(char *word,char *result,int length)
  44. {
  45.    int a,i,posRand;
  46.    char aux;
  47.  
  48.    strcpy(result,word);
  49.    for(a=0;a<length;a++){
  50.       for(i=0;i<length-(1+a);i++){
  51.          posRand=rand()%length;
  52.          aux=result[i];
  53.          result[i]=result[posRand];
  54.          result[posRand]=aux;
  55.       }
  56.    }
  57. }
  58. //-----------------------------------------------------------------------------
  59.  
  60. int SearchNextWords(char *word,int length,ListaPalabras *Lista)
  61. {
  62.    char cadena[SIZE],salida[SIZE];
  63.    char nameFile[13]={0};
  64.    char aux;
  65.    int a,i,contador,retval;
  66.    FILE *archivo;
  67.  
  68.    sprintf(nameFile,"%i_Letras.txt",length+1);
  69.    archivo=fopen(nameFile,"r");
  70.  
  71.    if(archivo != NULL){
  72.       if(Lista->nEncontradas !=0){
  73.          free(Lista->Palabras);
  74.          Lista->nEncontradas=0;
  75.       }
  76.       do{
  77.          retval=fread(cadena,SIZE,1,archivo);
  78.          strcpy(salida,cadena);
  79.          contador=length;
  80.          for(a=0;a<length;a++){
  81.             for(i=0;i<=contador;i++){
  82.                if(word[a]==cadena[i])
  83.                {
  84.                   aux=cadena[i];
  85.                   cadena[i]=cadena[contador];
  86.                   cadena[contador]=aux;
  87.                   contador--;
  88.                   break;
  89.                }
  90.             }
  91.          }
  92.          if(contador==0){
  93.             Lista->nEncontradas++;
  94.             Lista->Palabras = realloc(Lista->Palabras,Lista->nEncontradas*sizeof(Palabra));
  95.             strcpy(Lista->Palabras[Lista->nEncontradas-1].Palabra,salida);
  96.             Lista->Palabras[Lista->nEncontradas-1].PosCaracterExtra=(int)strchr(Lista->Palabras[Lista->nEncontradas-1].Palabra,cadena[0])-(int)Lista->Palabras[Lista->nEncontradas-1].Palabra;
  97.          }
  98.       }while(!feof(archivo));
  99.       retval=Lista->nEncontradas;
  100.       fclose(archivo);
  101.    }else{
  102.       retval=-1;
  103.    }
  104.    return retval;
  105. }
  106. //-----------------------------------------------------------------------------
  107.  
  108. int SearchFirstWord(char *word)
  109. {
  110.    int retval,nPalabras,posPalabra;
  111.    FILE *archivo;
  112.    char nameFile[13]={0};
  113.    char palabra[SIZE];
  114.  
  115.    sprintf(nameFile,"%i_Letras.txt",MIN_LEVEL);
  116.    archivo=fopen(nameFile,"r");
  117.    if(archivo != NULL){
  118.       fseek(archivo,0,SEEK_END);
  119.       nPalabras=ftell(archivo)/SIZE;
  120.       posPalabra=rand()%nPalabras;
  121.       fseek(archivo,posPalabra*SIZE,SEEK_SET);
  122.       retval=fread(palabra,SIZE,1,archivo);
  123.       if(retval==1)
  124.          strcpy(word,palabra);
  125.       fclose(archivo);
  126.    }else{
  127.       retval=-1;
  128.    }
  129.    return retval;
  130. }
  131. //-----------------------------------------------------------------------------
  #12 (permalink)  
Antiguo 19/11/2015, 07:56
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

Código C:
Ver original
  1. if(archivo != NULL){
  2.       if(Lista->nEncontradas !=0){
  3.          free(Lista->Palabras); // <<<--- AQUI!!!
  4.          Lista->nEncontradas=0;
  5.       }
  6.       do{
  7.          if(contador==0){
  8.             Lista->nEncontradas++;
  9.             Lista->Palabras = realloc(Lista->Palabras,Lista->nEncontradas*sizeof(Palabra)); // <<<--- AQUI!!!
  10.             strcpy(Lista->Palabras[Lista->nEncontradas-1].Palabra,salida);
  11.             Lista->Palabras[Lista->nEncontradas-1].PosCaracterExtra=(int)strchr(Lista->Palabras[Lista->nEncontradas-1].Palabra,cadena[0])-(int)Lista->Palabras[Lista->nEncontradas-1].Palabra;
  12.          }

Si haces un free y después intentas un realloc... no se cómo puede acabar la cosa pero no pinta demasiado bien. Quizás si pusieses Lista->Palabras a NULL después del free....

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #13 (permalink)  
Antiguo 19/11/2015, 13:17
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Gracias amigo, ese era el problema, ya va perfecto. Ahora intento otra cosa. Ya que ya obtengo siempre una combinacion valida, La idea es volcar el archivo de cuatro letras a la memoria y barajar las palabras, luego empiezo leyendo desde la primera en la lista hasta llegar al final de la lista y si no sirve ninguna de cuatro para crear una combinacion sale. El problema lo tengo con esto:

Código C:
Ver original
  1. #define SIZE 10
  2. ...
  3. ...
  4. char *lista[SIZE];
  5. int nPalabras;
  6.  
  7. srand(time(NULL));
  8. ObtenerListaInicial("4_Letras.txt",lista,&nPalabras);
  9. ...
  10. ...
  11.  
  12. int ObtenerListaInicial(char *nameFile,char *palabra[SIZE],int *nElementos)
  13. {
  14.    int i=0,retval,posPalabra;
  15.    FILE *archivo;
  16.  
  17.    archivo=fopen(nameFile,"rb");
  18.    if(archivo != NULL){
  19.       fseek(archivo,0,SEEK_END);
  20.       *nElementos=ftell(archivo)/SIZE;
  21.       palabra=malloc(*nElementos*sizeof(char*));
  22.       if(palabra != NULL){
  23.          fseek(archivo,0,SEEK_SET);
  24.          do{
  25.             retval=fread(palabra[i],SIZE,1,archivo);
  26.             if(retval != 1)
  27.                break;
  28.             i++;
  29.          }while(!feof(archivo));
  30.       }
  31.       fclose(archivo);
  32.    }else{
  33.       retval=-1;
  34.    }
  35.    return retval;
  36. }

El problema que tengo es con el modo de reservar la memoria y luego escribir en ella. Se que lo estoy haciendo mal porque da una excepcion al intentar escribir en NULL pero no se como hacerlo bien.
  #14 (permalink)  
Antiguo 20/11/2015, 01:41
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

Código C:
Ver original
  1. palabra=malloc(*nElementos*sizeof(char*));

No falta ahí un SIZE??

Según esa línea, si tienes 20 palabras el programa reservará 20 bytes.

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #15 (permalink)  
Antiguo 20/11/2015, 02:23
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Quizás es que no he entendido bien la que hago . Si en la declaración estoy declarando un puntero de arrays y estoy indicando que el array es de SIZE tamaño ¿no se crea un array de punteros donde cada uno ya tiene SIZE bytes?
O sea, si hago:
Código C:
Ver original
  1. char array [5];
Reservo 5 char pero si hago:
Código C:
Ver original
  1. char *array [5];
  2. array=malloc (2*sizeof (array));
¿no estaría creando dos punteros a dos arrays cada uno de 5 bytes?
  #16 (permalink)  
Antiguo 20/11/2015, 02:48
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

El segundo ejemplo está mal... array como tal es un puntero doble, es decir, un puntero a puntero y, como tal, ocupa el mismo tamaño que un puntero simple. *array, en cambio, indicaría un segmento de 5 bytes.

En cualquier caso fíjate que el tamaño lo indicas con nElementos*sizeof(char*), es decir, ahí no aparece reflejado ni SIZE ni palabra ni nada que indique el tamaño de cada segmento.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #17 (permalink)  
Antiguo 20/11/2015, 03:45
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

O sea que aunque al declarar que la fila es de 5 caracteres ¿tengo que encargarme de reservarla también? ¿me puedes decir como hacerlo? Esto me tiene loco
  #18 (permalink)  
Antiguo 20/11/2015, 07:01
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Al final lo hice asi:
Código C:
Ver original
  1. /******************************************************************************
  2. * Este juego busca una palabra de 4 letras, te la muestra desordenada y te    *
  3. * pide que la adivines.                                                       *
  4. * Una vez que la adivines busca una palabra en otro archivo que tenga una     *
  5. * letra mas y que contenga todas las letras de la anterior.                   *
  6. * El juego sigue igual hasta que adivines la palabra de 9 caracteres y en ese *
  7. * momento empieza de nuevo con otra palabra de 4 que escogera al azar del     *
  8. * archivo.                                                                    *
  9. *******************************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <ctype.h>
  15.  
  16. #define MIN_LEVEL 4
  17. #define MAX_LEVEL 9
  18. #define SIZE 10
  19. //-----------------------------------------------------------------------------
  20.  
  21. //Estructuras necesarias para obtener y almacenar una combinacion de palabras válida
  22. typedef struct PALABRA{
  23.    char Palabra[SIZE];
  24.    int PosCaracterExtra;
  25. }Palabra;
  26.  
  27. typedef struct LISTA_PALABRAS{
  28.    Palabra *Palabras;
  29.    int nEncontradas;
  30. }ListaPalabras;
  31.  
  32. typedef struct COMBINACION{
  33.    Palabra cuatroLetras;
  34.    ListaPalabras cincoLetras;
  35.    ListaPalabras seisLetras;
  36.    ListaPalabras sieteLetras;
  37.    ListaPalabras ochoLetras;
  38.    ListaPalabras nueveLetras;
  39. }Combinacion;
  40. //-----------------------------------------------------------------------------
  41.  
  42. //Prototipos de funciones
  43. int SearchCombination(Palabra CombRes[6],char **palabra,int nElementos);
  44. int SearchFirstWord(char *nameFile,char *word);
  45. int SearchNextWords(char *word,int length,ListaPalabras *Lista);
  46. int ShowFirst(char *word);
  47. void ShowMask(char *word,int length,int posCharExtra,int nCaracteresAMostrar);
  48. void RandomCharsOfWord(char *word,char *result,int length);
  49. void EliminarPalabra(ListaPalabras *Lista,int pos);
  50. int ObtenerListaInicial(char *nameFile,char **palabra,int *nElementos);
  51. void BarajarListaInicial(char **lista,int nElementos);
  52. char** AsignarMemoriaLista(char *nameFile, int *nPalabras,int *Error);
  53. void LiberarMemoriaLista(char **lista, int nPalabras);
  54. void Jugar(char **lista,int nPalabras);
  55. //-----------------------------------------------------------------------------
  56.  
  57. int main()
  58. {
  59.    char **listaPalabras4Letras;
  60.    char nameFile[]="4_Letras.txt";
  61.    int Error,nPalabras;
  62.  
  63.    listaPalabras4Letras=AsignarMemoriaLista(nameFile,&nPalabras,&Error);
  64.  
  65.    switch(Error){
  66.       case 0:
  67.          srand(time(NULL));
  68.          ObtenerListaInicial(nameFile,listaPalabras4Letras,&nPalabras);
  69.          Jugar(listaPalabras4Letras,nPalabras);
  70.          printf("Gracias por haber jugado.\n");
  71.          system("PAUSE");
  72.       break;
  73.  
  74.       case -1:
  75.          printf("No se pudo abrir el archivo.\n");
  76.       break;
  77.  
  78.       case -2:
  79.          printf("No hay memoria suficiente.\n");
  80.       break;
  81.  
  82.       default:
  83.          printf("Error desconocido.\n");
  84.    }
  85.    return 0;
  86. }
  87. //-----------------------------------------------------------------------------
  88.  
  89. //Se encarga de ejecutar el juego
  90. void Jugar(char **lista,int nPalabras)
  91. {
  92.    char entrada[SIZE];
  93.    int largo,i,x,pistas=0,salir=0;
  94.    Palabra CombResult[6]={0};
  95.  
  96.    if(SearchCombination(CombResult,lista,nPalabras)){
  97.       srand(time(NULL));
  98.       ShowFirst(CombResult[0].Palabra);
  99.       largo=MIN_LEVEL;
  100.       i=0;
  101.  
  102.       do{
  103.          printf("Adivina la palabra: ");
  104.          scanf("%s",entrada);
  105.          for(x=0;x<strlen(entrada);x++)
  106.             entrada[x]=toupper(entrada[x]);
  107.          if(strcmp(entrada,"0")==0)
  108.             salir=1;
  109.          else if(strcmp(entrada,"1") == 0){
  110.             if((largo == MIN_LEVEL && pistas < largo) || (largo > MIN_LEVEL && pistas<largo-1))
  111.                pistas++;
  112.             ShowMask(CombResult[i].Palabra,largo,CombResult[i].PosCaracterExtra,pistas);
  113.          }else if(strcmp(CombResult[i].Palabra,entrada) != 0){
  114.             printf("Nooop\n");
  115.          }else{
  116.             pistas=0;
  117.             printf("Correcto!\n");
  118.             if(largo==MAX_LEVEL){
  119.                system("PAUSE");
  120.                system("CLS");
  121.                largo=MIN_LEVEL;
  122.                if(SearchCombination(&CombResult[0],lista,nPalabras)){
  123.                   i=0;
  124.                   ShowFirst(CombResult[i].Palabra);
  125.                }else{
  126.                   printf("Huvo un error al obtener la siguiente palabra. El programa finalizara.\n");
  127.                   break;
  128.                }
  129.             }else{
  130.                i++;
  131.                largo++;
  132.                printf("La siguiente es: ");
  133.                ShowMask(CombResult[i].Palabra,largo,CombResult[i].PosCaracterExtra,0);
  134.             }
  135.          }
  136.       }while(salir == 0);
  137.       LiberarMemoriaLista(lista,nPalabras);
  138.    }else{
  139.       printf("No existen combinaciones validas.\n");
  140.    }
  141. }
  142. //-----------------------------------------------------------------------------
  143.  
  144. //Asigna a un array bidimensional char** la memoria necesaria para almacenar todas las
  145. //palabras del archivo indicado y retorna la direccion del array
  146. char** AsignarMemoriaLista(char *nameFile, int *nPalabras,int *Error)
  147. {
  148.    FILE *archivo;
  149.    char **lista=NULL;
  150.    int i;
  151.  
  152.    archivo=fopen(nameFile,"r");
  153.  
  154.    if(archivo != NULL){
  155.       fseek(archivo,0,SEEK_END);
  156.       *nPalabras=ftell(archivo)/SIZE;
  157.       lista=(char**)malloc(*nPalabras*sizeof(char*));
  158.       if(lista != NULL){
  159.          for(i=0;i < *nPalabras;i++){
  160.             lista[i]=(char*)malloc(SIZE);
  161.             if(lista[i] == NULL)
  162.                break;
  163.          }
  164.          if(i!=*nPalabras){
  165.             *Error=-2;
  166.             LiberarMemoriaLista(lista,*nPalabras);
  167.          }else
  168.             *Error=0;
  169.       }else{
  170.          *Error=-2;
  171.       }
  172.    }else{
  173.       *Error=-1;
  174.    }
  175.    return lista;
  176. }
  177. //-----------------------------------------------------------------------------
  178.  
  179. //Libera la memoria que se reservó para meter las palabras del archivo en memoria
  180. void LiberarMemoriaLista(char **lista, int nPalabras)
  181. {
  182.    int i;
  183.  
  184.    for(i=0;lista[i]!=NULL && i < nPalabras;i++)
  185.       free(lista[i]);
  186.    free(lista);
  187. }
  188. //-----------------------------------------------------------------------------
  189.  
  190. //Baraja los punteros del array al azar para poder tenerlos desordenados
  191. void BarajarListaInicial(char **lista,int nElementos)
  192. {
  193.    int i,pos;
  194.    char *aux;
  195.  
  196.    for(i=0;i<nElementos;i++){
  197.       pos=rand()%nElementos;
  198.       aux=lista[i];
  199.       lista[i]=lista[pos];
  200.       lista[pos]=aux;
  201.    }
  202. }
  203. //-----------------------------------------------------------------------------
  204.  
  205. //Rellena el array bidimensional con todas las palabras del archivo indicado
  206. int ObtenerListaInicial(char *nameFile,char **palabra,int *nElementos)
  207. {
  208.    int i=0,retval,posPalabra;
  209.    FILE *archivo;
  210.  
  211.    archivo=fopen(nameFile,"r");
  212.    if(archivo != NULL){
  213.       do{
  214.          retval=fread(palabra[i],SIZE,1,archivo);
  215.          if(retval != 1)
  216.             break;
  217.          i++;
  218.       }while(!feof(archivo) && retval != 0);
  219.       if(i==*nElementos)
  220.          retval=1;
  221.       fclose(archivo);
  222.    }else{
  223.       retval=-1;
  224.    }
  225.    return retval;
  226. }

Funcionar funciona pero me gustaria que si pudieran echarle un vistazo y me dijeran si hago alguna burrada que no vea yo para corregirlo y asi aprendo algo mas.
Muchas gracias por toda la ayuda.

Última edición por aguml; 20/11/2015 a las 07:10
  #19 (permalink)  
Antiguo 20/11/2015, 07:12
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Y otras de las funciones que no me dejaba ponerlo todo junto porque es muy largo:
Código C:
Ver original
  1. //Busca una combinacion correcta y rellena con ella la estructura
  2. int SearchCombination(Palabra CombRes[6],char *palabra[SIZE],int nPalabras)
  3. {
  4.    char entrada[SIZE];
  5.    int posCaracterExtra;
  6.    int index=0,largo,encontrada=0;
  7.    int selCincoLetras,selSeisLetras,selSieteLetras,selOchoLetras,selNueveLetras;
  8.    Combinacion combinacion;
  9.  
  10.    BarajarListaInicial(palabra,nPalabras);
  11.  
  12.    do{
  13.       strcpy(combinacion.cuatroLetras.Palabra,palabra[index]);
  14.       combinacion.cincoLetras.nEncontradas=0;
  15.       combinacion.cincoLetras.Palabras=NULL;
  16.       combinacion.seisLetras.nEncontradas=0;
  17.       combinacion.seisLetras.Palabras=NULL;
  18.       combinacion.sieteLetras.nEncontradas=0;
  19.       combinacion.sieteLetras.Palabras=NULL;
  20.       combinacion.ochoLetras.nEncontradas=0;
  21.       combinacion.ochoLetras.Palabras=NULL;
  22.       combinacion.nueveLetras.nEncontradas=0;
  23.       combinacion.nueveLetras.Palabras=NULL;
  24.       largo=MIN_LEVEL;
  25.       if(SearchNextWords(combinacion.cuatroLetras.Palabra,largo,&combinacion.cincoLetras) > 0){
  26.          do{
  27.             selCincoLetras=rand()%combinacion.cincoLetras.nEncontradas;
  28.             largo=MIN_LEVEL+1;
  29.             if(SearchNextWords(combinacion.cincoLetras.Palabras[selCincoLetras].Palabra,largo,&combinacion.seisLetras) > 0){
  30.                do{
  31.                   selSeisLetras=rand()%combinacion.seisLetras.nEncontradas;
  32.                   largo=MIN_LEVEL+2;
  33.                   if(SearchNextWords(combinacion.seisLetras.Palabras[selSeisLetras].Palabra,largo,&combinacion.sieteLetras) > 0){
  34.                      do{
  35.                         selSieteLetras=rand()%combinacion.sieteLetras.nEncontradas;
  36.                         largo=MIN_LEVEL+3;
  37.                         if(SearchNextWords(combinacion.sieteLetras.Palabras[selSieteLetras].Palabra,largo,&combinacion.ochoLetras) > 0){
  38.                            do{
  39.                               selOchoLetras=rand()%combinacion.ochoLetras.nEncontradas;
  40.                               largo=MIN_LEVEL+4;
  41.                               if(SearchNextWords(combinacion.ochoLetras.Palabras[selOchoLetras].Palabra,largo,&combinacion.nueveLetras) > 0){
  42.                                  selNueveLetras=rand()%combinacion.nueveLetras.nEncontradas;
  43.                                  strcpy(CombRes[0].Palabra,combinacion.cuatroLetras.Palabra);
  44.                                  CombRes[0].PosCaracterExtra=-1;
  45.                                  strcpy(CombRes[1].Palabra,combinacion.cincoLetras.Palabras[selCincoLetras].Palabra);
  46.                                  CombRes[1].PosCaracterExtra=combinacion.cincoLetras.Palabras[selCincoLetras].PosCaracterExtra;
  47.                                  strcpy(CombRes[2].Palabra,combinacion.seisLetras.Palabras[selSeisLetras].Palabra);
  48.                                  CombRes[2].PosCaracterExtra=combinacion.seisLetras.Palabras[selSeisLetras].PosCaracterExtra;
  49.                                  strcpy(CombRes[3].Palabra,combinacion.sieteLetras.Palabras[selSieteLetras].Palabra);
  50.                                  CombRes[3].PosCaracterExtra=combinacion.sieteLetras.Palabras[selSieteLetras].PosCaracterExtra;
  51.                                  strcpy(CombRes[4].Palabra,combinacion.ochoLetras.Palabras[selOchoLetras].Palabra);
  52.                                  CombRes[4].PosCaracterExtra=combinacion.ochoLetras.Palabras[selOchoLetras].PosCaracterExtra;
  53.                                  strcpy(CombRes[5].Palabra,combinacion.nueveLetras.Palabras[selNueveLetras].Palabra);
  54.                                  CombRes[5].PosCaracterExtra=combinacion.nueveLetras.Palabras[selNueveLetras].PosCaracterExtra;
  55.                                  free(combinacion.nueveLetras.Palabras);
  56.                                  combinacion.nueveLetras.Palabras=NULL;
  57.                                  combinacion.nueveLetras.nEncontradas=0;
  58.                                  encontrada=1;
  59.                               }else{
  60.                                  EliminarPalabra(&combinacion.ochoLetras,selOchoLetras);
  61.                               }
  62.                            }while(encontrada == 0 &&combinacion.nueveLetras.nEncontradas < 1 && combinacion.ochoLetras.nEncontradas > 0);
  63.                            free(combinacion.ochoLetras.Palabras);
  64.                            combinacion.ochoLetras.Palabras=NULL;
  65.                            combinacion.ochoLetras.nEncontradas=0;
  66.                            if(encontrada==0)
  67.                               EliminarPalabra(&combinacion.sieteLetras,selSieteLetras);
  68.                         }else{
  69.                            EliminarPalabra(&combinacion.sieteLetras,selSieteLetras);
  70.                         }
  71.                      }while(encontrada == 0 && combinacion.ochoLetras.nEncontradas < 1 && combinacion.sieteLetras.nEncontradas > 0);
  72.                      free(combinacion.sieteLetras.Palabras);
  73.                      combinacion.sieteLetras.Palabras=NULL;
  74.                      combinacion.sieteLetras.nEncontradas=0;
  75.                      if(encontrada==0)
  76.                         EliminarPalabra(&combinacion.seisLetras,selSeisLetras);
  77.                   }else{
  78.                      EliminarPalabra(&combinacion.seisLetras,selSeisLetras);
  79.                   }
  80.                }while(encontrada == 0 && combinacion.sieteLetras.nEncontradas < 1 && combinacion.seisLetras.nEncontradas > 0);
  81.                free(combinacion.seisLetras.Palabras);
  82.                combinacion.seisLetras.Palabras=NULL;
  83.                combinacion.seisLetras.nEncontradas=0;
  84.                if(encontrada==0)
  85.                   EliminarPalabra(&combinacion.cincoLetras,selCincoLetras);
  86.             }else{
  87.                EliminarPalabra(&combinacion.cincoLetras,selCincoLetras);
  88.             }
  89.          }while(encontrada == 0 && combinacion.seisLetras.nEncontradas < 1 && combinacion.cincoLetras.nEncontradas > 0);
  90.          free(combinacion.cincoLetras.Palabras);
  91.          combinacion.cincoLetras.Palabras=NULL;
  92.          combinacion.cincoLetras.nEncontradas=0;
  93.       }
  94.       index++;
  95.    }while(encontrada == 0 && combinacion.cincoLetras.nEncontradas < 1 && index < nPalabras);
  96.    return encontrada;
  97. }
  98. //-----------------------------------------------------------------------------
  99.  
  100. //Realmente no elimina nada, lo que hace es colocar dicha palabra al final de la
  101. //lista indicada y decrementa el valor de la variable que indica el numero de
  102. //elementos para que deje de trabajar con dicha palabra
  103. void EliminarPalabra(ListaPalabras *Lista,int pos)
  104. {
  105.    int i;
  106.    if(pos < Lista->nEncontradas-1 && pos > 0)
  107.       for(i=Lista->nEncontradas-1;i>pos;i--)
  108.          memcpy(&Lista->Palabras[i-1],&Lista->Palabras[i],sizeof(Palabra));
  109.    if(Lista->nEncontradas > 0)
  110.       Lista->nEncontradas--;
  111. }
  112. //-----------------------------------------------------------------------------
  113.  
  114. //Muestra la primera palabra con sus caracteres desordenados
  115. int ShowFirst(char *word)
  116. {
  117.    char cadena[MIN_LEVEL+1];
  118.    char titulo[]="*  Juega a 'Adivina la palabra'  *";
  119.    char barra[]="**********************************";
  120.    int largoTitulo=strlen(titulo);
  121.    int centrado;
  122.  
  123.    centrado=(80-largoTitulo)/2;
  124.    printf("%*s\n",centrado+largoTitulo,barra);
  125.    printf("%*s\n",centrado+largoTitulo,titulo);
  126.    printf("%*s\n\n",centrado+largoTitulo,barra);
  127.    printf("Introduce '0' y pulsa intro para salir del juego en cualquier momento.\n");
  128.    printf("Introduce '1' y pulsa intro para obtener una ayuda.\n");
  129.    printf("======================================================================\n\n");
  130.  
  131.    do{
  132.       RandomCharsOfWord(word,cadena,MIN_LEVEL);
  133.    }while(strcmp(cadena,word)==0);
  134.  
  135.    printf ("La palabra desordenada es: %s\n",cadena);
  136.    return 0;
  137. }
  138. //-----------------------------------------------------------------------------
  139.  
  140. //Muestra la palabra enmascarada para que la adivinemos
  141. void ShowMask(char *word,int length,int posCharExtra,int nCaracteresAMostrar)
  142. {
  143.    int i;
  144.    for(i=0;i<length;i++)
  145.       if(i==posCharExtra)
  146.          printf("%c ",word[i]);
  147.       else if(nCaracteresAMostrar > 0){
  148.          printf("%c ",word[i]);
  149.          nCaracteresAMostrar--;
  150.       }else
  151.          printf("_ ");
  152.    printf("\n");
  153. }
  154. //-----------------------------------------------------------------------------
  155.  
  156. //Desordena la palabra indicada
  157. void RandomCharsOfWord(char *word,char *result,int length)
  158. {
  159.    int a,i,posRand;
  160.    char aux;
  161.  
  162.    strcpy(result,word);
  163.    for(a=0;a<length;a++){
  164.       for(i=0;i<length-(1+a);i++){
  165.          posRand=rand()%length;
  166.          aux=result[i];
  167.          result[i]=result[posRand];
  168.          result[posRand]=aux;
  169.       }
  170.    }
  171. }
  #20 (permalink)  
Antiguo 20/11/2015, 07:13
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

Y tercera y ultima parte:
Código C:
Ver original
  1. //-----------------------------------------------------------------------------
  2.  
  3. //Busca las palabras de length caracteres en la lista de palabras y las guarda en
  4. //la estructura indicada
  5. int SearchNextWords(char *word,int length,ListaPalabras *Lista)
  6. {
  7.    char cadena[SIZE],salida[SIZE];
  8.    char nameFile[13]={0};
  9.    char aux;
  10.    int a,i,contador,retval;
  11.    FILE *archivo;
  12.  
  13.    sprintf(nameFile,"%i_Letras.txt",length+1);
  14.    archivo=fopen(nameFile,"r");
  15.  
  16.    if(archivo != NULL){
  17.       if(Lista->nEncontradas !=0){
  18.          free(Lista->Palabras);
  19.          Lista->Palabras=NULL;
  20.          Lista->nEncontradas=0;
  21.       }
  22.       do{
  23.          retval=fread(cadena,SIZE,1,archivo);
  24.          strcpy(salida,cadena);
  25.          contador=length;
  26.          for(a=0;a<length;a++){
  27.             for(i=0;i<=contador;i++){
  28.                if(word[a]==cadena[i])
  29.                {
  30.                   aux=cadena[i];
  31.                   cadena[i]=cadena[contador];
  32.                   cadena[contador]=aux;
  33.                   contador--;
  34.                   break;
  35.                }
  36.             }
  37.          }
  38.          if(contador==0){
  39.             Lista->nEncontradas++;
  40.             Lista->Palabras = realloc(Lista->Palabras,Lista->nEncontradas*sizeof(Palabra));
  41.             strcpy(Lista->Palabras[Lista->nEncontradas-1].Palabra,salida);
  42.             Lista->Palabras[Lista->nEncontradas-1].PosCaracterExtra=(int)strchr(Lista->Palabras[Lista->nEncontradas-1].Palabra,cadena[0])-(int)Lista->Palabras[Lista->nEncontradas-1].Palabra;
  43.          }
  44.       }while(!feof(archivo));
  45.       retval=Lista->nEncontradas;
  46.       fclose(archivo);
  47.    }else{
  48.       retval=-1;
  49.    }
  50.    return retval;
  51. }
  52. //-----------------------------------------------------------------------------
  53.  
  54. //Elije una palabra al azar del archivo elegido
  55. int SearchFirstWord(char *nameFile,char *word)
  56. {
  57.    int retval,nPalabras,posPalabra;
  58.    FILE *archivo;
  59.    char palabra[SIZE];
  60.  
  61.    archivo=fopen(nameFile,"r");
  62.    if(archivo != NULL){
  63.       fseek(archivo,0,SEEK_END);
  64.       nPalabras=ftell(archivo)/SIZE;
  65.       posPalabra=rand()%nPalabras;
  66.       fseek(archivo,posPalabra*SIZE,SEEK_SET);
  67.       retval=fread(palabra,SIZE,1,archivo);
  68.       if(retval==1)
  69.          strcpy(word,palabra);
  70.       fclose(archivo);
  71.    }else{
  72.       retval=-1;
  73.    }
  74.    return retval;
  75. }
  #21 (permalink)  
Antiguo 21/11/2015, 13:15
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

Pues a ver, yo cambiaría varias cosas... algunas ya te las he comentado en mensajes anteriores:

precarga de todas las palabras antes de empezar el juego
La manipulación de datos en memoria es más rápido y más sencillo que leer constantemente desde ficheros.

almacenamiento de las palabras en una lista enlazada circular.

Una lista enlazada circular es una lista enlazada normal y corriente pero, al añadir el último elemento, haces que su sig apunte al primer elemento. De esta forma consigues que la lista "no tenga fín", lo que te permite recorrerla hacia delante sin miedo a acceder a punteros no válidos.

Para liberar la memoria coges un elemento cualquiera, digamos A y te quedas con su posición y con la del siguiente, B. Después haces A->sig=0. Finalmente, coges B y liberas la memoria como si de una lista enlazada normal se tratase.

Funciones más pequeñas

Sin tener en cuenta lo anterior, la función SearchNextWords se puede dividir sin problemas en dos funciones independientes... una que lea el fichero y otra que verifique si la palabra leída es válida. Funciones más pequeñas = código más sencillo de probar.

Elegir cuando liberar la memoria

Si en SearchNextWords liberas la memoria de Lista->Palabras... ¿qué sentido tiene hacer después un realloc o, dicho al revés... si vas a hacer un realloc... tiene sentido hacer un free??

Sugerencia:

Lo de usar listas enlazadas también podrías aplicarlo a otros conceptos.

Podrías, por ejemplo, hacer que la función que te saca el listado de palabras válidas cogiese la lista enlazada de palabras con n+1 letras y la palabra de n letras... entonces crea una nueva lista enlazada en la que se encuentra una copia de las palabras que encajen con los requisitos del juego... así puedes reutilizar la lista inicial de palabras entre juegos.

Si además haces que la lista de palabras válidas sea también circular... elegir una puede ser tan sencillo como elegir un número al azar y avanzar ese número de posiciones... total, no te vas a salir de la lista por mucho que avances.

No se, son algunas sugerencias... para darte más tendría que analizar el código a fondo y ahora mismo no tengo el tiempo necesario para ello.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #22 (permalink)  
Antiguo 22/11/2015, 03:59
 
Fecha de Ingreso: febrero-2015
Mensajes: 404
Antigüedad: 9 años, 2 meses
Puntos: 3
Respuesta: problema con juego de palabras

La verdad es que no entiendo muy bien todo lo que dices. Me vendría muy bien algún ejemplo de código para cada cosa que sugieres aunque no tenga nada que ver con mi código para entender lo que intentas decirme. Creo entender que debería crear todas las combinaciones válidas antes del juego y crear una lista enlazada circular con ellas. El problema es que mi pc es prehistórico y tener que hacer eso se demorará bastante ya que cada archivo puede tener más de 10000 palabras y pueden ser muchísimas combinaciones válidas. Otra cosa sería crearme un archivo con todos los resultados válidos y luego solo tendría que usar dicho archivo el cual si que seria más viable e incluso ahorrar memoria porque sería más sencillo de leer en un ucle con scanf.
  #23 (permalink)  
Antiguo 22/11/2015, 05:20
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: problema con juego de palabras

Si puedo, esta tarde o mañana te pongo algún ejemplo.

En cuanto al rendimiento... 10k palabras*10B por palabra*6 tipos~600k B ~ 585KB de memoria.

Como ves, el consumo de memoria no es excesivo y las operaciones en memoria son mucho más rápidas que las operaciones sobre ficheros.

Lo dicho, cuando pueda te pongo algún ejemplo.

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.

Etiquetas: cadena, char, funcion, int, juego, palabras, programa, string
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 10:45.