elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: Estamos en la red social de Mastodon


  Mostrar Mensajes
Páginas: 1 ... 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 [48] 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ... 102
471  Programación / Programación C/C++ / Re: Juego del gato usuario vs maquina con srand en: 1 Noviembre 2019, 21:11 pm
Si de verdad me estás diciendo que tu profesor no te deja aplicar ninguno de los consejos y que por ende te está enseñando/obligando a no usar constantes, usar variables globales, repetir código, escribir código innecesario y no organizarlo en funciones... Siento decirte que tienes un pésimo profesor.

Pero bueno, tu duda era cómo generar un valor aleatorio para la máquina y en la función <elegirPosicion()> te he mostrado cómo hacerlo. Así que no sé si tienes alguna duda más.
472  Programación / Programación C/C++ / Re: Alguna manera de saber si un numero es narcisista sin utilizar el pow? en: 1 Noviembre 2019, 21:03 pm
Antes de nada, los códigos entre etiquetas de Código GeSHi.
Lo único que tienes que hacer es usar un bucle para "simular" la función <pow()>. Como la función <pow()> lo que hace es elevar la base a una potencia y las potencias no son otra cosa que sucesivos productos, lo que al final te piden es que calcules la potencia de un número usando un bucle que multiplique ese número x veces.
En pseudocódigo tu solución quedaría así:
Código:
INICIO
    PEDIR numero
    digitos[LONGITUD_MAXIMA] // array de longitud igual al maximo numero de digitos que puede tener el numero
    numeroDigitos := calcularDigitos(numero, digitos)

    sumaTotal := 0
    PARA i := 0 HASTA numeroDigitos-1 HACER
        resultadoPotencia := 1
        PARA j := 0 HASTA numeroDigitos-1 HACER // Este es el bucle que simula la potencia
            resultadoPotencia := resultadoPotencia * digitos[i]
        FIN PARA
        sumaTotal := sumaTotal + resultadoPotencia
    FIN PARA

    SI sumaTotal == numero ENTONCES
        MOSTRAR "El numero es narcisista"
    SINO ENTONCES
        MOSTRAR "El numero no es narcisista"
    FIN SI
