【问题标题】:Code executes differently on Windows and Android代码在 Windows 和 Android 上的执行方式不同
【发布时间】:2021-03-16 05:16:18
【问题描述】:

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

所有代码在 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;

【问题讨论】:

  • 字符串中的字符索引?你说:通过调试器运行代码有时也会显示局部变量不正确。究竟是什么方式?

标签: android delphi delphi-10.3-rio


【解决方案1】:

注意:在 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;

【讨论】:

  • 这是一个很好的答案。它解决了我的问题,简洁明了,代码在那里,并且有一个链接可以帮助我更好地理解正在发生的事情。谢谢!
  • 附注即使阅读了 Embarcadero 关于设置 Android 开发的说明,我也不知道这种变化。对其他人来说也可能有问题,因为即使是初学者也使用字符串和索引,任何从 10.3 社区版开始并升级到 10.4 的人都可能遇到同样的问题。
  • @AlC 自从 Delphi 引入对移动平台的支持以及从零开始的字符串以来,人们遇到了类似的问题。这就是为什么 Delphi 10.4 在所有支持的平台上都使用基于 One 的字符串来避免这种混淆。是的,从一开始就在 Delphi 中使用基于 One 的字符串。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
  • 2013-06-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-21
相关资源
最近更新 更多