Untitled

 avatar
unknown
plain_text
24 days ago
6.0 kB
11
Indexable
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <ctype.h>

#define TMAX_MATRIZ 26

typedef struct {
    char tabuleiro[TMAX_MATRIZ][TMAX_MATRIZ];
    int linhas, colunas;
    bool carregouTabuleiro;
    bool looping;
} Estado;

// Define um tipo de ponteiro chamado comando que aponta para uma função que retorna bool e recebe aqueles argumentos
// Comando já é o próprio ponteiro
typedef bool (*Comando)(char cmd, char *arg, Estado *e);

void mostrarTabuleiro(Estado *e) {
    printf("\n");
    for (int i = 0; i < e->linhas; i++) {
        for (int j = 0; j < e->colunas; j++) {
            printf("%c ", e->tabuleiro[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

bool cmdLer(char cmd, char *arg, Estado *e) {
    if (cmd != 'l' || arg == NULL) return false;
    // ficheiro é ponteiro para o tipo file (fopen retorna endereco)
    FILE *ficheiro = fopen(arg, "r");
    if (ficheiro == NULL) {
        printf("Erro ao abrir %s\n", arg);
        return true; // O comando foi reconhecido apesar de ter havido erro
    }
    // armazena no estado -> linhas
    if (fscanf(ficheiro, "%d %d", &(e->linhas), &(e->colunas)) != 2) {
        fclose(ficheiro);
        printf("Formato inválido no ficheiro\n");
        return true;
    }

    if (e->linhas <= 0 || e->colunas <= 0 || e->linhas > TMAX_MATRIZ || e->colunas > TMAX_MATRIZ) {
        printf("As dimensões do tabuleiro são inválidas\n");
        fclose(ficheiro);
        return true;
    }

    while (fgetc(ficheiro) != '\n'); // Retira os espaços e passa o "cursor" para depois do \n

    char linha[TMAX_MATRIZ + 2]; // adiciona o \n e o \0

    for (int i = 0; i < e->linhas; i++) {
        if (fgets(linha, sizeof(linha), ficheiro) == NULL) {
            printf("Erro ao ler a linha %d\n", i+1);
            break;
        }
        // Remove o '\n' no final (strcspn retorna o indice do \n) p possibilitar futura comparacao
        linha[strcspn(linha, "\n")] = '\0';

        for (int j = 0; j < e->colunas; j++) {
            if (linha[j] == '\0') {
                printf("Aviso linha %d menor que o esperado\n", i+1); // se introduziu uma dimensao e depois a linha era dif
                break;
            }
            e->tabuleiro[i][j] = linha[j];
        }
    }

    fclose(ficheiro);
    
    e->carregouTabuleiro = true;
    printf("\nTabuleiro inicial %dx%d carregado:\n", e->linhas, e->colunas);
    mostrarTabuleiro(e);
    return true;
}

bool cmdSair(char cmd, char *arg, Estado *e) {
    if (cmd == 's' && arg == NULL) {
        e->looping = false;
        return true; // comando foi reconhecido
    }
    return false; // comando não foi reconhecido
}

bool cmdPintar(char cmd, char *arg, Estado *e) {
    if (cmd != 'b' || e->carregouTabuleiro == false) return false;
    
    int x;
    char y;
    if (sscanf(arg, "%c%d", &y, &x) != 2) return false;

    int coluna = y - 'a'; // 'a' corresponde a 0, 'b' a 1 etc
    if (x >= 0 && x < e->linhas && coluna >= 0 && coluna < e->colunas) {
        e->tabuleiro[x][coluna] = toupper(e->tabuleiro[x][coluna]);
        mostrarTabuleiro(e);
        return true;
    }
    return false;
}

bool cmdRiscar(char cmd, char *arg, Estado *e) {
    if (cmd != 'r' || e->carregouTabuleiro == false) return false;
    
    int x;
    char y;
    if (sscanf(arg, "%c%d", &y, &x) != 2) return false;
    
    int coluna = y - 'a';
    if (x >= 0 && x < e->linhas && coluna >= 0 && coluna < e->colunas) {
        e->tabuleiro[x][coluna] = '#';
        mostrarTabuleiro(e);
        return true;
    }
    return false;
}

int main() {
    Estado estado = {0}; // inicializa todos os campos com zero
    estado.looping = true;
    
    Comando comandos[] = {cmdLer,cmdSair,cmdPintar,cmdRiscar,NULL};

    char input[100];
    
    printf("Bem-vindo ao Puzzle!\n");
    printf("Comandos disponíveis:\n");
    printf("  l [arquivo] - Carregar tabuleiro\n");
    printf("  b [coord]   - Pintar casa (ex: b a1)\n");
    printf("  r [coord]   - Riscar casa (ex: r b2)\n");
    printf("  s           - Sair\n");

    while (estado.looping) {

        // le o que foi introduzido (stdin) e armazena em input (para quando chega no \n ou ultrapassa o sizeof) e retorna o ponteiro
        if (fgets(input, sizeof(input), stdin) == NULL) estado.looping = false;

        // Quando escrevemos b a1 e damos enter o ultimo caractere é o \n, precisamos remove-lo.
        int length = strlen(input);
        if (length > 0 && input[length-1] == '\n') { // se for \n substitui.
            input[length-1] = '\0';
        }

        char cmd = '\0';
        char arg[100] = {0};
        // vai ler da string input (%99s para usar no máx 99 caracteres (precisa de espaço pro \0 no fim))
        int argsLido = sscanf(input, "%c %99s", &cmd, arg);

        bool temArgumento = (cmd == 'l' || cmd == 'b' || cmd == 'r');

        // ver se leu o comando
        if (argsLido < 1) {
            printf("Comando inválido!\n");
        }
        // ver se era necessário argumento e não havia
        else if (temArgumento && argsLido < 2) {
            printf("Este comando requer um argumento!\n");
        }
        else {
            bool reconhecido = false; // é uma flag
            // enquanto não chegar ao fim da lista de comandos e não houver nenhum que foi reconhecido procura o comando
            for (int i = 0; comandos[i] != NULL && !reconhecido; i++) {
                if (argsLido > 1) {
                    reconhecido = comandos[i](cmd, arg, &estado);
                }
                else {
                    // se não tiver argumentos passa o ponteiro nulo
                    reconhecido = comandos[i](cmd, NULL, &estado);
                }
            }
        
            if (!reconhecido) { // se não houve nenhum reconhecido então é inválido
                printf("Comando inválido.\n");
            }
        }
    }
    
    printf("Jogo encerrado.\n");
    return 0;
}
Editor is loading...
Leave a Comment