FIN
Ahora te queda a ti ver cómo sería la función <calcularDigitos()> ya que no existe de manera predefinida y cómo traducir este pseudocódigo a C++. Bueno... Y lo más importante: entender el procedimiento.
473  Programación / Programación C/C++ / Re: Juego del gato usuario vs maquina con srand en: 1 Noviembre 2019, 17:33 pm
Código
  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<windows.h>
  4. #include<conio.h>
  5.  
  6. int tablero[3][3];
  7. int col, fila;
  8. int modo, ban;
  9. int win;
  10. int pos;
  11. int player;
  12.  
  13. void gotoxy(int x,int y){
  14.    HANDLE hcon;
  15.    hcon = GetStdHandle(STD_OUTPUT_HANDLE);
  16.    COORD dwPos;
  17.    dwPos.X = x;
  18.    dwPos.Y= y;
  19.    SetConsoleCursorPosition(hcon,dwPos);
  20. }
  21.  
  22. void escenario(){
  23.    gotoxy(33,2); printf("#############");
  24.    gotoxy(33,3); printf("# 1 # 2 # 3 #"); //35,3 39,3 43,3
  25.    gotoxy(33,4); printf("#############");
  26.    gotoxy(33,5); printf("# 4 # 5 # 6 #"); //35,5 39,5 43,5
  27.    gotoxy(33,6); printf("#############");
  28.    gotoxy(33,7); printf("# 7 # 8 # 9 #"); //35,7 39,7 43,7
  29.    gotoxy(33,8); printf("#############");
  30.  
  31.    gotoxy(33,10); printf("#############");
  32.    gotoxy(33,11); printf("#   #   #   #"); //35,11 39,11 43,11
  33.    gotoxy(33,12); printf("#############");
  34.    gotoxy(33,13); printf("#   #   #   #"); //35,13 39,13 43,13
  35.    gotoxy(33,14); printf("#############");
  36.    gotoxy(33,15); printf("#   #   #   #"); //35,15 39,15 43,15
  37.    gotoxy(33,16); printf("#############");
  38. }
  39.  
  40.  
  41. main(){
  42.    for(col=0; col<3; col++){
  43.        for(fila=0; fila<3; fila++){
  44.            tablero[col][fila]=5;
  45.        }
  46.    }
  47.  
  48.    do{
  49.        system("cls");
  50.        printf("El juego del Gato\n");
  51.        ban=0;
  52.        gotoxy(1,18);printf("Elija la modalidad de juego: 1 Usuario1 vs Usuario2 - 2 Usuario vs Maquina");
  53.        gotoxy(1,19);printf("Modalidad: ");
  54.        scanf("%d",&modo);
  55.        if(modo == 1){
  56.            ban=1;
  57.            if(modo==1){
  58.                gotoxy(1,20);printf("Usuario1 <<X>> vs Maquina <<O>>");
  59.                escenario();
  60.                win=0;
  61.                player=1;
  62.            }
  63.            do{
  64.                gotoxy(1,21); printf("En que cuadro quiere tirar: ");
  65.                scanf("%d",&pos);
  66.                if(pos>=1 && pos<=9){
  67.                    switch(pos){
  68.                        case 1:
  69.                            if(tablero[0][0]==5){
  70.                                if(player==1){
  71.                                    tablero[0][0]=1;
  72.                                    player=2;
  73.                                    gotoxy(35,11);printf("%d",tablero[0][0]);
  74.                                }
  75.                                else{
  76.                                    tablero[0][0]=0;
  77.                                    player=1;
  78.                                    gotoxy(35,11);printf("%d",tablero[0][0]);
  79.                                }
  80.                            }
  81.                            else{
  82.                                printf("La Casilla ya esta ocupada, intente de nuevo");
  83.                            }
  84.                            break;
  85.  
  86.                        case 2:
  87.                            if(tablero[0][1]==5){
  88.                                if(player==1){
  89.                                    tablero[0][1]=1;
  90.                                    player=2;
  91.                                    gotoxy(39,11);printf("%d",tablero[0][1]);
  92.                                }
  93.                                else{
  94.                                    tablero[0][1]=0;
  95.                                    player=1;
  96.                                    gotoxy(39,11);printf("%d",tablero[0][1]);
  97.                                }
  98.                            }
  99.                            else{
  100.                                printf("La Casilla ya esta ocupada, intente de nuevo");
  101.                            }
  102.                            break;
  103.                    }
  104.                }
  105.  
  106.            }while(win!=1);
  107.  
  108.        }
  109.        else{
  110.            printf("La Opcion Seleccionada es Erronia intente nuevamente");
  111.        }
  112.  
  113.        getch();
  114.    }while(ban!=1);
  115.    getch();
  116. }
Esto era lo que estaba pidiendo que hicieras para poder leer tu código porque sino es realmente imposible saber hasta donde llega cada llave...

Deberías usar funciones y usar variables locales. Las variables globales hacen a los programas inconsistentes... Para algo existen los parámetros a funciones. Además si te das cuenta:
  • Las líneas 55y 57 son lo mismo. Si entra en el primer <if> obviamente entrará en el segundo también.
  • No sé cuál es la utilidad de la variable <ban>.
  • La línea 66 no es necesaria ya que puedes hacer el <switch> del 1 al 9 y un caso <default> para cualquier otro caso.
  • No utilices números mágicos (es decir, número literales como para el tamaño de la matriz o los bucles for). Es mejor crear unas constantes por ejemplo así:
Código
  1. #define TAM_COLS 3
  2. #define TAM_FILAS 3
  • En vez de inicializar toda la matriz a 5 (que entiendo que es un número al azar) sería mejor inicializarla a 0 y usar el 1 para el primer jugador y el 2 para el segundo.
  • Cada <case> es prácticamente igual al resto y ocupa 15 líneas. Agrupar código en una función te ahorrará bastante.


Yo haría lo siguiente: inicializar el tablero a 0, usar la variable <jugador> con valor {1,2} para determinar el jugador en cada momento, la variable <modo> con valor {1,2} para determinar 2 jugadores o 1 jugador vs máquina, respectivamente; y la variable <ganador> con valor {0,1,2} para representar ningún ganador, el primer jugador gana o el segundo jugador gana, respectivamente.

