Hundir la flota en C

El hundir la flota en C y con la librería gráfica allegro.

Hay que instalar Allegro con la versión 4 (versión probada allegro4-4.4.2-2), la cinco no consigo compilar. Se compila con gcc -o hundirLaFlota hundirlaflota.c `allegro-config –libs`

Hundir la flota: Pulsa para ver/ocultar el código
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <allegro.h>

//#define TRUE 1
//#define FALSE 0
//#define FILA 10
//#define COLUMNA 10
#define NUMBARCOS 5
#define VERTICAL 1
#define HORIZONTAL 2
//valores que puede tomar la matriz y que significa, a partir del cuatro, son los barcos en tamaño incremental (4-5-6-7-8) restando 3
#define NADA 0
#define AGUA 1
#define TIROAGUA 2
#define TOCADO 3


#define ALTOVENTANA 480
#define ANCHOVENTANA 640
#define BORDELATERAL 35
#define BORDESUPERIOR 40
#define MARGENINFERIOR 100
#define MARGENLATERALTEXTO 30
#define INTERESPACIADO 15
#define WHITE makecol(255,255,255)
#define BLACK makecol(0,0,0)

int numBarcos[]={0,0,1,0,0};
int FILA=10;
int COLUMNA=10;
BITMAP* BUFFER;

void colocarBarcosManualmente(int *matriz);
void colocarBarcosAutomaticamente(int *matriz);
void inicializarTablero(int *matriz);
void imprimirTablero(int *matriz);
int comprobacionEspacioParaBarco(int fila, int columna, int orientacion, int tamano, int *matriz);
int compruebaGanador(int *matriz);
int compruebaDisparo(int *matriz, int fila, int columna, int enemigo);
void juegoManual(int *matriz);
void juegoAutomatico(int *matriz);
void imprimirMenu(int numOpciones, char *opciones[]);
int compruebaOpcion(int min, int max, int opcion);
void ordenador();
void jugador();
int compruebaRangoCasilla(int fila, int columna);
void colocarBarco(int fila, int columna, int orientacion, int tamano, int *matriz);
int aleatorio(int min, int max);
void rellenarAguaAlrededor(int columna, int fila, int orientacion, int tamano, int *matriz);
void rellenarAgua(int *matriz);
void bucleJuego(int *jugador, int *enemigo);
void imprimirTableroJuego(int *enemigo, int *jugador, int barcos);
void limpiarMargenInferior();
int leerNumero();
void ponerTituloCasillas(int numTablas);
void opciones();

int main(int argc, char* argv[]){
    allegro_init();
    install_keyboard();
    set_gfx_mode(GFX_AUTODETECT_WINDOWED, ANCHOVENTANA, ALTOVENTANA, 0, 0);
    BUFFER = create_bitmap(SCREEN_W,SCREEN_H);
    int numOpciones=4;
    int opcion;
    char *op[]={
        "Jugar (ordenador vs jugador)",
        "Jugar (ordenador vs ordenador)",
        "Opciones",
        "Salir"
    };
    srand(time(NULL));

    while(TRUE){
        do{
            //muestro menú y pido opcion
            imprimirMenu(numOpciones, op);
            opcion=(readkey() & 0xff)-48;
            //scanf("%d", &opcion);
        }while(!compruebaOpcion(1,numOpciones, opcion));

        //según la opción....
        switch(opcion){
            case 1:
                jugador(); //jugador contra ordenador
                break;
            case 2:
                ordenador(); //ordenador contra ordenador
                break;
            case 3:
                opciones();
                break;
            case 4:
                return 0; //cierro el programa
        }
    }
 return 0;
}
END_OF_MAIN()

//modificar opciones
void opciones(){
    int numero, i, opcion, salto;
    int numOpciones=3;
    char *op[]={
            "Cambiar tamaño del tablero",
            "Cambiar número de barcos",
            "Salir"
    };

    while(TRUE){
        do{
            //muestro menú y pido opcion
            imprimirMenu(numOpciones, op);
            opcion=(readkey() & 0xff)-48;
            //scanf("%d", &opcion);
        }while(!compruebaOpcion(1,numOpciones, opcion));
        rectfill(screen, 0, 0, ANCHOVENTANA, ALTOVENTANA, makecol(255, 255, 255)); //ventana en blanco
        switch(opcion){
            case 1:
                textprintf_ex(screen, font, MARGENLATERALTEXTO, INTERESPACIADO*2, makecol(0, 0, 0), -1,
                              "Columnas: %d. Escriba el nuevo valor", COLUMNA);
                COLUMNA=leerNumero();
                textprintf_ex(screen, font, MARGENLATERALTEXTO, INTERESPACIADO*3, makecol(0, 0, 0), -1,
                                  "Establecido en %d", COLUMNA);
                textprintf_ex(screen, font, MARGENLATERALTEXTO, INTERESPACIADO*5, makecol(0, 0, 0), -1,
                              "Filas: %d. Escriba el nuevo valor", FILA);
                FILA=leerNumero();
                textprintf_ex(screen, font, MARGENLATERALTEXTO, INTERESPACIADO*6, makecol(0, 0, 0), -1,
                                  "Establecido en %d", FILA);
                readkey();
                break;
            case 2:
                for(i=0, salto=0; i<NUMBARCOS; i++){
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, INTERESPACIADO*(salto+1), makecol(0, 0, 0), -1,
                                  "%d barcos de tamaño %d", numBarcos[i], i+1);
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, INTERESPACIADO*(salto+2), makecol(0, 0, 0), -1,
                                  "Especifique cuantos serán");
                    numBarcos[i]=leerNumero();
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, INTERESPACIADO*(salto+3), makecol(0, 0, 0), -1,
                                  "Establecido en %d", numBarcos[i]);
                    salto=salto+4;
                }
                readkey();
                break;
            case 3:
                return;
        }
    }
}

