Ir ao conteúdo

Posts recomendados

Postado

Boa tarde pessoal!

Procurei em muitos fóruns e de todas formas que consegui pensar, mas não encontrei solução para meu problema, nem alguém com problema parecido.
Tenho 4 dias pra entregar um jogo da memória feito em C, e devo gerar peças aleatórias a cada jogo novo. O código funciona algumas vezes, mas outras não executa, simplesmente fica a tela do console toda preta e o cursor piscando. O debugger também não funciona assim que chamo uma função no main, logo após a declaração de srand. Se eu tiro srand do código, ele funciona todas as vezes que executado. Alguém por favor consegue me ajudar? (OBS.: Ainda estão faltando algumas lógicas do jogo em si, portanto, tem outras coisas que estou com dificuldades a serem finalizadas):


 

//BIBLIOTECAS
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>

#define SIZE 6 //Constante global para o uso da palavra SIZE


//PROTÓTIPOS DAS FUNÇÕES
void game     (char deck[][SIZE]);
void generate (char deck[][SIZE]);
void table    (char matrix[][SIZE]);
void request  (char printable_deck[][SIZE], char deck[][SIZE]);


//FUNÇÃO PRINCIPAL
int main()
{
    setlocale (LC_ALL, "Portuguese");
    srand (time(NULL)); //Alimenta rand() com números diferentes


    char deck[5][SIZE]={}; //Baralho que conterá as cartas


    game(deck); //Chama a função que dá início ao jogo

    return 0;
}


//EXECUÇÃO DO JOGO
void game(char deck[][SIZE])
{
    char printable_deck[5][SIZE]={}; //Matriz que oculta as cartas

    generate (deck);
    table    (deck);

    system ("pause");
    system ("cls");

    table (printable_deck);

    request (printable_deck, deck);
}


//GERA AS CARTAS PARA O BARALHO
void generate (char deck[][SIZE])
{
    char cards[15]={'A','E','I','O','U','a','e','i','o','u','&','<','>','?','@'}; //Cartas disponíveis no jogo
    int n=0, x1, y1, x2, y2;

    while (n<15)
    {
        x1=rand()%5;
        x2=rand()%5;
        y1=rand()%6;
        y2=rand()%6;

        if (deck[x1][y1]==0 && deck[x2][y2]==0)
        {
            if (x1!=x2 && y1!=y2)
            {
                deck[x1][y1]=cards[n];
                deck[x2][y2]=cards[n];

                n++;
            }
        }
    }
}


//IMPRIME O BARALHO NA TELA
void table (char matrix[][SIZE])
{
    int i, j;
    int m=1;

    printf ("\n      1   2   3   4   5   6\n\n"); //Imprime o índice das colunas

    for (i=0; i<5; i++)
    {
        printf (" %d   ", m); //Imprime o índice das linhas

        for (j=0; j<SIZE; j++)
            printf ("[%c] ", matrix[j]);

        printf ("\n\n");

        m++;
    }
}


//PERGUNTA AO USUÁRIO A CARTA QUE DESEJA VIRAR
void request (char printable_deck[][SIZE], char deck[][SIZE])
{
    int i, m, n;
    int x[2], y[2];

    for (i=0; i<=1; i++)
    {
        printf ("Qual a localização da carta desejada?"
                "\nLinha:  ");
        scanf  ("%d", &m);
        printf ("Coluna: ");
        scanf  ("%d", &n);

        x=m-1;
        y=n-1;

        printable_deck[m-1][n-1]=deck[m-1][n-1];

        system ("cls");

        table (printable_deck);
    }

    if (deck[x[0]][y[0]]!=deck[x[1]][y[1]])
        printf ("\n\nVocê errou! Tente novamente.");
    else
    {
        printf ("Parabéns! Você acertou.\n\n");

        request (printable_deck, deck);
    }
}

Postado

Testei seu código, e aqui também da umas bugadas no console, mas eu acho que isso é algum bug interno nas bibliotecas, pode ser alguma falha do srand, que necessita um certo tempo para ser executado novamente, não sei muito sobre isso, resumindo, só arrumei a função table, segue:


#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>
#define SIZE 6 

void game     (char deck[][SIZE]);//Execução do jogo
void generate (char deck[][SIZE]);//Gerar cartas
void table    (char matrix[][SIZE]);//Mostrar cartas
void request  (char printable_deck[][SIZE], char deck[][SIZE]);//Operacao do jogador

int main()
{
	setlocale (LC_ALL, "Portuguese");
    srand ((unsigned)time(NULL)); 

    char deck[5][SIZE]={}; //Baralho que conterá as cartas

    game(deck); //Chama a função que dá início ao jogo
    return 0;
}


void game(char deck[][SIZE])
{
    char printable_deck[5][SIZE]={}; //Matriz que oculta as cartas
    generate (deck);
    table    (deck);
    system ("pause");
    system ("cls");
    table (printable_deck);
    request (printable_deck, deck);
}

void generate (char deck[][SIZE])
{
    char cards[15]={'A','E','I','O','U','a','e','i','o','u','&','<','>','?','@'}; //Cartas disponíveis no jogo
    int n=0, x1, y1, x2, y2;
    
    while (n<15)
    {
        x1=rand()%5;
        x2=rand()%5;
        y1=rand()%6;
        y2=rand()%6;
        if (deck[x1][y1]==0 && deck[x2][y2]==0)
        {
            if (x1!=x2 && y1!=y2)
            {
                deck[x1][y1]=cards[n];
                deck[x2][y2]=cards[n];
                n++;
            }
        }
    }
}

void table (char matrix[][SIZE])
{
    int i, j;
    printf ("\n      1   2   3   4   5   6\n\n"); //Indice colunas
    for (i=0; i<5; i++){
        printf (" %d   ", i+1); //Indice cartas
        for (j=0; j<SIZE; j++)
            printf ("[%c] ", matrix[i][j]);
        	printf ("\n\n");
    }
}

void request (char printable_deck[][SIZE], char deck[][SIZE])
{
    int i, m, n;
    int x[2], y[2];
    
    for (i=0; i<=1; i++)
    {
        printf ("Qual a localização da carta desejada?" \
                "\nLinha:  ");
        scanf  ("%d", &m);
        printf ("Coluna: ");
        scanf  ("%d", &n);
        x[i]=m-1;
        y[i]=n-1;
        printable_deck[m-1][n-1]=deck[m-1][n-1];
        system ("cls");
        table (printable_deck);
    }
    if (deck[x[0]][y[0]]!=deck[x[1]][y[1]])
        printf ("\n\nVocê errou! Tente novamente.");
    else
    {
        printf ("Parabéns! Você acertou.\n\n");
        request (printable_deck, deck);
    }
}

 

  • Curtir 1
Postado

Agradeço pela simplificação da função table, de fato não pensei em utilizar o i+1. 

Meu professor disse que pode ser algo que escrevi errado na função rand() (porém ele não olhou o código). Pelo que revi diversas vezes, não há nada de errado com a forma em que utilizei rand() no código. Pior é que tenho 2 dias restantes pra terminar tudo, e não estou conseguindo finalizar.

Postado

O mais provavel é que essa linha esteja "travando" a geração randomica

Citação

if (x1!=x2 && y1!=y2)

Por exemplo se faltar só 2 cartas para preencher e elas forem na mesma linha ou coluna. Ele nunca vai entrar nesse if e por isso fica em um loop infinito. Para resolver isso só precisa mudar && para ||.

 

Outra coisa é que esse metodo de ficar sorteando as cartas até achar 2 que estejam vazias pode demorar muito se o tabuleiro for muito grande.

  • Curtir 2
Postado
2 horas atrás, MassakiMsk disse:

O mais provavel é que essa linha esteja "travando" a geração randomica

Por exemplo se faltar só 2 cartas para preencher e elas forem na mesma linha ou coluna. Ele nunca vai entrar nesse if e por isso fica em um loop infinito. Para resolver isso só precisa mudar && para ||.

 

