Jogo do Labirinto no Terminal
Publicado por Samuel Leonardo (última atualização em 14/05/2021)
[ Hits: 7.799 ]
Homepage: https://nerdki.blogspot.com.br/
Download labirintoC-1.0.0.tar.gz
Este é um pequeno programa que fiz há uns anos atrás. É apenas uma versão de jogo do labirinto em C. Você pode criar uma matriz de caracteres num arquivo chamado matrizLabirinto.txt e depois executar o jogo.
Para compilar:
$ gcc -o labirintoC labirintoC.c
Para executar:
$ ./labirintoC
Você pode baixar o pacote tar.gz e ver uma matriz de exemplo.
Se for criar a sua lembre que, a condição para ler a matriz é: ela deve ter o mesmo número de colunas. Ou seja, as linhas do matrizLabirinto.txt devem ter a mesma quantidade de caracteres. Os caracteres usados são o '.' (ponto) para caminho vazio, e o '#' para parede sólida, '@' é o jogador e a saída do labirinto é o 'E'.
/** * @file labirintoC.c * @author Samuel Leonardo (nerdki.blogspot.com.br) * @brief Pequeno jogo do labirinto em C * @version 1.0.0 * @date 2019-11-15 * * @copyright Samuel Leonardo (c) 2019 * para compilar use: * gcc -o labirintoC labirintoC.c * */ //jogo do labirinto em C #include <stdio.h> #include <stdlib.h> #include <ctype.h> #include <string.h> //struct do mapa typedef struct { //largura atual do mapa int largura; //altura atual do mapa int altura; //largura máxima que este mapa pode ter int maxLargura; //altura máxima que este mapa pode ter int maxAltura; //a matriz que guarda os caracteres do mapa char **matriz; } Mapa; /** * Inicia um novo labirinto * jogadorCol/Linha é a posição do jogador dentro da matriz */ Mapa * criarMapa ( int largura, int altura ) { Mapa * mapa = NULL; //aloca memória para o mapa mapa = (Mapa *)malloc(sizeof(Mapa)); if (!mapa) { printf("criarMapa::erro ao alocar novo mapa\n"); exit(1); } mapa->largura = largura; mapa->altura = altura; mapa->maxLargura = largura; mapa->maxAltura = altura; //aloca uma matriz com 'altura' ponteiros; mapa->matriz = (char **)malloc(sizeof(char *) * altura); //agora aloca a matriz for (int i = 0; i < altura; i++) { //NOTA: coloquei o +1 aqui para dar espaço ao '\0' (caractere nulo) mapa->matriz[i] = (char *)malloc(sizeof(char) * (largura + 1)); if (!mapa->matriz[i]) { printf("mapa->matriz[%d] não foi alocada.\n", i); exit(1); } //agora inicia os elementos da linha com 0 for (int j = 0; j < largura; j++) mapa->matriz[i][j] = 0; } //agora retorna o mapa return mapa; } void destruirMapa ( Mapa * mapa ) { if (mapa) { if (mapa->matriz) { //deleta a memoria da matriz int i = 0; for (; i < mapa->maxAltura; i++) { //deleta as linhas free(mapa->matriz[i]); } free(mapa->matriz); mapa->matriz = NULL; } free(mapa); mapa = NULL; } } //retorna 0 se der erro na leitura da matriz do arquivoMatriz //retorn 1 em caso de conseguir ler o arquivoMatriz int lerMatriz ( Mapa * mapa, const char * arquivoMatriz ) { if (!mapa) return 0; FILE * arquivo = fopen(arquivoMatriz, "r"); //verifica se abriu o arquivo normalmente (sem erros) if (!arquivo) { //see ntrou aqui é porque teve problemas ao abrir o arquivo printf("lerMatriz, deu erro ao ler o arquivo %s\n", arquivoMatriz); return 0; } //se estamos aqui foi porque o arquivo abriu sem problemas //agora vamos ler as células da matriz //NOTA: lembre-se que, a matriz é no máximo a largura de mapa->largura e // altura máxima de mapa->altura //quantidade de caracteres lidos int qtdeLidos = 0; int linhas = 0; int colunas = 0; int caractere = 0; for (; caractere != EOF && qtdeLidos < mapa->maxAltura * mapa->maxLargura; ) { caractere = fgetc(arquivo); //se não for um caractere visível if (isblank(caractere) || isprint(caractere) == 0 || caractere == EOF) { if (caractere == '\n' && colunas > 0) { if (colunas >= mapa->maxLargura) { printf("Erro temos uma linha com maior largura que o mapa"); break; } mapa->largura = colunas; colunas = 0; linhas++; //verifica se estamos no máximo de linhas if (linhas >= mapa->maxAltura) //se sim, quebra o loop break; } //pule o loop continue; } colunas++; //agora incrementa o contador de caracteres lidos qtdeLidos++; //agora coloca o caractere na posição na matriz //primeiro pega a linha atual int linhaAtual = linhas; //agora pega a coluna atual int colunaAtual = colunas - 1; if (linhas != 0) //essa coluna é somente o resto da divisão de qtdeLidos por mapa->largura colunaAtual = qtdeLidos % mapa->largura; //e por fim, bota o caractere no mapa mapa->matriz[linhaAtual][colunaAtual] = (char)caractere; } //por fim, fecha o arquivo fclose(arquivo); //se caso a gente ler menos linhas, coloca a nova altura if (linhas + 1 < mapa->maxAltura) { mapa->altura = linhas + 1; printf("lerMatriz::Leu um tamanho menor de matriz\nAgora o mapa tem tamanho: %dx%d\n", mapa->largura, mapa->altura); } //retorna 1 se der certo a leitura do mapa return 1; } typedef struct { int linhaAtual; int colunaAtual; int linhaInicial; int colunaInicial; char caractere; //caracteres do mapa que são sólidos, isso é pro player colidir char solidos[64]; } Jogador; Jogador * criarJogador ( int linhaInicial, int colunaInicial, char caractere, const char * solidos ) { Jogador * jogador = NULL; jogador = (Jogador *)malloc(sizeof(Jogador)); if (!jogador) { printf("criarJogador::deu erro ao criar novo jogador\n"); exit(1); } jogador->linhaAtual = linhaInicial; jogador->colunaAtual = colunaInicial; jogador->linhaInicial = linhaInicial; jogador->colunaInicial = colunaInicial; jogador->caractere = caractere; strcpy(jogador->solidos, solidos); return jogador; } void destruirJogador ( Jogador * jogador ) { if (jogador) { free(jogador); jogador = NULL; } } int ehSolido ( Mapa * mapa, int linha, int coluna, char * solidos ) { //por padrão, retornamos 1 pro caso de estar fora dos limites do mapa->matriz if (linha < 0 || linha >= mapa->altura) return 1; if (coluna < 0 || coluna >= mapa->largura) return 1; //coloca o ponteiro no começo da string de sólidos char * c = solidos; for (; *c != '\0'; c++) //se achar o caractere, etnão é sólido if (*c == mapa->matriz[linha][coluna]) return 1; //em linha coluna não é sólido return 0; } //retorna 0 se não pode mover na direcao //retorna 1 se pode mover o jogador na direacao int podeMover ( Mapa * mapa, int linhaAtual, int colunaAtual, char direcao, char * solidos ) { int ret = 0; switch (direcao) { case 'W': case 'w': if (linhaAtual - 1 >= 0) ret = 1; if (ehSolido(mapa, linhaAtual - 1, colunaAtual, solidos)) ret = 0; break; case 'S': case 's': if (linhaAtual + 1 < mapa->altura) ret = 1; if (ehSolido(mapa, linhaAtual + 1, colunaAtual, solidos)) ret = 0; break; case 'A': case 'a': if (colunaAtual - 1 >= 0) ret = 1; if (ehSolido(mapa, linhaAtual, colunaAtual - 1, solidos)) ret = 0; break; case 'D': case 'd': if (colunaAtual + 1 < mapa->largura) ret = 1; if (ehSolido(mapa, linhaAtual, colunaAtual + 1, solidos)) ret = 0; break; } return ret; } void limparEntrada ( ) { int c = 0; do { c = fgetc(stdin); } while (c != EOF && c != '\n'); } //faz mover o jogador //retorna 1 se conseguir mover //retorna 0 se não conseguir int moverJogador ( Jogador * jogador, Mapa * mapa ) { char direcao = 0; printf("Depois de digitar a direção, aperte enter para mover\n"); printf("Escolha a direção para mover:\n"); printf("W ou w move pra cima\n"); printf("S ou s move pra baixo\n"); printf("A ou a move pra esquerda\n"); printf("D ou d move pra direita\n"); printf("Digite sua escolha: \n"); direcao = (char)fgetc(stdin); limparEntrada(); //verifica se pode mover o jogador na direcao if (podeMover(mapa, jogador->linhaAtual, jogador->colunaAtual, direcao, jogador->solidos)) { //se sim, então, move o jogador na direção que ele pode mover switch (direcao) { //move o jogador pra cima case 'W': case 'w': jogador->linhaAtual--; return 1; //move o jogador pra baixo case 'S': case 's': jogador->linhaAtual++; return 1; //move o jogador para esquerda (esquerdopata!) case 'A': case 'a': jogador->colunaAtual--; return 1; //move o jogador para direita (coxinha!) case 'D': case 'd': jogador->colunaAtual++; return 1; //se não for uma direção válida, apenas sai do switch default: break; } } //se retornou 0 é porque não conseguiu mover o jogador return 0; } void desenharMapa (Mapa * mapa, Jogador * jogador) { for (int i = 0; i < mapa->altura; i++) { for (int j = 0; j < mapa->largura; j++) { //verifica se é o caractere do jogador if (jogador && jogador->linhaAtual == i && jogador->colunaAtual == j) { printf("%c", jogador->caractere); continue; } //desenha um caractere da matriz printf("%c", mapa->matriz[i][j]); } //pula uma linha, mas apenas se não ler um '\n' no final de matriz[i] if (mapa->matriz[i][mapa->largura - 1] != '\n') printf("\n"); } } //apenas uma pequena função auxiliar de limpar a tela void limparTela ( ) { for (int i = 0; i < 200; i++) { printf("\n"); } } //caso não saiba o que significa esses dois parâmetros: //argc = numero de parametros passados depois do nome do executável: ex.: ./labirintoC parametro0 //argv = os parametros em forma de strings de char, // tipo, "./labirintoC" será o argv[0], "parametro0" será o argv[1] int main (int argc, char **argv) { //cria um mapa de 100x100 caracteres Mapa * mapa = criarMapa(100, 100); //agora inicia a matriz do labirinto if (lerMatriz(mapa, "matrizLabirinto.txt") == 0) { printf("Erro ao ler arquivo de matriz\n"); exit(1); } //cria um novo jogador na posição linha=0, coluna=0 //era para apenas colocar sozinho o jogador na matriz //NOTA: rever código antes de postar no blog Jogador * jogador = criarJogador(0,0,'@',"#"); //loop do jogo do { //primeiro limpa a tela limparTela(); //depois desenha o mapa e o jogador juntos desenharMapa(mapa, jogador); //agora pergunta pra onde movber o jogador moverJogador(jogador, mapa); //veirifica se é o final do jogo } while (mapa->matriz[jogador->linhaAtual][jogador->colunaAtual] != 'E'); //caso saida do loop //destrua o jogador (desaloque mem[oria dele]) destruirJogador(jogador); //destrua o mapa (desaloca memoria da matriz) destruirMapa(mapa); return 0; }
Retorna o número elevado ao quadrado
Tabela hash com classes e tratamento de colisões por encadeamento
Passkeys: A Evolução da Autenticação Digital
Instalação de distro Linux em computadores, netbooks, etc, em rede com o Clonezilla
Título: Descobrindo o IP externo da VPN no Linux
Armazenando a senha de sua carteira Bitcoin de forma segura no Linux
Enviar mensagem ao usuário trabalhando com as opções do php.ini
Instalando Brave Browser no Linux Mint 22
vídeo pra quem quer saber como funciona Proteção de Memória:
Encontre seus arquivos facilmente com o Drill
Mouse Logitech MX Ergo Advanced Wireless Trackball no Linux
Compartilhamento de Rede com samba em modo Público/Anônimo de forma simples, rápido e fácil
PC não liga no filtro de linha (3)
Desde que seja DDR3, posso colocar qualquer memória? (3)
Instalar sem formatar, pergunta meio boba. [RESOLVIDO] (7)
Curso gratuito Defesa de redes 10ª Maratona CiberEducação Cisco Brasil... (0)