C#太空侵略者游戏出现NullReferenceException错误,求排查原因
问题分析与解决
你遇到的System.NullReferenceException原因很清晰:当BulletTimer触发计时逻辑时,玩家还没按下空格键创建任何子弹,此时bullets数组里的所有元素都是默认的null,直接访问bullets[0].Top自然会报错——这个位置根本没有实例化的PictureBox对象。
修复步骤
先检查子弹实例再操作
在BulletTimer_Tick方法里,先判断目标子弹是否存在,同时遍历所有已创建的子弹(而不是只盯着bullets[0]),避免空引用和逻辑局限:private void BulletTimer_Tick(object sender, EventArgs e) { // 遍历所有已经创建的子弹 for(int i = 0; i < BulletsCreated; i++) { if(bullets[i] != null) { bullets[i].Top -= 10; // 额外优化:子弹飞出窗体后移除控件并释放资源,避免内存浪费 if(bullets[i].Top < -bullets[i].Height) { this.Controls.Remove(bullets[i]); bullets[i].Dispose(); bullets[i] = null; } } } }可选:按需启停定时器
可以默认禁用BulletTimer,只有玩家第一次创建子弹时再启动它,从根源避免空引用:- 在窗体构造函数里添加:
BulletTimer.Enabled = false; - 在空格键创建子弹的代码块末尾,加入:
if(!BulletTimer.Enabled) { BulletTimer.Enabled = true; }
- 在窗体构造函数里添加:
额外优化建议
你当前用固定大小的数组存储子弹,其实可以改用List<PictureBox>实现动态存储,更灵活也不用担心容量限制:
// 替换原数组定义 List<PictureBox> bullets = new List<PictureBox>(); // 创建子弹的逻辑修改为: if (e.KeyValue == 32) { PictureBox newBullet = new PictureBox(); newBullet.Width = 2; newBullet.Height = 24; newBullet.BackColor = Color.Cyan; newBullet.Top = Turret.Top - 26; newBullet.Left = Turret.Left + Turret.Width / 2; newBullet.Enabled = true; newBullet.Visible = true; this.Controls.Add(newBullet); bullets.Add(newBullet); if(!BulletTimer.Enabled) { BulletTimer.Enabled = true; } } // 定时器逻辑修改为: private void BulletTimer_Tick(object sender, EventArgs e) { // 用ToList避免遍历中修改集合报错 foreach(var bullet in bullets.ToList()) { bullet.Top -= 10; if(bullet.Top < -bullet.Height) { this.Controls.Remove(bullet); bullet.Dispose(); bullets.Remove(bullet); } } }
内容的提问来源于stack exchange,提问作者Charles King
相关产品推荐
相关产品推荐