//Jugador contra ordenador
void jugador(){
    //allegro_init();
 int numMenu=3, opcion;
 int *jugador, *enemigo;
 char *menu2[]={
  "Colocar los barcos de forma automática.",
  "Colocar los barcos de forma manual",
  "Volver"
 };
 do{
  //muestro menú y pido opcion
  imprimirMenu(numMenu, menu2);
  opcion=(readkey() & 0xff)-48;
  //scanf("%d", &opcion);
 }while(!compruebaOpcion(1,numMenu, opcion));

 //voy inicializando
 jugador=(int*)malloc(sizeof(int)*FILA*COLUMNA); //inicializo matriz del jugador
 enemigo=(int*)malloc(sizeof(int)*FILA*COLUMNA); //inicializo matriz del ordenador
 //inicializo los tableros
 inicializarTablero(jugador);
 inicializarTablero(enemigo);

 //según la opcion...
 switch(opcion){
  case 2:
   //coloco barcos
   colocarBarcosManualmente(jugador);
   colocarBarcosAutomaticamente(enemigo);
   break;
  case 1:
   //coloco barcos
   colocarBarcosAutomaticamente(jugador);
   colocarBarcosAutomaticamente(enemigo);
   break;
  case 3:
   //por si no los vuelvo a usar, los libero
   free(jugador);
   free(enemigo);
   return; //salgo de aquí y regreso al menú principal
 }
 //comienzo a jugar!!
 bucleJuego(jugador, enemigo);
 free(jugador);
 free(enemigo);
}

//ordenador contra ordenador
void ordenador(){
    int ganador=FALSE;
 int fila, columna, colocacion, respuesta;
 int *jugador, *enemigo;

    jugador=(int*)malloc(sizeof(int)*FILA*COLUMNA); //inicializo matriz del jugador
 enemigo=(int*)malloc(sizeof(int)*FILA*COLUMNA); //inicializo matriz del ordenador
 //inicializo los tableros
 inicializarTablero(jugador);
 inicializarTablero(enemigo);
 //coloco barcos
 colocarBarcosAutomaticamente(jugador);
    colocarBarcosAutomaticamente(enemigo);

 imprimirTableroJuego(enemigo, jugador, TRUE);
    while(TRUE){
        //JUGADOR 1
        while(TRUE){
            //genero una tirada
            fila=aleatorio(1, FILA);
            columna=aleatorio(1, COLUMNA);
            respuesta=compruebaDisparo(jugador, fila, columna, FALSE);
            if(respuesta!=-1){break;}
        }

  if(respuesta==0){
   textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                             "%c%d -> Jugador 1 dió en agua", columna+64, fila);
  }else{
      textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                             "%c%d -> ¡Jugador 1 ha dado tocado!", columna+64, fila);
   if(compruebaGanador(jugador)){
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                             "¡¡Jugador 1 ha ganado!!");
                    ganador=TRUE;
            }
  }
  readkey();
  if(ganador){break;}
  limpiarMargenInferior();

  //JUGADOR 2
        while(TRUE){
            //genero una tirada
            fila=aleatorio(1, FILA);
            columna=aleatorio(1, COLUMNA);
            respuesta=compruebaDisparo(enemigo, fila, columna, TRUE);
            if(respuesta!=-1){break;}
        }

  if(respuesta==0){
   textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                             "%c%d -> Jugador 2 dió en agua", columna+64, fila);
  }else{
      textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                             "%c%d -> ¡Jugador 2 ha dado tocado!", columna+64, fila);
   if(compruebaGanador(enemigo)){
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                             "¡¡Jugador 2 ha ganado!!");
                    ganador=TRUE;
            }
  }
  readkey();
  if(ganador){break;}
  limpiarMargenInferior();

    }
    free(jugador);
 free(enemigo);
}