Outra coisa é que esse metodo de ficar sorteando as cartas até achar 2 que estejam vazias pode demorar muito se o tabuleiro for muito grande.

Poxa amigo, agradeço demais!! Realmente era a questão do && e ||. Quebrei muito a cabeça com isso, e pelo visto ainda tenho dificuldades com a lógica em geral.

No caso é um tabuleiro de 30 cartas, isso não será alterado. Mas qual dos métodos de sorteio seria mais eficiente no caso, você saberia indicar?

Infelizmente estes ainda são meus primeiros contatos com programação, e devido ao prazo dado pra fazer este trabalho juntamente de tantos outros compromissos, realmente preciso de ajuda ou qualquer crítica, caso não se importem. É de grande importância pra mim!

Postado

Eu também não sei qual a melhor forma, mas o ultimo codigo que fiz utilizei pilha, como se fosse uma pilha de cartas mesmo. randomizava a pilha uma vez só, e depois ia tirando carta a carta e setando o valor para ela.

Postado

Enfim, dei mais uma olhada e acho que agora ta tudo certo, o problema era devido a geração de cartas, onde você sempre escolhia as coordenadas que não fossem iguais, como x1 != x2 e y1 != y2, ou seja, se uma das duas forem diferentes, a coordenada ja não igual, portanto não precisa usar E mas sim OU '||'. A lógica ta no código:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>

#define SIZE 6 

void game     (char deck[][SIZE]);//Execução do jogo
void generate (char deck[][SIZE]);//Gerar cartas
void table    (char matrix[][SIZE]);//Mostrar cartas
void request  (char printable_deck[][SIZE], char deck[][SIZE]);//Operacao do jogador

int main()
{
	setlocale (LC_ALL, "Portuguese");
    srand ((unsigned)time(NULL)); 

    char deck[5][SIZE]={}; //Baralho que conterá as cartas

    game(deck); //Chama a função que dá início ao jogo
    return 0;
}


void game(char deck[][SIZE])
{
    char printable_deck[5][SIZE]={}; //Matriz que oculta as cartas
    generate (deck);
    table    (deck);
    system ("pause");
    system ("cls");
    table (printable_deck);
    request (printable_deck, deck);
}

void generate (char deck[][SIZE])
{
    char cards[15]={'A','E','I','O','U','a','e','i','o','u','&','<','>','?','@'}; //Cartas disponíveis no jogo
    int n, x1, y1, x2, y2;
    
    for(n = 0; n < 15;){
        x1=rand()%5;
        x2=rand()%5;
        y1=rand()%6;
        y2=rand()%6;
        if (deck[x1][y1]== 0 && deck[x2][y2]== 0)
        {
        	//X1 = 2 , X2 = 2
        	//X1 = X2
        	//Y1 = 2, Y2 = 2
        	//NESSE CASO NÃO É CONTINUADO
        	//MAS SE UM DOS DOIS FOREM DIFERENTES, JÁ NÃO É O MESMO LOCAL
            if (x1!=x2 || y1!=y2)
            {
                deck[x1][y1]=cards[n];
                deck[x2][y2]=cards[n];
                n++;
            }
        }
    }
}

void table (char matrix[][SIZE])
{
    int i, j;
    printf ("\n      1   2   3   4   5   6\n\n"); //Indice colunas
    for (i=0; i<5; i++){
        printf (" %d   ", i+1); //Indice cartas
        for (j=0; j<SIZE; j++)
            printf ("[%c] ", matrix[i][j]);
        	printf ("\n\n");
    }
}

