2

我有一个用delphi编写的代码,当我在客户端计算机上打开exe文件时,它说索引列表超出范围(0),我搜索了整个谷歌,但无法修复,我必须如何修复它?有一些东西错误 :D 谢谢大家

代码:

    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.
4

1 回答 1

10

超出范围的索引列表(0)

这意味着您试图引用列表的索引 0,但索引 0 处没有元素。换句话说,您的列表是空的。

我能看到的代码中唯一可能导致该错误的地方是您从中读取项目的位置Dictionary。所以,我的结论Dictionary是空的。您从中加载它的文件不存在,或者该文件为空。

此时代码中

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

您需要做的不仅仅是默默地忽略丢失的文件。就个人而言,无论如何我都会删除检查FileExists并尝试加载文件。如果加载失败,您的应用程序将引发异常。您还应该检查字典不为空。

您的程序假定您的进程的工作目录与包含可执行文件的目录相同。情况可能并非总是如此。不要使用相对路径,这对于 GUI 程序来说总是一件脆弱的事情,而是指定字典文件的完整路径:

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

您有许多布尔值:

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

这些都应该被枚举类型替换:

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

或类似的规定。声明一个字段FState: TState并初始化为stHealthy. 每次用户猜错时,写inc(FState). 当你到达时stDead,你明白了。关键是状态有一个总顺序,所有这些布尔值都为您提供了比可能拥有的更大的灵活性。它还会导致冗长和笨拙的代码。

于 2013-05-15T21:20:59.717 回答