Ir para o conteúdo
MacgyverPT

Ajuda em função save/continue num programa C

Mensagens Recomendadas

MacgyverPT    1
MacgyverPT

Boas.

Precisava de uma ajudinha. É assim, estou a desenvolver um jogo em C (jogo de aventura em modo texto, bastante básico), no entanto preciso de fazer uma função de save/continue no jogo, mas não estou a conseguir.

Para fazer a função save, preciso de gravar a informação num ficheiro (até aqui tudo bem), no entanto não sei como fazer, ou pelo menos, não tenho uma ideia de como fazer. A função depois de continuar o jogo através do save feito é fazer o inverso do processo anterior.

Agradecia então um empurrãozinho de como fazer isto, não quero o código feito, pretendo apenas umas ideias de como fazer isto. :thumbsup:

Cump.

MoffspringR

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Flinger    50
Flinger

Honestamente, há tantas formas de o fazer que fica difícil dar-te uma ajuda. Suponho que depende muito de que informação precises de gravar.

Podes optar por ter saves por slots, tipo Pes e afins, ou simplesmente permitir ao utilizador escolher o nome do save e gravar num ficheiro com esse nome toda a informação. Se for demasiada informação, ou demasiado confusa, para um só ficheiro, podes criar uma pasta com o nome que o jogador escolheu e gravar dentro dela vários ficheiros com nomes predefinidos.

Para fazer o continue, vais à directoria onde estão os saves, listas todos os ficheiros com a extensão que deres aos saves (no caso de usares 1 ficheiro por save), ou listas as subdirectorias (caso optes por uma subdirectoria por save).

De resto, a saber:

open()

close

read

write

Caso seja Linux:

opendir

readdir

closedir

telldir

seekdir

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
MacgyverPT    1
MacgyverPT

O jogo apenas guarda a posição do jogador (previamente guardada num array), nome, energia, posição do monstro e energia do monstro. Tendo como base esta informação, qual seria a forma mais indicada de fazer a função save?

Obrigado desde já pela ajuda.

Editado por M.offspring.R

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Flinger    50
Flinger

Se é pouca coisa, eu fazia um ficheiro por save:

Tens uma directoria para saves. Quando um jogador que gravar o jogo, listas todos os ficheiros dessa directoria com extensão .sav (por exemplo) e apresentas ao jogador.

Este pode escolher um desses, ou um novo. No caso de ser um existente truncas esse ficheiro, caso seja um novo crias o novo ficheiro.

A seguir gravas todas as variáveis sequencialmente, aconselho em formato binário. Também aconselho a usar uma hash, ou qualquer outro tipo de CRC no final do ficheiro, para teres a certeza que o ficheiro não foi alterado/corrompido.

Para fazer o continue, listas a directoria de saves, e apresentas todos os ficheiros com extensão correcta, o utilizador escolhe um, les os dados do ficheiro, verificas o CRC para garantir que os dados estão correctos, e segues para bingo :P

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
MacgyverPT    1
MacgyverPT

Um ficheiro por save, ou seja, 1 para cada personagem, ou 1 por cada campo (nome, posição energia...)?

Vou tentar fazer isso assim que possa. Vamos ver se dou conta do recado eheh

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
Flinger    50
Flinger

Nem uma coisa, nem outra.

Cada vez que o utilizador gravar o jogo, é ele que decide se vai criar um ficheiro novo ou reutilizar um que já existe. Mas toda a informação é gravada apenas num só ficheiro.

Isto obriga a abrir as directorias, listar ficheiros, etc, usando as funções que linkei no meu primeiro post.

Se achares que está uns furos acima do que consegues fazer para já, podes sempre optar por um modelo mais simples, como por exemplo, por slots:

Tens, por exemplo, 5 slots. Cada slot corresponde a um ficheiro pré-determinado : player1.sav, player2.save, player3.sav, etc.

Quando o jogador quer salvar, escolhe um dos slots, e tu gravas tudo no ficheiro correspondente. Ao continuar um jogo gravado, o mesmo: O utilizador escolhe qual o slot que quer usar, e tu lês o ficheiro correspondente.

Um modelo ainda mais simples, usas um save único, ou seja, tens apenas um ficheiro onde gravas a informação apenas de um save. Quando o jogador guarda o jogo usas esses ficheiro, quando o utilizador que recuperar o jogo, lês desse ficheiro. O mal, é que se o utilizador começar um jogo do 0, e o guardar, perde a informação que já lá estava anteriormente.

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
MacgyverPT    1
MacgyverPT

Boas.

Peço desculpa por este tempo todo de ausência, mas com outros trabalhos não consegui cá vir responder.

Consegui fazer o save de uma maneira "arcaica", mas que funciona... Eis o código:

FILE *f;

f = fopen("c:\\SO\\SaveGame.txt","w");

if (f != NULL){
	fprintf(f, "%s\n", jogador->nome);
	fprintf(f, "%d\n", jogador->energia);
	fprintf(f, "%d\n", jogador->posicao);
	fprintf(f, "%d\n", adversario->energia);
	fprintf(f, "%d\n", adversario->posicaoAdversario);
}else{
	system("cls");
	printf("Falha na gravação do jogo.\n\n");
	system("pause");
	exit(1);
}

fclose(f);

Agora surgiu outra dúvida: como fazer o inverso? Ou seja, como ler os dados do ficheiro para (por exemplo) o jogador->nome (nome do jogador)?

Editado por M.offspring.R

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1140
HappyHippyHippo

void load(const char * file, Jogador * jogador, Adversário * c) {
       FILE *f;
       char buffer[256];

       f = fopen("c:\\SO\\SaveGame.txt","r");

       if (f != NULL){
               fgets(jogador->nome, 256/* size of Jogador.nome */, f);
               if (jogador->nome[strlen(jogador->nome)] == '\n')
                       jogador->nome[strlen(jogador->nome)] = 0;

               fgets(buffer, 256, f);
               sscanf(buffer, "%d", &jogador->energia);

               fgets(buffer, 256, f);
               sscanf(buffer, "%d", &jogador->posicao);

               fgets(buffer, 256, f);
               sscanf(buffer, "%d", &jogador->energia);

               fgets(buffer, 256, f);
               sscanf(buffer, "%d", &adversario->energia);

               fgets(buffer, 256, f);
               sscanf(buffer, "%d", &adversario->posicaoAdversario);
       }else{
               system("cls");
               printf("Falha na leitura do jogo.\n\n");
               system("pause");
               exit(1);
       }

       fclose(f);
}

cuidado que este código tam o mesmo nível de segurança que o teu de gravar : praticamente nenhuma ...


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
MacgyverPT    1
MacgyverPT

Obrigado pela ajuda.

Sim, sei que não tem segurança, mas por enquanto fica assim. Quando terminar depois debruço-me sobre outras questões, nomeadamente essa. Primeiro quero ter isto a funcionar (por mais básico que seja) e depois ir acrescentando funcionalidades, limar arestas de outras, etc.

Explica-me só estas 2 coisas:

1)

fgets(jogador->nome, 256/* size of Jogador.nome */, f);
if (jogador->nome[strlen(jogador->nome)] == '\n')
  jogador->nome[strlen(jogador->nome)] = 0;

Neste caso, ele lê do ficheiro e percorre até ao fim até achar a mudança de linha, depois coloca o "valor" lido do ficheiro para o jogador->nome, certo?

2)

fgets(buffer, 256, f);
sscanf(buffer, "%d", &jogador->energia);

Neste caso, não percebi tão bem como o anterior... ou melhor, aquele "256" está a fintar-me o raciocínio... o "buffer" já tem os 256, porque é que tenho que utilizar, depois à frente, os tais 256 novamente?

Editado por Rui Carlos
GeSHi

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
MacgyverPT    1
MacgyverPT

outra coisa, estou com alguma dificuldade na linha: if (jogador->nome[strlen(jogador->nome)] == '\n')

Ou seja, se colocar "const char *file" como parametro, depois ao chamar a função no main da-me erro porque falta qualquer coisa. Se apagar o "const char *file" da-me um erro no == nessa linha do if que coloquei acima...

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites
HappyHippyHippo    1140
HappyHippyHippo

1)

fgets(jogador->nome, 256/* size of Jogador.nome */, f);
if (jogador->nome[strlen(jogador->nome)] == '\n')
  jogador->nome[strlen(jogador->nome)] = 0;

Neste caso, ele lê do ficheiro e percorre até ao fim até achar a mudança de linha, depois coloca o "valor" lido do ficheiro para o jogador->nome, certo?

não ...

o fgets lê o stream de entrada até uma das 3 situações acontecer:

- o caracter '\n' é lido do stream

- o stream retorna um EOF

- foram lidos o número máximo de bytes passível de serem guardados no buffer

2)

fgets(buffer, 256, f);
sscanf(buffer, "%d", &jogador->energia);

Neste caso, não percebi tão bem como o anterior... ou melhor, aquele "256" está a fintar-me o raciocínio... o "buffer" já tem os 256, porque é que tenho que utilizar, depois à frente, os tais 256 novamente?

o 256 está a dizer à função qual o tamanho do buffer.

a função recebe um ponteiro, e um ponteiro não guarda o tamanho do buffer, logo necessitas de dizer à função esse tamanho

outra coisa, estou com alguma dificuldade na linha: if (jogador->nome[strlen(jogador->nome)] == '\n')

Ou seja, se colocar "const char *file" como parametro, depois ao chamar a função no main da-me erro porque falta qualquer coisa. Se apagar o "const char *file" da-me um erro no == nessa linha do if que coloquei acima...

se tens um erro nessa linha è porque não é feita a validação das operações anteriores:

- verificar se o ficheiro foi correctamente aberto

- o nome foi correctamente lido do ficheiro

tens de por const porque deverás estás a chamar a função deste modo:

funcao("nome do ficheiro"); // <--- o parâmetro é uma string constante !!!

mais informação é impossivel porque não apresentas código nenhum ...


IRC : sim, é algo que ainda existe >> #p@p

Partilhar esta mensagem


Link para a mensagem
Partilhar noutros sites

Crie uma conta ou ligue-se para comentar

Só membros podem comentar

Criar nova conta

Registe para ter uma conta na nossa comunidade. É fácil!

Registar nova conta

Entra

Já tem conta? Inicie sessão aqui.

Entrar Agora


×

Aviso Sobre Cookies

Ao usar este site você aceita os nossos Termos de Uso e Política de Privacidade. Este site usa cookies para disponibilizar funcionalidades personalizadas. Para mais informações visite esta página.