Erros no jogo da forca [RESOLVIDO]

1. Erros no jogo da forca [RESOLVIDO]

Rafael L.
SrKon

(usa Ubuntu)

Enviado em 19/02/2021 - 15:46h

Estou encontrando os seguintes erros no programa
- Primeira letra digitada, estando certa ou não, é contabilizada como erro.
- Indicar se a letra já foi digitada, não funciona.
- Em alguns casos ele conta 2 erros na primeira tentativa.
Para mim, parece esta contundente. Não sei se esqueci de zerar algo ou adicionar algo.
O código que tenho:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

char banco[30][30]=
{
"notebook",
"smartphone",
"pendrive",
"computador",
"seguraça"
};

char wordSorteada[30] = {0};
char wordDigitada[30] = {0};

int sorteio()
{
srand(time(NULL));
return (rand() % 10)/2;
}

void imprimir()
{
int tam = strlen(wordSorteada);
printf("\n%d letras\n", tam);
for(int r = 0; r < strlen(wordSorteada); r++)
{
printf("%c", wordDigitada[r]);
}
}

void copia(int lin)
{
for(int r = 0; r < 30; r++)
{
wordSorteada[r] = banco[lin][r];
}
}

void limpaWord()
{
for(int r = 0; r < strlen(wordSorteada); r++)
{
wordDigitada[r] = '_';
}
}

void imprimirForca(int erro)
{
switch(erro)
{
case 0:
printf("\n-------\n");
printf("| \n");
printf("| \n");
printf("| \n");
break;
case 1:
printf("\n-------\n");
printf("| o\n");
printf("| \n");
printf("| \n");
break;
case 2:
printf("\n-------\n");
printf("| o\n");
printf("| / \n");
printf("| \n");
break;
case 3:
printf("\n-------\n");
printf("| o\n");
printf("| /| \n");
printf("| \n");
break;
case 4:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| \n");
break;
case 5:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \n");
break;
case 6://default:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \\ \n");
break;
}
}

bool verifyLetter(char letra, char vetor[26])
{
for(int i = 0; i < strlen(vetor); i++)
{
if(letra == vetor[i])
{
return true;
}
}

return false;
}

void alocandoLetra(char letra)
{
for(int i = 0; i < strlen(wordSorteada); i++)
{
if(wordSorteada[i] == letra)
{
wordDigitada[i] = letra;
}
}
}

void letrasDigitadas(char let[26], int tam)
{
printf("\nJá fora digitadas: ");
for(int r = 0; r < strlen(let); r++)
{
printf("%c,", let[r]);
}
printf("\n");
}

bool wordCompleta()
{
for(int r=0;r<strlen(wordSorteada);r++)
{
if(wordDigitada[r] == '_')
{
return false;
}
}
return true;
}

int main()
{
int palavra = sorteio();
copia(palavra);
limpaWord();
int contLetras = 0;
int contaErros = 0;
char letraDig[26] = {0};
char letter;

do
{
system("clear");
imprimirForca(contaErros);
imprimir();
letrasDigitadas(letraDig, contLetras);
printf("\n\nTentativas restantes: %d\n", 6-contaErros);
printf("\n\n");
printf("Digite uma letra: \n");
scanf("%c", &letter);
letter = tolower(letter);
if(verifyLetter(letter, letraDig))
{
printf("\nEssa letra já foi digitada\nTente novament\n");
system("pause");
} else
{
letraDig[contLetras] = letter;
contLetras++;
if(verifyLetter(letter, wordSorteada))
{
alocandoLetra(letter);
} else
{
printf("Letra incorreta\nTente novamente\n\n");
contaErros++;
system("pause");
}
}
if(contaErros>=6)
{
system("clear");
printf("Game Over for you");
system("stop");
return 0;
} else if(wordCompleta())
{
system("clear");
printf("YOU WIN");
system("stop");
return 0;
}

}while(contaErros<=6);

return 0;
}




  


2. Re: Erros no jogo da forca [RESOLVIDO]

leandro peçanha scardua
leandropscardua

(usa Ubuntu)

Enviado em 19/02/2021 - 21:04h

Roda no gdb


3. Re: Erros no jogo da forca

Paulo
paulo1205

(usa Ubuntu)

Enviado em 20/02/2021 - 11:36h

SrKon escreveu:

Estou encontrando os seguintes erros no programa
- Primeira letra digitada, estando certa ou não, é contabilizada como erro.
- Indicar se a letra já foi digitada, não funciona.
- Em alguns casos ele conta 2 erros na primeira tentativa.
Para mim, parece esta contundente. Não sei se esqueci de zerar algo ou adicionar algo.
O código que tenho:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

char banco[30][30]=
{
"notebook",
"smartphone",
"pendrive",
"computador",
"seguraça"


Se você vai considerar ç como letra válida e diferente de c, então provavelmente não vai poder usar apenas 26 elementos para representar conjuntos de letras já digitadas ou que compõem a palavra.

Além disso, parece que faltou um n na palavra.

};

char wordSorteada[30] = {0};
char wordDigitada[30] = {0};


Eu acho meio feio misturar línguas diferentes nos nomes de variáveis de um mesmo programa, e pior ainda quando a mistura acontece na composição do nome de uma mesma variável.

Minha sugestão é que você escolha um padrão — tudo em Português ou tudo em Inglês — e que seja consistente ao longo de todo o programa.

Além disso, para variáveis estáticas, globais ou declaradas em escopo de arquivo, não é necessário atribuir valor inicial igual a zero, pois os valores são zerados por padrão. Só é necessário declarar valores iniciais quando você quiser que eles não sejam nulos. Apenas as variáveis locais e de armazenamento automático, cujos valores default são indeterminados, são as que precisam ser explícitas sobre valores iniciais que tenham de ser iguais a zero.


