4RAYA/4RAYA.CPP
2021-09-12 19:47:27 +02:00

324 lines
9.5 KiB
C++
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**************************************************************************\
|* *|
|* 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 estratgicas
// 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;
}