//bucle del juego en el que se van visualizando matrices, disparando hasta que uno de los dos gane
void bucleJuego(int *jugador, int *enemigo){
 int ganador=FALSE, salida=TRUE;
 int fila, columna, colocacion, respuesta;
 imprimirTableroJuego(enemigo, jugador, FALSE);
 while(TRUE){
  while(salida){
      textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, -1,
                                  "¿A dónde quieres disparar?");
      textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                                  "Introduce la letra");
            columna=(readkey() & 0xff);
            textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                             "Introduce el número");
            fila=leerNumero();
   limpiarMargenInferior();
   if(!compruebaRangoCasilla(fila, columna)){
                textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                        "Se pasó en la fila o columna, vuelva a seleccionar una casilla.");
                readkey();
                limpiarMargenInferior();
            }else{
                //formateo la casilla y compruebo si hay barco, si es así, marco tocado y devuelvo tamaño del barco
                respuesta=compruebaDisparo(enemigo, fila, columna, TRUE);
                if(respuesta!=-1){
                    salida=FALSE;
                }else{
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                        "La casilla ya estaba seleccionada, vuelva a seleccionar una casilla.");
                    readkey();
                    limpiarMargenInferior();
                }
            }
  }
  salida=TRUE;
  columna=toupper(columna);
  if(respuesta==0){
   textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                             "%c%d -> Diste en agua :(", columna, fila);
  }else{
   //printf("¡Tocado! es un barco de tamaño %d\n", respuesta-3);
   textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                             "%c%d -> ¡Tocado! es un barco de tamaño %d", columna, fila, respuesta-3);
            if(compruebaGanador(enemigo)){
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*3, BLACK, WHITE,
                             "¡¡¡¡Ha ganadooo!!!!");
                    ganador=TRUE;
            }
  }
  readkey();
  if(ganador){break;}
  limpiarMargenInferior();

        while(TRUE){
            //genero una tirada del enemigo
            fila=aleatorio(1, FILA);
            columna=aleatorio(1, COLUMNA);
            respuesta=compruebaDisparo(jugador, fila, columna, FALSE);
            if(respuesta!=-1){break;}
        }

  if(respuesta==0){
   //printf("Te dió en agua.\n");
   textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                             "%c%d -> Te dió en agua", columna+64, fila);
  }else{
      textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                             "%c%d -> ¡Tocado! :(", columna+64, fila);
   if(compruebaGanador(jugador)){
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*3, BLACK, WHITE,
                             "Ha perdido... :(");
                    ganador=TRUE;
            }
  }
  readkey();
  if(ganador){break;}
  limpiarMargenInferior();
 }
}

//comprueba que la opción esté dentro del rango
int compruebaOpcion(int min, int max, int opcion){
    if((opcion>=min && opcion<=max)){
        return TRUE;
    }else{
        return FALSE;
    }
}

//imprime el menú que se pasa por parámetros
void imprimirMenu(int numOpciones, char *opciones[]){
 int i, comienzoX=MARGENLATERALTEXTO*2, comienzoY=INTERESPACIADO*3, distancia=INTERESPACIADO;
    clear_bitmap(BUFFER);
    rectfill(BUFFER, 0, 0, ANCHOVENTANA, ALTOVENTANA, makecol(255, 255, 255)); //ventana en blanco
 for(i=0; i<numOpciones; i++){
        textprintf_ex(BUFFER, font, comienzoX, (comienzoY+(distancia*i)), makecol(0, 0, 0), -1, "%d. %s", i+1, *(opciones+i));
 }
 textprintf_ex(BUFFER, font, comienzoX-distancia, (comienzoY+(distancia*i+(distancia*2))), makecol(0, 0, 0), -1, "Seleccione su opción");

/***********************AAAAAAAAAAAAAARRRRRRRRRRGGGGGGGGGGGHHHHHHHHHHHHH!!!!!!!!!***********************
 BITMAP *punto;
     PALETTE paleta;
    punto=create_bitmap(500,500);
     punto = load_bitmap ("/home/dorian/barco.bmp", NULL);
        readkey ();
     draw_sprite (screen, punto, 0, 10);
     readkey ();
     destroy_bitmap (punto);*/

 blit(BUFFER, screen, 0,0,0,0,SCREEN_W, SCREEN_H);
}

//limpia el margen inferior usado para escribir
void limpiarMargenInferior(){
    rectfill(screen, 0, ALTOVENTANA-MARGENINFERIOR+10, ANCHOVENTANA, ALTOVENTANA, WHITE); //pintar el recuadro
}

