/** * Esta función se encarga de cambiar el turno en el juego */ public void cambiarTurno() { //Se cambia el turno en los jugadores (estructura de datos) jugadores.cambiarTurno(); //Se cambia el turno en el interfaz gráfico. turnoactual.Text = traductor.getCadena("turnode", jugadores.nombreJugadorActual()); //Vemos si el tablero está acabado o simplemente el jugador actual no puede tirar. if (tablero.estaAcabado(jugadores.consultarTurno())) { //Ahora comprobamos si el otro jugador no puede jugar. En tal caso, se acabó. if (tablero.estaAcabado(Jugador.fichaOponente(jugadores.consultarTurno()))) { //Sonido de finalización del juego. tada.Play(); terminado = true; turnoactual.Foreground = new SolidColorBrush(Colors.Red); turnoactual.Text = traductor.getCadena("juegoterminado") + "\n"; //Miramos a ver si hay tablas o si alguien ha ganado if (jugadores.consultarGanador(tablero) == "tttablas") { turnoactual.Text += traductor.getCadena("tablas"); } else { turnoactual.Text += traductor.getCadena("ganador") + ": " + jugadores.consultarGanador(tablero); } } else //No se pueden realizar mas jugadas, asi que tendrá que pasar. { turnoactual.Text = traductor.getCadena("nosepuedenhacermasjugadas"); } } //Si el juego no ha acabado y se quiere jugar contra la máquina, empezamos a usar el algoritmo. if (!terminado && jugadores.nombreJugadorActual() == "Robot") { //Jugada del robot //El último parámetro dependerá de la dificultad: facil(1), medio(3) y dificil(6) AlfaBeta algoritmo = new AlfaBeta(tablero, jugadores.consultarTurno(), 6); //Realizamos la jugada que hemos calculado con el algoritmo realizarJugada(algoritmo.obtenerJugada()); //IMPORTANTE: ESTO DE AQUI LO VOY A QUITAR, PERO AL FINALIZAR UNA JUGADA ME HA DADO NULLPOINTEREXCEPTION //jugadas.Text = algoritmo.obtenerJugada().toString(); } }
/** * Algoritmo recursivo alfa-beta que se encarga de recorrer el árbol de búsqueda y encontrar las mejores jugadas. * @param tablero del que se parte. * @param alfa valor. * @param beta valor. * @param profundidadaActual. * @param ficha con la que se juega. * @return valor alfa o beta heurístico. */ public int recurAlgoritmo(Tablero tablero, int alfa, int beta, int profundidadActual, char ficha) { int tmp_alfa, tmp_beta, devolver = 0; Celda celda; //Cuando la profundidad sea mayor de la que estamos, vamos por este camino if (profundidadActual < profundidad) { //Recorremos el tablero for (int a = 0; a < tablero.getTamaño(); a++) { for (int b = 0; b < tablero.getTamaño(); b++) { celda = new Celda(a, b, ficha); if (tablero.esLegal(celda) && tablero.comprobarSiHayCeldasAfectadas(celda)) { //Corte de nodos. if (alfa < beta) { if (profundidadActual % 2 == 1) //Estoy en MIN { // Debug.WriteLine("Tablero que voy a comprobar con profundidad "+profundidadActual); // nuevoTablero(tablero, celda).printearTableroDebug(); tmp_beta = recurAlgoritmo(nuevoTablero(tablero, celda), alfa, beta, profundidadActual + 1, Jugador.fichaOponente(ficha)); // Debug.WriteLine("Estoy en MIN. Celda: "+celda.toString()+". tmp_beta=" + tmp_beta + " beta=" + beta); if (tmp_beta < beta) { beta = tmp_beta; devolver = beta; } } else //Estoy en MAX { tmp_alfa = recurAlgoritmo(nuevoTablero(tablero, celda), alfa, beta, profundidadActual + 1, Jugador.fichaOponente(ficha)); // Debug.WriteLine("Estoy en MAX. Celda: " + celda.toString() + " tmp_alfa=" + tmp_alfa + " alfa=" + alfa); if (tmp_alfa > alfa) { alfa = tmp_alfa; devolver = alfa; } } } } } } } else { //Devolvemos el valor de la hoja. devolver = evaluarTablero(tablero, ficha); // Debug.WriteLine("Profundidad más baja. Devuelvo la heuristica del siguiente talbero: " + devolver); // tablero.printearTableroDebug(); } return(devolver); }
/** * Esta función inicializa el algoritmo alfabeta. * @param tablero del que partimos. */ public void inicioAlgoritmo(Tablero tablero) { int alfa = -999, beta = 999; int tmp_alfa; Celda celda; //Buscamos por todo el tablero celdas for (int a = 0; a < tablero.getTamaño(); a++) { for (int b = 0; b < tablero.getTamaño(); b++) { celda = new Celda(b, a, ficha); //Encontramos una celda en la que podemos jugar if (tablero.esLegal(celda) && tablero.comprobarSiHayCeldasAfectadas(celda)) { //La primera vez, se guarda, ya que siempre iremos como mínimo por la primera rama del árbol de búsqueda. if (jugada == null) { jugada = celda; } //Debug.WriteLine("llego con y: " + b + " y x: " + a); //Debug.WriteLine("Celda: "+celda.toString()); // Debug.WriteLine("Tablero a evaluar:"); // tablero.printearTableroDebug(); tmp_alfa = recurAlgoritmo(nuevoTablero(tablero, celda), alfa, beta, 1, Jugador.fichaOponente(ficha)); //Si la función de evaluación es mayor que el alfa que ya tenemos, se guarda esa jugada como favorita. if (tmp_alfa > alfa) { jugada = celda; alfa = tmp_alfa; } } } } }
/** * Función heurística que se encarga de evaluar el tablero a partir de una ficha. * Dependiendo de la ficha, un tablero puede ser bueno o malo. * @param tablero a evaluar. * @param ficha usada para evaluar el tablero. */ public int evaluarTablero(Tablero tablero, char ficha) { int evaluacion = 0; int multiploFicha = 0; //Si la profundidad es 1, usamos una función heurística sencillita if (profundidad == 1) { for (int a = 0; a < tablero.getTamaño(); a++) { for (int b = 0; b < tablero.getTamaño(); b++) { if (tablero.getCelda(b, a).getFicha() == ficha) { evaluacion++; } else if (tablero.getCelda(b, a).getFicha() == Jugador.fichaOponente(ficha)) { evaluacion--; } } } } else //Si no, usamos una función heurística más interesante { for (int a = 0; a < tablero.getTamaño(); a++) { for (int b = 0; b < tablero.getTamaño(); b++) { if (tablero.getCelda(b, a).getFicha() == '-') { multiploFicha = 0; } else if (tablero.getCelda(b, a).getFicha() == ficha) { multiploFicha = 1; } else if (tablero.getCelda(b, a).getFicha() == ficha) { multiploFicha = -1; } if (a == 0 || b == 0 || a == (tablero.getTamaño() - 1) || b == (tablero.getTamaño() - 1)) { //Esquinas if ((a == 0 && b == 0) || (a == (tablero.getTamaño() - 1) && b == 0) || (a == 0 && b == (tablero.getTamaño() - 1)) || (a == (tablero.getTamaño() - 1) && b == (tablero.getTamaño() - 1))) { evaluacion += multiploFicha * 6; } else //Bordes { evaluacion += multiploFicha * 4; } } //Anteriores al borde else if (a == 1 || b == 1 || a == (tablero.getTamaño() - 2) || b == (tablero.getTamaño() - 2)) { evaluacion += multiploFicha * 2 * -1; } else //Resto { evaluacion += multiploFicha; } } } } //Debug.WriteLine("Evaluacion tablero: " + evaluacion); return(evaluacion); }