cmds

 avatar
unknown
plain_text
13 days ago
9.6 kB
3
Indexable
#include "type.h"

// função geral para libertar memória
void libertarMemoria(ESTADO *e) {
    if (e->tabuleiro != NULL) {
        for (int i = 0; i < e->linhas; i++) {
            free(e->tabuleiro[i]);
        }
        free(e->tabuleiro);
        e->tabuleiro = NULL;
    }
}


// função geral para alocar memória
bool alocarMemoria(ESTADO *e) {
    e->tabuleiro = malloc(e->linhas * sizeof(char *));
    if (e->tabuleiro == NULL) return false;

    for (int i = 0; i < e->linhas; i++) {
        e->tabuleiro[i] = malloc(e->colunas * sizeof(char));
        // liberta a  memória alocada parcialmente em caso de erro
        if (e->tabuleiro[i] == NULL) {
            e->linhas = i; // para saber quantas linhas já estavam alocadas
            libertarMemoria(e);
            return false;
        }
    }
    return true;
}


// função geral para libertar o histórico
void libertarHistorico(ESTADO *e) {
    JOGADA_SALVA *atual = e->historico;
    while (atual != NULL) {
        JOGADA_SALVA *proximo = atual->ant;
        
        // liberta o tabuleiro salvo
        for (int i = 0; i < atual->linhas; i++) {
            free(atual->tabuleiro[i]);
        }
        free(atual->tabuleiro);
        
        // liberta a estrutura da jogada
        free(atual);
        atual = proximo;
    }
    e->historico = NULL;
}


int toInt_Alpha (char c) {
    return c - 'a';
}

int toInt_Number (char c) {
    return c - '0';
}

int isDigit (char c) {
    return ('0' <= c && c <= '9');
}

int isLower (char c) {
    return ('a' <= c && c <= 'z');
}

int capital (char c) {
    return c - ('a' - 'A');
}


// função do comando 'gravar'
bool gravar (char cmd, char *arg, ESTADO *e) {
    if (cmd == 'g') {
        if (arg == NULL) {
            fprintf(stderr, "Erro: O comando gravar precisa de um argumento!\n");
            return false;
        }
        printf("Gravado em %s\n", arg);
        return true;
    }
    else return false;
}


// função do comando 'sair'
bool sair(char cmd, char *arg, ESTADO *e) {
    if (arg != NULL) return false;

    if (cmd == 's') {
        // liberta a memória alocada para o tabuleiro
        libertarMemoria(e);
        
        // liberta a memória alocada para o histórico
        libertarHistorico(e);

        // sinaliza que o programa deve terminar
        e->looping = false;
        return true;
    }

    return false;
}