El programa general sería algo así:
Código
  1. // librerias
  2.  
  3. #define TAM_FILA 3
  4. #define TAM_COL 3
  5.  
  6. // prototipos de funciones
  7. // es mejor poner los prototipos antes del main y las funciones despues del main. Tambien se pueden poner las funciones completas antes del main
  8.  
  9. int main(){ // la funcion main es de tipo int. Es mejor ponerlo siempre
  10.    int tablero[TAM_FILA][TAM_COL]; // tablero del juego
  11.    int jugador = 1; // indica el jugador actual (por defecto el 1). valores = {1,2}
  12.    int modo; // indica el modo de juego. valores = {1,2}
  13.    int ganador = 0; // indica el ganador. valores = {0,1,2}
  14.  
  15.    inicializarTablero(tablero, 0);
  16.  
  17.    modo = elegirModo();
  18.  
  19.    while(!ganador && !tableroCompleto(tablero)){
  20.        posicion = elegirPosicion(tablero, jugador, modo);
  21.        actualizarTablero(tablero, jugador, posicion);
  22.        ganador = comprobarGanador(tablero);
  23.        jugador = (jugador + 1) % jugador; // intercambia el jugador de 1 a 2 y de 2 a 1
  24.    }
  25.  
  26.    if(ganador)
  27.        printf("Jugador %d gana!!", ganador);
  28.    else
  29.        printf("Empate...");
  30. }

Un código limpio, corto y sencillo... que con leer el <main> ya sabes lo que hace el programa. Si luego quieres ver cómo funciona una parte específica o quieres cambiar alguna parte, sólo tienes que ir a la función correspondiente.

Con esto claro puedes hacer una función como esta para que un jugador elija una posición VÁLIDA del tablero:
Código
  1. // como la variable tablero deberia ser declarada dentro del main, tendras que pasarla como parametro:
  2. int elegirPosicion(int tablero[][TAM_COLS], int jugador, int modo){
  3.    do{
  4.        if(jugador == 2 && modo == 2) // si le toca a la maquina...
  5.            posicion = 1 + rand() % (TAM_FILA * TAM_COL); // calcula una posicion aleatoria
  6.        else{
  7.            printf("Elige una posicion valida [%d, %d]: ", 1, TAM_FILA * TAM_COL);
  8.            scanf("%d", posicion);
  9.        }
  10.        int fila = (posicion - 1) / TAM_COL; // calculas la fila segun la posicion
  11.        int col = (posicion - 1) % TAM_COL; // calculas la columna segun la posicion
  12.    }  while(fila >= TAM_FILA || col >= TAM_COL || tablero[fila][col]); // la tercera expresion solo funciona si inicializas la matriz a 0 como dije antes
  13.    return posicion;
  14. }

El resto de funciones te las dejo a ti que yo creo que con esto ya te he hecho bastante. Te dejo como guía lo que debería hacer cada función:
Código
  1. // Poner todas las casillas del tablero con el valor <valor>
  2. void inicializarTablero(int tablero[][TAM_COL], int valor);
  3.  
  4. // Mostrar los modos, hacer un filtro para que el modo sea valido y devolverlo cuando lo sea
  5. int elegirModo();
  6.  
  7. // En la funcion <elegirPosicion(...) ya hemos comprobado que la casilla no este ocupada por lo que aqui
  8. // solo tienes que calcular la fila y columna correspondiente y asignarle el valor <jugador>
  9. void actualizarTablero(int tablero[][TAM_COL], int jugador, int posicion);
  10.  
  11. // Recorrer todo el tablero mientras no encuentres un 0 (valor por defecto de las casillas)
  12. // Si encuentras un 0 devuelves el 0 y si no devuelves un numero distinto de 0 (la opcion habitual es 1 para asemejarlo a un true/false).
  13. int tableroCompleto(tablero);
  14.  
  15. // Recorrer todo el tablero. Devolver el numero del jugador que ha ganado y si ninguno ha ganado, devolver un 0.
  16. int comprobarGanador(tablero)
474  Programación / Programación C/C++ / Re: Clase pila estática en: 31 Octubre 2019, 14:06 pm
Siempre que los objetos que se pasan como parámetro no se van a modificar es recomendable pasarlos constantes para asegurar que pase lo que pase no se va a modificar (como decirle al compilador "no me dejes modificar este objeto ni por error") y por referencia para que así se pase la dirección de memoria del objeto original y no se cree una copia local (ya que si no se pasa por referencia, se pasa por valor y entonces lo que se hace es crear una copia del objeto con su consiguiente gasto de memoria).
475  Programación / Programación C/C++ / Re: Clase pila estática en: 31 Octubre 2019, 13:41 pm
El constructor de copia tiene un problema y es que le asignas 10 a <max> en vez de asignarle <p.max> ya que la longitud del nuevo tiene que ser la misma que la del que copias.
Y la función <Copiar()> tiene otro problema y es que estás incrementando <cima> pero en ningún momento la pones a -1 antes de empezar a incrementar y tampoco actualizas el valor de <max>. Además como ya no estás usando las funciones <Apilar()> y <Desapilar()> en la función <Copiar()> (y por tanto ya no estás modificando la original) ahora sí puedes (y debes) pasar el parámetro constante y por referencia.
476  Programación / Programación C/C++ / Re: MATRICES en: 31 Octubre 2019, 00:15 am
Lo que estás haciendo es generar dos números aleatorios: el primero en el intervalo [0,4] para la i y el segundo en el intervalo [0,9] para la j.
Luego estás haciendo un bucle para recorrer toda la matriz (empezando i y j en 0 por lo que los valores aleatorios ya los has perdido) y estás asignando una "E" a cada casilla de la matriz.

