-1

我试图返回一个函数的值,以告诉我某个位置在该位置是否有熔岩或水。

问题是即使那里有熔岩或水,它仍然返回 true。水、熔岩和苍蝇的值来自玩家生物的列表。如果该生物具有水,熔岩或可以飞行的能力,那只是得到。我只是相应地将它们标记为真/假。位置是一个TPOINT。它将所有这些加载到一个函数中,只要函数 CheckLocation 返回 true,那么它的位置就可以了

  if FMyPlayers.Player[i].Values['water']='yes' then
       canwater := true;
   if FMyPlayers.Player[i].Values['Lava']='yes' then
       canlava := true;
   if FMyPlayers.Player[i].Values['fly']='yes' then
       canfly := true;
   cansnow := true;
   if checkLocation(position,cansnow,canlava,canwater,canfly) = False then
      exit;

function TBaseGameForm.checkLocation(position :Tpoint;Cansnow,canlava,canwater,canfly:bool):Bool;
begin
RESULT := True;
if canfly = true then
   RESULT := true
else begin
  if FGamePlay.waterLocations.IndexOfName('x'+inttostr(Position.x)+inttostr(Position.Y)) <> -1 then begin    //Check location
     Showmessage('Cant move there due to water');
     RESULT := FALSE;
   end;
  if FGamePlay.LavaLocations.IndexOfName('x'+inttostr(Position.x)+inttostr(Position.Y)) <> -1 then begin    //Check location
     Showmessage('Cant move there due to lava');
     RESULT := False;
    end;
  end;
end;

运行时,我检查 WaterLocations 中的值

[0]  x47
[1]  y47
[2]  x58
[3]  y58

Position.x 和 Position.y 的值是 (4,7) 因此它应该返回 false 因为 x47 在列表中。

4

1 回答 1

8

就像@SertacAkyuz 说的那样,问题在于您使用IndexOfName(). 你需要IndexOf()改用。

CheckLocation()您的函数中还有另一个错误。您将忽略除canfly. 如果canwatercanlava为 True,您的函数将在任何水/熔岩位置返回 False。您需要检查该位置是否确实与播放器的功能相匹配。如果canwater为真,则无需检查该位置是否为水。熔岩也是如此。

试试这个:

canwater := (FMyPlayers.Player[i].Values['water'] = 'yes');
canlava := (FMyPlayers.Player[i].Values['Lava'] = 'yes');
canfly := (FMyPlayers.Player[i].Values['fly'] = 'yes'); 
cansnow := true; 
if not CheckLocation(position, cansnow, canlava, canwater, canfly) then 
  Exit; 

.

function TBaseGameForm.CheckLocation(position: TPoint; cansnow, canlava, canwater, canfly: Boolean): Boolean; 
var
  loc: String;
begin 
  Result := True;
  if (not canfly) and ((not canwater) or (not canlava)) then
  begin
    loc := Format('x%d%d', [Position.X, Position.Y]);

    if (not canwater) and (FGamePlay.waterLocations.IndexOf(loc) <> -1) then
    begin
      Showmessage('Cant move there due to water'); 
      Result := False;
      Exit;
    end;

    if (not canlava) and (FGamePlay.LavaLocations.IndexOf(loc) <> -1) then
    begin
      Showmessage('Cant move there due to lava'); 
      Result := False;
      Exit;
    end;
  end; 
end; 

话虽如此,我同意@sarnold 的观点,即您的坐标系需要一些调整。只要您的 x/y 坐标都是个位数,就可以了。但如果它们是多位数字,它将不起作用。至少,您应该在 Y 坐标前面加上前缀,例如:

[0]  x4y7
[1]  x5y8

loc := Format('x%dy%d', [Position.X, Position.Y]);

就个人而言,我根本不会使用 aTStrings来保存这样的整数值。我会改用TListofTPoint实例,例如:

waterLocations: TList;

function FindLocation(List: TList; Position: TPoint): Integer;
begin
  for Result := 0 to List.Coun-1 do
  begin
    with PPoint(List[Result])^ do
    begin
      if (X = Position X) and (Y = Position.Y) then Exit;
    end;
  end;
  Result := -1;
end;

.

if (not canwater) and (FindLocation(FGamePlay.waterLocations, Position) <> -1) then
begin
  Showmessage('Cant move there due to water'); 
  Result := False;
  Exit;
end;

或者,如果您使用的是支持泛型的现代 Delphi 版本,则TList<TPoint>

waterLocations: TList<TPoint>;

function FindLocation(List: TList<TPoint>; Position: TPoint): Integer;
begin
  for Result := 0 to List.Coun-1 do
  begin
    with List[Result] do
    begin
      if (X = Position X) and (Y = Position.Y) then Exit;
    end;
  end;
  Result := -1;
end;

.

if (not canwater) and (FindLocation(FGamePlay.waterLocations, Position) <> -1) then
begin
  Showmessage('Cant move there due to water'); 
  Result := False;
  Exit;
end;

甚至是TDictionary存储任何给定 X/Y 坐标指定的位置类型的单个:

type
  locType = (locLand, locWater, locLava, locSnow);

locations: TDictionary<TPoint, locType>;

.

function TBaseGameForm.CheckLocation(position: TPoint; cansnow, canlava, canwater, canfly: Boolean): Boolean; 
var
  loc: locType;
begin 
  Result := True;
  if not canfly then
  begin
    locations.TryGetValue(Position, loc);
    case loc of
      locWater: begin
        if not canwater then
        begin
          Showmessage('Cant move there due to water'); 
          Result := False;
        end;
      end;
      locLava: begin
        if not canlava then
        begin
          Showmessage('Cant move there due to lava'); 
          Result := False;
          Exit;
        end;
      end;
    end;
  end; 
end; 
于 2012-07-06T01:30:57.507 回答