如何在循环中只执行一次代码行?

how to execute a line of code only once inside of a loop?

提问人:Finn 提问时间:11/12/2023 最后编辑:Finn 更新时间:11/13/2023 访问量:93

问:

初学者在这里,我正在尝试做一个 while true 循环,无限期地读取游戏中的整数值。我想做的是,当该整数 = x 值时,执行某个代码,但只执行一次。

我用了这个代码

while (true)
{

    
    var value = swed.ReadInt(localplayer, offsets.health);


    if (value == 70)
    {
        Console.WriteLine("hello");
    }


}

问题是,当值为 70 时,当我只想打印一次时,它会永远打印“hello”。请记住,我希望无限期地读取该值并在其 70 时打印一次“hello”,所以我不能使用 break,否则它只能工作一次。我尝试使用 for 循环,它按照我的意愿打印了该消息一次,但它仅在该值开始时为 70 时才有效。它不会像 While 循环那样连续读取该值。所以我想我需要使用嵌套循环?我尝试了很多不同的东西,到目前为止没有任何效果

C# 循环 for while 循环

评论

1赞 Mitch Wheat 11/12/2023
您需要创建一个布尔标志“hasExecuted”(或适当的名称)。检查并设置时检查并执行您的条件
0赞 Finn 11/12/2023
对不起,我忘了说我用了休息时间。每当值为 70 时,我希望“hello”打印一次。如果我使用休息时间,它只会工作一次,当值再次为 70 时,什么都不会发生
0赞 mousetail 11/12/2023
@Finn 请编辑问题以澄清您是否希望它发生多次
0赞 Peppermintology 11/12/2023
你想在有人输入 70 并且你已经回复了你好后完全打破 while 循环吗?
0赞 Finn 11/12/2023
不完全是。值不断变化。所以我需要无限期地阅读它。当它 70 岁时,我总是希望它打印“你好”,但只打印一次。所以我不能使用 break,因为如果值 let 说更改为 80 然后回到 70,则不会打印任何内容

答:

-1赞 TP95 11/12/2023 #1

正如评论所建议的,使用一个标志来触发“hello”一次,就像:

var hasExecuted = false;

while (true)
{
    
    var value = swed.ReadInt(localplayer, offsets.health);

    if (value == 70 && !hasExecuted)
    {
        Console.WriteLine("hello");
        hasExecuted = true;
    }
}

编辑:只是一个小小的疏忽,我将标志更改为循环外。

评论

0赞 Finn 11/12/2023
我试过了这个,一开始的值是 70,它仍然无限期地打印“hello”
0赞 Peppermintology 11/12/2023
hasExectued 应该在循环之外,否则它将始终重置为 false。
1赞 Finn 11/12/2023
你说得对,我把 hasExectued 移出循环后,它打印了一次“hello”。但同样的问题,如果值更改为其他值,然后又变回 70,则不会打印任何内容。所以基本上这与使用 break 相同
-1赞 Naser Hamdan 11/12/2023 #2

如果问题的目的是在值达到 70 时触发某些内容,则应该在属性上设置一个侦听器。

检查以下示例代码,假设它在 Unity 中使用:

using System;
using System.ComponentModel;

public class MyClass : INotifyPropertyChanged
{
    private string myAttribute;
    
    public string MyAttribute
    {
        get { return myAttribute; }
        set
        {
            if (myAttribute != value)
            {
                myAttribute = value;
                OnPropertyChanged(nameof(MyAttribute));
            }
        }
    }
    
    public event PropertyChangedEventHandler PropertyChanged;
    
    protected virtual void OnPropertyChanged(string propertyName)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

public class Program
{
    public static void Main()
    {
        MyClass myObject = new MyClass();
        myObject.PropertyChanged += MyObject_PropertyChanged;
        
        // Change the attribute value to trigger the event
        myObject.MyAttribute = "New value";
    }
    
    private static void MyObject_PropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        // Function to be triggered when the attribute changes
        // Check if the property name is "MyAttribute"
        if (e.PropertyName == nameof(MyAttribute))
        {
            // Get the new value of MyAttribute
            string newValue = MyAttribute;
        
            // Perform conditional logic based on the new value
            if (newValue == "SomeValue")
            {
                // Do something when the value is "SomeValue"
                Debug.Log("Property value is 'SomeValue'.");
            }
            else
            {
                // Do something else when the value is not "SomeValue"
                Debug.Log("Property value is not 'SomeValue'.");
            }
        }
    }
0赞 Peppermintology 11/12/2023 #3

如果您只想在输入值为 70 时打印 hello,而不想在值没有更改时打印,但如果它确实更改回 70,则再次打印,那么您可以跟踪以前的值。

var previousValue = 0;
var currentValue = 0;

while (true)
{
  currentValue = swed.ReadInt(localPlayer, offsets.health);

  if (currentValue == 70 && previousValue != 70)
  {
    Console.WriteLine(“hello”);
  }

  previousValue = currentValue;
}

不是最优雅的解决方案,但说明了基本思想。您可以根据需要进行整理。

评论

0赞 Finn 11/12/2023
非常感谢。这确实奏效了!
0赞 Peppermintology 11/12/2023
@Finn 好东西。您可以通过将 if 条件逻辑移动到它自己的方法(如果该逻辑将被重用)来改进它,并使值 70 成为它自己的变量并引用它,这样如果它发生变化,它只会在一个地方发生变化,但会在任何地方更新。
0赞 Javad J 11/12/2023 #4

多亏了@TP95,他/她的代码可以稍作更改以支持您的问题:

var hasExecuted = false;
while (true)
{

    var value = swed.ReadInt(localplayer, offsets.health);

    if (value == 70 && !hasExecuted)
    {
        Console.WriteLine("hello");
        hasExecuted = true;
    }
    if (value != 70 && hasExecuted)
    {
       hasExecuted = false;
    }
}

对不起,我无法对您的答案发表评论。