You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#控制台应用如何无需重复调用输出方法即可实时更新变量值

实现方案

方法1:使用INotifyPropertyChanged实现自动更新(推荐)

你可以让Player类实现属性变更通知接口,当health属性值发生变化时自动触发更新逻辑,全程不需要手动调用血量输出语句:

  1. 改造Player类:
using System.ComponentModel;
using System.Runtime.CompilerServices;

public class Player : INotifyPropertyChanged
{
    public string name { get; set; }
    private int _health;
    public int health
    {
        get => _health;
        set
        {
            _health = value;
            // 属性变更时触发通知事件
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
  1. 改造StartFight方法,订阅属性变更事件自动更新控制台:
public static void StartFight(Player p1, Player p2) {
    Console.Clear();
    Title(" BATTLE ");
    // 记录两行血量显示的固定行号,后续直接覆盖更新不需要重复输出
    int p1HealthLine = Console.CursorTop;
    Console.WriteLine($"{p1.name} Health: {p1.health} ");
    int p2HealthLine = Console.CursorTop;
    Console.WriteLine($"{p2.name} Health: {p2.health} ");

    // 订阅p1的属性变更事件,血量变化自动更新对应行
    p1.PropertyChanged += (s, e) => 
    {
        if (e.PropertyName == nameof(Player.health))
        {
            Console.SetCursorPosition(0, p1HealthLine);
            Console.Write($"{p1.name} Health: {p1.health} ");
            // 光标归位不影响后续其他内容输出
            Console.SetCursorPosition(0, Console.CursorTop);
        }
    };
    // 订阅p2的属性变更事件
    p2.PropertyChanged += (s, e) => 
    {
        if (e.PropertyName == nameof(Player.health))
        {
            Console.SetCursorPosition(0, p2HealthLine);
            Console.Write($"{p2.name} Health: {p2.health} ");
            Console.SetCursorPosition(0, Console.CursorTop);
        }
    };

    // 原有战斗逻辑完全不需要修改,不需要加任何血量输出语句
    while (true) {
        if (Fight(p1, p2)) {
            Title(" GAME OVER! ");
            PlayAgain();
            break;
        }

        if (Fight(p2, p1)) {
            Title(" GAME OVER! ");
            PlayAgain();
            break;
        }
    }
}

方法2:封装更新方法(轻量需求可选)

如果你不想改动Player类的结构,可以把血量更新逻辑封装成独立方法,只需要在循环里调用一次就行,不需要重复写整段输出代码:

// 全局记录血量显示的行号
static int p1HealthLine, p2HealthLine;

public static void UpdateHealth(Player p1, Player p2)
{
    Console.SetCursorPosition(0, p1HealthLine);
    Console.Write($"{p1.name} Health: {p1.health} ");
    Console.SetCursorPosition(0, p2HealthLine);
    Console.Write($"{p2.name} Health: {p2.health} ");
    Console.SetCursorPosition(0, Console.CursorTop);
}

之后只需要在每次Fight方法执行后调用UpdateHealth(p1,p2)即可。

注意:使用SetCursorPosition覆盖输出的方式比反复清屏的效率更高,也不会出现屏幕闪烁的问题。

内容的提问来源于stack exchange,提问作者ac88

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 23:45:03