C#焦点(25)练手小项目:飞机大战

打印 上一主题 下一主题

主题 1944|帖子 1944|积分 5832

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
简介

通过焦点部门的学习,我们已经可以做一些复杂的项目了。
我们这次会用我们学到的面向对象知识写一个飞机大战(性能大概不太好,因为毕竟是控制台项目)
如果你有所不懂,建议多查多思索多问。
因为这次的项目比较难,博主会稍微讲细致一点。
基类计划:GameObject 抽象类

  1. abstract class GameObject
  2. {
  3.     protected int x;       // 坐标X(列)
  4.     protected int y;       // 坐标Y(行)
  5.     protected bool isAlive; // 存活状态
  6.     public GameObject(int x, int y)
  7.     {
  8.         this.x = x;
  9.         this.y = y;
  10.         this.isAlive = true; // 初始化时存活
  11.     }
  12.     // 只读属性:暴露坐标和存活状态(IsAlive可写)
  13.     public int X { get { return x; } }
  14.     public int Y { get { return y; } }
  15.     public bool IsAlive { get { return isAlive; } set { isAlive = value; } }
  16.     // 抽象方法:强制子类实现核心行为
  17.     public abstract void Move();   // 移动逻辑
  18.     public abstract void Draw();   // 绘制逻辑
  19.     public abstract void Attack(); // 攻击逻辑
  20. }
复制代码


  • 焦点作用:定义所有游戏对象(飞机、仇人、子弹、道具)的公共属性(坐标、存活状态)和必须实现的行为接口。
  • 计划特点
         
    • protected 修饰的字段允许子类直接访问,避免过分封装。   
    • 抽象方法确保子类必须实现移动、绘制、攻击这三个焦点功能,实现多态性(如飞机和仇人的移动方式差别)。  

玩家飞机:Aircraft 类

  1. class Aircraft : GameObject
  2. {
  3.     public int health = 5;       // 玩家生命值(初始5点)
  4.     public List<Bullet> bullets = new List<Bullet>(); // 玩家发射的子弹列表
  5.     public Aircraft(int x, int y) : base(x, y) { } // 调用基类构造函数初始化坐标
  6.     public override void Move()
  7.     {
  8.         while (Console.KeyAvailable) // 处理所有未读取的按键(避免漏键)
  9.         {
  10.             ConsoleKeyInfo key = Console.ReadKey(true); // 读取按键并隐藏输入字符
  11.             switch (key.Key)
  12.             {
  13.                 case ConsoleKey.LeftArrow:  if (x > 1) x--; break;       // 左边界限制(x>1,避开左墙体)
  14.                 case ConsoleKey.RightArrow: if (x < Console.WindowWidth - 2) x++; break; // 右边界限制
  15.                 case ConsoleKey.UpArrow:    if (y > 1) y--; break;       // 上边界限制(避开顶部墙体)
  16.                 case ConsoleKey.DownArrow:  if (y < Console.WindowHeight - 3) y++; break; // 下边界限制(避开底部墙体和分数栏)
  17.                 case ConsoleKey.Spacebar:   Attack(); break; // 按下空格时调用攻击(发射子弹)
  18.             }
  19.         }
  20.     }
  21.     public override void Draw()
  22.     {
  23.         // 确保坐标在屏幕内,避免控制台异常
  24.         if (x >= 0 && x < Console.WindowWidth && y >= 0 && y < Console.WindowHeight)
  25.         {
  26.             Console.SetCursorPosition(x, y);
  27.             Console.Write("A"); // 用"A"字符表示玩家飞机
  28.         }
  29.     }
  30.     public override void Attack()
  31.     {
  32.         bullets.Add(new Bullet(x, y - 1)); // 在飞机当前位置上方一格生成子弹(玩家子弹向上移动)
  33.     }
  34. }
复制代码
关键逻辑


  • 移动控制:通过 Console.KeyAvailable 及时检测方向键,直接修改 x/y 坐标,并通过边界判断(如 x > 1)确保飞机不会移出墙体范围。
  • 子弹发射:按下空格时,调用 Attack() 方法,在飞机上方(y-1)生成一颗非仇人子弹(isEnemyBullet=false)。
  • 绘制逻辑:利用 Console.SetCursorPosition 定位后输出字符 "A",直观显示玩家位置
仇人范例:NormalEnemy 和 RandomMovingEnemy类