int sorteio()
{
srand(time(NULL));


O fato de você ter chamado a função de sorteio() dá a entender que a função poderia ser chamada mais de uma vez ao longo do programa (você não fez isso neste programa ainda, mas, além de sugerido pelo nome, poderia vir a fazê-lo caso o programa fosse modificado para apresentar a opção de jogar novamente). Se esse for o caso, então você deve saber que a forma típica de usar srand() é chamá-la apenas uma vez, no início do programa, não a cada sorteio realizado. Recomendo, portanto, tirar a chamada de dentro da função.

Se você de maneira nenhuma pretende que a função seja chamada mais de uma vez, então não faz muito sentido criar uma função separada cujo interior é tão simples.

    return (rand() % 10)/2; 


Por que essa forma de calcular? Por que não fazer simplesmente “rand()%5”?

Em tempo: muitas implementações de rand() têm baixa aleatoriedade nos bits de mais baixa ordem, de modo que simplesmente pegar o resto da divisão por um valor N também pequeno pode não produzir muito bons resultados. Isso pode ser melhorado através da transferência informação contida nos bits de mais alta ordem, com uma expressão parecida com a seguinte: “(int)((rand()/(1.0+RAND_MAX))*N)”.

}

void imprimir()
{
int tam = strlen(wordSorteada);
printf("\n%d letras\n", tam);
for(int r = 0; r < strlen(wordSorteada); r++)
{
printf("%c", wordDigitada[r]);
}


Não entendi a lógica de tomar o tamanho de uma string (wordSortead) para varrer e imprimeir os caracteres de outra string (wordDigitada). Eu perdi alguma coisa, ou foi você que se confundiu? Porque, se eu não tiver perdido nada, muito provavelmente você poderia substituir essa função por um mero “printf("\n%zu letras\n%s", strlen(wordSorteada), wordDigitada);”, que, por ser tão simples, novamente não precisaria residir numa função separada.

Em todo caso, note que a cláusula de parada do laço de repetição, que é testada a cada iteração do laço, contém uma chamada a strlen(). A não ser que o compilador seja muito, MUITO bom em otimização, ele possivelmente não tem como prever que o tamanho da string não mudou entre uma iteração e outra, e possivelmente será obrigado a recalcular o comprimento de wordSorteada a cada iteração, elevando o custo do laço de repetição de O(n) para O(n²). Curiosamente, você já tinha definido uma variável (tam) com o valor de strlen(wordSorteada), e eu não entendi por que você não usou essa variável na cláusula de parada, em lugar de repetir a chamada a strlen() a cada iteração.

}

void copia(int lin)
{
for(int r = 0; r < 30; r++)
{
wordSorteada[r] = banco[lin][r];
}


Outra função extremamente simples demais para justificar sua existência, podendo ser substituída simplesmente por “strcpy(wordSorteada, banco[lin]);”.

}

void limpaWord()
{
for(int r = 0; r < strlen(wordSorteada); r++)
{
wordDigitada[r] = '_';
}


De novo, eu vejo com muita suspeição essa chamada a strlen() na cláusula de parada, avaliada a cada iteração. Esse foi um vício que você usou ao longo de todo o programa.

Se você não quiser usar uma variável auxiliar para não ter de invocar a função a cada iteração, pode mudar a forma e a direção do laço de repetição, chamado strlen() apenas uma vez, na cláusula de inicialização, e ir do fim para o início da string.
for(size_t r = strlen(wordSorteada); r-- > 0; )
wordDigitada[r]='_';


}

void imprimirForca(int erro)
{
switch(erro)
{
case 0:
printf("\n-------\n");
printf("| \n");
printf("| \n");
printf("| \n");
break;
case 1:
printf("\n-------\n");
printf("| o\n");
printf("| \n");
printf("| \n");
break;
case 2:
printf("\n-------\n");
printf("| o\n");
printf("| / \n");
printf("| \n");
break;
case 3:
printf("\n-------\n");
printf("| o\n");
printf("| /| \n");
printf("| \n");
break;
case 4:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| \n");
break;
case 5:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \n");
break;
case 6://default:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \\ \n");
break;
}


O break não é necessário no último case label de um switch (tanto switch quanto break são formas disfarçadas de goto).

A primeira linha impressa em todos os casos é exatamente a mesma. Assim sendo, ela poderia ser impressa antes do switch, e ser removida de cada um dos casos.

As demais linhas poderiam ser impressas com uma única chamada a printf() ou puts(), em vez de três. Não sei se lhe foi ensinado mas, em C, a declaração
const char *const str_array[5]={
"paulo1205",
"paulo""1205",
"paulo" "1205",
"paulo"
"1025",
"p" "a" "u" "l" "o" /* bla, bla, bla */ "1" "2" "0" "5"
};
produz um array com cinco elementos que são strings constantes com exatamente o mesmo conteúdo. Então você também poderia trocar algo como
            printf("|     o\n");
printf("| /|\\ \n");
printf("| / \\ \n");
pelo seguinte (economizando a quantidade de chamadas a funções, sem perder a formatação visual do código fonte).
            printf("|     o\n"
"| /|\\ \n"
"| / \\ \n");


}

bool verifyLetter(char letra, char vetor[26])
{
for(int i = 0; i < strlen(vetor); i++)
{
if(letra == vetor[i])
{
return true;
}
}


De novo o strlen() na cláusula de parada. E, de novo, para fazer uma operação que já existe na biblioteca padrão; você poderia ter usado simplesmente “strchr(vetor, letra)!=NULL”.

    
return false;
}

void alocandoLetra(char letra)
{
for(int i = 0; i < strlen(wordSorteada); i++)


De novo...

    {
if(wordSorteada[i] == letra)
{
wordDigitada[i] = letra;
}
}
}

void letrasDigitadas(char let[26], int tam)
{
printf("\nJá fora digitadas: ");
for(int r = 0; r < strlen(let); r++)


... e de novo...

    {
printf("%c,", let[r]);
}
printf("\n");


Toda esta função poderia ser substituída simplesmente por uma única chamada a printf().

}

bool wordCompleta()
{
for(int r=0;r<strlen(wordSorteada);r++)


... e de novo.

    {
if(wordDigitada[r] == '_')
{
return false;
}
}
return true;


Em outras palavras, esta função testa se wordDigitada é igual a wordSorteada. Efeito semelhante poderia ser conseguido com “strcmp(wordDigitada, wordSorteada)==0”.

}

