Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

Sign in to follow this  
Miketo

Funciona do Ubuntu. No Windows compila mas depois da erro ....

Recommended Posts

Miketo

Boas pessoal. O problema é o seguinte. Eu fiz este jogo da memória no ubuntu. Corre e faz tudo sem problemas. Só falta ainda ordenar records mas isso faço depois. Agora quero correr o jogo no windows. Já alterei a função que apaga o ecrã, visto que o ubuntu nao suporta o system("cls").

Instalei o Dev C++ (parece-me ser antigo mas nao conheco outro. Se me aconselharem um melhor agradeço). Ele compila o programa e não dá qualquer erro. O programa corre às mil maravilhas, até acertarmos nos simbolos. Quando acertamos, o programa bloqueia e sai. Vou colocar aqui o código que crei. São duas funções, uma .cpp e uma .h. Vou assinalar no código o sitio onde dá erro. Se me puderem ajudar, agradecia imenso.

Ficheiro .ccp com o erro assinalado. Em baixo ponho também o ficheiro .h

#include <stdlib.h>			
#include <stdio.h>
#include <time.h>
#include <iomanip>
#include <iostream>
#include "funcoes.h"
#include <fstream>

using namespace std;

//
//	Programa Principal //////////////////////////////////////////////////////////
//

int main(int  argc, char *argv[]){

// *********** Variaveis *************

char op;	// recebe opcao no menu inicial
int niv;	// recebe o nivel escolhido
int TempEs=10;

// dimensao da matriz por definicao (nivel medio)
int* dim= new int[2]; 
dim[0]=6;	// altura da matriz
dim[1]=4;	// largura da matriz	

// Matrizes
int** tab;	// vai receber matriz aleatoria
int** tab2;	// vai receber matriz por preencher
int** tab_coord;	// matriz de controlo

char a[2]; // recebe as coordenadas do simbolo a mostrar

int b,c,temp=0,x,y,temp2,controlo=0, seg=0;

// variaveis de teste
bool teste=0, final, coordenadas=0; 

// variaveis de controlo para records
int jogadas, acertadas;

// *************** Menu *************
do{
	op=Esopcao();

        //printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	system("cls");       // Apaga ecra (windows)

	switch (op){
		case '1':{	// Jogar
			seg=1;				
			jogadas=0;
			acertadas=0;
			Cabecalho();	// imprime cabecalho

			cout << " A gerar tabuleiro de jogo.... " << endl << endl;
			espera(2);				

			tab=tabuleiro(dim);	// gera tabuleiro

			mostra(tab, dim);	// mostra tabuleiro

			cout << endl << endl << " Get ready ! " << endl << endl;
			cout << "tip: Caso seja extremamente dificil para ti acabar o jogo," << endl;
			cout << "introduz 'q' para desistir." << endl << endl;
			Contagem(TempEs,tab,dim);
			tab2=tabuleiro2(dim);	// gera tabuleiro escondido

			// tabela de controlo para as coordenadas
			tab_coord = new int*[dim[0]];
			for (int i=0; i< dim[0]; ++i){ 
				tab_coord[i] = new int[dim[1]];
			}
			for (int i=0; i<dim[0] ; ++i){
				for(int j=0; j<dim[1]; ++j){
					tab_coord[i][j]=0;
				}
			}

			do{
				if(controlo==0){	// Só gera novo simbolo se tiver adivinhado o anterior
					do{	
						srand ( time(NULL) ); //inicializaçao da semente
						b=rand()%dim[0]+1;
						c=rand()%dim[1]+1;
					}while(tab_coord[b-1][c-1]==1);	// se ja gerou este simbolo, nao volta a gerar
					tab_coord[b-1][c-1]++;
				};

				tab2[b-1][c-1]=tab[b-1][c-1];	// atribui a tab2 um valor de tab para o jogador adivinhar

				do{	// Seleccionar coordenadas

					//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	                system("cls");       // Apaga ecra (windows)

                    	Cabecalho();	// imprime cabecalho
					mostra(tab2, dim);	// mostra tabela com simbolo para adivinhar
					cout << endl;
					cout << "Para desistir introduz 'q'." << endl;
					cout << "Mostra: ";
					cin >> a;
					temp=atoi(&a[0]);
					teste=(a[0]=='q');

					coordenadas=0;	//dentro
					int contador=0;

					for (int i=0; i<dim[0] ; i++){
						x=(i+1)*10;
						y=x+1;
						if(temp<y){
							contador++;	//fora
						}
						y=x+dim[1];
						if(temp>y){
							contador++;	//fora
						}
					}
					if (contador==dim[0]) {coordenadas=1;}
				    
				}while(teste==0 && (coordenadas==1 || temp==(b*10+c)));

				jogadas++;	//so conta como jogada se for uma coordenada da matriz

				if (teste!=1){	// Ainda nao desistiu e colocou coordenadas correctamente
					x=temp/10;	// linha da matriz
					y=temp%10;	// coluna da matriz

					temp2=tab2[x-1][y-1];	// coloca em temp2 o valor de tab2 (-) na posicao das coordenadas
					tab2[x-1][y-1]=tab[x-1][y-1];	// coloca em tab2 o valor de tab na posicao das coordenadas

                        //printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	                system("cls");       // Apaga ecra (windows)

                        Cabecalho();	// imprime cabecalho
					mostra(tab2, dim);	// mostra matriz tab2

					if (tab2[x-1][y-1]!=tab2[b-1][c-1]) {	// Falhou

						cout << endl << " NOT !! Try again..." << flush;
						espera(1);
						tab2[x-1][y-1]=temp2;	// Se nao acertou, esconde a tentativa do jogador
						controlo=1;

						//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	                    system("cls");       // Apaga ecra (windows)
					}
// --->Dá erro quando 	else{	// Acertou
// entra neste else						
// imprime a frase			cout << endl << " Well done! Next one..." << flush;
// e depois puff			espera(1);
						tab_coord[x-1][y-1]++;	// Nao vai pedir um par de um simbolo já descoberto
						controlo=0;
						acertadas++;	// incrementa numero de jogadas acertadas

                            //printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
                     	system("cls");       // Apaga ecra (windows)
					}
				}
				else{	// Desistiu!

                        //printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
                        system("cls");       // Apaga ecra (windows)

                        Cabecalho();	// imprime cabecalho
					cout << endl <<" Better luck next time! " << flush;
					espera(1);

					//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
                  		system("cls");       // Apaga ecra (windows)
				}

				final=1;
				for (int i=0; i<dim[0] ; ++i){
					for(int j=0; j<dim[1]; ++j){
						if(tab2[i][j]!=tab[i][j]){	// Ainda nao descobriu todos os simbolos
							final=0;
						}	
					}
				}

				if (final==1){

					float percent=0;
					percent=((float)acertadas/(float)jogadas)*100;	// percentagem
					Cabecalho();	// imprime cabecalho
					cout << " Congratulations!! You finish it! " << endl;
					cout << " Game score: " << acertadas << "/" << jogadas << " = " << percent << "%" << endl;
					escreve_record(percent);
					cout << " Now try a harder level ... if you dare... " << endl;
					espera(2);

					//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
                  		system("cls");       // Apaga ecra (windows)
				}

			}while(teste!=1 && final!=1);	// Sai se desistir ou completar
			break;
		}
		case '2':{	// Nivel
			Cabecalho();	// imprime cabecalho
			niv=nivel();	// escolhe nivel
			dim=dimensao(niv, dim);	// define dimensao do tabuleiro

                //printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	        system("cls");       // Apaga ecra (windows)

                break;
		}
		case '3':{ // Escolher Tempo
			Definirtempo(TempEs);
			break;
		}
		case '4':{	// Mostra Records
			char enter;
			Cabecalho();	// imprime cabecalho
			mostra_records();
			cout << endl << "introduza uma tecla para voltar: ";
			cin >> enter;

			//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	        system("cls");       // Apaga ecra (windows)

                break;
		}

		default:	// Nao faz nada
		break;
	};

}while(op!='5');

