Ver Mensaje Individual
  #8  
Antiguo 06-08-2014
Avatar de aguml
aguml aguml is offline
Miembro
 
Registrado: may 2013
Posts: 885
Reputación: 11
aguml Va por buen camino
Amigo al final asi me ha quedado todo lo que gestiona el ranking:

Este botón está en el form principal y es el que se usa para terminar el juego. Si la puntuacion es mas alta que la de alguna otra del ranking nos mostrará otra ventana que nos pregunta nuestro nombre y guarda los datos en el ranking. Si la puntuacion es igual a alguna del ranking se usa el numero de aciertos para ordenarlo:
Código:
void __fastcall TFormPrincipal::ButtonPararClick(TObject *Sender)
{
        //Desactivo el timer
        Timer1->Enabled = false;

        //Activo el boton Comenzar
        ButtonComenzar->Enabled = true;

        //Desactivo el Edit donde se introducen los resultados
        EditResultado->Enabled = false;

        //Desactivo el boton Comprobar
        ButtonComprobar->Enabled = false;

        //Desactivo el boton Parar
        ButtonParar->Enabled = false;

        //Inicializo la cuenta atras
        LabelCuentaAtras->Caption = TrackBarRangoTimer->Position;
        LabelCuentaAtras->Font->Color = clGreen;
        LabelCuentaAtras->Update();

        //Leer y actualizar ranking
        int hFile = FileOpen("Ranking.bin",fmOpenReadWrite);

        struct
        {
                int pos;
                char nombre[10];
                int aciertos;
                int puntuacion;
        }ranking[10], nuevoRanking[10];

        //Limpio ambas estructuras
        memset(ranking,0,sizeof(ranking));
        memset(nuevoRanking,0,sizeof(nuevoRanking));

        if(hFile == -1) //Si no existe el archivo de ranking
        {
                hFile=FileCreate("Ranking.bin"); //lo creo

                //Inicializado del archivo de ranking
                for(int i=0;i<10;i++)
                {
                        ranking[i].pos = i+1;
                        strcpy(ranking[i].nombre, "Agustin");
                        ranking[i].aciertos = 100-(i*10);
                        ranking[i].puntuacion = 10000-(i*1000);

                }
                FileSeek(hFile,0,0);
                FileWrite(hFile,ranking,sizeof(ranking));
                //fin del inicializado del ranking
        }

        //Lectura del ranking
        FileSeek(hFile,0,0);
        FileRead(hFile,ranking,sizeof(ranking));

        bool changed = false; //bandera que uso para saber si ya inserté el registro en el ranking

        //En el siguiente bucle recorro todo el ranking y si tengo que insertar la partida finalizada lo hago
        //Cuando inserte la nueva linea no incremento el indice del ranking para asi seguir leyendo por donde me quedé
        for(int i=0,j=0;i<10;i++)
        {
                if(ranking[i].puntuacion > EditPuntos->Text.ToDouble() || changed == true)
                { //Si la puntuacion de la posicion actual es mayor que la obtenida o ya fue insertada la nueva puntuacion...
                        nuevoRanking[i] = ranking[j]; //Copio los datos de esa linea del ranking en el nuevo ranking
                        j++; //Incremento el indice del ranking

                        //Voy incrementando la posicion
                        if(i > 0)
                        {
                                nuevoRanking[i].pos = nuevoRanking[i-1].pos + 1;
                        }
                }
                else if(ranking[j].puntuacion == EditPuntos->Text.ToDouble())
                { //Si la puntuacion del ranking es igual a la obtenida...
                        if(ranking[j].aciertos < EditAciertos->Text.ToDouble())
                        { //Si el numero de aciertos de la posicion actual del ranking es menor que los obtenidos

                                FormInsertName->ShowModal(); //Pregunto el nombre del jugador
                                nuevoRanking[i].pos = ranking[j].pos; //Inserto la posicion
                                strncpy(nuevoRanking[i].nombre, FormInsertName->EditName->Text.c_str(),10); //Inserto el nuevo nombre
                                nuevoRanking[i].aciertos = EditAciertos->Text.ToDouble(); //Inserto el nuevo numero de aciertos
                                nuevoRanking[i].puntuacion = EditPuntos->Text.ToDouble(); //Inserto la nueva puntuacion
                                changed = true; //Indico que ya se ha insertado la nueva linea
                        }
                }
                else
                {
                        FormInsertName->ShowModal(); //Pregunto el nombre del jugador
                        nuevoRanking[i].pos = ranking[j].pos; //Inserto la posicion
                        strncpy(nuevoRanking[i].nombre, FormInsertName->EditName->Text.c_str(),10); //Inserto el nuevo nombre
                        nuevoRanking[i].aciertos = EditAciertos->Text.ToDouble(); //Inserto el nuevo numero de aciertos
                        nuevoRanking[i].puntuacion = EditPuntos->Text.ToDouble(); //Inserto la la nueva puntuacion
                        changed = true; //Indico que ya se ha insertado la nueva linea
                }
        }

        //Si hubo cambio en el ranking actualizo el archivo
        if(changed == true)
        {
                FileSeek(hFile,0,0);
                FileWrite(hFile,nuevoRanking,sizeof(nuevoRanking));

                //Cierro el archivo de ranking
                FileClose(hFile);

                //Muestro el nuevo ranking
                FormRanking->ShowModal();
        }
        else
        {
                //Cierro el archivo de ranking
                FileClose(hFile);
        }
}
//---------------------------------------------------------------------------
Esto es para que se muestre el ranking correctamente:
Código:
void __fastcall TFormRanking::FormShow(TObject *Sender)
{
        //Posiciono la ventana centrada
        Left = (Screen->Width - Width)/2;
        Top  = (Screen->Height - Height)/2;

        //Abro el archivo donde está el ranking
        int hFile = FileOpen("Ranking.bin",fmOpenReadWrite);

        //Estructura que contendrá el ranking
        struct
        {
                int pos;
                char nombre[10];
                int aciertos;
                int puntuacion;
        }ranking[10];

        //Limpio la estructura
        memset(ranking,0,sizeof(ranking));

        if(hFile == -1) //Si no existe el archivo de ranking
        {
                hFile=FileCreate("Ranking.bin"); //lo creo

                //Inicializado del archivo de ranking
                for(int i=0;i<10;i++)
                {
                        ranking[i].pos = i+1;
                        strcpy(ranking[i].nombre, "Agustin");
                        ranking[i].aciertos = 100-(i*10);
                        ranking[i].puntuacion = 10000-(i*1000);

                }
                FileSeek(hFile,0,0); //Me posiciono al inicio del archivo
                FileWrite(hFile,ranking,sizeof(ranking)); //Guardo el ranking en el archivo
                //fin del inicializado del ranking
        }

        //Lectura del ranking
        FileSeek(hFile,0,0); //Me posiciono al inicio del archivo
        FileRead(hFile,ranking,sizeof(ranking)); //Leo el contenido del archivo y lo guardo en la estructura
        FileClose(hFile); //Cierro el archivo

        //Ajusto los anchos de las columnas
        StringGridRanking->ColWidths[0]=110;
        StringGridRanking->ColWidths[1]=175;
        StringGridRanking->ColWidths[2]=125;
        StringGridRanking->ColWidths[3]=150;

        //Pongo los titulos a la tabla
        StringGridRanking->Rows[0]->Strings[0] = "Posición";
        StringGridRanking->Rows[0]->Strings[1] = "Nombre";
        StringGridRanking->Rows[0]->Strings[2] = "Aciertos";
        StringGridRanking->Rows[0]->Strings[3] = "Puntuación";

        //Relleno el StringGrid que mostrará el ranking
        for(int row = 1; row < 11; row++)
        {
                StringGridRanking->Rows[row]->Strings[0] = AnsiString(ranking[row-1].pos) + " ";
                StringGridRanking->Rows[row]->Strings[1] = ranking[row-1].nombre;
                StringGridRanking->Rows[row]->Strings[2] = AnsiString(ranking[row-1].aciertos) + " ";
                StringGridRanking->Rows[row]->Strings[3] = AnsiString(ranking[row-1].puntuacion) + " ";
        }
}
//---------------------------------------------------------------------------