// função que imprime o tabuleiro
void imprimir_tabuleiro(ESTADO *e) {
    printf("\n");

    if (e -> tabuleiro == NULL || e -> linhas <= 0 || e -> colunas <= 0) {
        printf("Erro: Tabuleiro não inicializado ou inválido!\n");
        return;
    }

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


// função do comando 'ler'
bool ler(char cmd, char *arg, ESTADO *e) {
    if (cmd != 'l') return false;

    if (arg == NULL) {
        fprintf(stderr, "Erro: O comando ler precisa de um argumento!\n");
        return false;
    }

    guardarEstado(e);

    // liberta a memória do tabuleiro anterior, se existir
    libertarMemoria(e);

    // abre o ficheiro
    FILE *file = fopen(arg, "r");
    if (file == NULL) {
        fprintf(stderr, "Erro: Não foi possível abrir o ficheiro %s\n", arg);
        return false;
    }

    // lê as dimensões do tabuleiro
    if (fscanf(file, "%d %d", &e->linhas, &e->colunas) != 2) {
        fprintf(stderr, "Erro: Formato inválido no arquivo!\n");
        fclose(file);
        return false;
    }

    // aloca memória 
    if (!alocarMemoria(e)) {
        fprintf(stderr, "Erro: Falha ao alocar memória para o tabuleiro!\n");
        fclose(file);
        return false;
    }

    // lê o conteúdo do tabuleiro
    for (int i = 0; i < e -> linhas; i++) {
        int j = 0;
        while (j < e -> colunas) {
            char c = fgetc(file);
            if (c != '\n') e -> tabuleiro[i][j++] = c;
        }
    }
    printf("Tabuleiro carregado de %s:\n", arg);

    fclose(file);
    imprimir_tabuleiro(e);
    return true;
}


// função do comando 'riscar'
bool riscar(char cmd, char *arg, ESTADO *e) { 
    if (cmd != 'r') return false;

    // verifica se o tabuleiro está carregado
    if (e -> tabuleiro == NULL || e -> linhas <= 0 || e -> colunas <= 0) {
        fprintf(stderr, "Erro: Tabuleiro não carregado!\n");
        return false;
    }

    // verifica se o argumento é fornecido
    if (arg == NULL) {
        fprintf(stderr, "Erro: O comando riscar precisa de um argumento!\n");
        return false;
    }

    // verifica se as coordenadas são válidas
    if (strlen(arg) != 2 || !isLower(arg[0]) || !isDigit(arg[1])) {
        fprintf(stderr, "Erro: Coordenadas inválidas.\nUse o formato <letra><número> (ex: a1)\n");
        return false;
    }

    // converte as coordenadas
    int coluna = toInt_Alpha(arg[0]); 
    int linha =  toInt_Number(arg[1]) - 1;

    // valida os índices
    if (linha < 0 || linha >= e -> linhas || coluna < 0 || coluna >= e -> colunas) {
        fprintf(stderr, "Erro: Coordenadas fora dos limites do tabuleiro (%dx%d)!\n", e -> linhas, e -> colunas);
        return false;
    }
    // risca o caracter (substituir por um #)
    else {
        // guarda o tabuleiro antes de modificar
        guardarEstado(e);
        e -> tabuleiro[linha][coluna] = '#';
    }

    imprimir_tabuleiro(e);
    return true;
}


// função do comando 'branco'
bool branco (char cmd, char *arg, ESTADO *e) { 
    if (cmd != 'b') return false;

    // verifica se o tabuleiro está carregado
    if (e -> tabuleiro == NULL || e -> linhas <= 0 || e -> colunas <= 0) {
        fprintf(stderr, "Erro: Tabuleiro não carregado!\n");
        return false;
    }

    // verifica se o argumento é fornecido
    if (arg == NULL) {
        fprintf(stderr, "Erro: O comando riscar precisa de um argumento!\n");
        return false;
    }

    // verifica se as coordenadas são válidas
    if (strlen(arg) != 2 || !isLower(arg[0]) || !isDigit(arg[1])) {
        fprintf(stderr, "Erro: Coordenadas inválidas.\nUse o formato <letra><número> (ex: a1)\n");
        return false;
    }

    // converte as coordenadas
    int coluna = toInt_Alpha(arg[0]); 
    int linha =  toInt_Number(arg[1]) - 1; // a1 internamente vira (0,0)

    // valida os índices
    if (linha < 0 || linha >= e -> linhas || coluna < 0 || coluna >= e -> colunas) {
        fprintf(stderr, "Erro: Coordenadas fora dos limites do tabuleiro (%dx%d)!\n", e -> linhas, e -> colunas);
        return false;
    }
    
    //substitui por um caracter branco (maiúsculo)
    else {
        // guarda o tabuleiro antes de o modificar
        guardarEstado(e);
        char letter = e -> tabuleiro[linha][coluna];
        e -> tabuleiro[linha][coluna] = capital(letter);
    }

    imprimir_tabuleiro(e);
    return true;
}


// função para guardar o estado 
bool guardarEstado(ESTADO *estadoAtual) {
    // verificação da entrada
    if (!estadoAtual || !estadoAtual->tabuleiro) return false;

    // cria um novo nó para armazenar a cópia do tabuleiro atual
    JOGADA_SALVA *novaJogada = malloc(sizeof(JOGADA_SALVA));
    if(!novaJogada) return false;

    // aloca memória 
    novaJogada->tabuleiro = malloc(estadoAtual->linhas * sizeof(char *));
    if(!novaJogada->tabuleiro) {
        free(novaJogada);
        return false;
    }

    // copia dados do estado
    novaJogada->linhas = estadoAtual->linhas;
    novaJogada->colunas = estadoAtual->colunas;

    // copia cada linha do tabuleiro
    for(int i = 0; i < estadoAtual->linhas; i++) {
        novaJogada->tabuleiro[i] = malloc(estadoAtual->colunas * sizeof(char));
        if(!novaJogada->tabuleiro[i]) {
            // libertar memória em caso de erro
            for(int j = 0; j < i; j++) free(novaJogada->tabuleiro[j]);
            free(novaJogada->tabuleiro);
            free(novaJogada);
            return false;
        }
        
        // cópia dos elementos
        for(int j = 0; j < estadoAtual->colunas; j++) {
            novaJogada->tabuleiro[i][j] = estadoAtual->tabuleiro[i][j];
        }
    }

    // empilha o novo nó no topo da lista ligada
    novaJogada->ant = estadoAtual->historico; // o novo nó (novaJogada) aponta para o antigo topo da pilha (historico)
    estadoAtual->historico = novaJogada; // atualiza o topo da pilha para apontar para o novo nó.
    
    return true;
}

// função do comando 'desfazer'
bool desfazer(char cmd, char *arg, ESTADO *estadoAtual) {
    if (cmd != 'd' || arg != NULL) return false;

    // verifica o histórico
    if (!estadoAtual->historico) {
        printf("Não há mais estados para desfazer.\n");
        return true;
    }

    // salva o topo
    JOGADA_SALVA *topo = estadoAtual->historico;

    // restaura as dimensões e o tabuleiro
    estadoAtual->linhas = topo->linhas;
    estadoAtual->colunas = topo->colunas;

    libertarMemoria(estadoAtual);

    if (!alocarMemoria(estadoAtual)) {
        fprintf(stderr, "Erro: Falha ao alocar memória para desfazer.\n");
        return false;
    }

    for (int i = 0; i < topo->linhas; i++) {
        for (int j = 0; j < topo->colunas; j++) {
            estadoAtual->tabuleiro[i][j] = topo->tabuleiro[i][j];
        }
    }

    // atualiza o topo
    estadoAtual->historico = topo->ant;
    for (int i = 0; i < topo->linhas; i++) free(topo->tabuleiro[i]);
    free(topo->tabuleiro);
    free(topo);

    printf("Tabuleiro anterior restaurado:\n");
    imprimir_tabuleiro(estadoAtual);
    return true;
}
Editor is loading...
Leave a Comment