/**************************************************************************\ |* *| |* 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 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 #include #include #include #include #include //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 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= 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= 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= 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 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 ) { 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; }