//va pidiendo los datos de los barcos para ir colocándolos en la matriz
void colocarBarcosManualmente(int *matriz){
 int i, letra, numero, colocacion, pregunta=0, numDelBarco;
 char l;
 imprimirTablero(matriz);
 for(i=0; i<NUMBARCOS; i++){
  numDelBarco=numBarcos[i];
  while(numDelBarco>0){
   //printf("\n\n");
   switch(pregunta){
    case 0:
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, -1,
                                  "Estás colocando un barco de tamaño %d, te quedan %d barcos de ese tamaño.",
                                   i+1, numDelBarco);
     //printf("\nEstás colocando un barco de tamaño %d, te quedan %d barcos de ese tamaño para colocar.\n", i+1, numDelBarco);
     //printf("Introduzca número y letra de la casilla donde quiere colocarlo (separado por una coma): ");
     //scanf("%d, %c", &numero, &l);
     //letra=l;
     //while(getchar()!='\n');
     textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                                  "Introduce la letra");
                    letra=(readkey() & 0xff);
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                                  "Introduce el número");
                    numero=leerNumero();
     limpiarMargenInferior();
     if(compruebaRangoCasilla(numero, letra)){
      pregunta++;
     }else{
         textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                                  "Se pasó en la fila o columna, vuelva a seleccionar una casilla.");
                        readkey();
                        limpiarMargenInferior();
      //printf("Se pasó en la fila o columna, vuelva a seleccionar una casilla.\n");
     }
     break;
    case 1:
     //printf("¿Como quiere colocarlo?\n 1. Vertical\n 2. Horizontal\n(introduzca número): ");
     textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO, BLACK, WHITE,
                                  "¿Cómo quiere colocarlo?");
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                                  "1. Vertical");
                    textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*3, BLACK, WHITE,
                                  "2. Horizontal");

     //scanf("%d", &colocacion);
     colocacion=(readkey() & 0xff)-48;
     //while(getchar()!='\n');
     limpiarMargenInferior();
     if(colocacion==1 || colocacion==2){
      pregunta++;
     }else{
         textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                                  "Opción incorrecta, vuelva a introducirlo.");
      //printf("Opción incorrecta, vuelva a introducirlo.\n");
      readkey();
      limpiarMargenInferior();
     }
     break;
    case 2:
     pregunta=0;
     if(comprobacionEspacioParaBarco(numero, letra, colocacion, i+1, matriz)){
      numDelBarco--;
     }else{
         textprintf_ex(screen, font, MARGENLATERALTEXTO, ALTOVENTANA-MARGENINFERIOR+INTERESPACIADO*2, BLACK, WHITE,
                                  "El barco está en mal sitio, vuelva a colocarlo.");
      //printf("El barco está en mal sitio (fuera de tablero o con otro barco por el medio), vuelva a colocarlo\n");
      readkey();
      limpiarMargenInferior();
     }
     readkey();
   }
  }
 }
 rellenarAgua(matriz);
}

//comprueba que la casilla esté dentro del rango (lo formatea)
int compruebaRangoCasilla(int fila, int columna){
 fila--;
 if(fila<0 || fila>=FILA){
  return FALSE;
 }

 if(isalpha(columna)){
        if(isupper(columna)){
            columna=columna+32;
        }
  columna=columna-97;
 }else{
        columna--;
 }
 if(columna<0 || columna>=COLUMNA){
  return FALSE;
 }
 return TRUE;
}

//una vez comprobado que los datos son correctos (y está formateado la fila y columna), procedo a escribirlo en la matriz y dibujarlo
void colocarBarco(int fila, int columna, int orientacion, int tamano, int *matriz){
 int columnaFinal, filaFinal, posicion;
 int anchoCasilla, altoCasilla, color=makecol(0,200,0); //verde-barco;
 anchoCasilla=(ANCHOVENTANA-BORDELATERAL*2)/COLUMNA;
    altoCasilla=(ALTOVENTANA-MARGENINFERIOR-BORDESUPERIOR)/FILA;

 //selecciono la opcion que ha de incrementarse
 switch(orientacion){
  case HORIZONTAL:
   columnaFinal=columna+tamano-1; //hallo la columna final
   while(columna<=columnaFinal){
    posicion=COLUMNA*fila+columna; //posicion actual
    *(matriz+posicion)=tamano+3;
                rectfill(screen, BORDELATERAL+(columna*anchoCasilla), BORDESUPERIOR+(fila*altoCasilla),
                         BORDELATERAL+((columna+1)*anchoCasilla), BORDESUPERIOR+((fila+1)*altoCasilla), color); //pintar la casilla correspondiente
                rect(screen, BORDELATERAL+(columna*anchoCasilla), BORDESUPERIOR+(fila*altoCasilla),
                         BORDELATERAL+((columna+1)*anchoCasilla), BORDESUPERIOR+((fila+1)*altoCasilla), BLACK); //repintar el BORDELATERAL
    columna++;
   }
   break;
  case VERTICAL:
   filaFinal=fila+tamano-1; //hallo la fila final
   while(fila<=filaFinal){
    posicion=COLUMNA*fila+columna; //posicion actual
    *(matriz+posicion)=tamano+3;
    rectfill(screen, BORDELATERAL+(columna*anchoCasilla), BORDESUPERIOR+(fila*altoCasilla),
                         BORDELATERAL+((columna+1)*anchoCasilla), BORDESUPERIOR+((fila+1)*altoCasilla), color); //pintar la casilla correspondiente
                rect(screen, BORDELATERAL+(columna*anchoCasilla), BORDESUPERIOR+(fila*altoCasilla),
                         BORDELATERAL+((columna+1)*anchoCasilla), BORDESUPERIOR+((fila+1)*altoCasilla), BLACK); //repintar el BORDELATERAL
    fila++;
   }
   break;
 }
}