int main()
{
int palavra = sorteio();
copia(palavra);
limpaWord();
int contLetras = 0;
int contaErros = 0;
char letraDig[26] = {0};
char letter;

do
{
system("clear");


Evite usar system(), pois seu uso indiscriminado pode ser bastante ineficiente e inseguro.

Procure restringir seu uso a situações em que ele seja estritamente necessário, para executar operações que seriam inviáveis de fazer de outra forma. Mesmo quando isso for necessário, tome medidas para minimizar a chance de dar problema de segurança, tais como usar o caminho completo do programa que você quer invocar (por exemplo: em vez de apenas "clear", prefira "/usr/bin/clear") e predefinir o valor da variável de ambiente PATH para um conjunto mínimo e seguro de diretórios (fazendo, por exemplo, algo como “setenv("PATH", "/bin:/usr/bin", 1);” logo no início do programa), e possivelmente alterando também as variáveis de ambiente que definem aspectos de locale.

Veja as considerações sobre o uso de system)() e alternativas para limpeza de tela nas mensagens de nº 10 a 12 no tópico https://www.vivaolinux.com.br/topico/C-C++/Preciso-fazer-um-programa-em-C-para-cadastra-alunos-consu.... Uma discussão ainda mais aprofundada de possíveis problemas com system() pode ser encontrada na 3ª mensagem no tópico https://www.vivaolinux.com.br/topico/C-C++/Duvida-com-realloc-em-C, a partir do 12º parágrafo.

        imprimirForca(contaErros);
imprimir();
letrasDigitadas(letraDig, contLetras);
printf("\n\nTentativas restantes: %d\n", 6-contaErros);
printf("\n\n");
printf("Digite uma letra: \n");
scanf("%c", &letter);


Esta operação de leitura possivelmente é uma parte importante do problema que você reportou, porque não basta que você aperte uma letra, mas tem de digitar uma letra seguida da tecla <Enter> (ou <Return>, se você estiver num computador da Apple), que provoca o aparecimento de dois caracteres na entrada: a letra em si, e um caráter de fim-de-linha ('\n') correspondente ao <Enter>. Cada um desses caracteres será consumido numa iteração diferente do laço de repetição, e você não fez nenhuma validação de se o valor lido realmente corresponde a uma letra ou a um caráter válido.

A leitura de dados de entrada a partir do terminal exige certos cuidados, porque ela é normalmente orientada a linha (i.e. o sistema procura ler sempre linhas inteiras; mesmo que você solicite apenas um caráter, o sistema vai verificar se esse caráter já existe num buffer interno e, se existir, ele devolve o tal caráter imediatamente, mas, caso não exista, o sistema vai procurar encher o buffer com tanto caracteres quantos forem possíveis, até encontrar uma marca de fim-de-linha ou até não haver mais espaço no tal buffer interno antes de lhe entregar o único caráter que você pediu). Além disso, a função scanf() é muito complexa (possivelmente a mais complexa de todas as funções da biblioteca padrão do C), e requer uma boa e cautelosa leitura de sua documentação — e possivelmente alguma prática — para ser usada de modo efetivo e competente, com o devido conhecimento de quando acontecem descartes automáticos de caracteres e quando eles não ocorrem, como usar conversões, conversões sem atribuição/alteração de valor ou textos fixos, limitações de largura ou de conjuntos de caracteres, alocação automática de memória, indicadores de quantos caracteres foram consumidos, alteração de ordem de argumentos que podem receber atribuições e sinalização de erros ou grau de sucesso das conversões, entre outros aspectos. E eu não estou exagerando.

No mínimo, eu sugiro a você fazer as seguintes mudanças referentes a este pedaço:

  • teste o valor de retorno de scanf(), para ter certeza de que não ocorreu erro de leitura;

  • dentro da própria string de formatação de scanf(), procure descartar todos os caracteres que não interessarem (especialmente espaços, incluindo quebras de linha, cujo tratamento é muito fácil);

  • após a leitura, verifique que fruto de leitura seja válido, e dê o tratamento adequado caso não seja.

Acima, uma das palavras do dicionário incluía um ç. Lembre-se de que ç e vogais acentuadas são caracteres distintos do c comum e das vogais não-acentuadas. Além disso, dependendo do conjunto de caracteres que esteja em uso tanto no momento da compilação quanto no momento da execução, a representação dos caracteres acentuados ou com cedilha pode ser diferente, inclusive com mais do que um byte (ou caráter, pois em C cada char corresponde exatamente a um byte) por sinal gráfico (por exemplo, com o conjunto de caracteres europeu e codificação ISO-8859-1, o c corresponde ao byte com valor 99 e o c corresponde ao valor 231; já com o Unicode e codificação UTF-8, que é a mais comum no Linux hoje em dia, o c corresponde ao mesmo byte com valor 99, mas o ç corresponde a um par de bytes, sendo o primeiro com valor 195 e o segundo com o valor 167). Se você quiser tratar caracteres com marcas diacríticas, seu programa certamente vai ter de ser mais sofisticado.

        letter = tolower(letter); 


Aqui já há um exemplo de possível problema com caracteres com marcas diacríticas. Mesmo num conjunto de caracteres que usam estritamente apenas um byte, como o ISO-8859-1, todos os caracteres acentuados utilizam o oitavo bit do byte, o que, nos nossos PCs, corresponde a um valor negativo. A função tolower() não trata tais valores, a não ser que você os converta antes para uma representação de valor sem sinal. Assim sendo, depois de ter certeza de que a leitura foi bem sucedida, você deveria fazer algo parecido com o seguinte.
letter=tolower((unsigned char)letter); 


        if(verifyLetter(letter, letraDig))
{
printf("\nEssa letra já foi digitada\nTente novament\n");
system("pause");


Anteriormente você chamou system("clear"), dando a entender que estava num sistema UNIX-like, visto que no mundo Microsoft, o comando equivalente a clear seria CLS. Mas aqui você usa uma chamada a pause, que até onde eu sei, não existe no Linux ou sistemas UNIX em geral. Não existindo, esse comando só serve para dar erro.

        } else
{
letraDig[contLetras] = letter;
contLetras++;
if(verifyLetter(letter, wordSorteada))
{
alocandoLetra(letter);
} else
{
printf("Letra incorreta\nTente novamente\n\n");
contaErros++;
system("pause");
}
}
if(contaErros>=6)
{
system("clear");
printf("Game Over for you");
system("stop");


Esse system("stop") é algo que eu nunca vi, e não faria muito sentido, mesmo que existisse tal comando “stop”.

A forma de encerrar o programa em C é fazer como na linha que vem logo abaixo (i.e. através do comando return dentro de main()), ou por meio das funções da biblioteca exit() ou abort().

            return 0;
} else if(wordCompleta())
{
system("clear");
printf("YOU WIN");
system("stop");
return 0;
}

}while(contaErros<=6);

