/**************************************************************************\ |* *| |* 4 en Raya *| |* *| |* Algoritmo de combate dise¤ado por JD, capaz de profundizar en *| |* jugadas defensivas/ofensivas. *| |* *| |* *| |* *| \**************************************************************************/ #include char Tablero[7][7]; // [FILA][COLUMNA] #define TAMANYO_DEL_TABLERO 7*7 #define ANCHO_TABLERO 7 #define ALTO_TABLERO 3 #define NO_HAY_NADIE 0 #define JUGADOR1 1 #define JUGADOR2 2 #define PROFUNDIDAD_DE_JUEGO 5 class Conecta4 { private: char StatusError; char QuienSoy; char *TableroOriginal; char *CopiaDelTablero; char AveriguaQuienSoy(void); char GanaTurno( int *Pos_x, int *Pos_y, char JUGADOR_DUMMY ); void AlgInteligente( int *Pos_x, int *Pos_y, char JUGADOR_DUMMY ); public: Conecta4(char *DirTablero); ~Conecta4(); void JuegaTurno(void); char *Error(void); }; void Conecta4::JuegaTurno( void ) { int x, y; // Punto, donde pondr‚ mi ficha int X, Y; // Puntos de avance en el tiempo. char Enemigo; char ok, Turno; // ¨ Quien soy YO ? if ( QuienSoy == -1 ) AveriguaQuienSoy(); if ( QuienSoy == JUGADOR1 ) Enemigo = JUGADOR2; else Enemigo = JUGADOR1; // Realizamos una copia del Tablero para las profudizaciones memcpy( CopiaDelTablero, Tablero, sizeof( char ) * (TAMANYO_DEL_TABLERO) ); // ¨ Podemos ganar en este turno ? if ( GanaTurno( &x, &y, QuienSoy ) ) { *( TableroOriginal + ANCHO_TABLERO*y + x ) = QuienSoy; return; } // ¨ Tengo que defender en este turno ? if ( GanaTurno( &x, &y, Enemigo ) ) { *( TableroOriginal + ANCHO_TABLERO*y + x ) = QuienSoy; return; } ok = 0; Turno = 0; // Tengo libertad en este turno para colocar la ficha donde quiera... do { AlgInteligente( &x, &y, QuienSoy ); // Me adelanto en el tiempo para ver que pasa si pongo la ficha hay... // --------- OK == 0 JUGADA MALA :::: OK == 1 JUGADA BUENA ----------- // -- ¨ Tengo mas lugares donde poner ? (si esta jugada no es buena) if ( Turno > (ANCHO_TABLERO*ALTO_TABLERO) ) { // ­­ Que le vamos hacer !!, puede ganar el contrario ok = 1; } else { // Si pongo aqui: ¨ Gana el siguiente turno el enemigo ? 1==NO :: 0==SI if ( (ok = !GanaTurno( &X, &Y, Enemigo ) ) ) { // Vale, el enemigo no ganar  en el siguiente turno, pero... // ...que tal si nos adelantamos un poquito en el tiempo. AlgInteligente( &X, &Y, Enemigo ); *( CopiaDelTablero + ANCHO_TABLERO*Y + X ) = Enemigo; // Ahora juego yo... if ( GanaTurno( &X, &Y, QuienSoy ) ) { // Vale tengo asegurado el ganar dos turnos mas hacia adelante. ok = 1; } else { // Dentro de dos turnos no gano, pero... AlgInteligente( &X, &Y, QuienSoy ); *( CopiaDelTablero + ANCHO_TABLERO*Y + X ) = QuienSoy; // ...¨y el enemigo? if ( GanaTurno( &X, &Y, Enemigo ) ) { // Parece que el enemigo gana, y no me la va a dar, asi de facil. ok = 0; } else { // Juega mejor colega, por que a mi no me ganas. ok = 1; } } } } Turno++; } while ( !ok ); // Este el el punto de inserci¢n optimo. *( TableroOriginal + ANCHO_TABLERO*y + x ) = QuienSoy; } // Comprobamos si el JUGADOR_DUMMY puede ganar este turno (Dev: Pos ganadora) char Conecta4::GanaTurno( int *Pos_x, int *Pos_y, char JUGADOR_DUMMY ) { int i, j, k; int Lug_X, FichasHints; char QueHay; int Pos_Y[ANCHO_TABLERO]; // Posibles lugares donde meter la ficha for ( i = 0; i < ANCHO_TABLERO; i++ ) { // Por defecto, no es posible usar esta columna... Pos_Y[i] = -1; for ( j = 0; j < ALTO_TABLERO; j++ ) { if ( *( CopiaDelTablero + j * ANCHO_TABLERO + i ) == NO_HAY_NADIE ) { Pos_Y[i] = j; break; } } } // Si metemos la ficha en algun lugar, ¨ GANAMOS ? FichasHints = 0; for ( i = 0; i < ANCHO_TABLERO; i++ ) // Revisamos todos los huecos if ( Pos_Y[i] != -1 ) { //°²Û X //°²Û ¨ Posibilidad de ganar en HORIZONTAL ? X X //°²Û X * * - * //°²Û Insertando la ficha gano ----------^ for ( j = i-1; j>=0; j--) { QueHay = *( CopiaDelTablero + Pos_Y[i] * ANCHO_TABLERO + j ); if ( QueHay == JUGADOR_DUMMY ) FichasHints++; else break; } for ( j = i+1; j= 3 ) { *Pos_x = i; *Pos_y = Pos_y[i]; return 1; } //°²Û Insertando la ficha gano ---> - //°²Û * //°²Û ¨ Posibilidad de ganar en VERTICAL ? * X //°²Û * * X X X // Solo es posible si mi altura actual es >= 3 if ( Pos_Y[i] >= 3 ) { for ( j = Pos_Y[i]-1; j >= 0; j-- ) { QueHay = *( TableroOriginal + Pos_Y[i] * ANCHO_TABLERO + i ); if ( QueHay == JUGADOR_DUMMY ) FichasHints++; else break; } if ( FichasHints >= 3 ) { *Pos_x = i; *Pos_y = Pos_y[i]; return 1; } } //°²Û Insertando la ficha gano ÄÄÄÄÄÄÄÄÄ¿ * //°²Û * - * X //°²Û ¨ Posibilidad de ganar en DIAGONAL 1 ? X * X X X //°²Û * * X X X k = i - 1; for ( j = Pos_Y[i]-1; j >= 0 && k >= 0; j--, k-- ) { QueHay = *( CopiaDelTablero + j * ANCHO_TABLERO + k ); if ( QueHay == JUGADOR_DUMMY ) FichasHints++; else break; } k = i + 1; for ( j = Pos_Y[i]+1; j= 3 ) { *Pos_x = i; *Pos_y = Pos_y[i]; return 1; } //°²Û Insertando la ficha gano ÄÄÄÄÄÄÄ*Ä¿ X //°²Û X X - X X //°²Û ¨ Posibilidad de ganar en DIAGONAL 2 ? X * X * X //°²Û X * * X * k = i + 1; for ( j = Pos_Y[i]-1; j >= 0 && k < ANCHO_TABLERO; j--, k++ ) { QueHay = *( CopiaDelTablero + j * ANCHO_TABLERO + k ); if ( QueHay == JUGADOR_DUMMY ) FichasHints++; else break; } k = i - 1; for ( j = Pos_Y[i]+1; j= 0; j++, k-- ) { QueHay = *( CopiaDelTablero + j * ANCHO_TABLERO + k ); if ( QueHay == JUGADOR_DUMMY ) FichasHints++; else break; } // Bingo, Aqui ganamos if ( FichasHints >= 3 ) { *Pos_x = i; *Pos_y = Pos_y[i]; return 1; } } // Este turno no puede ser ganado, DIRECTAMENTE!!! return 0; } // El algoritmo inteligente es el nucleo de pensamiento de mi OBJETO // decidir  cual es la posici¢n mas acertada, (EN EL TURNO ACTUAL), para // ganar la partida... // // Partimos del supuesto que no nos es posible ganar directamente en este // turno y al enemigo tan poco le es posible en el siguiente. Por lo cual, // tenemos un total de ANCHO_TABLERO casillas donde poner nuestra ficha. // // Actualmente, solo compruebo la frecuencia de aparici¢n de fichas, en // la media luna de posiciones que me rodean. FREC_MAX -> max. pos. de ganar. // // Realmente en este algoritmo, se podr¡an tener algunas jugadas estrat‚gicas // ya prefijadas. Despues de jugar unas cuantas partidas con un HUMANO, nos // daremos cuenta que solo existen unas Xx jugadas estrategicas que se basan, // como mucho, en dos turnos adelante en el tiempo, de aqui mi control de // estos dos turnos en el tiempo... // Fdo: // Jose-David.Guillen@cs.us.es void Conecta4::AlgInteligente( int *Pos_x, int *Pos_y, char JUGADOR_DUMMY ) { } Conecta4::Conecta4(char *DirTablero) { StatusError = 0; QuienSoy = -1; TableroOriginal = DirTablero; if ( ( CopiaDelTablero = new char [TAMANYO_DEL_TABLERO] ) == NULL ) StatusError = 1; } Conecta4::~Conecta4() { delete [] CopiaDelTablero; } char *Conecta4::Error(void) { char *MensajesError[40] = { "No hay suficiente Memoria", "No quedan huecos libres", "Error Desconocido" }; if ( StatusError ) return MensajesError[StatusError]; else return NULL; }