// Sao sempre alocadas, para posterior eliminação.
// Previne erro caso nunca se jogue!
tab = new int*[dim[0]];
tab2 = new int*[dim[0]];
tab_coord = new int*[dim[0]];
for (int i=0; i< dim[0]; ++i){ 
	tab[i] = new int[dim[1]];
	tab2[i] = new int[dim[1]];
	tab_coord[i] = new int[dim[1]];
};
// Eliminar as tabelas
for (int i=0; i<dim[0] ; ++i){
		delete tab[i];
		delete tab2[i];
		delete tab_coord[i];		
}
delete tab;
delete tab2;
delete tab_coord;
delete dim;

system("pause");
        return 0;	// main
}

Ficheiro .h

// Ficheiro com funcoes criadas para o jogo da memoria
#include <stdlib.h>			
#include <stdio.h>
#include <time.h>
#include <iomanip>
#include <iostream>
#include <fstream>

using namespace std;

//
// Funcao que escreve records
//
int escreve_record(float percentagem){

char p[4];
int a=(int)percentagem/10;
int b=(int)percentagem%10;
int c=(int)(percentagem*10)%10;
p[0]=(char)a;
p[1]=(char)b;
p[2]='.';
p[3]=(char)c;

FILE* fich;

char nome[15];
fich = fopen ("records.txt" , "a");
if(!fich){
	cout << "Erro a abrir o ficheiro";
	return 0;
    }

cout << "Introduz o teu nome: ";
cin >> nome;
fputs (nome,fich);
fputs (" ---> ",fich);
fputs (p,fich);
fputs ("\n",fich);

fclose(fich);
return 0;
}

//
// Funcao que mostra os records no ecrã
//
int mostra_records(){

char str[150];
FILE* fich;

fich = fopen ("records.txt" , "a");	// caso nao exista o ficheiro, cria mas nao escreve nada nele
if(!fich){
	cout << "Erro a abrir o ficheiro";
	return 0;
    }
fclose(fich);



fich = fopen ("records.txt" , "r");


if(!fich){
	cout << "Erro a abrir o ficheiro";
	return 0;
    }
    
    cout << " Top 10 Jogo da memoria" << endl;
    cout << "Nome   ---   percentagem" << endl;
    
while(!feof(fich)){
	fgets (str, 150,fich );
	cout << str;
};

fclose(fich);
return 0;
}
                                                   
//
// Função que mostra o cabeçalho do jogo
//
void Cabecalho(){
cout << "****************************************************" << endl;
cout << "**                                                **" << endl;
cout << "**              JOGO DA MEMORIA                   **" << endl;
cout << "**                                                **" << endl;
cout << "****************************************************" << endl << endl;
}

//
// Função que escolhe o nivel
//
char nivel(){

char n;

do{
cout << "Escolha o nivel de jogo:" << endl;
cout << "1 - Facil" << endl << "2 - Medio" << endl << "3 - Dificil (MESMO!!)" << endl;
cin >> n;
}while(n!='1' && n!='2' && n!='3');

return n;
}

//
//	Funcao que da a dimensao da matriz
//
int* dimensao(char niv, int* dim) {
int dim1=0,dim2=0;

switch (niv){
	case '1':{
		dim1=4;
		dim2=3;
		break;
	}
	case '2':{
		dim1=6;
		dim2=4;
		break;
	}
	case '3':{
		dim1=8;
		dim2=6;
		break;
	}
	default:
	break;
};

dim[0]=dim1;
dim[1]=dim2;
return dim;
}

//
// Funcao que gera matriz de jogo
//
int** tabuleiro(int* dim){

int simb;	// vai receber o número de simbolos diferentes

simb=((dim[0])*dim[1])/2; // pares

int pares[simb];	// vector de controlo
int temp;

for(int i=0; i<simb; i++) {pares[i]=0;} // inicializaçao a zero do vector controlo

int **tab = new int*[dim[0]];
for (int i=0; i< dim[0]; ++i){ 
	tab[i] = new int[dim[1]];
};

srand ( time(NULL) ); //inicializaçao da semente

// cout << simb << endl; // controlo 

for (int i=0; i<dim[0] ; ++i){
	for(int j=0; j<dim[1]; ++j){

		do{
			temp = rand()%simb+65;	//gera inteiro aleatorio entre 1 e simb
			}while(pares[temp-65]==2);	// so queremos um par de cada simbolo

		tab[i][j] = temp;
		pares[temp-65]++;
	}
}

return tab;
}

//
// Funcao que espera
//
void espera ( int seconds ){
  clock_t endwait;
  endwait = clock () + seconds * CLOCKS_PER_SEC ;
  while (clock() < endwait) {}
}

//
// Funcao que mostra o tabuleiro
//
void mostra(int** tab, int* dim){
int i,j;

cout << " ";
for (i=0; i<dim[1]; ++i){
	cout << "   " << i+1 ;
}
cout << endl << endl;

for (i=0; i<dim[0] ; ++i){
	cout << i+1;

	for(j=0; j<dim[1]; ++j){
		cout << "   " << (char)tab[i][j];
	}
	cout << endl;
}
}

//
// Funcao que gera tabuleiro escondido
//
int** tabuleiro2(int* dim){

int simb;	// vai receber o número de simbolos diferentes

simb=((dim[0])*dim[1])/2; // pares

int **tab = new int*[dim[0]];
for (int i=0; i< dim[0]; ++i){ 
	tab[i] = new int[dim[1]];
};

for (int i=0; i<dim[0] ; ++i){
	for(int j=0; j<dim[1]; ++j){
		tab[i][j]=45;
	}
}
return tab;
}

//
// Função da contagem decrescente
//
int Contagem(int TemP,int** tab, int* dim){
int b=0,t,i;
long tem,ago,es;
time(&tem);
tem=tem+TemP+1;
time(&ago);
while(ago<tem){
	es=ago+1;
	time(&ago);
	i=0;
	while(ago<es){
		time(&ago);
		if(i==0){
			//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	        system("cls");       // Apaga ecra (windows)

                Cabecalho();
			mostra(tab, dim);
			t=TemP-b;
			cout<<endl<<"Tempo retante: "<<t<<"segundos"<<endl;
			i++;
			b++;
		}
	}
	//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	system("cls");       // Apaga ecra (windows)
}
return 0;
}

//
//Funcao para mostrar o menu
//
int Menu(){
cout<<"  *********** Menu  Principal *********** "<< endl << endl;
cout<<"I- iniciar jogo"<<endl;
cout<<"N- definir nivel"<<endl;
cout<<"T- defenir tempo"<<endl;
cout<<"R- ver os recordes"<<endl;
cout<<"S- sair"<<endl;
return 0;
}

//
//Funcao para proteger a opção de escolha
//
char Opcao(){

char Opc;

do{
	cout<<"Introduza a opção desejada: ";
	cin>>Opc;
	if(Opc!='s' && Opc!='S' && Opc!='i' && Opc!='I' && Opc!='t' && Opc!='T' && Opc!='r' && Opc!='R' && Opc!='n'&& Opc!='N' ){
		cout<<"Opção invalida"<<endl;
	}
}while(Opc!='s' && Opc!='S' && Opc!='i' && Opc!='I' && Opc!='t' && Opc!='T' && Opc!='r' && Opc!='R' && Opc!='n'&& Opc!='N' );

return Opc;
}

//
//	Converçao
//
char Esopcao(){

char op;
Cabecalho();
Menu();
op=Opcao();
		switch(op){
		case 'i':
			op='1';
			break;
		case 'I':
			op='1';
			break;
		case 'r':
			op='4';
			break;
		case 'R':
			op='4';
			break;
		case 't':
			op='3';
			break;
		case 'T':
			op='3';
			break;
		case 'n':
			op='2';
			break;
		case 'N':
			op='2';
			break;
		case 's':
			op='5';
			break;
		case 'S':
			op='5';
			break;
		default: 
			cout<<"ERRO";
		}
	return op;
}

//
//Função que define o tempo
//
int Definirtempo(int &TempM){

char resp;
Cabecalho();
while(1){
	//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
	system("cls");       // Apaga ecra (windows)

	Cabecalho();
	cout<<endl<<"Tempo actual para memorização é "<<TempM<<" segundos "<<endl;
	cout<<"Pretende alterar o tempo? [s/n] ";

	do{
		cin>>resp;
		if(resp!='s' && resp!='S' && resp!='n' && resp!='N'){
			cout<<"opção invalida"<<endl<<"Introduza novamente a opção: ";
		}
	}while(resp!='s' && resp!='S' && resp!='n' && resp!='N');

	if(resp=='n' || resp=='N'){
		//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
    	system("cls");       // Apaga ecra (windows)
		return 0;
	}

	do{
		//printf("\e[H\e[2J");	// Apaga ecra (ubuntu)
    	system("cls");       // Apaga ecra (windows)

        	Cabecalho();
		cout<<endl<<"Introduza o tempo desejado, entre 1 e 30 segundos ";
		cin>>TempM;

		if(TempM<1 || TempM>30){
			cout<<"Tempo invalido"<<flush;
			espera(1);
		}

	}while(TempM<1 || TempM>30);
}
return 0;		
}

Share this post


Link to post
Share on other sites
Miketo

Quando o programa é interrompido, ao fazer um debug com o visual studio aparece a seguinte mensagem:

"Access violation writing location 0x00000000."

Na net dizem que isto aparece quando temos uma "Null-pointer dereference".

Não sei o que o código faça para isto acontecer.

Espero que isto ajude a ajudarem-me  😳

Share this post


Link to post
Share on other sites
Miketo

O problema era uma coisa muito simples.

Não estava a criar uma tabela dinamicamente.  😳

Era uma coisa que tinha feito nas restantes... mas aquela escapou-me e estava a fazer uma alocação "normal" da memória para a tabela.

Mas o que me fez não reparar foi o facto de, para o mesmo problema, no linux ter dado erro para outras tabelas, e naquela não ter dado.  🤔 Daí não ter associado.

Esta é uma questão que não consegui perceber... mas o programa já funciona... é o que interessa  :thumbsup:

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.