return 0;
}


Outros problemas que eu acredito que você deveria considerar e corrigir ao longo do programa como um todo:

  • Várias constantes numéricas, tais como 30, 26 ou 6, espalhadas pelo programa não são geralmente uma boa prática. O programa provavelmente ficaria mais simples de compreender se essas constantes numéricas fossem substituídas por nomes descritivos de seu propósito, tais como TAM_MAX_PALAVRA, N_CARACTERES_VALIDOS e MAX_RODADAS, sendo cada um desses nomes associados apenas uma vez a seu respectivo valor numérico constante. Fazer desse modo teria ainda a vantagem adicional de facilitar eventuais alterações nesses valores — por exemplo, caso você decida trabalhar com palavras com mais de 30 caracteres, poderia alterar somente a definição do valor de TAM_MAX_PALAVRA, e automaticamente todos os outros lugares em que esse nome aparecesse teriam o valor correto automaticamente substituído, o que é bem melhor do que sair procurando a constante 30 ao longo do programa, verificar se cada ocorrência corresponde ao comprimento de uma palavra (porque poderia ser um outro valor 30, usado para outro propósito e que não deveria ser alterado) e então trocar manualmente cada ocorrência.

  • Você não especificou se seu programa é em C ou em C++. Parece ser em C, e eu vou considerar que realmente o seja, então eu acho importante que você saiba que, em C, uma lista de parâmetros vazia significa que a função poder receber uma quantidade qualquer de argumentos de quaisquer tipos; para declarar funções que não têm parâmetros (i.e. que não devem receber argumentos), a forma de fazer é declarar a função com a palavra-chave void como única coisa dentro da lista de parâmetros. No seu programa você tem várias funções, incluindo main, que são declaradas com lista de parâmetros vazias, mas que provavelmente deveriam ter sido declaradas explicitamente como não podendo receber argumentos. Desse modo, você provavelmente deveria ter dito, por exemplo, “int main(void)”, em vez de “int main()”, e o mesmo para diversas outras funções.

  • Acho que a escolha entre variáveis globais e variáveis locais não ficou muito consistente, bem como casos em que as funções separadas de main() recebem argumentos ou usam variáveis globais. Essa inconsistência sugere que você pode não ter planejado o programa de antemão, e pode ter juntado partes de modo meio improvisado na medida em que foi programando. Se esse realmente tiver sido o caso, procure planejar melhor antes de começar a codificar.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


4. Certo

Rafael L.
SrKon

(usa Ubuntu)

Enviado em 20/02/2021 - 18:05h

O strlen e o tam foi pq tinha parado de funcionar, quando fiz assim voltou;
Esqueci completamente do strcpy. No caso do switch foi apenas um teste;
Não entendi como trocar a função wordCompleta por um printf;
Eu usei o system mais nesse programa, normalmente não uso. Obrigado pela recomendação dos artigos;
O tolower foi só um teste, um detalhe;
Como o cara do comentário anterior disse, roda no gdb;
kkkk o stop, é que ele tava dando erro no pause (rs) aí eu pensei: não tá funcionando, como não tá funcionando? Se pause é para parar não tá parando, eu para com o que, stop, hmm vou testar. E foi;
Eu ainda acho sem sentido usar "int main(void)"; e
• Acho que a escolha entre variáveis globais e variáveis locais não ficou muito consistente, bem como casos em que as funções separadas de main() recebem argumentos ou usam variáveis globais. Essa inconsistência sugere que você pode não ter planejado o programa de antemão, e pode ter juntado partes de modo meio improvisado na medida em que foi programando. Se esse realmente tiver sido o caso, procure planejar melhor antes de começar a codificar.

Acredite, estou tentado trabalhar isso, bem como o nomes das variáveis e demais boas práticas.
Obrigado pela ajuda.


5. Mudanças

Rafael L.
SrKon

(usa Ubuntu)

Enviado em 20/02/2021 - 18:46h

SrKon escreveu:

O strlen e o tam foi pq tinha parado de funcionar, quando fiz assim voltou;
Esqueci completamente do strcpy. No caso do switch foi apenas um teste;
Não entendi como trocar a função wordCompleta por um printf;
Eu usei o system mais nesse programa, normalmente não uso. Obrigado pela recomendação dos artigos;
O tolower foi só um teste, um detalhe;
Como o cara do comentário anterior disse, roda no gdb;
kkkk o stop, é que ele tava dando erro no pause (rs) aí eu pensei: não tá funcionando, como não tá funcionando? Se pause é para parar não tá parando, eu para com o que, stop, hmm vou testar. E foi;
Eu ainda acho sem sentido usar "int main(void)"; e
• Acho que a escolha entre variáveis globais e variáveis locais não ficou muito consistente, bem como casos em que as funções separadas de main() recebem argumentos ou usam variáveis globais. Essa inconsistência sugere que você pode não ter planejado o programa de antemão, e pode ter juntado partes de modo meio improvisado na medida em que foi programando. Se esse realmente tiver sido o caso, procure planejar melhor antes de começar a codificar.

Acredite, estou tentado trabalhar isso, bem como o nomes das variáveis e demais boas práticas.
Obrigado pela ajuda.


Taí as mudanças, acho que fiz certo, não funcionou:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

char banco[30][30]=
{
"notebook",
"smartphone",
"pendrive",
"computador",
"seguraça"
};

char wordSorteada[30] = {0};
char wordDigitada[30] = {0};

void limpaWord()
{
for(int r = 0; r < strlen(wordSorteada); r++)
{
wordDigitada[r] = '_';
}
}

