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

C#坦克对战程序问题:数组坦克属性无法在循环中正常复用

问题:坦克对战项目中随机属性无法在攻击逻辑中生效

我正在开发一个坦克对战作业项目,在Tankstat类的Tankcreate方法中,通过以下方式创建带随机属性的坦克数组:

pantera[0] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));

但在attack方法的攻击逻辑中,使用如下while循环时:

while (ammunition > 0 && armor > 0 && maneuver > 0)

调试发现ammunition、armor、maneuver始终初始为0,而非创建时生成的0-100随机值,导致攻击后属性变为负数。请问如何让数组中坦克的随机属性值能在for/while循环逻辑中正常使用?

附完整代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace C
{
    class Tankstat
    {
        private string name { get; set; }
        private int ammunition { get; set; }
        private int armor { get; set; }
        private int maneuver { get; set; }

        private int ammunitionMinus { get; set; }
        private int armorMinus { get; set; }
        private int maneuverMinus { get; set; }

        public Tankstat(string name, int ammunition, int armor, int maneuver)
        {
            this.name = name;
            this.ammunition = ammunition;
            this.armor = armor;
            this.maneuver = maneuver;
        }
        public override string ToString()
        {
            return $"The name of the tank is {name} the amount of ammunition left is {ammunition} the strength of armor is {armor} the maneuver level is {maneuver}";
        }

        public static Tankstat operator *(Tankstat tank1, Tankstat tank2)
        {
            return tank1 * tank2;
        }

        public static Tankstat operator ^ (Tankstat tank1, Tankstat tank2)
        {
            return tank1 ^ tank2;
        }
        public Tankstat() { }
        public void Tankcreate()
        {
            Random rand = new Random();
            Tankstat[] pantera = new Tankstat[5];
            pantera[0] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            pantera[1] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            pantera[2] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            pantera[3] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            pantera[4] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));

            Tankstat[] T34 = new Tankstat[5];
            T34[0] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            T34[1] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            T34[2] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            T34[3] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            T34[4] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
            foreach (Tankstat panteras in pantera)
            {
                Console.WriteLine(panteras);
            }
            foreach (Tankstat T34S in T34)
            {
                Console.WriteLine(T34S);
            }

        }
        Tankstat[] pantera = new Tankstat[5];
        Tankstat[] T34 = new Tankstat[5];
        public void attack()
        {
            for (int i = 0; i < pantera.Length && i < T34.Length; i++)
                {
                while (ammunition > 0 && armor > 0 && maneuver > 0)
                Console.WriteLine("Initializer is going to attack the tank");
                Random rambo = new Random();
                ammunitionMinus = rambo.Next(1, 20);
                ammunition = ammunition - ammunitionMinus;
                armorMinus = rambo.Next(1, 10);
                armor = armor - armorMinus;
                maneuverMinus = rambo.Next(2, 15);
                maneuver = maneuver - maneuverMinus;
                Console.WriteLine($"The name of the tank {name} has {ammunition} ammunition left the armor is {armor} and the manuever is {maneuver}, wait for 2 seconds for next move");
                Thread.Sleep(2000);
            }
        }
    }
}

解决方案

问题根源

  1. 数组作用域冲突:Tankcreate方法内部重新定义了pantera和T34数组,与类级别的同名数组是完全独立的变量。方法内创建的坦克实例仅存在于局部作用域,类级别的数组始终是未初始化的空实例(默认属性值为0)。
  2. 未正确引用数组中的坦克实例:attack方法直接访问当前Tankstat对象自身的属性,而非数组中存储的具体坦克实例的属性。
  3. while循环语法错误:while循环后缺少大括号,仅Console.WriteLine属于循环,属性修改代码直接执行,且循环条件永远无法终止(初始值为0时直接跳过)。
  4. 属性访问权限不足:ammunition等属性为private,无法在类内的其他方法中直接访问数组中坦克实例的属性。
  5. 运算符重载无限递归:*和^运算符重载直接调用自身,会导致栈溢出。

修改步骤

1. 统一数组作用域

删除Tankcreate方法内的局部数组定义,直接使用类级别的数组:

public void Tankcreate()
{
    Random rand = new Random();
    // 直接使用类级别的数组,不再重新定义
    pantera[0] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    pantera[1] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    pantera[2] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    pantera[3] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    pantera[4] = new Tankstat("Pantera", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));

    T34[0] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    T34[1] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    T34[2] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    T34[3] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    T34[4] = new Tankstat("T-34", rand.Next(0, 100), rand.Next(0, 100), rand.Next(0, 100));
    
    foreach (Tankstat panteras in pantera)
    {
        Console.WriteLine(panteras);
    }
    foreach (Tankstat T34S in T34)
    {
        Console.WriteLine(T34S);
    }
}

2. 正确引用数组中的坦克实例

在attack方法中通过数组索引获取具体坦克对象,修改其属性:

public void attack()
{
    Random rambo = new Random(); // 只初始化一次Random,避免重复随机值
    for (int i = 0; i < pantera.Length && i < T34.Length; i++)
    {
        Tankstat attackingTank = pantera[i];
        Tankstat defendingTank = T34[i];
        
        // 攻击循环:直到攻击方弹药耗尽,或防守方装甲/机动为0
        while (attackingTank.ammunition > 0 && defendingTank.armor > 0 && defendingTank.maneuver > 0)
        {
            Console.WriteLine($"{attackingTank.name} 正在攻击 {defendingTank.name}");
            
            // 攻击方消耗弹药
            int ammoLoss = rambo.Next(1, 20);
            attackingTank.ammunition -= ammoLoss;
            if (attackingTank.ammunition < 0) attackingTank.ammunition = 0;
            
            // 防守方损失装甲和机动
            int armorLoss = rambo.Next(1, 10);
            defendingTank.armor -= armorLoss;
            if (defendingTank.armor < 0) defendingTank.armor = 0;
            
            int maneuverLoss = rambo.Next(2, 15);
            defendingTank.maneuver -= maneuverLoss;
            if (defendingTank.maneuver < 0) defendingTank.maneuver = 0;
            
            Console.WriteLine($"{attackingTank.name} 剩余弹药: {attackingTank.ammunition}");
            Console.WriteLine($"{defendingTank.name} 剩余装甲: {defendingTank.armor}, 剩余机动: {defendingTank.maneuver}");
            Console.WriteLine("等待2秒进行下一回合攻击...");
            Thread.Sleep(2000);
        }
        
        Console.WriteLine($"对战结束: {attackingTank.name} vs {defendingTank.name}\n");
    }
}

3. 修改属性访问权限

将name、ammunition等属性的访问修饰符改为public,允许类内其他方法访问:

public string name { get; set; }
public int ammunition { get; set; }
public int armor { get; set; }
public int maneuver { get; set; }

4. 修复或删除错误的运算符重载

当前的运算符重载会导致无限递归,可删除或实现实际逻辑:

// 删除无效的运算符重载,或替换为实际逻辑
// public static Tankstat operator *(Tankstat tank1, Tankstat tank2)
// {
//     // 示例逻辑:返回弹药翻倍的新坦克
//     return new Tankstat(tank1.name, tank1.ammunition * 2, tank1.armor, tank1.maneuver);
// }

额外优化建议

  • Random实例复用:在类级别初始化Random,避免循环中重复创建导致的重复随机值。
  • 代码复用:将创建坦克的逻辑封装为单独方法,减少重复代码。
  • 边界值处理:所有属性修改时确保数值不低于0,避免负数属性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:01:08