代码在 Windows 和 Android 上的执行方式不同

Code executes differently on Windows and Android

我正在编写一个名为 Jotto 的简单游戏。玩家试图猜测一个秘密的五个字母的单词;每个字母都是独一无二的。在每个 5 个字母的猜测单词之后,您会被告知猜测中有多少个字母也在秘密单词中。这是我第一次尝试使用 Delphi 进行跨平台开发。我在 Delphi 中开发了 Windows 个应用程序,并在 Android 中使用 Flutter 开发了一些应用程序。

所有代码在 Windows(32 位)上都按预期执行,但在 Android(64 位,SDK 25.2.5)上却没有。没有出现异常,但每轮计算出的正确猜测数是不正确且不可预测的(即下面 total 的计算结果是错误的)。 运行 通过调试器的代码有时也会显示局部变量不正确。

相关函数如下:

function TJotto.OccurrencesOfChar(const aWord, aChar: string): integer;
var
  i: integer;
begin
  result := 0;
  for i := 1 to Length(aWord) do
    if aWord[i] = aChar then
      inc(result);
end;

function TJotto.MakeGuess(aGuessWord: string): string;
var
  i: integer;
  total: integer;
  wordToDisplay: string;
begin
  total := 0; // number of matches
  wordToDisplay := aGuessWord;
  // save copy of guess before deleting duplicate letters
  // because guess will be displayed
  // did user solve puzzle?
  if aGuessWord = FSecretWord then
    Exit('You did it! The word was ' + aGuessWord);
  // make sure all letters in aGuessWord are different
  // otherwise a guess like 'vexed' will say an E is present in FSecretWord twice
  for i := 5 downto 1 do
    if OccurrencesOfChar(aGuessWord, aGuessWord[i]) > 1 then
      Delete(aGuessWord, i, 1);
  // go through each letter in aGuessWord to see if it's in FSecretWord
  // keep a running total number of matches
  for i := 1 to Length(aGuessWord) do
    total := total + OccurrencesOfChar(FSecretWord, aGuessWord[i]);

  result := wordToDisplay + #9 + total.ToString;
end;

注意:在 Delphi 10.4 之前,移动编译器默认使用基于 0 的字符串索引。参见 Zero-based strings

使用 Low()High() 内部函数迭代字符串。

您看到的不规则现象是因为索引超出了字符串的边界。调试时,使用溢出和范围检查来检测此类错误。

您的代码将如下所示:

function TJotto.OccurrencesOfChar(const aWord, aChar: string): integer;
var
  i: integer;
begin
  result := 0;
  for i := Low(aWord) to High(aWord) do
    if aWord[i] = aChar then
      inc(result);
end;

function TJotto.MakeGuess(aGuessWord: string): string;
var
  i: integer;
  total: integer;
  wordToDisplay: string;
begin
  total := 0; // number of matches
  wordToDisplay := aGuessWord;
  // save copy of guess before deleting duplicate letters
  // because guess will be displayed
  // did user solve puzzle?
  if aGuessWord = FSecretWord then
    Exit('You did it! The word was ' + aGuessWord);
  // make sure all letters in aGuessWord are different
  // otherwise a guess like 'vexed' will say an E is present in FSecretWord twice
  for i := High(aGuessWord) downto Low(aGuessWord) do
    if OccurrencesOfChar(aGuessWord, aGuessWord[i]) > 1 then 
      Delete(aGuessWord, i+1-Low(aGuessWord), 1); // Delete uses one-based array indexing even in platforms where the strings are zero-based.
  // go through each letter in aGuessWord to see if it's in FSecretWord
  // keep a running total number of matches
  for i := Low(aGuessWord) to High(aGuessWord) do
    total := total + OccurrencesOfChar(FSecretWord, aGuessWord[i]);

  result := wordToDisplay + #9 + total.ToString;
end;