void imprimirForca(int erro)
{
switch(erro)
{
case 0:
printf("\n-------\n");
printf("| \n");
printf("| \n");
printf("| \n");
break;
case 1:
printf("\n-------\n");
printf("| o\n");
printf("| \n");
printf("| \n");
break;
case 2:
printf("\n-------\n");
printf("| o\n");
printf("| / \n");
printf("| \n");
break;
case 3:
printf("\n-------\n");
printf("| o\n");
printf("| /| \n");
printf("| \n");
break;
case 4:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| \n");
break;
case 5:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \n");
break;
default:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \\ \n");
}
}

bool verifyLetter(char letra, char vetor[26])
{
for(int i = 0; i < strlen(vetor); i++)
{
if(letra == vetor[i])
{
return true;
}
}

return false;
}

void alocandoLetra(char letra)
{
for(int i = 0; i < strlen(wordSorteada); i++)
{
if(wordSorteada[i] == letra)
{
wordDigitada[i] = letra;
}
}
}

void letrasDigitadas(char let[26], int tam)
{
printf("\nJá fora digitadas: ");
for(int r = 0; r < strlen(let); r++)
{
printf("%c,", let[r]);
}
printf("\n");
}

bool wordCompleta()
{
for(int r=0;r<strlen(wordSorteada);r++)
{
if(wordDigitada[r] == '_')
{
return false;
}
}
return true;
}

int main()
{
srand(time(NULL));
int palavra = rand() % 5;
strcpy(wordSorteada, banco[palavra]);
limpaWord();
int contLetras = 0;
int contaErros = 0;
char letraDig[26] = {0};
char letter;

while(contaErros<=6)
{
system("clear");
imprimirForca(contaErros);
printf("\n%d letras\n%s", strlen(wordSorteada), wordDigitada);
letrasDigitadas(letraDig, contLetras);
printf("\n\nTentativas restantes: %d\n", 6-contaErros);
printf("\n\n");
printf("Digite uma letra: \n");
scanf(" %c", &letter);
if(strchr(letraDig, letter)!=NULL)//verifyLetter(letter, letraDig)
{
printf("\nEssa letra já foi digitada\nTente novament\n");
break;
} else
{
letraDig[contLetras] = letter;
contLetras++;
if(strchr(letter, wordSorteada)!=NULL)//verifyLetter(letter, wordSorteada)
{
alocandoLetra(letter);
} else
{
printf("Letra incorreta\nTente novamente\n\n");
contaErros++;
break;
}
}
if(contaErros>=6)
{
system("clear");
printf("Game Over for you");
break;
//return 0;
} else if(wordCompleta())
{
system("clear");
printf("YOU WIN");
break;
//return 0;
}

}

return 0;
}





6. Re: Erros no jogo da forca

Paulo
paulo1205

(usa Ubuntu)

Enviado em 28/02/2021 - 09:35h

Quando eu salvei seu programa aqui e tentei compilá-lo, deu vários erros, como você pode ver na figura anexa.

Os erros, na ordem mostrada na figura, têm as seguintes explicações:

  1) Na linha 137, você tentou imprimir o valor retornado pela função strlen() como se o valor fosse do tipo int (conversão "%d" de printf()). O problema é que o tipo retornado por strlen() não é int, mas sim size_t. A conversão correta de printf() para imprimir valores do tipo size_t é "%zu".

  2 e 3) Na linha 151, os dois argumentos na chamada da função estão com a ordem trocada (pode ter sido culpa minha ao mostrar o exemplo). São mostrados dois erros nessa mesma linha porque o compilador não tem como saber que você simplesmente trocou a ordem dos argumentos, então ele indica um erro para cada um deles, porque os tipos de dados não correspondem aos tipos esperados por cada parâmetro da função.

  4 a 7) Nas linhas 135, 142, 163 e 169, o compilador está avisando que as funções system() e scanf() devolvem valores de retorno que o seu programa deveria testar antes de prosseguir com a execução. Essa exigência de teste normalmente é colocada em funções cujos comportamentos em situações de erro podem deixar seu programa num estado inconsistente, prejudicando operações futuras. Para sua segurança, seria bom que você verificasse o valor retornado a fim de interceptar prematuramente possíveis sinalizações de erro, e responder devidamente.

      No caso de system(), minha sugestão, já apresentada em minha resposta anterior, é suprimir totalmente seu uso, substituindo cada uma delas ou por uma solução nativa (também indicada em mensagem anterior), ou mesmo apagando sem colocar nada no lugar.

      Para scanf(), eu recomendo algo como o seguinte.
    if(scanf(" %c", &ch)!=1){
fprintf(strderr, "Erro de leitura. Abortando o programa.\n");
exit(1);
}


Fora tais erros, vi que você não alterou as chamadas a strlen() como parte da condição de parada em vários laços de repetição. Assim sendo, repito o aviso, porque strlen() é uma função lenta (O(n)), e chamá-la em cada iteração de um laço de repetição (que também é O(n)) faz com que a complexidade do algoritmo aumente muito (passando a O(n²)).

Para corrigir isso, em alguns casos você pode simplesmente contar de trás para frente, chamando strlen() na inicialização do laço de repetição, que só é ativada uma vez, e ir caminhando no sentido do início da string, reduzindo o valor do índica a cada iteração — como, aliás, eu já mostrei como fazer na mensagem anterior. Se não der para ser assim, você pode ter uma variável antes do laço de repetição recebendo o valor de strlen() apenas uma vez, e usar esse valor constante na condição de parada, assim evitando o aumento de complexidade do seu laço de repetição. Duas formas de fazer poderiam ser as seguintes.
const size_t len=strlen(string);
for(size_t index=0; index<len; ++index){ /* ... */ }
for(size_t len=strlen(string), index=0; index<len; ++index){ /* ... */ } 



... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


7. Re: Erros no jogo da forca [RESOLVIDO]

Rafael L.
SrKon

(usa Ubuntu)

Enviado em 06/03/2021 - 07:01h


paulo1205 escreveu:

Quando eu salvei seu programa aqui e tentei compilá-lo, deu vários erros, como você pode ver na figura anexa.