普通仇人:垂直移动 + 概率射击(NormalEnemy)

  1. class NormalEnemy : GameObject
  2. {
  3.     public List<Bullet> enemyBullets = new List<Bullet>(); // 敌人发射的子弹列表
  4.     public NormalEnemy(int x, int y) : base(x, y) { } // 初始化坐标
  5.     public override void Move()
  6.     {
  7.         // 50%概率向下移动(通过随机数控制速度,避免频繁移动)
  8.         if (new Random().Next(2) == 0)  
  9.         {
  10.             y++; // 向下移动
  11.             if (y >= Console.WindowHeight - 2) // 触达底部墙体时死亡
  12.                 isAlive = false;
  13.         }
  14.     }
  15.     public override void Draw()
  16.     {
  17.         if (isAlive && y < Console.WindowHeight - 2 && x >= 0 && x < Console.WindowWidth)
  18.         {
  19.             Console.SetCursorPosition(x, y);
  20.             Console.Write("E"); // 用"E"字符表示普通敌人
  21.         }
  22.         // 处理敌人子弹:移动、绘制、移除死亡子弹
  23.         for (int i = enemyBullets.Count - 1; i >= 0; i--)
  24.         {
  25.             Bullet bullet = enemyBullets[i];
  26.             bullet.Move(); // 子弹移动
  27.             bullet.Draw(); // 子弹绘制
  28.             if (!bullet.IsAlive) // 子弹超出屏幕则移除
  29.                 enemyBullets.RemoveAt(i);
  30.         }
  31.     }
  32.     public override void Attack()
  33.     {
  34.         // 10%概率发射子弹(向下移动的敌人子弹)
  35.         if (new Random().Next(100) < 10)  
  36.             enemyBullets.Add(new Bullet(x, y + 1, true)); // isEnemyBullet=true标识敌人子弹
  37.     }
  38. }
复制代码
随机移动仇人:四方向随机移动 + 概率射击(RandomMovingEnemy)

  1. class RandomMovingEnemy : GameObject
  2. {
  3.     public List<Bullet> enemyBullets = new List<Bullet>(); // 敌人子弹列表
  4.     private Random random = new Random(); // 随机数生成器(成员变量,避免重复创建)
  5.     public RandomMovingEnemy(int x, int y) : base(x, y) { }
  6.     public override void Move()
  7.     {
  8.         // 50%概率随机移动(上下左右四方向)
  9.         if (random.Next(2) == 0)  
  10.         {
  11.             int direction = random.Next(4); // 0-3对应上下左右
  12.             switch (direction)
  13.             {
  14.                 case 0: if (y > 1) y--; break;       // 上移(避开顶部墙体)
  15.                 case 1: if (y < Console.WindowHeight - 2) y++; break; // 下移(避开底部墙体)
  16.                 case 2: if (x > 1) x--; break;       // 左移(避开左墙体)
  17.                 case 3: if (x < Console.WindowWidth - 2) x++; break; // 右移(避开右墙体)
  18.             }
  19.         }
  20.     }
  21.     public override void Draw()
  22.     {
  23.         // 逻辑与NormalEnemy类似,仅绘制字符为"R"
  24.         if (isAlive && y < Console.WindowHeight - 2 && x >= 0 && x < Console.WindowWidth)
  25.         {
  26.             Console.SetCursorPosition(x, y);
  27.             Console.Write("R"); // 用"R"字符表示随机移动敌人
  28.         }
  29.         // 子弹处理逻辑与NormalEnemy完全一致
  30.         for (int i = enemyBullets.Count - 1; i >= 0; i--)
  31.         {
  32.             Bullet bullet = enemyBullets[i];
  33.             bullet.Move();
  34.             bullet.Draw();
  35.             if (!bullet.IsAlive)
  36.                 enemyBullets.RemoveAt(i);
  37.         }
  38.     }
  39.     public override void Attack()
  40.     {
  41.         // 与NormalEnemy相同:10%概率发射向下子弹
  42.         if (random.Next(100) < 10)  
  43.             enemyBullets.Add(new Bullet(x, y + 1, true));
  44.     }
  45. }
复制代码


  • 计划差别
         
    • 移动方式:普通仇人仅垂直向下移动,随机仇人通过 Random.Next(4) 实现四方向随机移动,增加游戏难度。   
    • 性能细节:RandomMovingEnemy 中将 Random 作为成员变量,避免每次调用 Move() 时创建新实例  

子弹与道具:Bullet 和 ClearScreenItem 类

子弹类:区分敌我子弹的移动方向(Bullet)

  1. class Bullet : GameObject
  2. {
  3.     public bool isEnemyBullet; // 是否为敌人发射的子弹(决定移动方向)
  4.     public Bullet(int x, int y, bool isEnemyBullet = false) : base(x, y)
  5.     {
  6.         this.isEnemyBullet = isEnemyBullet; // 默认为玩家子弹(false)
  7.     }
  8.     public override void Move()
  9.     {
  10.         if (isEnemyBullet)
  11.      
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

钜形不锈钢水箱

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表