//comprueba que según la casilla, orientación y tamaño, ese barco pueda colocarse en la matriz dada y lo escribe si es correcto
int comprobacionEspacioParaBarco(int fila, int columna, int orientacion, int tamano, int *matriz){
 int filaFinal, columnaFinal, posicion;
     //char letra[]={columna};
 //compruebo si la columna necesita ser formateada
 if(isalpha(columna)){
        if(isupper(columna)){
            columna=columna+32;
        }
  columna=columna-97;
 }else{
        columna--;
 }

 //resto uno para ajustar indices
 fila--;

 //sumo a la fila o columna (según orientación) para hallar la casilla final y voy comprobando por el camino que no haya otros barcos
 switch(orientacion){
  case HORIZONTAL:
   columnaFinal=columna+tamano-1; //hallo la columna final
   if(columnaFinal>=COLUMNA){
    return FALSE;
   }

   while(columna<=columnaFinal){
    posicion=COLUMNA*fila+columna; //posicion actual
    if(*(matriz+posicion)!=0){
     return FALSE; //incorrecto, aborto operación
    }else{
     columna++; //correcto, avanzo una posicion
    }
   }
   columna--; //restauro el contador de las columnas
   //llegado aquí, no hay problemas por el camino y puedo escribirlo
   colocarBarco(fila, columna-tamano+1, orientacion, tamano, matriz);
   break;
  case VERTICAL:
   filaFinal=fila+tamano-1; //hallo la fila final
   if(filaFinal>=FILA){
    return FALSE;
   }
   while(fila<=filaFinal){
    posicion=COLUMNA*fila+columna;//posicion actual
    if(*(matriz+posicion)!=0){
     return FALSE; //incorrecto, aborto operación
    }else{
     fila++;//correcto, avanzo una posicion
    }
   }
   fila--; //restauro el contador de las filas
   //llegado aquí, no hay problemas por el camino y puedo escribirlo
   colocarBarco(fila-tamano+1, columna, orientacion, tamano, matriz);
   break;
 }
 return TRUE;
}

//relleno alrededor del barco dado con agua
void rellenarAguaAlrededor(int columna, int fila, int orientacion, int tamano, int *matriz){
 int posicion, filaFinal, columnaFinal, filaInicial, columnaInicial;
 switch(orientacion){
  case VERTICAL:
   printf("La fila y columna iniciales son: %d %d\n", fila, columna);
   filaFinal=fila+tamano-1; //hallo la fila final
   filaInicial=fila;

   //por encima del barco pongo un agua
   if(fila>0){//compruebo que pueda hacerlo
    fila--;
    posicion=COLUMNA*fila+columna;
    if(*(matriz+posicion)==NADA){
     *(matriz+posicion)=8;
    }
   }
   //me pongo a la izquierda del barco y voy rellenando (si puedo hacerlo)
   if(columna>0){
    columna--;
    while(fila<=filaFinal){
     posicion=COLUMNA*fila+columna;
     if(*(matriz+posicion)==NADA){
      *(matriz+posicion)=8;
     }
     fila++;
    }
    if(*(matriz+posicion)==NADA){
     *(matriz+posicion)=8;
    }
    //bajo uno más
    if(fila<FILA){//compruebo que pueda hacerlo
     fila++;
     posicion=COLUMNA*fila+columna;
     if(*(matriz+posicion)==NADA){
      *(matriz+posicion)=8;
     }
    }
    columna++; //recupero la posicion y añado justo debajo del barco
    if(*(matriz+posicion)==NADA){
     *(matriz+posicion)=8;
    }
   }
   //me pongo a la derecha del barco y voy rellenando (si puedo hacerlo)
   if(columna<COLUMNA){
    columna++;
    while(fila>=filaInicial){
     posicion=COLUMNA*fila+columna;
     if(*(matriz+posicion)==NADA){
      *(matriz+posicion)=8;
     }
     fila--;
    }
    if(*(matriz+posicion)==NADA){
     *(matriz+posicion)=8;
    }
    if(fila>0){//subo uno más si puedo
     fila--;
     posicion=COLUMNA*fila+columna;
     if(*(matriz+posicion)==NADA){
      *(matriz+posicion)=8;
     }
    }
   }
   break;
  case HORIZONTAL:
   /*columnaFinal=columna+tamano-1; //hallo la columna final
   columnaInicial=columna;

   //al lado del barco pongo un agua
   if(columna>0){//compruebo que pueda hacerlo
    columna--;
    posicion=COLUMNA*fila+columna;
    *(matriz+posicion)=AGUA;
   }
   //me pongo  arriba del barco y voy rellenando (si puedo hacerlo)
   if(fila>0){
    fila--;
    while(columna<columnaFinal){
     posicion=COLUMNA*fila+columna;
     *(matriz+posicion)=AGUA;
     columna++;
    }
    //voy a la derecha uno más
    if(columna<COLUMNA){//compruebo que pueda hacerlo
     columna++;
     posicion=COLUMNA*fila+columna;
     *(matriz+posicion)=AGUA;
    }
    fila--; //recupero la posicion
   }
   //me pongo abajo del barco y voy rellenando (si puedo hacerlo)
   if(fila<FILA){
    fila++;
    while(columna>=columnaInicial){
     posicion=COLUMNA*fila+columna;
     *(matriz+posicion)=AGUA;
     fila--;
    }
    if(columna>0){//voy más a la izquierda si puedo
     columna--;
     posicion=COLUMNA*fila+columna;
     *(matriz+posicion)=AGUA;
    }
   }*/
   break;
 }
}