Os erros, na ordem mostrada na figura, têm as seguintes explicações:

  1) Na linha 137, você tentou imprimir o valor retornado pela função strlen() como se o valor fosse do tipo int (conversão "%d" de printf()). O problema é que o tipo retornado por strlen() não é int, mas sim size_t. A conversão correta de printf() para imprimir valores do tipo size_t é "%zu".

  2 e 3) Na linha 151, os dois argumentos na chamada da função estão com a ordem trocada (pode ter sido culpa minha ao mostrar o exemplo). São mostrados dois erros nessa mesma linha porque o compilador não tem como saber que você simplesmente trocou a ordem dos argumentos, então ele indica um erro para cada um deles, porque os tipos de dados não correspondem aos tipos esperados por cada parâmetro da função.

  4 a 7) Nas linhas 135, 142, 163 e 169, o compilador está avisando que as funções system() e scanf() devolvem valores de retorno que o seu programa deveria testar antes de prosseguir com a execução. Essa exigência de teste normalmente é colocada em funções cujos comportamentos em situações de erro podem deixar seu programa num estado inconsistente, prejudicando operações futuras. Para sua segurança, seria bom que você verificasse o valor retornado a fim de interceptar prematuramente possíveis sinalizações de erro, e responder devidamente.

      No caso de system(), minha sugestão, já apresentada em minha resposta anterior, é suprimir totalmente seu uso, substituindo cada uma delas ou por uma solução nativa (também indicada em mensagem anterior), ou mesmo apagando sem colocar nada no lugar.

      Para scanf(), eu recomendo algo como o seguinte.
    if(scanf(" %c", &ch)!=1){
fprintf(strderr, "Erro de leitura. Abortando o programa.\n");
exit(1);
}


Fora tais erros, vi que você não alterou as chamadas a strlen() como parte da condição de parada em vários laços de repetição. Assim sendo, repito o aviso, porque strlen() é uma função lenta (O(n)), e chamá-la em cada iteração de um laço de repetição (que também é O(n)) faz com que a complexidade do algoritmo aumente muito (passando a O(n²)).

Para corrigir isso, em alguns casos você pode simplesmente contar de trás para frente, chamando strlen() na inicialização do laço de repetição, que só é ativada uma vez, e ir caminhando no sentido do início da string, reduzindo o valor do índica a cada iteração — como, aliás, eu já mostrei como fazer na mensagem anterior. Se não der para ser assim, você pode ter uma variável antes do laço de repetição recebendo o valor de strlen() apenas uma vez, e usar esse valor constante na condição de parada, assim evitando o aumento de complexidade do seu laço de repetição. Duas formas de fazer poderiam ser as seguintes.
const size_t len=strlen(string);
for(size_t index=0; index<len; ++index){ /* ... */ }
for(size_t len=strlen(string), index=0; index<len; ++index){ /* ... */ } 



... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


Obrigado pela sua ajuda. Eu gosto das suas resposta, elas sempre trazem detalhes interessantes.
Eu preciso ver mais sobre esse size_t. Esses comando fprintf, exit() e strderr eu tbm não conheço.
Não sabia desse problema do strlen().
Vou remover o system(clear), e tentar usar o que você recomendou.

eu tive este erro:
error: initializer element is not constant
const size_t tam = strlen(wordSorteada);

E o codigo esta assim:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

char banco[30][30]=
{
"notebook",
"smartphone",
"pendrive",
"computador",
"seguraça"
};

char wordSorteada[30] = {0};
char wordDigitada[30] = {0};
const size_t tam = strlen(wordSorteada);

void limpaWord()
{
for(int r = 0; r < tam; r++)
{
wordDigitada[r] = '_';
}
}

void imprimirForca(int erro)
{
switch(erro)
{
case 0:
printf("\n-------\n");
printf("| \n");
printf("| \n");
printf("| \n");
break;
case 1:
printf("\n-------\n");
printf("| o\n");
printf("| \n");
printf("| \n");
break;
case 2:
printf("\n-------\n");
printf("| o\n");
printf("| / \n");
printf("| \n");
break;
case 3:
printf("\n-------\n");
printf("| o\n");
printf("| /| \n");
printf("| \n");
break;
case 4:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| \n");
break;
case 5:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \n");
break;
default:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \\ \n");
}
}

bool verifyLetter(char letra, char vetor[26])
{
const size_t tam2 = strlen(vetor);
for(int i = 0; i < tam2; i++)
{
if(letra == vetor[i])
{
return true;
}
}

return false;
}

void alocandoLetra(char letra)
{
for(int i = 0; i < tam; i++)
{
if(wordSorteada[i] == letra)
{
wordDigitada[i] = letra;
}
}
}

void letrasDigitadas(char let[26], int tam)
{
printf("\nJá fora digitadas: ");
const size_t len = strlen(let);
for(int r = 0; r < len; r++)
{
printf("%c,", let[r]);
}
printf("\n");
}

bool wordCompleta()
{
for(int r=0;r<tam;r++)
{
if(wordDigitada[r] == '_')
{
return false;
}
}
return true;
}

int main()
{
srand(time(NULL));
int palavra = rand() % 5;
strcpy(wordSorteada, banco[palavra]);
limpaWord();
int contLetras = 0;
int contaErros = 0;
char letraDig[26] = {0};
char letter;

while(contaErros<=6)
{
imprimirForca(contaErros);
printf("\n%zu letras\n%s", tam, wordDigitada);
letrasDigitadas(letraDig, contLetras);
printf("\n\nTentativas restantes: %d\n", 6-contaErros);
printf("\n\n");
printf("Digite uma letra: \n");
scanf("%c", &letter);
if(strchr(letraDig, letter)!=NULL)//verifyLetter(letter, letraDig)
{
printf("\nEssa letra já foi digitada\nTente novament\n");
break;
} else
{
letraDig[contLetras] = letter;
contLetras++;
if(strchr(wordSorteada, letter)!=NULL)//verifyLetter(letter, wordSorteada)
{
alocandoLetra(letter);
} else
{
printf("Letra incorreta\nTente novamente\n\n");
contaErros++;
break;
}
}
if(contaErros>=6)
{
setenv("PATH", "/bin:/usr/bin", 1);
printf("Game Over for you");
break;
} else if(wordCompleta())
{
printf("YOU WIN");
break;
}

}

return 0;
}






8. Re: Erros no jogo da forca

Paulo
paulo1205

