Visualizzazione dei risultati da 1 a 9 su 9

Discussione: Delphi: StrUtils

  1. #1
    Utente di HTML.it L'avatar di gokan
    Registrato dal
    Feb 2003
    Messaggi
    262

    Delphi: StrUtils

    Girovagando per il web ho trovato tale istruzione:
    CellIndex := StrToInt(RightStr(TLabel(Sender).Name,1));
    Dove
    CellIndex:0..8

    Vediamo se ho capito quello che dovrebbe fare: questa funzione prende il nome di un certo numero di Label ed estrae l’ultima lettera a destra (ad esempio da Paolo estrae la “0”). Un commento su tale funzione diceva che per essere usata RightStr deve essere dichiarata nella sezione Uses l’unità StrUtils. Ho provata a farlo ma Delphi non la riconosce, ho cercato nella guida in linea ma non sono riuscito a trovare nulla di interessante.Qualcuno di voi mi sa dire qualcosa in merito? Come potrei utilizzarla?
    Grazie

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,301
    La parte di codice che hai analizzato è probabilmente il tentativo di interpretare il nome di un controllo TLabel estraendo il numero che conclude tale nome per simulare quello che in VB si chiama matrice di controlli.

    La funzione RightStr appartiene ad un gruppo di funzioni, definite appunto nella unit StrUtils, che hanno parametri e nomi simili alle analoghe funzioni in VB, e altro non servono se non a facilitare il passaggio da quest'ultimo ambiente di sviluppo a Delphi.

    Io suggerirei di usare solo e soltanto la funzione Copy, che poi è quella chiamata internamente dalla RightStr. La Copy permette l'estrazione di uno o più caratteri da una stringa partendo da una posizione, pertando consente di implementare tutti i tipi di estrazioni disponibili in VB.

    La disponibilità della unit StrUtils dipende dalla versione di Delphi che stai utilizzando. Mi risulta che sia stata introdotta nella versione 7, pertanto se fai uso di una versione precedente non avrai tale unit a disposizione, ma come ti ho detto puoi usare sempre e comunque l'istruzione Copy per raggiungere i tuoi obiettivi.

    Trovi informazioni sulla funzione Copy, come sempre, nella Guida in linea di Delphi.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Utente di HTML.it L'avatar di gokan
    Registrato dal
    Feb 2003
    Messaggi
    262
    Originariamente inviato da alka
    .........
    La disponibilità della unit StrUtils dipende dalla versione di Delphi che stai utilizzando. Mi risulta che sia stata introdotta nella versione 7, pertanto se fai uso di una versione precedente non avrai tale unit a disposizione, ma come ti ho detto puoi usare sempre e comunque l'istruzione Copy per raggiungere i tuoi obiettivi.
    ..............

    Ciao!
    Hai ragione ho trovato questo:
    codice:
    function RightStr
       (Const Str: String; Size: Word): String;
    begin
     if Size > Length(Str) then Size := Length(Str);
     RightStr := Copy(Str, Length(Str)-Size+1, Size)
    end;
    Chiarissimo come sempre!! Io uso la versione 5, per questo motivo il compilatore mi dava problemi!!

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,301
    Nei sorgenti originali di Delphi la funzione era implementata in questo modo:
    codice:
    function RightStr(const AText: AnsiString; const ACount: Integer): AnsiString; overload;
    begin
      Result := Copy(WideString(AText), Length(WideString(AText)) + 1 - ACount, ACount);
    end;
    Direi che è tutt'altro che complessa: fondamentalmente, si tratta di estrarre caratteri da una stringa partendo da n caratteri prima della fine della stringa.

    Semplificando, equivale a scrivere
    codice:
    Copy(Testo, Length(Testo) + 1 - N, N);
    Suggerisco sempre e comunque di usare Copy per non legarsi eccessivamente a queste funzioni semplificatrici che potrebbero mutare nel tempo e nelle versioni di Delphi.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Utente di HTML.it L'avatar di gokan
    Registrato dal
    Feb 2003
    Messaggi
    262
    Scusa Alka, vado un poco OT, ti volevo chiedere come devo interpretare un errore del tipo:
    [Error] trisU.pas(72): Unsatisfied forward or external declaration: 'TfmMain.CheckWin'


  6. #6
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,301
    La dichiarazione della classe TFmMain, probabilmente inserita nella sezione 'interface' della unit, prevede un metodo CheckWin che però non è stato implementato nella sezione 'implementation'.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  7. #7
    Utente di HTML.it L'avatar di gokan
    Registrato dal
    Feb 2003
    Messaggi
    262
    codice:
    unit trisU;
    
    interface
    
    uses
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      Grids, StdCtrls, ExtCtrls, Menus, ExtDlgs;
      
    type
          posArray= array [1..3,1..3] of integer;
    
    type
      TfmMain = class(TForm)
        StaticText1: TStaticText;
        StaticText2: TStaticText;
        MainMenu1: TMainMenu;
        File1: TMenuItem;
        New1: TMenuItem;
        N1: TMenuItem;
        Exit1: TMenuItem;
        N3: TMenuItem;
        Player1Avatar1: TMenuItem;
        Player2Avatar1: TMenuItem;
        Help1: TMenuItem;
        About1: TMenuItem;
        imAvatar1: TImage;
        imAvatar2: TImage;
        OPD: TOpenPictureDialog;
        SPD: TSavePictureDialog;
        etPlayer1: TEdit;
        etPlayer2: TEdit;
        tmTimer1: TTimer;
        StaticText3: TStaticText;
        lbTempo1: TLabel;
        StaticText4: TStaticText;
        lbTempo2: TLabel;
        tmTimer2: TTimer;
        btStart1: TButton;
        btStart2: TButton;
        lbCella1: TLabel;
        lbCella5: TLabel;
        lbCella6: TLabel;
        lbCella9: TLabel;
        lbCella8: TLabel;
        lbCella7: TLabel;
        lbCella4: TLabel;
        lbCella2: TLabel;
        lbCella3: TLabel;
        btNewGame: TButton;
        btResetScore: TButton;
        rgPlayFirst: TRadioGroup;
        gbPunteggio: TGroupBox;
        lbX: TLabel;
        lbMinus: TLabel;
        lbO: TLabel;
        lbXpun: TLabel;
        lbOpun: TLabel;
        lbColon: TLabel;
        procedure Player1Avatar1Click(Sender: TObject);
        procedure Player2Avatar1Click(Sender: TObject);
        procedure tmTimer1Timer(Sender: TObject);
        procedure tmTimer2Timer(Sender: TObject);
        procedure FormCreate(Sender: TObject);
        procedure lbCella1Click(Sender: TObject);
        procedure btNewGameClick(Sender: TObject);
        procedure btResetScoreClick(Sender: TObject);
    
      
      private
        { Private declarations }
        Function RightStr(Stringa: string; Size: Word):string;
        Function CheckWin(iPos: posArray): integer;
        Procedure IniziaGioco;
        Function GamePlay(xo_Move: integer): integer;
    
      public
        { Public declarations }
    
      end;
    
    var
      fmMain: TfmMain;
    
      Xpos, Opos: posArray;
    
      sPlaySign: String;
      bGameOver: Boolean;
      iMove: Integer;
      iXScore: Integer;
      iOScore: Integer;
    
    
    implementation
    
    
    {$R *.DFM}
    
    function RightStr(Stringa: string; Size:word): string;
    begin
    if Size > Length(Stringa) then Size := Length(Stringa);
     RightStr := Copy(Stringa, Length(Stringa)-Size+1, Size)
    end;
    
    procedure TfmMain.IniziaGioco;
    var
     i, j, k: integer;
    begin
      for i := 1 to 3 do
      begin
        for j := 1 To 3 do
        begin
          k:= (i - 1) * 3 + j - 1; // 0 .. 8
          TLabel(FindComponent('lbCella' + IntToStr(k))).Caption := '';
          XPos[i, j] := 0;
          OPos[i][j] := 0;
        end;
      end;
    if rgPlayFirst.ItemIndex= 0 then sPlaySign:='X';
    if rgPlayFirst.ItemIndex= 1 then sPlaySign:='O';
    bGameOver:= False;
    iMove:=0;
    end;
    
    procedure TfmMain.FormCreate(Sender: TObject);
    begin
     iXScore:=0;
     iOScore:=0;
    
     IniziaGioco;
    end;
    
    function CheckWin(iPos: posArray): integer;
    var
     iScore: integer;
     i,j: integer;
    begin
    Result:=-1;
    //in rows?
    iScore:=0;
    for i:=1 to 3 do
     begin
     iScore:=0;
     Inc(Result);
     for j:=1 to 3 do Inc(iScore, iPos[i,j]);
     if iScore =3 then Exit;
     end;
     //top-left bottom-right diagonal?
     iScore := 0;
     Inc(Result);
     for i := 1 to 3 do Inc(iScore, iPos[i,i]);
     if iScore = 3 then Exit;
    
     //top-right bottom-left diagonal?
     iScore := 0;
     Inc(Result);
     for i := 1 to 3 do Inc(iScore, iPos[i,4-i]);
     if iScore = 3 then Exit;
    
     //columns?
     for i := 1 to 3 do
     begin
      iScore := 0;
      Inc(Result);
      for j := 1 to 3 do Inc(iScore, iPos[j,i]);
      if iScore = 3 then Exit;
     end;//for i
    
     Result := -1;
    end;
    
    Function TfmMain.GamePlay(xo_Move: integer): integer;
    var
     x,y: 1..3;
     iWin: integer;
    begin
    Result:=-1;
    
    Inc(iMove);
    x:= (xo_Move div 3) +1;
    y:= (xo_Move mod 3) +1;
    
     if sPlaySign ='0' then
       begin
       OPos[x,y]:=1;
     iWin:= CheckWin(Opos);
       end
     else
       begin
       Xpos[x,y]:=1;
      iWin:= CheckWin(Xpos);
       end;
    TLabel(FindComponent('lbCella' + IntToStr(xo_Move))).Caption:=sPlaySign;
    
    Result:=iWin;
    if iWin >=0 then
     begin
     bGameOver:= TRUE;
     if sPlaySign ='X' then
       begin
       iXScore:=iXScore+1;
       lbXpun.Caption:= IntToStr(iXScore);
       end
     else
       begin
       iOScore:=iOScore+1;
       lbOpun.Caption:=IntToStr(iOScore);
       end;
       ShowMessage(sPlaySign +'-Wins!!');
     end;
    if (iMove=9) AND (bGameOver= FALSE) then
     begin
     ShowMessage('Pareggio!!');
     bGameOver:= True;
     end;
    
    if sPlaySign = 'O' then sPlaySign:='X'
    else sPlaySign := 'O';
    end;
    
    procedure TfmMain.lbCella1Click(Sender: TObject);
    var
      iWin:integer;
      IndiceCella: 1..9;
    begin
     if bGameOver= TRUE then Exit;
    
     if TLabel(Sender).Caption <>'' then
       begin
       ShowMessage('Cella Occupata!');
       Exit;
       end;
       IndiceCella:= StrToInt(RightStr(TLabel(Sender).Name,1));
       iWin:= GamePlay(IndiceCella);
    end;
    
    procedure TfmMain.btNewGameClick(Sender: TObject);
    var
      Res: integer;
    begin
     if bGameOver = False then
       begin
       Res:=MessageDlg('Finisci la partita corrente?',mtConfirmation,mbOkCancel, 0);
       if Res= mrCancel then Exit;
       end;
    IniziaGioco;
    end;
    
    procedure TfmMain.btResetScoreClick(Sender: TObject);
    begin
     if MessageDlg('Azzero il punteggio?', mtConfirmation, mbOkCancel,0)= mrCancel then Exit;
    
     iXScore:=0;
     iOScore:=0;
     lbXpun.Caption:= IntToStr(iXScore);
     lbOpun.Caption:= IntToStr(iOScore);
    end;
    procedure TfmMain.Player1Avatar1Click(Sender: TObject);
    begin
    if OPD.Execute then //Si sceglie l'avatar del primo giocatore
         imAvatar1.Picture.LoadFromFile(OPD.FileName); //carico l'avatar
         if (imAvatar1.Picture.Width > 115) OR (imAvatar1.Picture.Height > 170) then
           begin
           if MessageDlg('Hai scelto un avatar troppo grande!,selezionalo di nuovo..',mtError,[mbRetry],0)= mrRetry then
           Player1Avatar1Click(Sender);
           end;
    end;
    
    
    
    
    procedure TfmMain.Player2Avatar1Click(Sender: TObject);
    begin
    if OPD.Execute then //Si sceglie l'avatar del primo giocatore
         imAvatar2.Picture.LoadFromFile(OPD.FileName); //carico l'avatar
         if (imAvatar1.Picture.Width > 115) OR (imAvatar1.Picture.Height > 170) then
           begin
           if MessageDlg('Hai scelto un avatar troppo grande!,selezionalo di nuovo..',mtError,[mbRetry],0)= mrRetry then
           Player1Avatar1Click(Sender);
           end;
    end;
    
    procedure TfmMain.tmTimer1Timer(Sender: TObject);
    begin
    //if il tempo del player1 è finito (=0) then
     // begin
      //Comincia a giocare il player2
      //Si bloccano le mosse del Player1
      //end
    //else
     //   lbTempo1.Caption:=IntToStr(StrToInt(lbTempo1.Caption)-1);
    end;
    
    procedure TfmMain.tmTimer2Timer(Sender: TObject);
    begin
    //if il tempo del player2 è finito (=0) then
     // begin
      //Comincia a giocare il player1
      //Si bloccano le mosse del Player2
      //end
    //else
     //   lbTempo2.Caption:=IntToStr(StrToInt(lbTempo2.Caption)-1);
    end;
    
    
    
    
    
    end.
    Noti qualcosa che non va nella disposizione?
    Ciao
    :master:

  8. #8
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,301
    Credo che per il rispetto degli utenti del forum, ma soprattutto dei gestori dei database che ospitano il contenuto di questi thread, avresti potuto evitare di postare tutto il codice della unit, dato che comunque ti avevo anticipato che si trattava di un problema di dichiarazione.

    Come ti ho detto nel messaggio precedente, è un problema di mancata implementazione, non di ordine.

    L'errore non è nella disposizione, ma nel fatto che la dichiarazione della classe del tuo form include un metodo CheckWin:
    codice:
      TfmMain = class(TForm)
      private
        { Private declarations }
        Function CheckWin(iPos: posArray): integer;
      public
        { Public declarations }
      end;
    e questo metodo non è implementato (ad esempio, come segue):
    codice:
    function TfmMain.CheckWin(iPos: posArray): integer;
    begin
    ...
    end;
    Probabilmente è dovuto al fatto che il nome del metodo nel tuo codice non è preceduto dal nome della classe TfmMain.

    Un suggerimento: se devi aggiungere nuovi metodi alla tua form, posizionati nella sezione della classe in cui questo deve apparire (private, public, ecc.), aggiunti la dichiarazione del metodo digitandola a mano e premi CTRL+ALT+C (oppure seleziona "Complete class at cursor") per fare in modo che Delphi crei automaticamente il corpo di implementazione del metodo che, a quel punto, va solo "farcito" con le istruzioni.
    Questo procedimento, oltre a velocizzare la stesura del codice, riduce drasticamente gli errori di distrazione simili al tuo.

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  9. #9
    Utente di HTML.it L'avatar di gokan
    Registrato dal
    Feb 2003
    Messaggi
    262
    Non intendevo mancare di rispetto a nessuno ...
    Non conoscevo questa tecnica (comunque è SHIFT+CTRL+C), è molto utile, ti risparmia un bel pò di lavoretto. Grazie come sempre , il problema è adesso risolto. W Delphi :metallica

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.