| |||
Juego 4 en raya Hola a todos estoy haciendo el juego del 4 en raya y a la hora de sacar el ganador no me funciona bien porque creo que al estar sumando filas y columnas me estoy saliendo de la matriz de enteros. Estoy usando Qt designer C++ para hacer la interfaz del juego. Si alguien puede ayudarme con el método Ganado(); para sacar las horizontales, verticales y diagonales le estaría muy agradecido. Adjunto el enunciado y el programa por partes ya que esta dividido en ficheros: ENUNCIADO: En este ejercicio vamos a implementar el conocido juego de las 4 en raya o conecta 4. El programa arrancará con un panel de 6x7 vacío, informando que es el turno de las piezas rojas. Cuando tire el primer jugador (pinchando con el ratón en alguno de los botones azules) se colocará la ficha en la columna correspondiente y dará el turno al segundo jugador (piezas amarillas). En cualquier momento se podrá reiniciar la partida (segundo botón), salir, o mostrar el Acerca de (About) de la aplicación. El programa controlará que no se tira sobre una columna llena y también comprobará tras cada jugada si ha ganado alguno de los jugadores o han quedado empates (Figura 2). Cuando algún jugador gane o queden en tablas informaremos al usuario y la partida se reiniciará (borraremos el tablero y será el turno de las rojas de nuevo). CÓDIGO: <mainwindow.h> ----------------------------------------------------------------------------------------------- #ifndef MAINWINDOW_H #define MAINWINDOW_H #include <QMainWindow> #include <QPushButton> #include<iostream> using namespace std; namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void on_actionSalir_triggered(); void on_actionAcerca_de_triggered(); void on_pushButton_7_clicked(); void on_pushButton_9_clicked(); void on_pushButton_11_clicked(); void on_pushButton_13_clicked(); void on_pushButton_15_clicked(); void on_pushButton_17_clicked(); void on_pushButton_19_clicked(); void on_actionNuevo_Juego_triggered(); void BotonPulsado(int columna); void Ganado(int fila,int columna,int ficha); private: //declaracion de los atributos necesarios para nuestro codigo. Ui::MainWindow *ui; QPushButton *M[6][7]; int V[7]; int Mint[6][7]; bool turno; bool ganadorojas; bool ganadoamar; }; #endif // MAINWINDOW_H ---------------------------------------------------------------------------------------------- <main.cpp> #include "mainwindow.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; w.show(); return a.exec(); } --------------------------------------------------------------------------------------------- <mainwindow.cpp> #include "mainwindow.h" #include "ui_mainwindow.h" //librerias para las distinas opciones #include <QMessageBox> #include <QPushButton> #include <QIcon> #include <QPixmap> //Constructor de la ventana principal MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { //Inicializacion de la ventana. ui->setupUi(this); //Asignacion de los botones a las distintas posiciones de la matriz. M[0][0] = ui->pushButton_8; M[0][1] = ui->pushButton_10; M[0][2] = ui->pushButton_12; M[0][3] = ui->pushButton_14; M[0][4] = ui->pushButton_16; M[0][5] = ui->pushButton_18; M[0][6] = ui->pushButton_20; M[1][0] = ui->pushButton_21; M[1][1] = ui->pushButton_22; M[1][2] = ui->pushButton_23; M[1][3] = ui->pushButton_24; M[1][4] = ui->pushButton_25; M[1][5] = ui->pushButton_26; M[1][6] = ui->pushButton_27; M[2][0] = ui->pushButton_28; M[2][1] = ui->pushButton_29; M[2][2] = ui->pushButton_30; M[2][3] = ui->pushButton_31; M[2][4] = ui->pushButton_32; M[2][5] = ui->pushButton_33; M[2][6] = ui->pushButton_34; M[3][0] = ui->pushButton_35; M[3][1] = ui->pushButton_36; M[3][2] = ui->pushButton_37; M[3][3] = ui->pushButton_38; M[3][4] = ui->pushButton_39; M[3][5] = ui->pushButton_40; M[3][6] = ui->pushButton_41; M[4][0] = ui->pushButton_42; M[4][1] = ui->pushButton_43; M[4][2] = ui->pushButton_44; M[4][3] = ui->pushButton_45; M[4][4] = ui->pushButton_46; M[4][5] = ui->pushButton_47; M[4][6] = ui->pushButton_48; M[5][0] = ui->pushButton_49; M[5][1] = ui->pushButton_50; M[5][2] = ui->pushButton_51; M[5][3] = ui->pushButton_52; M[5][4] = ui->pushButton_53; M[5][5] = ui->pushButton_54; M[5][6] = ui->pushButton_55; for(int i=0;i<7;i++){ V=0; } for(int j=0;j<6;j++){ for(int k=0;k<7;k++){ Mint[j][k]=0; } } turno=true; ganadorojas=false; ganadoamar=false; } //Destructor MainWindow::~MainWindow() { delete ui; } //funcion salir triggered void MainWindow::on_actionSalir_triggered() { close(); } //funcion acerca de triggered void MainWindow::on_actionAcerca_de_triggered() { QMessageBox::information(this,"Acerca del Juego","Realizado por Alvaro Garrido Tafalla y Jorge Medina Carbonell","Aceptar"); } //funcion reiniciar juego triggered void MainWindow::on_actionNuevo_Juego_triggered() { for(int i=0;i<6;i++){ for(int j=0;j<7;j++){ M[j]->setIcon(QIcon(":/Iconos/Material ejercicio 1/circle_grey.png")); Mint[j]=0; } } for(int i=0;i<7;i++){ V=0; } turno=true; ganadorojas=false; ganadoamar=false; ui->label->setText("Turno de las rojas"); } //Funciones clicked de cada boton del panel, que llaman a la funcion BotonPulsado void MainWindow::on_pushButton_7_clicked() { BotonPulsado(0); } void MainWindow::on_pushButton_9_clicked() { BotonPulsado(1); } void MainWindow::on_pushButton_11_clicked() { BotonPulsado(2); } void MainWindow::on_pushButton_13_clicked() { BotonPulsado(3); } void MainWindow::on_pushButton_15_clicked() { BotonPulsado(4); } void MainWindow::on_pushButton_17_clicked() { BotonPulsado(5); } void MainWindow::on_pushButton_19_clicked() { BotonPulsado(6); } //funcion BotonPulsado que permite cambir el icono de los botones. void MainWindow::BotonPulsado(int columna){ if(V[columna]<6){//comprueba que no se tira sobre una columna llena int pos=5-V[columna]; V[columna]=V[columna]+1; if(turno==true){ M[pos][columna]->setIcon(QIcon(":/Iconos/Material ejercicio 1/circle_red.png")); Mint[pos][columna]=1; turno=false; ui->label->setText("Turno de las amarillas"); Ganado(pos,columna,1); }else{ M[pos][columna]->setIcon(QIcon(":/Iconos/Material ejercicio 1/circle_yellow.png")); Mint[pos][columna]=2; turno=true; ui->label->setText("Turno de las rojas"); Ganado(pos,columna,2); } } } //Ganado void MainWindow::Ganado(int fila,int columna,int ficha){ //horizontales int cont=1; if(Mint[fila][columna-1]==ficha || Mint[fila][columna+1]==ficha){ cont++; if(Mint[fila][columna-2]==ficha || Mint[fila][columna+2]==ficha){ cont++; if(Mint[fila][columna-3]==ficha || Mint[fila][columna+3]==ficha){ cont++; if(ficha==1 && cont==4){ ganadorojas=true; }else{ ganadoamar=true; } } } } //verticales if(Mint[fila-1][columna]==ficha || Mint[fila+1][columna]==ficha){ if(Mint[fila-2][columna]==ficha || Mint[fila+2][columna]==ficha){ if(Mint[fila-3][columna]==ficha || Mint[fila+3][columna]==ficha){ if(ficha==1){ ganadorojas=true; }else{ ganadoamar=true; } } } } if(ganadorojas==true ){ QMessageBox::information(this,"Fin de juego","Ganan las Rojas","OK"); on_actionNuevo_Juego_triggered(); } if(ganadoamar==true){ QMessageBox::information(this,"Fin de juego","Ganan las Amarillas","OK"); on_actionNuevo_Juego_triggered(); } } ----------------------------------------------------------------------------------------------- |
| |||
Respuesta: Juego 4 en raya Hola: Según lo que tu mismo dices, tiene pinta de que éstas sentencias:
Código C++:
Ver original pueden acceder a posiciones de memoria no deseadas, ya que si estas en la fila 0 y columna 0, cuando haces
Código C++:
por ejemplo, estarías accediendo a Mint[0][-1]Ver original Por lo que has de refinar las condiciones del recorrido para no salirse de los límites. Igual cuando recorres las verticales Pero no he mirado nada más, así que esto que digo puede ser que sí, o puede ser que haya algo más. Por cierto, y ya por curiosidad, ¿podrías suministrar el fichero ui_mainwindow.h o el fichero *.ui generado por el Designer? Saludos |
| |||
Respuesta: Juego 4 en raya Si, quería subir la carpeta donde tengo todos los ficheros pero soy nuevo aquí y he estado buscando como adjuntar un .rar pero no se como hacerlo... |
| |||
Respuesta: Juego 4 en raya Bueno, creo que sólo hace falta el ui_mainwindow.h o el *.ui para poder ejecutar tu programa. Por otro lado releyendo el mensaje ya veo que lo que pides es cómo implementar la función Ganado() para que funcione y no se salga de los límites. A ver si en pseudocódigo: variables de partida: int lineadecuatro =0; //buscar horizontales recorro el tablero por filas fila 0: Si columna 0 tiene mi ficha, incrementar variable lineadecuatro Si la variable lineadecuatro==4 retornar true y salir de la función si no es así, volver a poner lineadecuatro a 0, para no acumular "trues" no consecutivos Seguir así con columna 1, columna 2, etc.... si la fila 0 no contenía ninguna poner lineadecuatro a 0 y repetir con la siguiente fila //horizontales: Sería lo mismo pero recorriendo el array en vertical //diagonales Aquí es menos automático. Entiendo que hay que hacer el barrido de derecha-arriba, luego derecha-abajo, luego izquierda-arriba y luego izquierda-abajo Para el primer caso (derecha-arriba) Puedes partir de que no merece la pena leer hasta la fila 3 (la 4 del array) porque antes no hay posibilidad de 4 en raya, y que cuando llegues a la columna 4 tampoco por la misma cuestión Y luego hay que ir probando por cada fila (o columna) y siguiendo la misma técnica, recorrer las casillas que tengan una fila menos y una columna mas. Para el resto de recorridos, el planteamiento es parecido pero cambiando los límites de búsqueda y los incrementos/decrementos de fila/columna para que vayan en diagona izquierda/derecha arriba/abajo. Bueno, y he hecho un poco de código. Es un programa que crea un tablero. Lo he hecho con bool siendo false donde no hay ficha y true donde sí las hay. He rellenado el tablero en los casos horizontales, verticales y uno de los casos de diagonal. Creo que la búsqueda horizontal y vertical funcionan sin problemas. La búsqueda diagonal, sólo está implementada en el caso de buscar en dirección derecha-superior. Además no la he comprobado mucho, así que no pongo la mano en el fuego por ella. Pero la idea es la que te comenté más arriba.
Código C++:
Ver original Creo que con una pocas adaptaciones lo puedes adaptar a tu función Ganado(). |
| |||
Respuesta: Juego 4 en raya Es posible hacer el chequeo mucho mas económicamente, tanto en el tamaño del código como en la complejidad del mismo: - no requiere hacer loops, - solo requiere hacer un número fijo de adiciones y comparaciones. - pero requiere mantener 2 arreglos y 2 enteros. Esto es lo que se asume, o se fabrica: - Suponemos que la matriz está llena de 0s inicialmente. - Poner una de las 2 opciones cambia el 0 por 1 y poner la otra opcion cambia el 0 por -1. La gracia de esto es que se sabe si hay 4 en linea si al sumar una fila el resultado da N o -N, pero NO ES NECESARIO sumar toda la fila (o todas las filas) o toda la columna (o todas las columnas). - Se mantiene 2 arreglos: suma_fila[N], suma_columna[N], que guardan la suma de cada fila y columna, parten en 0. - Cada vez que se juega alguna opción se actualiza solo 1 posicion de cada arreglo, y solo se chequea si ese valor cambio a N (o -N). No es posible que OTRA FILA haya hecho gato si estoy jugando en una. - La diagonal o contradiagonal solo son 1 entero, tambien parten en 0. Finalmente el codigo podria ser algo asi (podria tener errores menores)
Código C++:
Ver original Ahi está: El chequeo en menos de 10 líneas, sin loops
__________________ Visita mi perfil en LinkedIn Última edición por CalgaryCorpus; 06/06/2014 a las 10:12 |
| |||
Respuesta: Juego 4 en raya Ahora me dan ganas de borrar mi código por vergüenza (que por cierto, para las diagonales no habría que hacer las cuatro combinaciones sino que con 2 serían suficientes, aunque....."ya pa qué") |
| |||
Respuesta: Juego 4 en raya Resolver el problema de 4 en raya en un tablero de 4x4 se puede simplificar como he mostrado. Ahora cómo resolver el problema de 4 en raya en un tablero de 6x7 seguro resulta mas complejo que lo mostrado. ¿o no? Simplificaciones posibles: - no es necesario hacer todos los recorridos todas las veces cuando se sabe que la ultima jugada pasó por la coordenada (fila,columna). - Es facil saber que la ultima jugada no ha hecho 4 si la suma es menor que 4. Solo es necesario chequear si la suma es 4 o más.
__________________ Visita mi perfil en LinkedIn Última edición por CalgaryCorpus; 06/06/2014 a las 10:39 |
| |||
Respuesta: Juego 4 en raya Muchas gracias por la ayuda pero ya he resuelto mi problema. Aqui os dejo el código y si alguien quiere el mainwindow.ui tambien puedo pasarlo pero es demasiado largo por eso he preferido dejarlo.
Código C++:
Ver original |
| |||
Respuesta: Juego 4 en raya Cita: Hola, la verdad es que te respondí sin haber entendido el código. Estas cosas me llevan varias horas. Y la verdad es que no termino de entender el código.
Iniciado por CalgaryCorpus Resolver el problema de 4 en raya en un tablero de 4x4 se puede simplificar como he mostrado. Ahora cómo resolver el problema de 4 en raya en un tablero de 6x7 seguro resulta mas complejo que lo mostrado. ¿o no? Simplificaciones posibles: - no es necesario hacer todos los recorridos todas las veces cuando se sabe que la ultima jugada pasó por la coordenada (fila,columna). - Es facil saber que la ultima jugada no ha hecho 4 si la suma es menor que 4. Solo es necesario chequear si la suma es 4 o más. ¿Como funcionan suma_fila[] y suma_columna[] Cita: ¿Qué quiere decir esto exactamente?Es facil saber que la ultima jugada no ha hecho 4 si la suma es menor que 4. Solo es necesario chequear si la suma es 4 o más @alvarogt91 Me alegro que hayas resuelto el tema. Pero hay una cosa que no entiendo (lo pregunto para el que me lo pueda responer)
Código C++:
Ver original ¿Cómo se leen esas líneas? Por cierto, aunque soy pesado (es que estoy metiendo las manazas en Qt y por eso me interesa todo esto), has probado a enviar el archivo ui_mainwindow.h, a ver si éste si cabe (aunque sea en dos post) Saludos y gracias! |
| |||
Respuesta: Juego 4 en raya Si sumas 1 por cada vez que alguien pone x en la fila 1 sabes que no hay 4 en la fila 1 si la suma es menor que 4. Lo mismo para el resto de filas y columnas. Pero para lograrlo se requeriria mantener tantas sumas como filas y columnas. De ahi los arreglos mencionados.
__________________ Visita mi perfil en LinkedIn |
| |||
Respuesta: Juego 4 en raya Gracias CalgaryCorpus. Ahora sí entiendo la idea. Por cierto, y sobre estas sentencias...¿cómo se interpretan?
Código C++:
Ver original Gracias! |
| |||
Respuesta: Juego 4 en raya En el fondo solo cambia la variable si la expresion es 1 (verdadera) Similar a
Código C++:
Ver original Si la expresion es falsa, no hay cambios.
__________________ Visita mi perfil en LinkedIn |
| |||
Respuesta: Juego 4 en raya Gracias siempre por responder CalgaryCorpus. A sabiendas de que le estoy desvirtuando el hilo a su dueño..... Entonces, esto sólo funciona partiendo de false, y además si llego a true no hay vuelta atrás, no? Hago así:
Código C++:
Ver original Y aunque la última expresión no es cierta, ya no vuelvo al valor false, por lo que veo. ¿Es así? |
| |||
Respuesta: Juego 4 en raya Es cierto que si llegas a true, la expresión que comentamos se asegura que siempre quede así, pero no estás obligado a partir de false. Si partes de true, también permanecerá en true, por lo que estoy de acuerdo con lo que dices excepto con la frase "Entonces, esto sólo funciona partiendo de false", porque tambien funciona cuando partes en true. Ahora, reconozo que para este ejercicio, en donde se está ocupando esta técnica, sólo tiene sentido partir en false y finalmente ver si alguna vez se convirtió en true.
__________________ Visita mi perfil en LinkedIn Última edición por CalgaryCorpus; 11/06/2014 a las 04:02 |
Etiquetas: |