324 lines
9.5 KiB
C++
324 lines
9.5 KiB
C++
/**************************************************************************\
|
||
|* *|
|
||
|* 4 en Raya *|
|
||
|* *|
|
||
|* Algoritmo de combate dise¤ado por JD, capaz de profundizar en *|
|
||
|* jugadas defensivas/ofensivas. *|
|
||
|* *|
|
||
|* *|
|
||
|* *|
|
||
\**************************************************************************/
|
||
|
||
#include <mem.h>
|
||
|
||
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<ANCHO_TABLERO; j++)
|
||
{
|
||
QueHay = *( CopiaDelTablero + Pos_Y[i] * ANCHO_TABLERO + j );
|
||
if ( QueHay == JUGADOR_DUMMY )
|
||
FichasHints++;
|
||
else break;
|
||
}
|
||
// Bingo, Aqui ganamos
|
||
if ( FichasHints >= 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<ALTO_TABLERO && k < ANCHO_TABLERO; 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;
|
||
}
|
||
|
||
//°²Û 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<ALTO_TABLERO && k >= 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;
|
||
}
|
||
|
||
|
||
|