void request (char printable_deck[][SIZE], char deck[][SIZE])
{
    int i, m, n;
    int x[2], y[2];
    
    //O laço é de apenas uma tentativa?!
    for (i=0; i<=1; i++)
    {
        printf ("Qual a localização da carta desejada?" \
                "\nLinha:  ");
        scanf  ("%d", &m);
        
        printf ("Coluna: ");
        scanf  ("%d", &n);
        
        x[i]=m-1;
        y[i]=n-1;
        printable_deck[m-1][n-1]=deck[m-1][n-1];
        system ("cls");
        table (printable_deck);
    }
    if (deck[x[0]][y[0]]!=deck[x[1]][y[1]])
        printf ("\n\nVocê errou! Tente novamente.");
    else
    {
        printf ("Parabéns! Você acertou.\n\n");
        request (printable_deck, deck);
    }
}

crédito ao @MassakiMsk

  • Curtir 2
Postado

@1freakday Realmente me equivoquei naquela parte, não pensando em todas as condições. Agradeço a vocês por me ajudarem com isto. E no laço aonde você perguntou seria executado 2 vezes, sendo i=0 é executado até se tornar i=1, porém passei o dia escrevendo o código e alterei algumas coisas, então desfiz o laço por necessidade de ocupar valores independentes depois.

Outra pergunta que é um dos principais requisitos para o jogo, existe algum modo de, em qualquer momento que pressionado ESC, saia do jogo (ou apareça uma tela com a opção)? O requisito informa que a qualquer momento que pressionada a tecla saia do jogo, mas eu somente consegui implementar em dados momentos do jogo, utilizando a condição "if (getch()=27)". Tentei executar todo o jogo dentro de um "do{} while (getch()!=27)", mas não funcionou (talvez por não saber de onde começar e terminar o que incluo dentro de do while).

Como não vou ter tempo de passar o jogo para uma biblioteca tipo allegro, muito menos de aprender a usar tal, será que é possível criar alguma condição utilizando somente bibliotecas padrão, ou no máximo "conio2"?

Segue o código mais atual:

 

//BIBLIOTECAS
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <time.h>
#include <windows.h>
#include <conio2.h>

 

#define SIZE 6


//PROTÓTIPOS DAS FUNÇÕES
void game();
void table    (char hidden[][SIZE]);
void score    (int *points);
void generate (char pieces[][SIZE]);
void request  (char pieces[][SIZE], char hidden[][SIZE], int *points);

 

//FUNÇÃO PRINCIPAL

int main()
{
    setlocale (LC_ALL, "Portuguese");

    SetConsoleTitle ("Memory Game in C - by Arthur & Paola"); //Define o título para a janela do console

    srand ((unsigned)time(NULL)); //Alimenta rand() com números diferentes

    game(); //Chama a função que dá início ao jogo

    return 0;
}


//EXECUÇÃO DO JOGO
void game()
{
    char pieces[5][SIZE]={}; //Matriz que conterá as peças
    char hidden[5][SIZE]={}; //Matriz que conterá os pares encontrados
    int points=0; //Pontuação do jogo

    table    (hidden);
    score    (&points);
    generate (pieces);
    request  (pieces, hidden, &points);
}


//IMPRIME A MESA
void table (char hidden[][SIZE])
{
    int i, j;

    cputsxy (8,2, "1   2   3   4   5   6\n\n"); //Imprime o índice das colunas

    for (i=0; i<5; i++)
    {
        printf ("  %d   ", i+1); //Imprime o índice das linhas

        for (j=0; j<SIZE; j++)
            printf ("[%c] ", hidden[j]);

        printf ("\n\n");
    }
}


//IMPRIME A PONTUAÇÃO
void score (int *points)
{
    gotoxy (7,15);

    printf ("Pontuação: %d", *points);
}


//GERA AS PEÇAS
void generate (char pieces[][SIZE])
{
    char cards[15]={'A','E','I','O','U','a','e','i','o','u','&','<','>','?','@'}; //Peças do jogo
    int n=0, x1, y1, x2, y2;

    while (n<15)
    {
        x1=rand()%5;
        x2=rand()%5;
        y1=rand()%6;
        y2=rand()%6;

        if (pieces[x1][y1]==0 && pieces[x2][y2]==0)
        {
            if (x1!=x2 || y1!=y2)
            {
                pieces[x1][y1]=cards[n];
                pieces[x2][y2]=cards[n];

                n++;
            }
        }
    }
}