(usa Ubuntu)

Enviado em 08/03/2021 - 04:31h

SrKon escreveu:

Obrigado pela sua ajuda. Eu gosto das suas resposta, elas sempre trazem detalhes interessantes.
Eu preciso ver mais sobre esse size_t. Esses comando fprintf, exit() e strderr eu tbm não conheço.


Rapidamente:

  • size_t é um apelido (um nome alternativo) para um tipo inteiro sem sinal capaz de representar tamanhos de objetos alocados na memória. É o tipo de dados do resultado de operações com sizeof, offsetof e _Alignof, bem como de funções como strlen(). Em nossos PCs com 64 bits, barramento endereçável com 48 bits ou mais e sistemas operacionais de 64 bits, size_t costuma ser sinônimo de unsigned long long; se fosse um PC mais antigo, com registradores e barramento de 32 bits, ou mesmo um sistema moderno rodando um sistema de 32 bits em modo de compatibilidade, size_t possivelmente seria sinônimo de unsigned long.
    Se você souber o tipo fundamental exato ao qual o apelido size_t se refere, pode se aventurar a usar a representação nativa em alguns lugares, ou mesmo uma conversão nativa tal como "%llu" (para unsigned long long) ou "%lu" (para unsigned long) em printf() ou scanf(). Mas é melhor recorrer ao apelido e a conversões que correspondem automaticamente àquilo que ele representa, tais como "%zu" em printf() e scanf(), porque isso permite que o mesmo programa possa ser compilado em máquinas com diferentes características sem a necessidade de alterações que tenham de ser feitas manualmente pelo programador cada vez que ele levar o programa de uma máquina para outra, pois o compilador de cada máquina cuida de usar a melhor representação em cada máquina.

  • stderr é um dos fluxos de saída de dados padronizados (a parte “std” vem de standard, que significa padrão), normalmente usado como destino de mensagens de erro (de onde vem a parte “err”). Esse destino para mensagens de erro, separado das mensagens normais do programa (cujo fluxo de saída é chamada de stdout, uma abreviação de “standard output”, a saída padrão de dados) pode ser útil quando você quer separar mensagens de erro das demais mensagens gerada pelo programa. Isolando, no código do programa, a saída de mensagens normais e a saída de erro, você pode pedir ao sistema operacional que redirecione um deles, ou mesmo ambos, para destino diferente do usual antes de invocar o seu programa, sem que você precise reprogramá-lo.

  • fprintf() é uma função da família de printf() que permite especificar o fluxo de saída, enquanto printf() sempre joga a saída em stdout. Funcionamente, “printf(lista_de_argumentos)” é um sinônimo de “fprintf(stdout, lista_de_argumentos)”.

  • exit() é uma função que serve para encerrar o programa. O argumento passado à função é encaminhado ao sistema operacional, que o reencaminha a quem invocou o programa no momento em que o programa termina.

Não sabia desse problema do strlen().
Vou remover o system(clear), e tentar usar o que você recomendou.

eu tive este erro:
error: initializer element is not constant
const size_t tam = strlen(wordSorteada);


Eu vi, no código do programa, que você colou essa atribuição fora de qualquer função, tentando declarar tam como uma variável global, mas você não pode chamar uma função no escopo de declaração de variáveis globais: invocar funções só pode ocorrer dentro do corpo de definição de uma função.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


9. Retorno da ultima mensagem

Rafael L.
SrKon

(usa Ubuntu)

Enviado em 08/03/2021 - 08:34h


Agora ele executa, mas ao digitar a primeira letra o programa encerra.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>

char banco[30][30]=
{
"notebook",
"smartphone",
"pendrive",
"computador",
"seguraça"
};

char wordSorteada[30] = {0};
char wordDigitada[30] = {0};

void limpaWord()
{
const size_t tam = strlen(wordSorteada);
for(int r = 0; r < tam; r++)
{
wordDigitada[r] = '_';
}
}

void imprimirForca(int erro)
{
switch(erro)
{
case 0:
printf("\n-------\n");
printf("| \n");
printf("| \n");
printf("| \n");
break;
case 1:
printf("\n-------\n");
printf("| o\n");
printf("| \n");
printf("| \n");
break;
case 2:
printf("\n-------\n");
printf("| o\n");
printf("| / \n");
printf("| \n");
break;
case 3:
printf("\n-------\n");
printf("| o\n");
printf("| /| \n");
printf("| \n");
break;
case 4:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| \n");
break;
case 5:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \n");
break;
default:
printf("\n-------\n");
printf("| o\n");
printf("| /|\\ \n");
printf("| / \\ \n");
}
}

bool verifyLetter(char letra, char vetor[26])
{
const size_t tam2 = strlen(vetor);
for(int i = 0; i < tam2; i++)
{
if(letra == vetor[i])
{
return true;
}
}

return false;
}

void alocandoLetra(char letra)
{
const size_t tam = strlen(wordSorteada);
for(int i = 0; i < tam; i++)
{
if(wordSorteada[i] == letra)
{
wordDigitada[i] = letra;
}
}
}

void letrasDigitadas(char let[26], int tam)
{
printf("\nJá fora digitadas: ");
const size_t len = strlen(let);
for(int r = 0; r < len; r++)
{
printf("%c,", let[r]);
}
printf("\n");
}

bool wordCompleta()
{
const size_t tam = strlen(wordSorteada);
for(int r=0;r<tam;r++)
{
if(wordDigitada[r] == '_')
{
return false;
}
}
return true;
}

int main()
{
srand(time(NULL));
int palavra = rand() % 5;
strcpy(wordSorteada, banco[palavra]);
limpaWord();
int contLetras = 0;
int contaErros = 0;
char letraDig[26] = {0};
char letter;

while(contaErros<=6)
{
const size_t tam = strlen(wordSorteada);
imprimirForca(contaErros);
printf("\n%zu letras\n%s", tam, wordDigitada);
letrasDigitadas(letraDig, contLetras);
printf("\n\nTentativas restantes: %d\n", 6-contaErros);
printf("\n\n");
printf("Digite uma letra: \n");
scanf("%c", &letter);
if(strchr(letraDig, letter)!=NULL)//verifyLetter(letter, letraDig)
{
printf("\nEssa letra já foi digitada\nTente novament\n");
break;
} else
{
letraDig[contLetras] = letter;
contLetras++;
if(strchr(wordSorteada, letter)!=NULL)//verifyLetter(letter, wordSorteada)
{
alocandoLetra(letter);
} else
{
printf("Letra incorreta\nTente novamente\n\n");
contaErros++;
break;
}
}
if(contaErros>=6)
{
setenv("PATH", "/bin:/usr/bin", 1);
printf("Game Over for you");
break;
} else if(wordCompleta())
{
printf("YOU WIN");
break;
}

}

return 0;
}