//termino de rellenar el tablero con agua
void rellenarAgua(int *matriz){
 int i;
 for(i=0; i<FILA*COLUMNA; i++){
  if(*(matriz+i)==NADA){
   *(matriz+i)=AGUA;
  }
 }
}

//coloco los barcos aleatoriamente cuidando de no ponerlos juntos
void colocarBarcosAutomaticamente(int *matriz){
 int fila, columna, orientacion, i, numDelBarco;
 for(i=0; i<NUMBARCOS; i++){
  numDelBarco=numBarcos[i];
  while(numDelBarco>0){
   //selecciono una casilla al azar (los valores como si me los pasara el usuario porque después se ajustan indices)
   fila=aleatorio(1, FILA+1);
   columna=aleatorio(1, COLUMNA+1);
   //selecciono una orientación
   //orientacion=aleatorio(1,2);
   orientacion=1;
   //compruebo que sea correcto y lo escriba dado el caso
   if(comprobacionEspacioParaBarco(fila, columna, orientacion, i+1, matriz)){
    numDelBarco--;
    //siendo correcto, añado alrededor del barco agua para que no se ponga otro barco ahí
    //rellenarAguaAlrededor(columna-1, fila-1, orientacion, i+1, matriz);
   }
  }
 }
 rellenarAgua(matriz);
}

//inicializo la matriz a ceros
void inicializarTablero(int *matriz){
 int i;
 for(i=0; i<FILA*COLUMNA; i++){
  *(matriz+i)=NADA; //inicializo a 0 (NADA según la enumeración)
 }
}

//comprueba que uno de los dos haya ganado
int compruebaGanador(int *matriz){
    int i;
    for(i=0; i<FILA*COLUMNA; i++){
        if(*(matriz+i)>3){
            return FALSE;
        }
    }
    return TRUE;

}

//formateo la casilla y compruebo si hay barco, si es así, marco tocado y devuelvo tamaño del barco
//-1 si ya está usada
//0 si agua
//>=1 tamaño del barco tocado
int compruebaDisparo(int *matriz, int fila, int columna, int enemigo){
 int color, devuelta, anchoCasilla, altoCasilla;
 int ancho=ANCHOVENTANA-(BORDELATERAL*3), anadido=(ancho/2)+BORDELATERAL;
    anchoCasilla=(ancho/2)/COLUMNA;
    altoCasilla=(ALTOVENTANA-MARGENINFERIOR-BORDESUPERIOR)/FILA;
 fila--;
 if(isalpha(columna)){
        if(isupper(columna)){
            columna=columna+32;
        }
  columna=columna-97;
 }else{
        columna--;
 }
 int posicion=COLUMNA*fila+columna, barco;
 switch(*(matriz+posicion)){
        case 2://casilla utilizada
        case 3:
            devuelta=-1;
            break;
        case 1: //agua
            *(matriz+posicion)=TIROAGUA;
            color=makecol(50, 50, 150);
            devuelta=0;
            break;
        default: //barcos
            barco=*(matriz+posicion);
            *(matriz+posicion)=TOCADO;
            color=makecol(255, 0, 0); //rojo
            devuelta=barco;
            break;
 }

 //codigo para marcar la casilla
 if(devuelta!=-1){
        if(enemigo){
            rectfill(screen, BORDELATERAL+(columna*anchoCasilla), BORDESUPERIOR+(fila*altoCasilla),
                BORDELATERAL+((columna+1)*anchoCasilla), BORDESUPERIOR+((fila+1)*altoCasilla), color); //pintar la casilla correspondiente
            rect(screen, BORDELATERAL+(columna*anchoCasilla), BORDESUPERIOR+(fila*altoCasilla),
                BORDELATERAL+((columna+1)*anchoCasilla), BORDESUPERIOR+((fila+1)*altoCasilla), BLACK); //pintar el recuadro
        }else{
            rectfill(screen, BORDELATERAL+(columna*anchoCasilla)+anadido, BORDESUPERIOR+(fila*altoCasilla),
                BORDELATERAL+((columna+1)*anchoCasilla)+anadido, BORDESUPERIOR+((fila+1)*altoCasilla), color); //pintar la casilla correspondiente
            rect(screen, BORDELATERAL+(columna*anchoCasilla)+anadido, BORDESUPERIOR+(fila*altoCasilla),
                BORDELATERAL+((columna+1)*anchoCasilla)+anadido, BORDESUPERIOR+((fila+1)*altoCasilla), BLACK); //pintar el recuadro
        }
 }
 return devuelta;
}

