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

691 lines
20 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 7
#define NO_HAY_NADIE 0
#define JUGADOR1 1
#define JUGADOR2 2
#define PROFUNDIDAD_DE_JUEGO 5
int Post_X, Post_Y;
class Conecta4
{
private:
char StatusError;
char QuienSoy;
char *TableroOriginal;
char *CopiaDelTablero;
char AveriguaQuienSoy(void);
void PosiblesLugares( char Pos_Y[ANCHO_TABLERO] );
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);
};
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
///NOTA LOS VALORES DE X E Y OSCILAN ENTRE 1-7
//BIBLIOTECAS EMPLEADAS
#include<dos.h>
#include<graphics.h>
#include<stdlib.h>
#include<stdio.h>
#include<conio.h>
#include<process.h>
//DECLARACION DE FUNCIONES
void InicializaSVGA(void);
void dibujamalla();
void dibujacoordenada();
int comprueba();
void algoritmojugador1();
void algoritmojugador2();
//VARIABLES GLOBALES
int x=0;
int y=0;
int jugador=1;
char coordenada[7][7];
int huge DetectVGA256(){ return 2; }
//FUNCION PRINCIPAL
void main()
{
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
char buffer[80];
Conecta4 JugadorJD( &coordenada[0][0] );
if ( JugadorJD.Error() != NULL )
return;
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
int a,b,resultado;
char o='0';
//inicializa graficos
InicializaSVGA();
while(o!='q')
{
clearviewport();
resultado=0;
//inicializa coordenadas a cero
for (a=0;a<7;a++)
for (b=0;b<7;b++)
coordenada[a][b]=0;
//dibuja malla
dibujamalla();
//dibuja circulo en coordenada
while(resultado!=1&&resultado!=2)
{
//JUEGAN AMBOS JUGADORES
if(jugador==1) algoritmojugador1();
///////////////////////////////////////////////////////////////////////////////
else {
JugadorJD.JuegaTurno(); x = Post_X; y = Post_Y;
bar( 0, 0, 100, 30 );
sprintf( buffer, "%d, %d", x, y );
outtextxy( 10, 10, buffer );
// sound(150);delay(200);nosound();
// getch();
// x++; y++;
}
//////////////////////////////////////////////////////////////////////////////
//algoritmojugador2();
//COMPRUEBA LAS COORDENADAS CORRECTAS
if((x<7&&y<7&&x>-1&&y>-1) )//&&coordenada[x][y]==0&&((coordenada[x][y-1]!=0)||y==0))
{
dibujacoordenada();
if(jugador==1) {coordenada[x][y]=1;jugador=2;}
else {coordenada[x][y]=2;jugador=1;}
resultado=comprueba();
}
else {
bar( 100, 0, 600, 30 );
sprintf( buffer, "COORDENADA ERRONEA PRODUCIDA POR EL JUGADOR:%d",(int)jugador );
outtextxy( 110, 10, buffer );
}
}
//dice quien gano
if(jugador==2) sprintf( buffer, "GANO EL JUGADOR1");
else sprintf( buffer, "GANO EL JUGADOR2");
bar( 100, 0, 600, 30 );
outtextxy( 110, 10, buffer );
//cierra el modo grafico
o=getch();
};
closegraph();
}
//DIBUJA CIRCULO EN COORDENADA
void dibujacoordenada()
{
int a,c=0;
x=x+1;y=y+1;
while(c<=(8-y))
{
//elije color segun jugador
if(jugador==1) setcolor(1);
else setcolor(5);
//dibuja circulo
for(a=0;a<20;a++)
circle(50 * x+110,50 * c+50,a);
delay(250);
//borra circulo
if(c+1<=(8-y))
{
setcolor(0);
for(a=0;a<20;a++)
circle(50 * x+110,50 * c+50,a);
}
c=c+1;
}
x=x-1;
y=y-1;
}
//DIBUJA LA MALLA DEL JUEGO
void dibujamalla()
{
int a;
setcolor(15);
for(a=135;a<500;a=a+50)
line(a,75,a,425);
for(a=75;a<426;a=a+50)
line(135,a,485,a);
}
//INICIALIZA MODO GRAFICO EN SVGA
void InicializaSVGA(void) {
int Gd = DETECT, Gm;
int Drv, errorcode;
installuserdriver("Svga256",DetectVGA256);
initgraph(&Gd,&Gm,"c:\\program\\borlandc\\bgi");
/* read result of initialization */
errorcode = graphresult();
if (errorcode != grOk) /* an error occurred */
{
cprintf("Graphics error: %s\n", grapherrormsg(errorcode));
cprintf("Presione una tecla para finalizar:");
getch();
exit(1); /* return with error code */
}
}
//COMPRUEBA SI HA GANADO ALGUIEN Y DEVUELVE UN VALOR
int comprueba()
{
int w=0,suma=0,suma1=0,suma2=0,suma3=0,cx1,cy1;
cy1=0;cx1=0;
//LECTURA DEL ARRAY HORIZONTAL Y VERTICAL
while(cy1<8&&suma!=4&&suma1!=4&&suma2!=4&&suma3!=4)
{
suma=0;suma1=0;suma2=0;suma3=0;cx1=0;
while(cx1<8&&suma!=4&&suma1!=4&&suma2!=4&&suma3!=4)
{
if(coordenada[cx1][cy1]==0) {suma=0;suma1=0;}
if(coordenada[cx1][cy1]==1) {suma++;suma1=0;}
if(coordenada[cx1][cy1]==2) {suma1++;suma=0;}
if(coordenada[cy1][cx1]==0) {suma2=0;suma3=0;}
if(coordenada[cy1][cx1]==1) {suma2++;suma3=0;}
if(coordenada[cy1][cx1]==2) {suma3++;suma2=0;}
cx1++;
}
cy1++;
}
//LECTURA EN DIAGONAL Y DIAGONAL INVERSA
if(suma<4&&suma1<4&&suma2<4&&suma3<4) {cx1=1;cy1=1;suma=0;suma1=0;suma2=0;suma3=0;}
while(cy1<8&&suma!=4&&suma1!=4&&suma2!=4&&suma3!=4)
{
suma=0;suma1=0;suma2=0;suma3=0;cx1=1;
while(cx1<8&&suma!=4&&suma1!=4&&suma2!=4&&suma3!=4)
{
if(coordenada[cx1][cy1]==0) {suma=0;suma1=0;suma2=0;suma3=0;}
if(coordenada[cx1][cy1]==1) {suma++;suma1=0;}
if(coordenada[cx1][cy1]==2) {suma1++;suma=0;}
if(coordenada[cy1][cx1]==1) {suma2++;suma3=0;}
if(coordenada[cy1][cx1]==2) {suma3++;suma2=0;}
cx1++;
}
cy1++;
}
//DA [0] SI NO GANO NADIE,[1] SI GANO EL JUGADOR1,[2] SI GANO EL JUGADOR2
if(suma==4||suma2==4) w=1;
if(suma1==4||suma3==4) w=2;
return w;
}
//ALGORITMO DE JD
void algoritmojugador1()
{
//PRIMER MOVIMIENTO CENTRAL
int c=0,suma=0,suma1=0,suma2=0,suma3=0,cx1=0,cy1=0,a=0;
//LECTURA DEL ARRAY HORIZONTAL Y VERTICAL
while(cy1<7&&suma!=4&&suma1!=4&&suma2!=4&&suma3!=4)
{
suma=0;suma1=0;suma2=0;suma3=0;cx1=0;
while(cx1<7&&suma!=4&&suma1!=4&&suma2!=4&&suma3!=4)
{
if(coordenada[cx1][cy1]==0) {suma=0;suma1=0;}
if(coordenada[cx1][cy1]==1) {suma++;suma1=0;}
if(coordenada[cx1][cy1]==2) {suma1++;suma=0;}
if(coordenada[cy1][cx1]==0) {suma2=0;suma3=0;}
if(coordenada[cy1][cx1]==1) {suma2++;suma3=0;}
if(coordenada[cy1][cx1]==2) {suma3++;suma2=0;}
//MOVIMIENTO DE DEFENSA
if(suma1==3&&cx1<6)
if(coordenada[cx1+1][cy1]==0)
{x=cx1+1;y=cy1;a=1;}
if(suma3==3&&cx1<6)
if(coordenada[cy1][cx1+1]==0)
{x=cy1;y=cx1+1;a=1;}
//MOVIMIENTO DE ATAQUE
if(suma==3&&cx1<6)
if(coordenada[cx1+1][cy1]==0)
{x=cx1+1;y=cy1;a=1;}
if(suma2==3&&cx1<6)
if(coordenada[cy1][cx1+1]==0)
{x=cy1;y=cx1+1;a=1;}
cx1++;
}
cy1++;
}
if(((suma<3&&suma1<3&&suma2<3&&suma3<3)||(coordenada[x][y-1]==0))&&a==0)
{
randomize();
x=(rand() %3) +2;
while(coordenada[x][c]!=0)
{
c=c+1;
}
y=c;
}
}
//ALGORITMO DE OSCAR
void algoritmojugador2()
{
int c=0;
randomize();
x=rand() %7;
while(coordenada[x][c]!=0)
{
c=c+1;
}
y=c;
}
/**************************************************************************\
|* *|
|* 4 en Raya *|
|* *|
|* Algoritmo de combate dise¤ado por JD, capaz de profundizar en *|
|* jugadas defensivas/ofensivas. *|
|* *|
|* *|
|* *|
\**************************************************************************/
// #include <mem.h>
char Conecta4::AveriguaQuienSoy(void)
{
return ( QuienSoy = JUGADOR2 );
}
void Conecta4::JuegaTurno( void )
{
int x, y; // Punto, donde pondr mi ficha
int X, Y; // Puntos de avance en el tiempo.
char *tmp;
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, TableroOriginal, sizeof( char ) * (TAMANYO_DEL_TABLERO) );
// ¨ Podemos ganar en este turno ?
if ( GanaTurno( &x, &y, QuienSoy ) )
{
*( TableroOriginal + ANCHO_TABLERO*x + y ) = QuienSoy;
////////////////////////////////////////////////////////////////////////////////////
Post_X = x; Post_Y = y;
////////////////////////////////////////////////////////////////////////////////////
return;
}
// ¨ Tengo que defender en este turno ?
if ( GanaTurno( &x, &y, Enemigo ) )
{
*( TableroOriginal + ANCHO_TABLERO*x + y ) = QuienSoy;
////////////////////////////////////////////////////////////////////////////////////
Post_X = x; Post_Y = y;
////////////////////////////////////////////////////////////////////////////////////
return;
}
ok = 0; Turno = 0;
// Tengo libertad en este turno para colocar la ficha donde quiera...
do {
AlgInteligente( &x, &y, QuienSoy );
*( CopiaDelTablero + ANCHO_TABLERO*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 )
{
// ­­ 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*X + Y ) = 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...
tmp = ( CopiaDelTablero + ANCHO_TABLERO*X + Y );
AlgInteligente( &X, &Y, QuienSoy );
*( CopiaDelTablero + ANCHO_TABLERO*X + Y ) = QuienSoy;
// ...¨y el enemigo?
if ( GanaTurno( &X, &Y, Enemigo ) )
{
// Parece que el enemigo gana, y no me la va a dar, asi de facil.
// Si se puede poner ahora, tapo la jugada
if ( *( TableroOriginal + ANCHO_TABLERO*X + ( (Y-1)<0 ? 0 : (Y-1) ) ) == NO_HAY_NADIE )
{
ok = 1;
x = X; y = Y;
} else {
// De lo contrario, realizo otra jugada. (Alg int. debe intervenir)
ok = 0;
}
*( CopiaDelTablero + ANCHO_TABLERO*X + Y ) = NO_HAY_NADIE;
*tmp = NO_HAY_NADIE;
} else {
// Juega mejor colega, por que a mi no me ganas.
ok = 1;
}
}
} else {
// El enemigo ganar¡a directamente, deshacemos el movimiento.
*( CopiaDelTablero + ANCHO_TABLERO*x + y ) = NO_HAY_NADIE;
}
}
Turno++;
} while ( !ok );
// Este el el punto de inserci¢n optimo.
*( TableroOriginal + ANCHO_TABLERO*x + y ) = QuienSoy;
////////////////////////////////////////////////////////////////////////////////////
Post_X = x; Post_Y = y;
////////////////////////////////////////////////////////////////////////////////////
}
// 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;
char Pos_Y[ANCHO_TABLERO];
PosiblesLugares( Pos_Y );
// 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 ----------^
FichasHints = 0;
for ( j = i-1; j>=0; j--)
{
QueHay = *( CopiaDelTablero + j * ANCHO_TABLERO + Pos_Y[i] );
if ( QueHay == JUGADOR_DUMMY )
FichasHints++;
else break;
}
for ( j = i+1; j<ANCHO_TABLERO; j++)
{
QueHay = *( CopiaDelTablero + j * ANCHO_TABLERO + Pos_Y[i] );
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 )
{
FichasHints = 0;
for ( j = Pos_Y[i]-1; j >= 0; j-- )
{
QueHay = *( CopiaDelTablero + i * ANCHO_TABLERO + j );
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
FichasHints = 0;
k = i - 1;
for ( j = Pos_Y[i]-1; j >= 0 && k >= 0; j--, k-- )
{
QueHay = *( CopiaDelTablero + k * ANCHO_TABLERO + j );
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 + k * 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 ÄÄÄÄÄÄÄ*Ä¿ X
//°²Û X X - X X
//°²Û ¨ Posibilidad de ganar en DIAGONAL 2 ? X * X * X
//°²Û X * * X *
FichasHints = 0;
k = i + 1;
for ( j = Pos_Y[i]-1; j >= 0 && k < ANCHO_TABLERO; j--, k++ )
{
QueHay = *( CopiaDelTablero + k * ANCHO_TABLERO + j );
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 + k * 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;
}
}
// 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 )
{
char Pos_Y[ANCHO_TABLERO];
char Frec_Y[ANCHO_TABLERO], Frec_abs;
char i, j;
PosiblesLugares( Pos_Y );
// ? ?
// Por cada casilla, vemos la frecuencia de apariciones ? * ?
// en la media luna que hay por debajo y arriba! ? ? ?
for ( i = 0; i < ANCHO_TABLERO; i++ )
{
Frec_Y[i] = 0;
if ( Pos_Y[i] != -1 )
{
for ( j = ( ( Pos_Y[i] - 1 ) < 0 ? 0 : ( Pos_Y[i] - 1 ) ); j <= ( (Pos_Y[i] + 1) >= ALTO_TABLERO ? (ALTO_TABLERO-1) : (Pos_Y[i] + 1) ); j++ )
{
if ( (i-1) >= 0 &&
*( CopiaDelTablero + (i-1) * ANCHO_TABLERO + j ) == JUGADOR_DUMMY )
Frec_Y[i] ++;
if ( (i+1) <= (ANCHO_TABLERO-1) &&
*( CopiaDelTablero + ( (i+1)>=ANCHO_TABLERO ? (ANCHO_TABLERO-1) : (i+1) ) * ANCHO_TABLERO + j ) == JUGADOR_DUMMY )
Frec_Y[i] ++;
}
if ( *( CopiaDelTablero + ( i * ANCHO_TABLERO + ( (Pos_Y[i]-1) < 0 ? 1 : (Pos_Y[i]-1) ) ) ) == JUGADOR_DUMMY )
Frec_Y[i] ++;
}
}
// Coloco mi ficha en la posici¢n con mayor frecuencia:
Frec_abs = -1;
for ( i = 0; i < ANCHO_TABLERO; i++ )
if ( Frec_Y[i] > Frec_abs || (Frec_Y[i] == Frec_abs && Pos_Y[i] < *Pos_y) )
{
Frec_abs = Frec_Y[i];
*Pos_x = i;
*Pos_y = Pos_Y[i];
}
}
void Conecta4::PosiblesLugares( char Pos_Y[ANCHO_TABLERO] )
{
// char Pos_Y[ANCHO_TABLERO];
int i, j;
// 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 + i * ANCHO_TABLERO + j ) == NO_HAY_NADIE )
{
Pos_Y[i] = j;
break;
}
}
}
}
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;
}