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!