Head First C# 实验室2(冒险游戏)
TheQuest
构建一个冒险游戏,一关一关打败危险的敌人
基本设定:
- 按回合进行
- 玩家进行一步操作,敌人走一步
- 玩家和敌人都可以移动或者攻击
- 总共7个关卡
- 游戏一直进行直到通关或者死亡
角色:
(玩家)
武器装备:
(长剑sword)
- 攻击半径为10
- 攻击伤害为1-3
- 可以攻击任意方向敌人
(战斧battleaxe)
攻击半径为30
攻击伤害为1-5
可以攻击任意方向敌人
(弓bow)
- 攻击距离为100
- 伤害为1点
(狼牙棒mace)
- 攻击半径为20
- 攻击伤害为1-6
- 可以攻击任意方向敌人
(蓝色药水potion_blue)
使用后回复1-5点生命值
(红色药水potion_red)
使用后回复1-10点生命值
敌人:
(蝙蝠bat)
- 蝙蝠初始点数为6
- 移动时有0.5的几率向玩家移动,0.5几率随机移动
- 达到攻击距离攻击玩家,随机造成1-3点的伤害
(幽灵ghost)
- 初始点数为8
- 移动时有1/3的几率向玩家移动,2/3几率原地不动
- 达到攻击距离攻击玩家,随机造成1-3点伤害
(食尸鬼ghoul)
- 初始点数为10
- 移动时有2/3几率向玩家移动,1/3的几率原地不动
- 达到攻击距离攻击玩家,随机造成1-4点伤害
(游戏背景)
关卡设置:
- 第一关:敌人:蝙蝠bat;武器:长剑sword
- 第二关:敌人:蝙蝠bat,幽灵ghost;武器:potion_red红色药水
- 第三关:敌人:蝙蝠bat,幽灵ghost;武器:battleaxe战斧
- 第四关:敌人:蝙蝠bat,食尸鬼ghoul;武器:bow弓箭
- 第五关:敌人:幽灵ghost,食尸鬼ghoul;武器:potion_blue蓝色药水
- 第六关:敌人:蝙蝠bat,幽灵ghost,食尸鬼ghoul;武器:mace狼牙棒
- 第七关:敌人:蝙蝠bat,幽灵ghost,食尸鬼ghoul;武器:无
体系结构:
各类和函数的实现:
Game对象:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Drawing; namespace TheQuest3 { enum Direction { Up,Down,Left,Right}; class Game { public List<Enemy> Enemies //多个敌人 { get; private set; } public Weapon WeaponInRoom { get; private set; } public Weapon equipedWeapon { get { return player.equippedWeapon; } } private Player player; //玩家 public Point PlayerLocation //玩家位置 { get { return player.Location; } } public int PlayerHitPoints //玩家生命值 { get { return player.HitPoints; } } public IEnumerable<string> PlayerWeapons //玩家的武器 { get { return player.Weapons; } } public bool isEquip(string Name) { if (player.equippedWeapon.Name == Name) return true; else return false; } private int level = 0; //关卡 public int Level { get { return level; } } private Rectangle boundaries; //游戏边界 public Rectangle Boundaries { get { return boundaries; } } public Game(Rectangle boundaries) { this.boundaries = boundaries; player = new Player(this, new Point(boundaries.Left + 10, boundaries.Top + 70)); } public void Move(Direction direction,Random random) //玩家按direction移动,敌人按random随机移动 { player.Move(direction); foreach (Enemy enemy in Enemies) enemy.Move(random); } public void Equip(string WeaponName) //玩家装备武器 { player.Equip(WeaponName); } public bool CheckPlayerInventory(string WeaponName) //判断是否包含某装备 { return player.Weapons.Contains(WeaponName); } public void HitPlayer(int maxDamage,Random random) //攻击伤害判断 { player.Hit(maxDamage, random); } public void IncreasePlayerHealth(int health,Random random)//玩家恢复生命值 { player.IncreaseHealth(health, random); } public void Attack(Direction direction,Random random) //攻击判定 { player.Attack(direction, random); foreach (Enemy enemy in Enemies) enemy.Move(random); } private Point GetRandomLocation(Random random) //获取一个随机位置 { return new Point(boundaries.Left + random.Next(boundaries.Right / 10 - boundaries.Left / 10) * 10, boundaries.Top + random.Next(boundaries.Bottom / 10 - boundaries.Top / 10) * 10); } public void NewLevel(Random random) //对不同关卡的敌人和武器进行设置 { level++; switch (level) { case 1: //第一关 Enemies = new List<Enemy>() { new Bat(this,GetRandomLocation(random)), }; WeaponInRoom = new Sword(this, GetRandomLocation(random)); break; case 2: Enemies = new List<Enemy>() { new Bat(this,GetRandomLocation(random)), new Ghost(this,GetRandomLocation(random)) }; WeaponInRoom = new Potion_red(this, GetRandomLocation(random)); break; case 3: Enemies = new List<Enemy>() { new Bat(this,GetRandomLocation(random)), new Ghost(this,GetRandomLocation(random)) }; WeaponInRoom = new Battleaxe(this, GetRandomLocation(random)); break; case 4: Enemies = new List<Enemy>() { new Bat(this,GetRandomLocation(random)), new Ghoul(this,GetRandomLocation(random)) }; WeaponInRoom = new Bow(this, GetRandomLocation(random)); break; case 5: Enemies = new List<Enemy>() { new Ghost(this,GetRandomLocation(random)), new Ghoul(this,GetRandomLocation(random)) }; WeaponInRoom = new Potion_blue(this, GetRandomLocation(random)); break; case 6: Enemies = new List<Enemy>() { new Bat(this,GetRandomLocation(random)), new Ghost(this,GetRandomLocation(random)), new Ghoul(this,GetRandomLocation(random)) }; WeaponInRoom = new Mace(this, GetRandomLocation(random)); break; case 7: Enemies = new List<Enemy>() { new Bat(this,GetRandomLocation(random)), new Ghost(this,GetRandomLocation(random)), new Ghoul(this,GetRandomLocation(random)) }; break; default: break; } } } class Player : Mover { public Weapon equippedWeapon; //正在装备的武器 public int HitPoints { get; private set; } private List<Weapon> inventory = new List<Weapon>(); //武器列表 public IEnumerable<string> Weapons { get { List<string> names = new List<string>(); foreach(Weapon weapon in inventory) names.Add(weapon.Name); return names; } } public Player(Game game,Point location) : base(game, location) { HitPoints = 1000; //初始生命值为10 } public void Hit(int maxDamage,Random random) //玩家攻击伤害随机,最大值为maxDamage { HitPoints -= random.Next(1, maxDamage); } public void IncreaseHealth(int health,Random random)//使用药水时回复随机生命值,最大值为health { HitPoints += random.Next(1, health); } public void Equip(string weaponName) //在工具栏装备武器 { foreach (Weapon weapon in inventory) { if (weapon.Name == weaponName) equippedWeapon = weapon; } } public void quiverDischarge(Weapon weapon) { if (inventory.Contains(weapon)) { inventory.Remove(weapon); } } public void Move(Direction direction) //玩家移动后判断是否有武器可以拾取,添加进装备栏,如果之前没有武器则直接使用 { base.location = Move(direction, game.Boundaries);//Move为基类Mover的函数,朝direction移动一步 if (!game.WeaponInRoom.PickedUp) { if (game.WeaponInRoom.Location == base.location) { game.WeaponInRoom.PickedUpWeapon(); inventory.Add(game.WeaponInRoom); } } } public void Attack(Direction direction,Random random)//玩家朝某个方向攻击产生随机伤害 { if (equippedWeapon != null) { equippedWeapon.Attack(direction, random); if (equippedWeapon is IPotion) inventory.Remove(equippedWeapon); } } } abstract class Weapon : Mover { public bool PickedUp //武器是否被玩家拾取 { get; private set; } public Weapon(Game game,Point location) : base(game, location) { PickedUp = false; } public void PickedUpWeapon() { PickedUp = true; } public abstract string Name { get; } public abstract void Attack(Direction direction, Random random); //弓箭 protected bool DamageEnemy(Direction direction,int distance,int damage,Random random) { foreach(Enemy enemy in game.Enemies) { if (Nearby(direction, enemy.Location, distance)) { enemy.Hit(damage, random); return true; } } return false; } protected bool DamageEnemy(int radius,int damage,Random random) { Point target = game.PlayerLocation; foreach(Enemy enemy in game.Enemies) { if (Nearby(target, enemy.Location, radius)) { enemy.Hit(damage, random); return true; } } return false; } } public interface IPotion { bool Used { get; } } class Sword : Weapon { public Sword(Game game,Point location) : base(game, location) { } public override string Name { get { return "Sword"; } } public override void Attack(Direction direction, Random random) { DamageEnemy(10, 3, random); } } class Battleaxe : Weapon { public Battleaxe(Game game,Point location) : base(game, location) { } public override string Name { get { return "Battleaxe"; } } public override void Attack(Direction direction, Random random) { DamageEnemy(30, 5, random); } } class Bow : Weapon { public Bow(Game game,Point location) : base(game, location) { } public override string Name { get { return "Bow"; } } public override void Attack(Direction direction, Random random) { DamageEnemy(direction, 1000, 1, random); } } class Mace : Weapon { public Mace(Game game,Point location) : base(game, location) { } public override string Name { get { return "Mace"; } } public override void Attack(Direction direction, Random random) { DamageEnemy(20, 6, random); } } class Potion_blue : Weapon, IPotion { private bool used=false; public Potion_blue(Game game,Point location) : base(game, location) { } public bool Used { get { return used; } } public override string Name { get { return "Potion_blue"; } } public override void Attack(Direction direction, Random random) { game.IncreasePlayerHealth(5, random); used = true; } } class Potion_red : Weapon, IPotion { private bool used = false; public Potion_red(Game game,Point location) : base(game, location) { } public bool Used { get { return used; } } public override string Name { get { return "Potion_red"; } } public override void Attack(Direction direction, Random random) { game.IncreasePlayerHealth(10, random); used = true; } } abstract class Enemy:Mover { private const int NearPlayerDistance = 25; public int HitPoints { get; private set; } public bool Dead { get { if (HitPoints <= 0) return true; else return false; } } public Enemy(Game game,Point location,int hitPoints) : base(game, location) { HitPoints = hitPoints; } public abstract void Move(Random random); public void Hit(int maxDamage,Random random) { HitPoints -= random.Next(1, maxDamage); } protected bool NearPlayer() { return (Nearby(game.PlayerLocation,this.location,NearPlayerDistance)); } protected Direction FindPlayerDirection(Point playerLocation) { Direction directionToMove; if (playerLocation.X > location.X + 10) directionToMove = Direction.Right; else if (playerLocation.X < location.X - 10) directionToMove = Direction.Left; else if (playerLocation.Y > location.Y + 10) directionToMove = Direction.Down; else directionToMove = Direction.Up; return directionToMove; } } class Bat : Enemy { public Bat(Game game,Point location) : base(game, location, 6) { } public override void Move(Random random) { if (NearPlayer()) { game.HitPlayer(3, random); return; } if (random.Next(2) == 0) { Direction direction = FindPlayerDirection(game.PlayerLocation); this.location = Move(direction, game.Boundaries); } else { Direction direction = (Direction)random.Next(4); this.location = Move(direction, game.Boundaries); } } } class Ghost : Enemy { public Ghost(Game game, Point location) : base(game, location,8) { } public override void Move(Random random) { if (NearPlayer()) { game.HitPlayer(3, random); return; } if (random.Next(3) == 1) { Direction direction = FindPlayerDirection(game.PlayerLocation); this.location = Move(direction, game.Boundaries); } else { return; } } } class Ghoul : Enemy { public Ghoul(Game game,Point location) : base(game, location, 10) { } public override void Move(Random random) { if (NearPlayer()) { game.HitPlayer(4, random); return; } if (random.Next(3) == 1) { return; } else { Direction direction = FindPlayerDirection(game.PlayerLocation); this.location = Move(direction, game.Boundaries); } } } abstract class Mover { private const int MoveInterval = 10; protected Point location; public Point Location { get { return location; } } protected Game game; public Mover(Game game,Point location) { this.game = game; this.location = location; } //弓箭判断是否敌人是否在功击范围 public bool Nearby(Direction direction,Point locationToCheck,int distance) { switch (direction) { case Direction.Up: if (Math.Abs(game.PlayerLocation.X - locationToCheck.X) <= 20 && Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) <= distance) return true; break; case Direction.Down: if (Math.Abs(game.PlayerLocation.X - locationToCheck.X) <= 20 && Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) <= distance) return true; break; case Direction.Left: if (Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) <= 20 && Math.Abs(game.PlayerLocation.X - locationToCheck.X) <= distance) return true; break; case Direction.Right: if (Math.Abs(game.PlayerLocation.Y - locationToCheck.Y) <= 20 && Math.Abs(game.PlayerLocation.X - locationToCheck.X) <= distance) return true; break; default: return false; } return false; } //剑和锤的判断,是否在攻击范围内 public bool Nearby(Point location,Point locationToCheck,int radius) { if (Math.Abs((location.X - locationToCheck.X) * (location.X - locationToCheck.X)) + Math.Abs((location.Y - locationToCheck.Y) * (location.Y - locationToCheck.Y))<=radius) return true; else return false; } public Point Move(Direction direction,Rectangle boundaries) //移动一步 { Point newLocation= location; switch (direction) { case Direction.Up: if (newLocation.Y - MoveInterval >= boundaries.Top) newLocation.Y -= MoveInterval; break; case Direction.Down: if (newLocation.Y + MoveInterval <= boundaries.Bottom) newLocation.Y += MoveInterval; break; case Direction.Left: if (newLocation.X - MoveInterval >= boundaries.Left) newLocation.X -= MoveInterval; break; case Direction.Right: if (newLocation.X + MoveInterval <= boundaries.Right) newLocation.X += MoveInterval; break; default:break; } return newLocation; } } }
Form对象:
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace TheQuest3 { public partial class Form1 : Form { public Form1() { InitializeComponent(); } private Game game; private Random random = new Random(); private void Form1_Load(object sender, EventArgs e) { game = new Game(new Rectangle(78, 57, 420, 155)); game.NewLevel(random); UpdateCharacters(); } public void UpdateCharacters() { player.Visible = true; player.Location = game.PlayerLocation; playerHitPoints.Text = game.PlayerHitPoints.ToString(); //显示和隐藏生成的敌人 int enemiesShown = game.Enemies.Count(); bat.Visible = false; ghost.Visible = false; ghoul.Visible = false; batHitPoints.Text = "0"; ghostHitPoints.Text = "0"; ghoulHitPoints.Text = "0"; foreach (Enemy enemy in game.Enemies) { if (enemy is Bat) { bat.Location = enemy.Location; batHitPoints.Text = enemy.HitPoints.ToString(); if (enemy.HitPoints > 0) { bat.Visible = true; } else { enemiesShown--; bat.Visible = false; game.Enemies.Remove(enemy); batHitPoints.Text = "0"; break; } } if(enemy is Ghost) { ghost.Location = enemy.Location; ghostHitPoints.Text = enemy.HitPoints.ToString(); if (enemy.HitPoints > 0) { ghost.Visible = true; } else { enemiesShown--; ghost.Visible = false; game.Enemies.Remove(enemy); ghostHitPoints.Text = "0"; break; } } if(enemy is Ghoul) { ghoul.Location = enemy.Location; ghoulHitPoints.Text = enemy.HitPoints.ToString(); if (enemy.HitPoints > 0) { ghoul.Visible = true; } else { enemiesShown--; ghoul.Visible = false; game.Enemies.Remove(enemy); ghoulHitPoints.Text = "0"; break; } } } //在房间地图中的武器 sword.Visible = false; bow.Visible = false; potion_red.Visible = false; potion_blue.Visible = false; mace.Visible = false; battleaxe.Visible = false; Control weaponControl = null; switch (game.WeaponInRoom.Name) { case "Sword": weaponControl = sword; break; case "Bow": weaponControl = bow; break; case "Mace": weaponControl = mace; break; case "Battleaxe": weaponControl = battleaxe; break; case "Potion_blue": weaponControl = potion_blue; break; case "Potion_red": weaponControl = potion_red; break; default: break; } if (weaponControl != null) { weaponControl.Visible = true; weaponControl.Location = game.WeaponInRoom.Location; } if (game.WeaponInRoom.PickedUp) weaponControl.Visible = false; else weaponControl.Visible = true; //装备栏 swordTool.Visible = false; battleaxeTool.Visible = false; bowTool.Visible = false; maceTool.Visible = false; potionTool_blue.Visible = false; potionTool_red.Visible = false; foreach(string weapon in game.PlayerWeapons) { switch (weapon) { case "Sword": swordTool.Visible = true; break; case "Battleaxe": battleaxeTool.Visible = true; break; case "Bow": bowTool.Visible = true; break; case "Mace": maceTool.Visible = true; break; case "Potion_blue": potionTool_blue.Visible = true; break; case "Potion_red": potionTool_red.Visible = true; break; default: break; } } swordTool.BorderStyle = BorderStyle.None; battleaxeTool.BorderStyle = BorderStyle.None; bowTool.BorderStyle = BorderStyle.None; maceTool.BorderStyle = BorderStyle.None; potionTool_blue.BorderStyle = BorderStyle.None; potionTool_red.BorderStyle = BorderStyle.None; if (game.equipedWeapon != null) { switch (game.equipedWeapon.Name) { case "Sword": swordTool.BorderStyle = BorderStyle.FixedSingle; break; case "Battleaxe": battleaxeTool.BorderStyle = BorderStyle.FixedSingle; break; case "Bow": bowTool.BorderStyle = BorderStyle.FixedSingle; break; case "Mace": maceTool.BorderStyle = BorderStyle.FixedSingle; break; case "Potion_blue": potionTool_blue.BorderStyle = BorderStyle.FixedSingle; break; case "Potion_red": potionTool_red.BorderStyle = BorderStyle.FixedSingle; break; default: break; } } if (game.PlayerHitPoints <= 0) { MessageBox.Show("You died"); Application.Exit(); } if (game.Level > 7) { MessageBox.Show("You have be cleared by the customs"); Application.Exit(); } if (enemiesShown < 1) { MessageBox.Show("You have defeated the enemies on thi level"); game.NewLevel(random); UpdateCharacters(); } } private void tableLayoutPanel2_Paint(object sender, PaintEventArgs e) { } private void textBox1_TextChanged(object sender, EventArgs e) { } private void textBox2_TextChanged(object sender, EventArgs e) { } private void button6_Click(object sender, EventArgs e) { game.Attack(Direction.Right, random); UpdateCharacters(); } private void dateTimePicker1_ValueChanged(object sender, EventArgs e) { } private void textBox1_TextChanged_1(object sender, EventArgs e) { } private void bow_Click(object sender, EventArgs e) { } private void player_Click(object sender, EventArgs e) { } private void potion_red_Click(object sender, EventArgs e) { } private void sword_Click(object sender, EventArgs e) { } private void playerPanel_Click(object sender, EventArgs e) { } private void ghostPanel_Click(object sender, EventArgs e) { } private void MoveLeft_Click(object sender, EventArgs e) { game.Move(Direction.Left, random); UpdateCharacters(); } private void MoveRight_Click(object sender, EventArgs e) { game.Move(Direction.Right, random); UpdateCharacters(); } private void mace_Click(object sender, EventArgs e) { } private void ghoul_Click(object sender, EventArgs e) { } private void potion_blue_Click(object sender, EventArgs e) { } private void wizard_Click(object sender, EventArgs e) { } private void shield_Click(object sender, EventArgs e) { } private void quiver_Click(object sender, EventArgs e) { } private void MoveUp_Click(object sender, EventArgs e) { game.Move(Direction.Up, random); UpdateCharacters(); } private void bat_Click(object sender, EventArgs e) { } private void ghost_Click(object sender, EventArgs e) { } private void ShieldTool_Click(object sender, EventArgs e) { } private void AttackUp_Click(object sender, EventArgs e) { game.Attack(Direction.Up, random); UpdateCharacters(); } private void MoveDown_Click(object sender, EventArgs e) { game.Move(Direction.Down, random); UpdateCharacters(); } private void AttackLeft_Click(object sender, EventArgs e) { game.Attack(Direction.Left, random); UpdateCharacters(); } private void AttackDown_Click(object sender, EventArgs e) { game.Attack(Direction.Down, random); UpdateCharacters(); } private void potionTool_red_Click(object sender, EventArgs e) { game.Equip("Potion_red"); UpdateCharacters(); } private void potionTool_blue_Click(object sender, EventArgs e) { game.Equip("Potion_blue"); UpdateCharacters(); } private void swordTool_Click(object sender, EventArgs e) { game.Equip("Sword"); UpdateCharacters(); } private void bowTool_Click(object sender, EventArgs e) { game.Equip("Bow"); UpdateCharacters(); } private void maceTool_Click(object sender, EventArgs e) { game.Equip("Mace"); UpdateCharacters(); } private void battleaxeTool_Click(object sender, EventArgs e) { game.Equip("Battleaxe"); UpdateCharacters(); } private void playerHitPoints_Click(object sender, EventArgs e) { } private void ghostHitPoints_Click(object sender, EventArgs e) { } } }
图片下载:https://files.cnblogs.com/files/asahiLikka/Resources.zip