/* ************************************************************ */ /* Nome do aluno: Danilo R. Vieira Número USP: 5653262 */ /* Curso: Bach. em Oceanografia Data: 09/11/2007 */ /* MAC-115 Introdução à Computação */ /* Exercício Programa número 4 */ /* ************************************************************ */ #include #include #include /* Declaração de constantes */ #define MAXLIN 20 #define MAXCOL 22 #define MAXNOME 31 /* Cabecalhos de funcoes */ void leia_ate_fim_linha(FILE *arq); void leia_mapa(int *plin, int *pcol, char mapa[][MAXCOL]); void escreva_mapa_tela(char mapa[][MAXCOL], int nlin, int ncol); void escreva_mapa_arquivo(FILE *arq, char mapa[][MAXCOL], int nlin, int ncol); int coluna_inicial_barco(char mapa[][MAXCOL], int ncol); int rema_barco(FILE *arq, char mapa[][MAXCOL], int *barco_lin, int *barco_col); int num_aleatorio(int k); int dispara_tiros(FILE *arq, char mapa[][MAXCOL], int nlin, int ncol); int main () { /* Declaração de variáveis */ char mapa[MAXLIN][MAXCOL]; /* Armazena o mapa */ int i, /* variável para os laços for que preenchem a margem */ nlin, /* numero de linhas no mapa */ ncol, /* numero de colunas no mapa */ barco_lin, /* linha na qual o barco encontra-se */ barco_col, /* coluna na qual o barco encontra-se */ njogada, /* numero da jogada atual */ fim_de_jogo; /* armazena 1 caso ocorra alguma * das condiçoes que encerram o jogo */ FILE *arqsaida; /* arquivo de saída */ char nomearq[MAXNOME]; /* nome do arquivo de saida */ srand((unsigned int) time(NULL)); leia_mapa(&nlin, &ncol, mapa); printf("Digite o nome (maximo %d caracteres) do arquivo de saida :\n", MAXNOME-1); scanf("%s", nomearq); arqsaida = fopen(nomearq, "w"); if (arqsaida == NULL) { printf("ERRO: nao foi possivel criar o arquivo %s\n", nomearq); exit(-1); } fprintf(arqsaida, "*****************************" "*****************************\n" "* Nome do aluno: Danilo R. Vieira " "Numero USP: 5653262 *\n" "*****************************" "*****************************\n\n"); /* faz as margens ao redor do mapa */ for (i = 0; i <= ncol+1; i++) mapa[0][i] = mapa[nlin+1][i] = '#'; for (i = 1; i <= nlin; i++) mapa[i][0] = mapa[i][ncol+1] = '#'; /* Inicialização de variáveis */ barco_col = coluna_inicial_barco(mapa, ncol); fprintf(arqsaida, "Usuario escolheu a coluna %d\n\n",barco_col); barco_lin = njogada = 1; fim_de_jogo = 0; escreva_mapa_tela(mapa, nlin, ncol); escreva_mapa_arquivo(arqsaida, mapa, nlin, ncol); while (!fim_de_jogo) { fprintf(arqsaida, "\n----------- Jogada %d -----------\n", njogada); njogada++; rema_barco(arqsaida, mapa, &barco_lin, &barco_col);//, nlin, ncol); if (dispara_tiros(arqsaida, mapa, nlin, ncol)) { printf("+-----------------------------------------+\n" "| Seu barco foi atingido por um tiro! |\n" "| --- FIM DE JOGO --- |\n" "+-----------------------------------------+\n"); fprintf(arqsaida, "\nFim de jogo. Motivo: o barco foi atingido.\n"); fim_de_jogo = 1; } else if (!fim_de_jogo && (barco_lin == nlin)) { printf("+-----------------------------------------+\n" "| Seu barco atravessou em seguranca! |\n" "| --- VOCE GANHOU! --- |\n" "+-----------------------------------------+\n"); fprintf(arqsaida, "\nFim de jogo. Motivo: o barco atravessou em seguranca.\n"); fim_de_jogo = 1; } } fclose(arqsaida); system("PAUSE"); return 0; } /* funcao leia_ate_fim_linha(arq); * Lê caracteres do arquivo associado * a arq até que um fim-de-linha (’\n’) seja lido. */ void leia_ate_fim_linha(FILE *arq) { char carac; fscanf(arq, "%c", &carac); while (carac != '\n') fscanf(arq, "%c", &carac); } /* funcao leia_mapa(*plin, *pcol, mapa); * Lê de um dado arquivo dois inteiros nlin e ncol, e uma matriz * de caracteres com nlin linhas e ncol colunas (representando um * mapa de uma região), e armazena em *plin o valor de nlin, * em *pcol o valor de ncol, e em mapa a matriz de caracteres lida. */ void leia_mapa(int *plin, int *pcol, char mapa[][MAXCOL]) { FILE *arqentrada; /* Arquivo de entrada */ char nomearq[MAXNOME]; /* Nome do arquivo de entrada */ int i, /* "Percorre" as linhas */ j; /* "Percorre" as colunas */ printf("Digite o nome (maximo %d caracteres) do arquivo de entrada :\n", MAXNOME-1); scanf("%s", nomearq); arqentrada = fopen(nomearq, "r"); if (arqentrada == NULL) { printf("ERRO: nao foi possivel abrir arquivo %s\n", nomearq); exit(-1); } fscanf(arqentrada, "%d %d", plin, pcol); leia_ate_fim_linha(arqentrada); for (i = 1; i <= *plin; i++) { for (j = 1; j <= *pcol; j++) fscanf(arqentrada, "%c", &mapa[i][j]); leia_ate_fim_linha(arqentrada); } fclose(arqentrada); } /* funcao escreva_mapa_tela(mapa, nlin, ncol); * Recebe uma matriz mapa com nlin linhas e ncol colunas, e * escreve na tela o mapa (visível para o jogador), destacando * cada uma de suas posições, e escreve também os índices de * cada linha e coluna. */ void escreva_mapa_tela(char mapa[][MAXCOL], int nlin, int ncol) { int i, j; printf(" "); for (j = 1; j <= ncol; j++) printf("%2d ",j); printf("\n"); printf(" +"); for (j = 1; j <= ncol; j++) printf("---"); printf("+\n"); for (i = 1; i <= nlin; i++) { printf("%2d |", i); for (j = 1; j <= ncol; j++) switch (mapa[i][j]) { case '*': case 'B': case '+': printf(" %c ", mapa[i][j]); break; default: printf(" . "); break; } printf("|\n"); } printf(" +"); for (j = 1; j <= ncol; j++) printf("---"); printf("+\n"); } /* funcao escreva_mapa_arquivo(*arq, mapa, nlin, ncol); * Recebe uma matriz mapa com nlin linhas e ncol colunas, e * escreve mapa no arquivo associado a arq. Escreve também * os índices de cada linha e coluna da matriz. */ void escreva_mapa_arquivo(FILE *arq, char mapa[][MAXCOL], int nlin, int ncol) { int i, j; fprintf(arq, " "); for (j = 1; j <= ncol; j++) fprintf(arq, "%2d ",j); fprintf(arq, "\n"); fprintf(arq, " +"); for (j = 1; j <= ncol; j++) fprintf(arq, "---"); fprintf(arq, "+\n"); for (i = 1; i <= nlin; i++) { fprintf(arq, "%2d |", i); for (j = 1; j <= ncol; j++) fprintf(arq, " %c ", mapa[i][j]); fprintf(arq, "|\n"); } fprintf(arq, " +"); for (j = 1; j <= ncol; j++) fprintf(arq, "---"); fprintf(arq, "+\n"); } /* funcao coluna_inicial_barco(mapa, ncol); * Lê (via teclado) um índice de coluna para a posição inicial * do barco, marca com ’B’ esta posição na matriz mapa, e devolve * este índice. O inteiro ncol representa o número de colunas * da matriz mapa. */ int coluna_inicial_barco(char mapa[][MAXCOL], int ncol) { int col_barco; printf("Por favor, digite a coluna inicial do barco\n" "(um inteiro entre 1 e %d, inclusive):\n", ncol); scanf("%d", &col_barco); while (mapa[1][col_barco] != '-' || (col_barco < 1 || col_barco > ncol)) { printf("Desculpe, mas a posicao especificada nao pode ser ocupada.\nMotivos possiveis:\n" "- Ja ha uma embarcacao nesta posicao;\n" "- O numero digitado nao se encontra no intervalo 1 e %d.\n" "Por favor, digite outra posicao (um inteiro entre 1 e %d):\n", ncol, ncol); scanf("%d", &col_barco); } mapa[1][col_barco] = 'B'; return col_barco; } /* funcao rema_barco(*arq, mapa, *barco_lin, *barco_col); * Vai tentar movimentar o barco ou para baixo (na direção da * última linha) ou na horizontal, tomando cuidado para não ir * para uma posição ocupada por alguma embarcação ou uma * posição inválida da matriz. */ int rema_barco(FILE *arq, char mapa[][MAXCOL], int *barco_lin, int *barco_col) { char movimento; printf("Comandos:\n" "B para mover o barco para baixo;\n" "D para mover o barco para a direita; E para mover o barco para a esquerda.\n"); scanf(" %c", &movimento); switch (movimento) { case 'B': case 'b': if (mapa[*barco_lin+1][*barco_col] == '*' || mapa[*barco_lin+1][*barco_col] == '-') { mapa[*barco_lin][*barco_col] = '-'; (*barco_lin)++; mapa[*barco_lin][*barco_col] = 'B'; printf("+-----------------------------------------+\n" "| O barco foi para baixo |\n" "+-----------------------------------------+\n"); fprintf(arq, "O barco foi para baixo.\n"); return 1; } break; case 'D': case 'd': if (mapa[*barco_lin][*barco_col+1] == '*' || mapa[*barco_lin][*barco_col+1] == '-') { mapa[*barco_lin][*barco_col] = '-'; (*barco_col)++; mapa[*barco_lin][*barco_col] = 'B'; printf("+-----------------------------------------+\n" "| O barco foi para a direita |\n" "+-----------------------------------------+\n"); fprintf(arq, "O barco foi para a direita\n"); return 1; } break; case 'E': case 'e': if (mapa[*barco_lin][*barco_col-1] == '*' || mapa[*barco_lin][*barco_col-1] == '-') { mapa[*barco_lin][*barco_col] = '-'; (*barco_col)--; mapa[*barco_lin][*barco_col] = 'B'; printf("+-----------------------------------------+\n" "| O barco foi para a esquerda |\n" "+-----------------------------------------+\n"); fprintf(arq, "O barco foi para a esquerda.\n"); return 1; } break; } printf("+-----------------------------------------+\n" "| Nao e' possivel seguir nessa direcao! |\n" "+-----------------------------------------+\n"); fprintf(arq, "O usuario tentou efetuar um movimento invalido (%c).\n", movimento); return 0; } /* funcao num_aleatorio(k); * Esta função recebe um inteiro k, e devolve um inteiro no * intervalo [1, k]. */ int num_aleatorio(int k) { return (int)(1 + (rand() / (RAND_MAX + 1.0)) * k); } /* funcao dispara_tiros(*arq, mapa, nlin, ncol); * Esta função determina as posições dos três tiros a serem * disparados pelo computador, e escrever (tela e arquivo) * a posição de cada tiro e as mensagens correspondentes ao * efeito de cada tiro. * * Retorna 1 se o barco for atingido e 0 em caso contrário */ int dispara_tiros(FILE *arq, char mapa[][MAXCOL], int nlin, int ncol){ int i, n, m, lin, col, cont; for (i = 1; i<=3; i++) { lin = num_aleatorio(nlin); col = num_aleatorio(ncol); fprintf(arq, "\n--- Tiro ---\nLinha: %d\nColuna: %d\n", lin, col); printf("\n--- Tiro ---\nLinha: %d\nColuna: %d\n", lin, col); cont = 0; switch (mapa[lin][col]) { case 'B': /* O barco foi atingido */ mapa[lin][col] = '+'; escreva_mapa_tela(mapa, nlin, ncol); fprintf(arq, "O barco foi atingido.\n"); escreva_mapa_arquivo(arq , mapa, nlin, ncol); return 1; case 'S': /* Um submarino foi atingido */ fprintf(arq, "Um submarino foi atingido.\n"); printf("Um submarino foi atingido.\n"); mapa[lin][col] = '*'; break; case 'D': /* Um destroyer foi atingido */ fprintf(arq, "Um destroyer foi atingido.\n"); printf("Um destroyer foi atingido.\n"); for (n = -1; n <= 1 && cont < 2; n++) for (m = -1; m <= 1 && cont < 2; m++) if (mapa[lin+n][col+m] == 'D') { mapa[lin+n][col+m] = '*'; cont++; } break; case 'C': /* Um cruzador foi atingido */ fprintf(arq, "Um cruzador foi atingido.\n"); printf("Um cruzador foi atingido.\n"); for (n = -1; n <= 1 && cont < 4; n++) for (m = -1; m <= 1 && cont < 4; m++) if (mapa[lin+n][col+m] == 'C') { mapa[lin+n][col+m] = '*'; cont++; } break; case 'P': /* Um porta-avioes foi atingido */ fprintf(arq, "Um porta-avioes foi atingido.\n"); printf("Um porta-avioes foi atingido.\n"); if ((mapa[lin+1][col] == 'P')||(mapa[lin-1][col] == 'P')) { /* O porta-aviões está na vertical */ for (n = 0; mapa[lin+n][col] == 'P' && cont < 4; cont++, n++) mapa[lin+n][col] = '*'; for (n = 1; mapa[lin-n][col] == 'P' && cont < 4; cont++, n++) mapa[lin-n][col] = '*'; } else { /* O porta-aviões está na horizontal */ for (n = 0; mapa[lin][col+n] == 'P' && cont < 4; n++, cont++) mapa[lin][col+n] = '*'; for (n = 1; mapa[lin][col-n] == 'P' && cont < 4; n++, cont++) mapa[lin][col-n] = '*'; } break; default: /* Nenhuma embarcacao foi atingida */ fprintf(arq, "O tiro nao acertou nenhuma embarcacao.\n"); printf("O tiro nao acertou nenhuma embarcacao.\n"); break; } escreva_mapa_tela(mapa, nlin, ncol); escreva_mapa_arquivo(arq , mapa, nlin, ncol); } return 0; }