10. Re: Erros no jogo da forca [RESOLVIDO]

Walker Luiz de Freitas
WalkerPR

(usa Linux Mint)

Enviado em 08/03/2021 - 15:51h


paulo1205 escreveu:

. . .


Achei legal a imagem do seu avatar e resolvi fazer um plágio.
Espero que não se importe . . . . rsrsrsrs!!!

--------------------------------------------------------------
"Linux: several flavors, one way: - Freedom of choice!"


11. Re: Erros no jogo da forca [RESOLVIDO]

Paulo
paulo1205

(usa Ubuntu)

Enviado em 08/03/2021 - 22:16h

SrKon escreveu:


Agora ele executa, mas ao digitar a primeira letra o programa encerra.


Em minha primeira resposta, eu disse o seguinte a respeito da operação de leitura.

Esta operação de leitura possivelmente é uma parte importante do problema que você reportou, porque não basta que você aperte uma letra, mas tem de digitar uma letra seguida da tecla <Enter> (ou <Return>, se você estiver num computador da Apple), que provoca o aparecimento de dois caracteres na entrada: a letra em si, e um caráter de fim-de-linha ('\n') correspondente ao <Enter>. Cada um desses caracteres será consumido numa iteração diferente do laço de repetição, e você não fez nenhuma validação de se o valor lido realmente corresponde a uma letra ou a um caráter válido.

A leitura de dados de entrada a partir do terminal exige certos cuidados, porque ela é normalmente orientada a linha (i.e. o sistema procura ler sempre linhas inteiras; mesmo que você solicite apenas um caráter, o sistema vai verificar se esse caráter já existe num buffer interno e, se existir, ele devolve o tal caráter imediatamente, mas, caso não exista, o sistema vai procurar encher o buffer com tanto caracteres quantos forem possíveis, até encontrar uma marca de fim-de-linha ou até não haver mais espaço no tal buffer interno antes de lhe entregar o único caráter que você pediu). Além disso, a função scanf() é muito complexa (possivelmente a mais complexa de todas as funções da biblioteca padrão do C), e requer uma boa e cautelosa leitura de sua documentação — e possivelmente alguma prática — para ser usada de modo efetivo e competente, com o devido conhecimento de quando acontecem descartes automáticos de caracteres e quando eles não ocorrem, como usar conversões, conversões sem atribuição/alteração de valor ou textos fixos, limitações de largura ou de conjuntos de caracteres, alocação automática de memória, indicadores de quantos caracteres foram consumidos, alteração de ordem de argumentos que podem receber atribuições e sinalização de erros ou grau de sucesso das conversões, entre outros aspectos. E eu não estou exagerando.

No mínimo, eu sugiro a você fazer as seguintes mudanças referentes a este pedaço:

  • teste o valor de retorno de scanf(), para ter certeza de que não ocorreu erro de leitura;

  • dentro da própria string de formatação de scanf(), procure descartar todos os caracteres que não interessarem (especialmente espaços, incluindo quebras de linha, cujo tratamento é muito fácil);

  • após a leitura, verifique que fruto de leitura seja válido, e dê o tratamento adequado caso não seja.

Acima, uma das palavras do dicionário incluía um ç. Lembre-se de que ç e vogais acentuadas são caracteres distintos do c comum e das vogais não-acentuadas. Além disso, dependendo do conjunto de caracteres que esteja em uso tanto no momento da compilação quanto no momento da execução, a representação dos caracteres acentuados ou com cedilha pode ser diferente, inclusive com mais do que um byte (ou caráter, pois em C cada char corresponde exatamente a um byte) por sinal gráfico (por exemplo, com o conjunto de caracteres europeu e codificação ISO-8859-1, o c corresponde ao byte com valor 99 e o c corresponde ao valor 231; já com o Unicode e codificação UTF-8, que é a mais comum no Linux hoje em dia, o c corresponde ao mesmo byte com valor 99, mas o ç corresponde a um par de bytes, sendo o primeiro com valor 195 e o segundo com o valor 167). Se você quiser tratar caracteres com marcas diacríticas, seu programa certamente vai ter de ser mais sofisticado.


Como você não fez as modificações sugeridas, o programa continua com o mesmo comportamento de antes.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)


12. Re: Erros no jogo da forca

Paulo
paulo1205

(usa Ubuntu)

Enviado em 08/03/2021 - 22:29h

WalkerPR escreveu:

Achei legal a imagem do seu avatar e resolvi fazer um plágio.
Espero que não se importe . . . . rsrsrsrs!!!


Eu não registrei nenhuma marca, e não creio que eu mesmo tenha sido muito original, então é evidente que você pode usar sua própria imagem à vontade.

Parece-me que nós protestamos contra coisas diferentes. Vergonha, para mim, está num STF que destrói a Constituição da República, legisla sem mandato para tal e interfere descaradamente nos outros Poderes da República, e também num Congresso Nacional que se ajoelha num dia e, dois dias depois, cria uma PEC para blindar quem sobrou, a fim de não acontecer com eles o que eles deixaram acontecer impunemente com um dos seus pares.

Não que eu tenha qualquer simpatia pelo Daniel Silveira, de quem nunca antes tinha ouvido falar. Mas é inegável que esse foi um caso de muitas formas emblemático.

E não vou nem falar sobre o que aconteceu hoje...

Só espero que não venha nenhum STF nos perseguir e nenhuma turba para nos cancelar por conta de nossas mensagens de protesto.


... Então Jesus afirmou de novo: “(...) eu vim para que tenham vida, e a tenham plenamente.” (João 10:7-10)



01 02



Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts