Thread: Save and Load game....Issue.

  1. #1
    Registered User
    Join Date
    Nov 2013
    Posts
    15

    Save and Load game....Issue.

    Hi! i'm trying to put my Save and Load function in my game, this is what i have:


    Code:
    /* Save game */ 
    void GuardarJuego()
    {
        FILE *fsave;
        char turno;
        fsave=fopen("SAVE.txt", "w");
        fputs(*****, fsave);
        fseek(fsave,66,SEEK_SET);
        fputc(turno, fsave);
        fclose(fsave);
    }
    */
    
    /* Load Game */
    void CargarJuego()
    {
        FILE *fload;
        char turno;
        fload=fopen("SAVE.txt", "r");
        if (fload==NULL)
        {
            printf("No existe un archivo guardado del juego.");
            main();
    
        }
        else
        {
            fgets( 64, fload);
            fseek(fload,66,SEEK_SET);
            turno=fgetc(fload);
        }
        fclose(fload);
    }
    My game code is this:

    [C] GameCode - Pastebin.com

    Ideas ?

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,907
    It would be better if you posted your full code in this forum. Also, it would be helpful if you provided config.h, functions.h, data.h constants.h.

    Some notes on your save and load functions:

    • You need to check the return value of fopen in your save game function, to make sure it succeeded. If it failed, you should not call any of your file functions (fputs, fseek, fputc, fgetc, fclose).
    • You should not call main recursively for error handling (or for any other reason). Instead, you should return; from the function, or exit() your program.
    • If you chose to return from your function in case of error, I suggest you make the functions return an int, and return a success/error code so the function that calls your save/load game code can deal with the error. See below for an example.
    • You should check the return value of all of your file funcitons for that matter.
    • Don't use magic numbers. What are 64 and 66? Are you even sure those are the correct numbers?
    • Your call to fputs is wrong. It needs a string. If you want to write 5 * characters, then you need to do "*****" with the double quotes.
    • In your save game function, you write turno to the file, but it's uninitialized, so you are writing a garbage value. You need to assign it a meaningful (and correct) value before you write it.
    • Read the documentation, fgetc returns an integer. That is so it can return all possible char values and special values like EOF. You should thus declare turno to be an int, otherwise if fgetc returns EOF, your code will assume it's a valid character, which is wrong.
    • You have a stray close-comment */ on line 12 in the above code.


    Code:
    int CargarJuego()
    {
        FILE *fload;
        char turno;
        fload=fopen("SAVE.txt", "r");
        if (fload==NULL)
        {
            printf("No existe un archivo guardado del juego.");
            return 1;
     
        }
        else
        {
            fgets( 64, fload);
            fseek(fload,66,SEEK_SET);
            turno=fgetc(fload);
        }
        fclose(fload);
        return 0;
    }
    ...
    if (CargarJuego() != 0) {
        error loading game
        do something appropriate
    }
    That's all I have for now, but that should give you lots to think about. I haven't looked at the rest of your code, but I assume it's of similar quality and has similar mistakes. Apply the core concepts my advice above to all your code: avoid magic numbers, read the documentation and use functions correctly, and check for all possible errors.

  3. #3
    Registered User
    Join Date
    Nov 2013
    Posts
    15
    Thanks you very much man, i just have less than 1 month using C, i will read the documentations, Thanks

  4. #4
    Registered User
    Join Date
    Nov 2013
    Posts
    15
    Config.h

    Code:
    #pragma once
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    #include <time.h>
    #include <windows.h>
    Functions.h

    Code:
    #ifndef FUNCTIONS_H_INCLUDED
    #define FUNCTIONS_H_INCLUDED
    
    #pragma once
    #include "Casilla.h"
    
    
    
    /* Funciones */
    void IniciarTablero(char[10][10],char);
    void IniciarTableroJ2();
    void DibujarTablero(char[10][10]);
    void PedirCasilla(int);
    int VerificarCasilla(char[10][10],Casilla,int,char);
    void Almacenar(char[10][10],int,Casilla,char);
    void TurnoJ1();
    void TurnoJ2();
    char AtacarCasilla(char[10][10],Casilla);
    void GenerarLista();
    int empezar();
    
    
    #endif // FUNCTIONS_H_INCLUDED
    data.h

    Code:
    #ifndef DATA_H_INCLUDED
    #define DATA_H_INCLUDED
    
    #pragma once
    #include "Casilla.h"
    
    //Use Extern para decir que la posicion de memoria de esa variable sera encontrada en otro archivo
    
    extern char TableroJ1[10][10],TableroJ2[10][10],Aux[10][10],frase[50];
    extern int Barcos[5];
    extern Casilla Lista[100];
    extern int aux,contador,tocadosJ1,tocadosJ2;
    
    #endif // DATA_H_INCLUDED
    Constants.h

    Code:
    #pragma once
    
    
    #define AGUA '0'
    #define HERIDO '*'
    #define OCULTA '#'
    #define AIRCRAFTCARRIER 5
    #define BATTLESHIP 4
    #define SUBMARINE 3
    #define CRUISER 3
    #define DESTROYER 2

  5. #5
    Registered User
    Join Date
    Nov 2013
    Posts
    15
    Functions.c
    Code:
    #include "config.h"
    #include "functions.h"
    #include "data.h"
    #include "constants.h"
    
    
    int empezar()
    {
    
    
         IniciarTablero(TableroJ1,AGUA); // Poner todas las casillas con el símbolo de agua (^).
         DibujarTablero(TableroJ1); // Dibujar el tablero.
    
    
       /* Colocar los barcos en las posiciones deseadas */
       strcpy(frase,"[Casillas del AirCraft Carrier (5 casillas)]\n");
       printf("%s",frase);
       PedirCasilla(AIRCRAFTCARRIER);
       strcpy(frase,"[Casillas del BattleShip (4 casillas)]\n\0");
       printf("%s",frase);
       PedirCasilla(BATTLESHIP);
       strcpy(frase,"[Casillas del Submarine (3 casillas)]\n");
       printf("%s",frase);
       PedirCasilla(SUBMARINE);
       strcpy(frase,"[Casillas del Cruiser (3 casillas)]\n");
       printf("%s",frase);
       PedirCasilla(CRUISER);
       strcpy(frase,"[Casillas del Destroyer (2 casillas)]\n");
       printf("%s",frase);
       PedirCasilla(DESTROYER);
       printf("     Su tablero ha sido creado.\n");
       Sleep(1000);
    
       system("cls");
       printf("Creando tablero de la maquina...");
       IniciarTablero(Aux,OCULTA); // Poner todas las casillas con el símobolo de casilla oculta(O).
       IniciarTableroJ2(); // Generar aleaoriamente el tablero del oponente.
       GenerarLista();
       system("cls");
       printf("\n\n\n\n\n\n                              Vamos al mambo!\n");
       Sleep(2000);
    
       /* Iniciar la batalla */
       while (1)
       {
          TurnoJ1(); // Turno del jugador
          if (tocadosJ1 == 17) // Si se han destruído todos los barcos
          {                // del oponente se gana y acaba el juego.
             system("cls");
             printf(" GANASTE\n");
             return 0;
          }
    
          TurnoJ2(); // Turno del oponente.
          if (tocadosJ1 == 17) // Si se han destruído todos los barcos
          {                // del jugador se pierde y acaba el juego.
             system("cls");
             printf(" PERDISTE\n");
             return 0;
          }
       }
    }
    
    
    
    /* Inicia el tablero */
    void IniciarTablero(char Tablero[10][10],char simbolo)
    {
       int i,j;
    
       for(i=0;i<10;i++)
       {
          for (j=0;j<10;j++)
             Tablero[i][j]=simbolo;
       }
    }
    
    /* Función que genera el tablero del oponente aleatoriamente */
    void IniciarTableroJ2()
    {
    
       Casilla aleatoria;
       char pos,posicion[2]={'v','h'};
       int i;
    
       IniciarTablero(TableroJ2,AGUA); // Primero se rellena el tablero con el símoblo de agua (^).
       srand(time(NULL));
       for (i=0;i<5;i++)
       {
          do
          {
             aleatoria.letra=(rand()%10)+65; // Casilla
             aleatoria.numero=(rand()%10)+1; // Random.
             pos=posicion[rand()%2]; // Posición Random.
          }while(!VerificarCasilla(TableroJ2,aleatoria,Barcos[i],pos)); // Verificar si la casilla es válida.
          Almacenar(TableroJ2,Barcos[i],aleatoria,pos); // Se almacena el barco en el tablero.
       }
    }
    
    
    /* Dibujar el tablero */
    void DibujarTablero(char Tablero[10][10])
    {
    
       int i,j,letra=65;
    
       system("cls");
       printf("        1 2 3 4 5 6 7 8 9 10\n\n");
       for (i=0;i<10;i++,letra++)
       {
          printf("     %c  ",letra);
          for (j=0;j<10;j++)
             printf("%c ",Tablero[i][j]);
          printf("\n\n");
       }
       printf("%s",frase);
    }
    
    /* Función que pide una casilla a partir de la cual se introduce */
    /* un barco determinado en posición vertical u horizontal */
    void PedirCasilla(int barco)
    {
       Casilla cas;
       char posicion;
       int valida;
    
       do {
          valida=0;
          fflush(stdin);
          printf("Letra: ");
          scanf("%c",&cas.letra);
          cas.letra=toupper(cas.letra);
          if (cas.letra < 65 || cas.letra > 74) // Verificar si la letra pertenece al rango válido.
             valida++;
          printf("Numero: ");
          scanf("%d",&cas.numero);
          if (cas.numero < 1 || cas.numero > 10) // Verificar si el número pertenece al rango válido.
             valida++;
          printf("Vertical u horizontal (v/h): ");
          fflush(stdin);
          scanf("%c",&posicion);
          if (posicion != 'v' && posicion != 'h') // Verificar si la posición es válida.
             valida++;
          if (!VerificarCasilla(TableroJ1,cas,barco,posicion))
             valida++;
          if (valida > 0) // Si falla algún parámetro anterior
          {            // se muestra un mensaje de error.
             printf("Casilla no valida o posicion no valida\n");
             Sleep(1000);
          }
          DibujarTablero(TableroJ1);
       }while(valida > 0); // Se vuelven a pedir los parámetros hasta que sean correctos.
       Almacenar(TableroJ1,barco,cas,posicion); // Almacenar el barco en le tablero
       strcpy(frase,"\0");
       DibujarTablero(TableroJ1); // Dibujar el tablero
    }
    
    /* Función que verifica si la casilla inroducida es correcta */
    int VerificarCasilla(char Tablero[10][10],Casilla cas,int barco,char posicion)
    {
       int fila,columna,i,cont=0,tope;
    
       fila=cas.letra-65;
       columna=cas.numero-1;
       if (Tablero[fila][columna] != AGUA) // Si la casilla está ocupada.
          return 0;
       if (posicion == 'h') // Si la posición es horizontal, se verifica si
       {                // el barco cabe en la fila a partir de esa casilla.
          tope=columna+barco;
          for (i=columna;i<10 && i<tope;i++)
          {
             if (Tablero[fila][i] == AGUA) // Contar las casillas libres que tiene
                cont++;                 // la casilla elegida a partir de esta.
             else
                return 0;
          }
          if (cont < barco) // Si las casillas libres son insuficientes, la casilla no vale.
             return 0;
          return 1;
       }
       else // Mismo método que el anterior pero en vertical.
       {
          tope=fila+barco;
          for (i=fila;i<10 && i<tope;i++)
          {
             if (Tablero[i][columna] == AGUA)
                cont++;
             else
                return 0;
          }
          if (cont < barco)
             return 0;
          return 1;
       }
    }
    
    void Almacenar(char Tablero[10][10],int barco,Casilla cas,char posicion)
    {
       int i,fila,columna,tope;
       char tipo;
       int aux1=0;
    
       fila=cas.letra-65;
       columna=cas.numero-1;
       switch(barco) // Colocar una letra según el barco.
       {
          case AIRCRAFTCARRIER:
             tipo='P';
             break;
          case BATTLESHIP:
             tipo='A';
             break;
          case SUBMARINE:
             if (aux1 == 0)
             {
                tipo='S';
                aux1++;
             }
             else
                tipo='C';
             break;
          case DESTROYER:
             tipo='D';
             break;
       }
    
       /* Almacenar el barco según la posición y la casilla */
       if (posicion == 'h')
       {
          tope=columna+barco;
          for (i=columna;i<tope;i++)
             Tablero[fila][i]=tipo;
       }
       else
       {
          tope=fila+barco;
          for (i=fila;i<tope;i++)
             Tablero[i][columna]=tipo;
       }
    }
    
    /* Función turno del jugador */
    void TurnoJ1()
    {
       Casilla cas;
       int valida,fila,columna, tocadosJ1=0;
    
       strcpy(frase,"[Tu turno]\n");
       DibujarTablero(Aux);
       do {
          valida=0;
          fflush(stdin);
          printf("Letra: ");
          scanf("%c",&cas.letra);
          cas.letra=toupper(cas.letra);
          if (cas.letra < 65 || cas.letra > 74) // Verificar si la letra pertenece al rango válido
             valida++;
          printf("Numero: ");
          scanf("%d",&cas.numero);
          if (cas.numero < 1 || cas.numero > 10) // Verificar si el número pertenece al rango válido.
             valida++;
          fila=cas.letra-65;
          columna=cas.numero-1;
          if (Aux[fila][columna] != OCULTA) // Verificar si la casilla ya está "tocada".
             valida++;
          if (valida > 0) // Si falla algún parámetro anterior
          {            // se muestra un mensaje de error.
             printf("Casilla no valida\n");
             Sleep(1000);
          }
          DibujarTablero(Aux); // Se refresca" la pantalla.
       }while(valida > 0);
       Aux[fila][columna]=AtacarCasilla(TableroJ2,cas); // Comprobar la casilla.
       if (Aux[fila][columna] == HERIDO) // Si se ha tocado un barco oponente.
       {
          strcpy(frase,"[Tocado]\n");
          tocadosJ1++;
       }
       else // Si ha caído en agua.
          strcpy(frase,"[Agua]\n");
       DibujarTablero(Aux); // Dibujar el tablero
       system("pause");
    }
    
    /* Función turno del oponente */
    void TurnoJ2()
    {
       Casilla cas;
       int fila,columna, contador=0, tocadosJ2=0;
    
       strcpy(frase,"[Turno de tu oponente]\n");
       DibujarTablero(TableroJ1);
       cas=Lista[contador++];
       fila=cas.letra-65;
       columna=cas.numero-1;
       TableroJ1[fila][columna]=AtacarCasilla(TableroJ1,cas); // Comprobar la casilla.
       if (TableroJ1[fila][columna] == HERIDO) // Si se ha tocado un barco oponente.
       {
          strcpy(frase,"[Herido!]\n");
          tocadosJ2++;
       }
       else // Si ha caído en agua.
          strcpy(frase,"[Toco Agua!]\n");
       DibujarTablero(TableroJ1); // Dibujar el tablero
       system("pause");
    }
    
    /* Comprobamos la casilla para atacar */
    char AtacarCasilla(char Tablero[10][10],Casilla cas)
    {
       int fila,columna;
    
       fila=cas.letra-65;
       columna=cas.numero-1;
       if (Tablero[fila][columna] == 'P' || Tablero[fila][columna] == 'A' || Tablero[fila][columna] == 'S' || Tablero[fila][columna] == 'C' || Tablero[fila][columna] == 'D')
          return HERIDO; // Si se acierta.
       return AGUA;
    }
    
    /* Lista aleatoria de casillas */
    /* Ataque de la maquina */
    void GenerarLista()
    {
       int i,j,num;
       Casilla aux;
    
       for (i=0;i<100;i++)
       {
          for (j=1;j<11;j++)
          {
             Lista[i].letra=j+64; // Guarda todas las casillas
             Lista[i].numero=j;  // válidas en orden ascendente.
          }
       }
       srand(time(NULL));
       for (i=0;i<100;i++) // Desordenar las casillas.
       {
          num=rand()%100;
          aux=Lista[i];
          Lista[i]=Lista[num];
          Lista[num]=aux;
       }
    }
    Data.c
    Code:
    #include "config.h"
    #include "data.h"
    #include "constants.h"
    #include "Casilla.h"
    
    char TableroJ1[10][10],TableroJ2[10][10],Aux[10][10],frase[50]="\0";
    int Barcos[5]={AIRCRAFTCARRIER,BATTLESHIP,SUBMARINE,CRUISER,DESTROYER};
    Casilla Lista[100];
    int aux=0,contador=0,tocadosJ1=0,tocadosJ2=0;
    Main.c
    Code:
    #include "config.h"
    #include "constants.h"
    #include "Casilla.h"
    #include "data.h"
    #include "functions.h"
    
    int main()
    {
    
    
      int liMenu;
        do
        {
         system("color 02");
            //IMPRIMIR MENU
            Inicio:;
            system("cls");
            printf("%45s","******MENU PRINCIPAL******\n\n\n\n");
            printf("\t\t1) Empezar BattleShip\n\n");
            printf("\t\t2) Cargar Juego.\n\n");
            printf("\t\t3) Instrucciones.\n\n");
            printf("\t\t4) Salir.\n\n");
            printf("\n\nIngrese la opci%cn deseada: ", 162);
            scanf("%d", &liMenu);
            switch(liMenu)
            {
                case 1:    empezar();
                        system("pause");
                        break;
    //            case 2: CargarJuego();
                system("pause");
                        break;
       //         case 3: Instrucciones();
                system("pause");
                        break;
                case 4:  return 0;
                default: printf("Esta opci%cn no es v%clida. Presione ENTER e intente de nuevo.\n", 162, 160);
                        liMenu=0;
                         break;
            }
        }
        while(liMenu!=9);
    
        return 0;
    }

  6. #6
    Registered User
    Join Date
    Nov 2013
    Posts
    15
    ..................
    Last edited by johndoe1336; 11-27-2013 at 01:43 PM.

  7. #7
    Registered User
    Join Date
    Dec 2006
    Location
    Canada
    Posts
    3,226
    Quote Originally Posted by johndoe1336 View Post
    mmm btw i'm using
    **
    Code:
    TEXT
    TEXT
    **
    to paste here, is it right ?
    That is right.

  8. #8
    Registered User
    Join Date
    Nov 2013
    Posts
    15
    Thanks

  9. #9
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    A quick nit I noticed... you are using this quite a bit:

    Code:
    fflush(stdin);
    FAQ > Why fflush(stdin) is wrong
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How to make a Console Save and Load Game
    By vitinho444 in forum C++ Programming
    Replies: 2
    Last Post: 02-19-2011, 10:32 AM
  2. File Save and Load
    By lukesowersby in forum C Programming
    Replies: 3
    Last Post: 05-13-2009, 12:49 AM
  3. C++ save/load
    By XjX in forum C++ Programming
    Replies: 7
    Last Post: 02-17-2006, 02:01 PM
  4. Save/Load
    By RedRookie in forum Game Programming
    Replies: 8
    Last Post: 05-24-2005, 02:13 PM
  5. Save Load....
    By KrAzY CrAb in forum C Programming
    Replies: 2
    Last Post: 06-02-2002, 11:18 PM