void __fastcall TFormRanking::StringGridRankingDrawCell(TObject *Sender, int ACol,
      int ARow, TRect &Rect, TGridDrawState State)
{
        TStringGrid *SG = static_cast<TStringGrid*>((TStringGrid*)(Sender));
        String cad = SG->Cells[ACol][ARow];
        HDC dc = SG->Canvas->Handle;

        //Asignamos a Flags los flags deseados segun la posicion de la celda
        //Esto equivale a:
        /*register int Flags;
        if(ACol == 1 || State.Contains(gdFixed))
                Flags = DT_CENTER | DT_VCENTER | DT_SINGLELINE;
        else
                Flags = DT_RIGHT | DT_VCENTER | DT_SINGLELINE;
        */

        register int Flags = (ACol == 1 || State.Contains(gdFixed) ? DT_CENTER | DT_VCENTER | DT_SINGLELINE :
                              DT_RIGHT | DT_VCENTER | DT_SINGLELINE);

        //Aqui se añade un espacio al final de la cadena siempre que no sea un titulo y no sea de la columna 1
        //Esto equivale a:
        /*if(ACol != 1 && ARow > 0)
                cad += " ";
        */

        cad += (ACol != 1 && ARow > 0 ? " " : "");

        if (State.Contains(gdFixed)) {
                SG->Canvas->Brush->Color = clBtnFace;
                SG->Canvas->Font->Color = clWindowText;
                SG->Canvas->FillRect(Rect);
                DrawText(dc, cad.c_str(), cad.Length(), &Rect, Flags);
        }
        else if(State.Contains(gdSelected)) {
                SG->Canvas->Brush->Color = clWindow;
                SG->Canvas->Font->Color = clWindowText;
                SG->Canvas->FillRect(Rect);
                HDC dc = StringGridRanking->Canvas->Handle; //No se porque pero aqui tengo que repetir esta linea para que funcione en este caso
                DrawText(dc, cad.c_str(), cad.Length(), &Rect, Flags);
        }
        else {
                if (ARow % 2 == 0){
                        SG->Canvas->Brush->Color = clSilver;
                        SG->Canvas->Font->Color = clWindowText;
                }
                else {
                        SG->Canvas->Brush->Color = SG->Color;
                        SG->Canvas->Font->Color = SG->Font->Color;
                }
                SG->Canvas->FillRect(Rect);
                DrawText(dc, cad.c_str(), cad.Length(), &Rect, Flags);
        }
}
//---------------------------------------------------------------------------
Funciona correctamente pero me gustaria que le echases un vistazo para ver si ves algo de codigo redundante que se pueda mejorar. ¡Gracias por todo!
Responder Con Cita