//imprimo ambos tableros al mismo tiempo
void imprimirTableroJuego(int *enemigo, int *jugador, int barcos){
    int i,j, posicion, colorear=FALSE, contador=0, anadido;
 int anchoCasilla, altoCasilla, color, *matriz;
 int ancho=ANCHOVENTANA-(BORDELATERAL*3), alto=ALTOVENTANA-MARGENINFERIOR-BORDESUPERIOR;
    anchoCasilla=(ancho/2)/COLUMNA;
    altoCasilla=alto/FILA;

    clear_bitmap(BUFFER);
    rectfill(BUFFER, 0, 0, ANCHOVENTANA, ALTOVENTANA, makecol(255, 255, 255)); //fondo blanco
    rectfill(BUFFER, BORDELATERAL, BORDESUPERIOR, (anchoCasilla*COLUMNA)+BORDELATERAL,
             (altoCasilla*FILA)+BORDESUPERIOR, makecol(0, 0, 200)); //fondo de la matriz
    rectfill(BUFFER, (ancho/2)+BORDELATERAL*2, BORDESUPERIOR, (ancho/2)+(anchoCasilla*COLUMNA)+BORDELATERAL*2,
             (altoCasilla*FILA)+BORDESUPERIOR, makecol(0, 0, 200)); //el otro fondo de la matriz

    matriz=enemigo;
    anadido=0;
    //barcos=TRUE;
    while(contador<2){
        contador++;
        for(i=0; i<FILA; i++){
            for(j=0; j<COLUMNA; j++){
                posicion=COLUMNA*i+j;
                switch(*(matriz+posicion)){
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                    case 8:
                        if(barcos){
                            colorear=TRUE;
                        }else{
                            colorear=FALSE;
                        }
                        //caracter=*(matriz+posicion)-3+48;
                        color=makecol(0,200,0); //verde-barco
                        break;

                    case 2: //tiro agua
                        //caracter=174;
                        color=makecol(50, 50, 150); //ni idea
                        colorear=TRUE;
                        break;
                    case 3: //tocado
                        color=makecol(255, 0, 0); //rojo
                        colorear=TRUE;
                        break;
                    default: //agua, sin tiros
                        //caracter=32;
                        colorear=FALSE;
                        break;
                }
                if(colorear){
                    rectfill(BUFFER, BORDELATERAL+(j*anchoCasilla)+anadido, BORDESUPERIOR+(i*altoCasilla),
                             BORDELATERAL+((j+1)*anchoCasilla)+anadido, BORDESUPERIOR+((i+1)*altoCasilla), color); //pintar la casilla correspondiente
                }
            }
        }
        matriz=jugador;
        barcos=TRUE;
        anadido=(ancho/2)+BORDELATERAL;
    }
    rect(BUFFER, BORDELATERAL, BORDESUPERIOR, (anchoCasilla*COLUMNA)+BORDELATERAL, (altoCasilla*FILA)+BORDESUPERIOR, BLACK);
    rect(BUFFER, (ancho/2)+BORDELATERAL*2, BORDESUPERIOR, (ancho/2)+(anchoCasilla*COLUMNA)+BORDELATERAL*2, (altoCasilla*FILA)+BORDESUPERIOR, BLACK);
 for(i=1; i<COLUMNA; i++){
        vline(BUFFER, (anchoCasilla*i)+BORDELATERAL, BORDESUPERIOR, (altoCasilla*FILA)+BORDESUPERIOR, BLACK);
        vline(BUFFER, (anchoCasilla*i)+BORDELATERAL*2+(ancho/2), BORDESUPERIOR, (altoCasilla*FILA)+BORDESUPERIOR, BLACK);
    }
    for(i=1; i<FILA; i++){
        hline(BUFFER, BORDELATERAL, (altoCasilla*i)+BORDESUPERIOR, (anchoCasilla*COLUMNA)+BORDELATERAL, BLACK);
        hline(BUFFER, BORDELATERAL*2+(ancho/2), (altoCasilla*i)+BORDESUPERIOR, (ancho/2)+(anchoCasilla*COLUMNA)+BORDELATERAL*2, BLACK);
    }
    ponerTituloCasillas(TRUE);
 blit(BUFFER, screen, 0,0,0,0,SCREEN_W, SCREEN_H);
}

