cmds
unknown
plain_text
6 months ago
9.6 kB
4
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