//OPERAÇÃO DO JOGADOR
void request (char pieces[][SIZE], char hidden[][SIZE], int *points)
{
    int x[2], y[2];

    do
    {
        cputsxy (35,4, "Qual a localização da primeira peça?");
        cputsxy (35,6, "Linha:  ");
        scanf   ("%d", &x[0]);
        cputsxy (35,7, "Coluna: ");
        scanf   ("%d", &y[0]);

        hidden[x[0]-1][y[0]-1]=pieces[x[0]-1][y[0]-1];

        system ("cls");
        table  (hidden);
        score  (points);


        cputsxy (35,4, "Qual a localização da primeira peça?");
        cputsxy (35,6, "Linha:  ");
        scanf   ("%d", &x[1]);
        cputsxy (35,7, "Coluna: ");
        scanf   ("%d", &y[1]);


        if ((x[0]==x[1]) && (y[0]==y[1])) //Caso o jogador digite 2 vezes a mesma peça, ela é virada novamente
        {
            printf ("\a"); //Emite um som de alerta
            cputsxy (35,10, "Digite uma posição diferente!");

            delay (1500);

            hidden[x[0]-1][y[0]-1]=0;
            hidden[x[1]-1][y[1]-1]=0;

            system ("cls");
            table  (hidden);
            score  (points);

        } else {

            hidden[x[1]-1][y[1]-1]=pieces[x[1]-1][y[1]-1];

            system ("cls");
            table  (hidden);
            score  (points);

            gotoxy (2,15);

            if  (hidden[x[0]-1][y[0]-1]==hidden[x[1]-1][y[1]-1])
            {
                cputsxy (35,4, "Parabéns, você acertou!");

                *points+=100;

                score (points);

                delay (1500);

            } else {

                printf ("\a"); //Emite um som de alerta
                cputsxy (35,4, "Você errou! Tente novamente.");

                if (*points!=0)
                    *points-=100;

                score (points);

                delay (1500);

                hidden[x[0]-1][y[0]-1]=0;
                hidden[x[1]-1][y[1]-1]=0;

                table (hidden);
            }
        }

    }while (*points<=1500);
}
 

Postado

Olha, em varios metódos que conheço, não há muitas opções que não levem a gambiarras, porém é possível sim obter uma tecla que permite sair do jogo, porém o CTRL+C ja faz esse trabalho.

Nas funções mais usadas tem o 'signal', você poderia utilizar para capturar teclas que informam ao sistema para fechar o console(programa), mas ele captura as teclas básicas como CTRL+C, etc, não sei se captura ESC. Enfim, com o signal, você poderia desviar a saída do programa, para uma determinada função.

Outra alternativa seria usando uma thread que captura as teclas, e quando ela identificar que foi apertado ESC, você poderia identifica-la e sair do jogo.

Exemplo de thread:

#include <stdio.h>
#include <conio.h>
#include <windows.h>

bool sair = false;
int in = 0;

//Captura ESC e Avisa...
DWORD WINAPI thread(void* data) {
	while(1){
		in = getch();//Armazena entrada
		if(in == 27){// 27 é ESC em ASCII
          	in = 0;
			printf("ESC Apertado!\n");
			sair = true;//flag para sair
		}
	}
  return 0;
}

int main() {
  HANDLE th = CreateThread(NULL, 0, thread, NULL, 0, NULL);
  	while(!sair){
        //nesse while é usado qualquer código
  		if(in){//Enquanto nao for ESC vai receber os dados
		  printf("%c\n",in);
		  in = 0;//limpa entrada	  
		}
	}
}

Mas o problema dessa alternativa é que você precisa criar uma lógica de quando usar o thread, caso contrário, você vai perder dados para ele, quando você quiser usar scanf ou gets na função principal.

Visitante
Este tópico está impedido de receber novas respostas.

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...

LANÇAMENTO!

eletronica2025-popup.jpg


CLIQUE AQUI E BAIXE AGORA MESMO!