//imprimo un tablero
void imprimirTablero(int *matriz){
 int i,j, posicion, colorear=FALSE;
 int anchoCasilla, altoCasilla, color;
 int ancho=ANCHOVENTANA-BORDELATERAL*2, alto=ALTOVENTANA-MARGENINFERIOR-BORDESUPERIOR;
    anchoCasilla=ancho/COLUMNA;
    altoCasilla=alto/FILA;

    clear_bitmap(BUFFER);
    rectfill(BUFFER, 0, 0, ANCHOVENTANA, ALTOVENTANA, makecol(255, 255, 255)); //fondo blanco
    rectfill(BUFFER, BORDELATERAL, BORDESUPERIOR, (anchoCasilla*COLUMNA)+BORDELATERAL,
             (altoCasilla*FILA)+BORDESUPERIOR, makecol(0, 0, 200)); //fondo de la matriz

 //char caracter;
 for(i=0; i<FILA; i++){
  for(j=0; j<COLUMNA; j++){
   posicion=COLUMNA*i+j;
   switch(*(matriz+posicion)){
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
     //caracter=*(matriz+posicion)-3+48;
                    color=makecol(0,200,0); //verde-barco
                    colorear=TRUE;
     break;

    case 2: //tiro agua
     //caracter=174;
     color=makecol(50, 50, 150); //ni idea
     colorear=TRUE;
     break;
                case 3: //tocado
                    color=makecol(255, 0, 0); //rojo
                    colorear=TRUE;
                    break;
    default: //agua, sin tiros
     //caracter=32;
     colorear=FALSE;
     break;

   }
            if(colorear){
                rectfill(BUFFER, BORDELATERAL+(j*anchoCasilla), BORDESUPERIOR+(i*altoCasilla),
                         BORDELATERAL+((j+1)*anchoCasilla), BORDESUPERIOR+((i+1)*altoCasilla), color); //pintar la casilla correspondiente
   }
  }
 }
 rect(BUFFER, BORDELATERAL, BORDESUPERIOR, (anchoCasilla*COLUMNA)+BORDELATERAL, (altoCasilla*FILA)+BORDESUPERIOR, BLACK);
 for(i=1; i<COLUMNA; i++){
        vline(BUFFER, (anchoCasilla*i)+BORDELATERAL, BORDESUPERIOR, (altoCasilla*FILA)+BORDESUPERIOR, BLACK);
    }
    for(i=1; i<FILA; i++){
        hline(BUFFER, BORDELATERAL, (altoCasilla*i)+BORDESUPERIOR, (anchoCasilla*COLUMNA)+BORDELATERAL, BLACK);
    }
    ponerTituloCasillas(FALSE);
 blit(BUFFER, screen, 0,0,0,0,SCREEN_W, SCREEN_H);
}

//coloca las letras y números alrededor de la tabla
void ponerTituloCasillas(int dosTablas){
    int letra='A', i;
    int anchoCasilla, altoCasilla, ancho, alto;

    if(dosTablas){
        ancho=ANCHOVENTANA-(BORDELATERAL*3);
        alto=ALTOVENTANA-MARGENINFERIOR-BORDESUPERIOR;
        anchoCasilla=(ancho/2)/COLUMNA;
        altoCasilla=alto/FILA;
        for(i=0; i<COLUMNA; i++){
            textprintf_ex(BUFFER, font, BORDELATERAL+(i*anchoCasilla)+(anchoCasilla/2), BORDESUPERIOR/2, BLACK, -1,
                                  "%c", letra+i);
            textprintf_ex(BUFFER, font, BORDELATERAL*2+(ancho/2)+(i*anchoCasilla)+(anchoCasilla/2), BORDESUPERIOR/2, BLACK, -1,
                                  "%c", letra+i);
        }
        for(i=0; i<FILA; i++){
            textprintf_ex(BUFFER, font, BORDELATERAL/2, BORDESUPERIOR+(i*altoCasilla)+(altoCasilla/2) , BLACK, -1,
                                  "%d", i+1);
            textprintf_ex(BUFFER, font, (BORDELATERAL/2)+(ancho/2)+BORDELATERAL, BORDESUPERIOR+(i*altoCasilla)+(altoCasilla/2) , BLACK, -1,
                                  "%d", i+1);
            textprintf_ex(BUFFER, font, (BORDELATERAL/2)+(ancho)+BORDELATERAL*2, BORDESUPERIOR+(i*altoCasilla)+(altoCasilla/2) , BLACK, -1,
                                  "%d", i+1);
        }

    }else{
        ancho=ANCHOVENTANA-BORDELATERAL*2;
        alto=ALTOVENTANA-MARGENINFERIOR-BORDESUPERIOR;
        anchoCasilla=ancho/COLUMNA;
        altoCasilla=alto/FILA;
        for(i=0; i<COLUMNA; i++){
            textprintf_ex(BUFFER, font, BORDELATERAL+(i*anchoCasilla)+(anchoCasilla/2), BORDESUPERIOR/2, BLACK, -1,
                                  "%c", letra+i);
        }
        for(i=0; i<FILA; i++){
            textprintf_ex(BUFFER, font, BORDELATERAL/2, BORDESUPERIOR+(i*altoCasilla)+(altoCasilla/2) , BLACK, -1,
                                  "%d", i+1);
            textprintf_ex(BUFFER, font, (BORDELATERAL/2)+(ancho)+BORDELATERAL, BORDESUPERIOR+(i*altoCasilla)+(altoCasilla/2) , BLACK, -1,
                                  "%d", i+1);
        }
    }
}

//genero un número aleatorio, min y max incluidos
int aleatorio(int min, int max){
 int aleatorio;
 aleatorio=rand()%(max-min+1);
 aleatorio=aleatorio+min;
 return aleatorio;
}

//leo un número
int leerNumero(){
    int lectura, resultado=0;
    do{
        lectura=(readkey() & 0xff)-48;
        if(lectura>=0 && lectura<=9){
            resultado=resultado*10+lectura;
        }else{
            break;
        }
    }while(TRUE);
    return resultado;
}

Etiquetas: ,,. Guarda el enlace permanente.

Deja un comentario ^^