Como lo que quieres es generar 3 posiciones aleatorias y supongo que no sirve que la misma posición se repita 3 veces, deberás primero generar un valor aleatorio para i y para j, poner una "E" en esa posición y después volver a generar un valor aleatorio para cada variable y comprobar que esa posición no tenga ya una "E".

Lo primero: si no asignas ningún valor a la matriz te saldrá "basura" es decir caracteres aleatorios. Lo mejor es que inicialices toda la matriz con el mismo carácter (el que prefieras... un 0, un -, un *,... lo único importante es que sea un carácter, es decir, entre comillas simples y que no sea la E lógicamente).

Después de eso puedes hacer un bucle que se repita mientras no se hayan generado 3 posiciones aleatorias diferentes. Y eso cómo se sabe? Bueno pues en pseudocódigo sería algo así (el pseudocódigo no es lenguaje C, sirve para que entiendas el proceso que has de seguir pero una vez que lo entiendas debes implementar el mismo comportamiento en C).
Código:
INICIO
    MIENTRAS posicionesGeneradas < 3 HACER
        i := generarAleatorio(0,4) // creas una i aleatoria entre 0 y 4
        j := generarAleatorio(0,9) // creas una j aleatoria entre 0 y 9
        SI matriz[i][j] != 'E' ENTONCES // si esa posicion aleatoria no tiene una E...
            matriz[i][j] = 'E' // se la pones
            posicionesGeneradas := posicionesGeneradas + 1 // e incrementas el numero de posiciones en las que ya has puesto una E
        FIN SI
    FIN MIENTRAS
FIN
De esta manera si se genera una i y una j aleatorias pero ya habías asignado una 'E' ahí, no cuenta entonces y vuelve a calcularlo otra vez hasta que tengas 3 posiciones de la matriz con una 'E'.

