从零开发游戏需要学习的c#模块,第三章(方法)
上一章我们学习了循环和集合,今天我们来学习方法
代码的复用车床——方法 (Method)
到目前为止,我们的所有代码都挤在 Main 里面。如果我想在游戏里让角色“攻击”三次,就得把攻击逻辑复制粘贴三遍。这太蠢了。
方法,就是给一段代码起个名字。你需要它的时候,喊它的名字就行。这是消除重复代码的最基本手段。
看一个最简单的例子:一个只会打印“普通攻击!”的方法
// 这是一个方法的定义
static void Attack()
{
Console.WriteLine("你发动了普通攻击!");
}
static:静态的。现阶段你所有的 Main 方法里直接调用的方法,都先加上 static。我们后面讲类时会深究。
void:这表示“这个方法执行完了,什么都不给我返回”。就像开灯,它只做事,不给你结果。
Attack:我们自己起的方法名字。跟变量名一样,用动词或动词短语。
():括号是方法的标志。里面可以放参数。
{ ... }:方法体。这个方法被调用时会执行的代码块。
如何“叫”它调用方法
定义了方法,它不会自己执行。你需要喊它的名字,也就是调用。
static void Main(string[] args)
{
Console.WriteLine("遇到敌人!");
Attack(); // 喊一声"Attack",程序就跳去执行上面的方法
Attack(); // 再喊一次,它就再执行一次
Attack(); // 打第三次
Console.WriteLine("敌人被消灭了!");
}
// 方法定义在 Main 方法的外面,但还在 class Program 的大括号里面
static void Attack()
{
Console.WriteLine("你发动了普通攻击!");
}
(这个代码没有外壳,只有核心内容,如果要运行用下面这个代码)
using System;
namespace MyFirstGameCode
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("遇到敌人!");
Attack(); // 喊一声"Attack",程序就跳去执行上面的方法
Attack(); // 再喊一次,它就再执行一次
Attack(); // 打第三次
Console.WriteLine("敌人被消灭了!");
Console.ReadKey(); // 暂停一下,让你能看到结果
}
// 方法定义在 Main 方法的外面,但还在 class Program 的大括号里面
static void Attack()
{
Console.WriteLine("你发动了普通攻击!");
}
}
}
百变金刚——有参数的方法
普通的攻击每次都一样,太单调了。我想让角色能释放不同名字的技能。“火球术”、“冰箭术”等等 这就需要用参数来告诉方法。
// string skillName 就是我们定义的一个参数,用来接收技能名字
static void CastSpell(string skillName)
{
Console.WriteLine("你对敌人释放了" + skillName + "!");
}
(调用时,必须给它一个参数:)
CastSpell(“火球术”);
CastSpell(“冰箭术”);
CastSpell(“治疗术”);
// 输出:你对敌人释放了火球术! ...
一个方法可以有多个参数,用逗号隔开。我们做一个有目标、有伤害的完整攻击:
static void DealDamage(string targetName, int damage)
{
Console.WriteLine("对" + targetName + "造成了" + damage + "点伤害!");
}
现在,我们可以在 Main 里这样用:
DealDamage(“哥布林”, 25);
DealDamage(“巨龙”, 8);
有“还”有“报”——有返回值的方法
有些方法不只做事,还要给你一个计算结果。比如一个“计算暴击后伤害值”的方法,你得把计算后的数值拿回来。这时,void 就不够用了,我们需要返回值。
void 表示“不返回任何东西”。要返回一个整数,我们就写 int;要返回一个字符串,就写 string。
看这个方法,它计算伤害,并用 return 把结果传回来。
// 计算范围伤害,对一个区域内的敌人造成的伤害只计算65%
static float CalculateAOEDamage(int baseDamage)
{
float aoeMultiplier = 0.65f; // 范围伤害系数
float finalDamage = baseDamage * aoeMultiplier; // 计算结果
return finalDamage; // return 就像工厂的出货口,把结果交出去
}
调用它,并用变量接住:
int mySpellPower = 100;
float aoeDamage = CalculateAOEDamage(mySpellPower); // 把100传进去,用aoeDamage接住65的结果
Console.WriteLine("你的范围攻击造成了 " + aoeDamage + " 点伤害。");
实战演练:整合一个简单战斗系
现在,把我们学到的所有东西整合起来。我们不在 Main 里写任何具体逻辑,只用来调度我们造好的方法。
class Program
{
// 玩家属性(现在声明在Main外面,这样所有方法都能用,暂时先这样写)
static int playerHp = 100;
static string playerName = “勇者”;
static void Main(string[] args)
{
Console.WriteLine(“=== 战斗开始! ===”);
// 用带参数的方法攻击一系列敌人
DealDamage(“哥布林”, 30);
DealDamage(“暗影魔”, 45);
// 受伤
TakeDamage(25);
TakeDamage(18);
// 检查状态
CheckStatus();
Console.WriteLine(“\n=== 战斗结束 ===”);
Console.ReadKey();
}
// 1. 攻击方法
static void DealDamage(string enemyName, int damage)
{
Console.WriteLine(“\n你对” + enemyName + “造成了” + damage + “点伤害!”);
// 有10%几率追加一次暴击
Random rng = new Random();
if (rng.Next(1, 101) <= 10)
{
Console.WriteLine(“ ⚔️ 暴击!额外造成” + damage + “点伤害!”);
}
}
// 2. 受伤方法
static void TakeDamage(int damage)
{
playerHp = playerHp - damage;
Console.WriteLine(“你受到了” + damage + “点伤害!当前血量:” + playerHp);
// 检查是否死亡
if (playerHp <= 0)
{
Console.WriteLine(“你倒下了... Game Over.”);
}
}
// 3. 检查状态方法
static void CheckStatus()
{
Console.WriteLine(“\n--- 状态 ---”);
Console.WriteLine(“角色:” + playerName);
Console.WriteLine(“剩余血量:” + playerHp);
}
}

留给大家一个小小的作业,在最后的代码中加入护甲的概念,如果护甲高于伤害,则造成零点伤害,需要答案的小伙伴可以私信我。
今天的学习到此结束,今天我们学习了方法,关注我,下一期更精彩(如果报错可以检查一下双引号是不是中文)
还有一张打击运行图

更多推荐

所有评论(0)