user1942983
user1942983

Reputation:

List of index out of bound(0) Delphi

I have a code wrote in delphi,and when I open exe file on cliens computer It says List of index out of bound(0),I searched the whole google,but couldn't fix,How I must fix it?There is somethins wrong :D Thanks to all

Code:

    unit UntMain;

interface

uses
  Windows, Messages, SysUtils, Classes, Controls, StdCtrls, Forms,
  Graphics, ExtCtrls, Mask, Dialogs, Spin;

type
  TfrmMain = class(TForm)
    Panel1: TPanel;
    PaintBox1: TPaintBox;
    Button1: TButton;
    Timer1: TTimer;
    Edit1: TEdit;
    SpinEdit1: TSpinEdit;
    Button2: TButton;
    procedure PaintBox1Paint(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormKeyPress(Sender: TObject; var Key: Char);
    procedure Timer1Timer(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
    Head: Boolean;
    Body: Boolean;
    RArm: Boolean;
    LArm: Boolean;
    LLeg: Boolean;
    RLeg: Boolean;
    WordStr:String;
    SlashedWord: string;
    Loaded: Boolean;
  protected
   Dictionary: TStringList;
   procedure reset;
   procedure HangMan;
   function SolveWord(SlashedWord, WordStr: String; C: Char): String;
   function isHanged: Boolean;
  public
    { Public declarations }
  end;

var
  frmMain: TfrmMain;

implementation

uses UntHangman, UntAbout;

{$R *.dfm}

function TfrmMain.isHanged: Boolean;
begin
result:= (Head=True) AND (Body=True) AND (RARM=True) AND (LARM=true) AND (RLeg=True) AND (LLeg=true);
end;

procedure TfrmMain.HangMan;
begin
 if not Head then begin Head:= true; PaintBox1.Invalidate; exit; end else
 if not Body then begin Body:= true; PaintBox1.Invalidate; exit; end else
 if not RArm then begin RArm:= true; PaintBox1.Invalidate; exit; end else
 if not LArm then begin LArm:= true; PaintBox1.Invalidate; exit; end else
 if not RLeg then begin RLeg:= true; PaintBox1.Invalidate; exit; end else
 if not LLeg then begin LLeg:= true; PaintBox1.Invalidate; exit; end;
end;

function TfrmMain.SolveWord(SlashedWord, WordStr: String; C: Char): String;
var
 idx: Integer;
begin
 result:= SlashedWord;
 for Idx := 1 to length(WordStr) do
 begin
  if upcase(WordStr[Idx]) = upcase(C) then
  begin
   result[Idx]:= C;
  end;
 end;
end;


procedure TfrmMain.Timer1Timer(Sender: TObject);
var
 I: Integer;
begin
I:= SpinEdit1.Value;
if I <> 0 then
 begin

 I:= I-1;

 SpinEdit1.Value:=   SpinEdit1.Value -1;
 end
 else
begin
 Timer1.Enabled:= False;
 ShowMessage('You Lost!');
 reset;
 end;
end;

function SlashWord(Str: String): String;
var
 I: Integer;
begin
 for I := 1 to length(str) do
  if Str[I] <> ' ' then
   result:= result + '-'
  else
   result:= result + ' ';
end;

procedure TfrmMain.reset;
begin

 Head:= False;
 Body:= False;
 LArm:= False;
 RArm:= False;
 LLeg:= False;
 RLeg:= False;
 paintBox1.Invalidate;

 Edit1.Clear;
 SpinEdit1.Value:= 30;
end;

procedure TfrmMain.Button1Click(Sender: TObject);
var
 idx: Integer;
begin
idx:= random(Dictionary.Count);

 WordStr:= Dictionary[Idx];
 SlashedWord:= SlashWord(WordStr);
 Edit1.Text:= SlashedWord;
 Loaded:= True;

 Timer1.Enabled:= True;
end;

procedure TfrmMain.Button2Click(Sender: TObject);
begin
 frmAbout.ShowModal;
 PaintBox1.Invalidate;
end;

procedure TfrmMain.FormCreate(Sender: TObject);
begin
 self.KeyPreview:= True;
 randomize;
 Dictionary:= TStringList.Create;

 if FileExists('Dictionary.dat') then
 Dictionary.LoadFromFile('Dictionary.dat');
end;

procedure TfrmMain.FormDestroy(Sender: TObject);
begin
Dictionary.Free;
end;

procedure TfrmMain.FormKeyPress(Sender: TObject; var Key: Char);
begin
if loaded then
 begin

 if pos(upcase(Key), Uppercase(WordStr)) > 0 then
 begin
 SlashedWord:= SolveWord(SlashedWord, WordStr, Key);
 Edit1.Text:= SlashedWord;
if Uppercase(SlashedWord) = UpperCase(WordStr) then
  begin
 Timer1.Enabled:= False;
 ShowMessage('You Won!');
 reset;

    exit;
  end;
 end
 else
 begin

  HangMan;
 if isHanged then
  begin

   Timer1.Enabled:= False;

   Edit1.Text:= WordStr;
   ShowMessage('You Lost!');

   reset;
   exit;
  end;
 end;
 end;
end;

procedure TfrmMain.PaintBox1Paint(Sender: TObject);
var
 X,Y: Integer;
begin
 inherited;
 with PaintBox1 do
 begin
 Canvas.Pen.Color:= clBlack;
 Canvas.Pen.Width:= 5;
 Canvas.Pen.Style:= psSolid;
 Canvas.Rectangle(1,1, ClientWidth-1, ClientHeight-1);
 Canvas.Brush.Color:= clWhite;
 Canvas.FloodFill(10,10,clBlack, fsBorder);
 Canvas.MoveTo(ClientWidth div 2, 1);
 Canvas.LineTo(Clientwidth div 2, ClientHeight Div 4);
 X:= Clientwidth div 2; Y:= ClientHeight Div 4;
 Canvas.Pen.Width:= 3;
 if Head then

 Canvas.Ellipse(X-25, Y-25, X+25, Y+25);
 Y:= Y + 25;
 Canvas.MoveTo(X, Y);
 if Body then
 Canvas.LineTo(X, Y + 100);
 Canvas.MoveTo(X, Y + 25);
 if LArm then
 Canvas.LineTo(X-25, Y+50);

 Canvas.MoveTo(X, Y + 25);

 if RArm then
 Canvas.LineTo(X+25, Y+50);

 Canvas.MoveTo(X, Y + 100);
 if LLeg then
 Canvas.LineTo(X-25, Y+150);

 Canvas.MoveTo(X, Y + 100);
 if RLeg then
 Canvas.LineTo(X+25, Y+150);
 end;
end;

end.

Upvotes: 2

Views: 9985

Answers (1)

David Heffernan
David Heffernan

Reputation: 612794

List of index out of bound(0)

This means that you attempted to reference index 0 of the list, but there is no element at index 0. In other words, your list is empty.

The only place in the code that I can see which could lead to that error is where you read items from Dictionary. So, I conclude that Dictionary is empty. Either the file you loaded it from is not present, or that file is empty.

At this point in the code

if FileExists('Dictionary.dat') then
  Dictionary.LoadFromFile('Dictionary.dat');

you need to do more than silently ignore the missing file. Personally I would remove the check for FileExists and attempt to load the file no matter what. If it fails to load, your application will raise an exception to that effect. You should also add a check that the dictionary is not empty.

Your program assumes that the working directory of your process is the same directory as contains the executable. That may not always be the case. Instead of using relative paths, always a brittle affair for GUI programs, specify the full path to the dictionary file:

Dictionary.LoadFromFile(ExtractFilePath(Application.ExeName)+'Dictionary.dat');

You have a number of booleans:

Head: Boolean;
Body: Boolean;
RArm: Boolean;
LArm: Boolean;
LLeg: Boolean;
RLeg: Boolean;

These should all be replaced by an enumerated type:

type
  TState = (stHealthy, stHead, stBody, ..., stDead);

or something along those lines. Declare a field FState: TState and initialise to stHealthy. Every time the user guesses wrong, write inc(FState). When you reach stDead, well you get the idea. The point is that there is a total order on the state and all those booleans provide you more flexibility than is possible to have. It also leads to verbose and awkward code.

Upvotes: 9

Related Questions