EDIT: Repito, lo que está escrito en pseudocódigo no funciona si lo copias y lo pegas tal cual. La función <generarAleatorio(0,4)> por ejemplo no existe en C. Es para que entiendas lo que tienes que hacer y luego lo hagas como se hace en C (que en este caso es usando <rand() % 5>.
477  Programación / Programación C/C++ / Re: Clase pila estática en: 30 Octubre 2019, 22:52 pm
Bueno, a ver. Lo primero es que en la imagen estás usando un constructor de Pila que recibe un parámetro (int) y ese constructor no sé qué hace por lo que supondré que el parámetro es el tamaño de la pila y el constructor sin parámetros pone un tamaño estándar de 3.

Los <new> y los <delete> no se usan a lo loco pensando "así me aseguro de que hay espacio reservado", no. Tienes que saber cuando hay espacio reservado y cuando no, reservar la memoria justa y necesaria y liberarla correctamente.

Los constructores son las funciones que llaman los objetos cuando se crean. Estos objetos como justo se están creando no tienen nada todavía por lo que sí necesitas reservar memoria. El de por defecto está bien, el de con parámetros supondré que también pero el de copia no. Cuando creas una instancia con el constructor de copia, no le estás asignando espacio.
Código
  1. Pila miPila1(5); // sigo suponiendo que esto es una pila de longitud 5
  2. Pila miPila2(miPila1); // miPila2 no tiene memoria reservada para el array interno

El destructor como bien dices debe liberar la memoria de esa Pila. Y es más, no necesitas <Vaciar()> la Pila; con liberar la memoria reservada sería suficiente.

La función <Copiar()> no está bien. Esa función la usarás siempre sobre instancias que has creado antes por lo que ya tienen memoria reservada. La duda es: tendrá el mismo tamaño la Pila sobre la que copias que la Pila que copias? Es algo que no puedes asegurar si puedes crear Pilas de distintos tamaños por lo que lo que tendrías que hacer es liberar la memoria de la que quieres copiar y asignarle la misma longitud que a la otra nuevamente (pero sin olvidar primero liberar la memoria que ya tenía).
Código
  1. Pila pilaTam5(5); // se reserva memoria para 5 elementos
  2. Pila pilaTam10(10); // se reserva memoria para 10 elementos
  3. pilaTam5.Copiar(pilaTam10); // la funcion Copiar() tiene que borrar la memoria para 5 elementos y crear nueva memoria para 10

El operador = está bien ya que haces lo que te digo para la función <Copiar()> pero claro, lo de borrar la memoria que tenía y crear memoria nueva... una de dos, o lo haces dentro de la función <Copiar()> o lo haces fuera pero no lo hagas dos veces.



EDIT: Si las funciones <Altura()> y <Altura2()> son para mostrar el tamaño de la Pila, no tiene sentido que las hagas externas a la clase y reciban la Pila como parámetro. Es mejor que las hagas dentro de la clase y que no crees dos funciones diferentes para lo mismo.
478  Programación / Programación C/C++ / Re: Juego del gato usuario vs maquina con srand en: 30 Octubre 2019, 16:54 pm
Si quieres recibir ayuda de alguien, pónselo un poco más fácil a quien te intente ayudar...
Es un código bastante grande, la tabulación está regular y sin resaltado de sintaxis (en la etiqueta de apertura de code puedes poner "=c" o "=cpp" sin comillas para que se resalte la sintaxis de C o de C++ o directamente elegir el lenguaje del desplegable "Código GeSHi"). Además no especificas nada de tu problema. Obligas a quien te quiera ayudar a leerse el código entero... y te aseguro que no es para nada apetecible.
479  Programación / Programación C/C++ / Re: Clase pila estática en: 30 Octubre 2019, 16:47 pm
Te recomiendo cuando pongas un código en el que tienes problemas que lo copies del original. No sería la primera vez que el código está mal escrito, al escribirlo aquí se escribe bien y es imposible detectar el error.
Aunque en este caso veo un par de problemas:
  • Si en el constructor asignas siempre un tamaño de 3 al array que usas como contenedor para la pila, es mejor que directamente lo hagas de forma estática (v[MAX]) en vez de usar un puntero y asignarlo de forma dinámica (te ahorrarás de tener que liberar la memoria dinámica manualmente cosa que parece que no haces).
  • En el constructor reservas memoria para el array pero... y en el constructor de copia?? En ningún momento estás reservando memoria. Tienes que pensar qué estado tendrá un objeto cuando llama a una función. En el caso de los constructores, son objetos que todavía no se han creado (se crean con el constructor) entonces todavía no tienen memoria reservada. Aprovecho para decirte que pienses cómo debería funcionar la función <Copiar()> (si debería reservar memoria o no).
  • La función <Cimapila()> no funciona bien. Estás perdiendo el valor del tope y devolviendo un valor basura.
480  Programación / Programación C/C++ / Re: Clase pila estática en: 30 Octubre 2019, 02:24 am
Muchas gracias. No había pensado que podía usar las funciones sobre el propio objeto, muchas horas delante de esto xD.
Esa es precisamente la utilidad de las funciones miembro de una clase: actuar sobre el objeto/instancia que las llama de forma implícita.

Vengo con la última duda, pensaba que había acabado pero no :(. He intentado hacer la sobrecarga del operador =. Tengo esto:

Código:
const Pila& Pila::operator= (const Pila & p)
{
    Vaciar(); //vacía la pila objeto
    Copiar(p); //copia la p en la pila objeto.
    Return p;
}

Creo que está bien, pero al compilar la línea p = p2 (siendo p una pila llena con valores {1...4} y p2 una pila vacía), salta el error "exited, segmentation fault".
Es mejor que añadas también el código de las funciones que intervengan en todo el proceso de alguna manera u otra para saber dónde está el fallo exactamente.
Además ten cuidado con las mayúsculas. Suele ser habitual usar la nomenglatura UpperCamelCase (que como se nota en el nombre, cada palabra empieza por mayúscula, para designar clases) y la nomenglatura lowerCamelCase (todas las palabras empiezan por mayúscula menos la primera) para funciones. Esto es una convención, no son reglas estrictas pero en el caso del <return> si es necesario ya que C++ es un lenguaje sensible a mayúsculas y minúsculas (no es lo mismo escribir una palabra usando mayúsculas que minúsculas).
Páginas: 1 ... 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 [48] 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 ... 102
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines