有点简陋,呵呵。
首先一个塔防游戏的主要大类肯定是塔类,怪物类以及地图类了。
塔类代码:
class Ta
{
public static List<Ta> haveta = new();
private int atk;
private int money = 0;
public byte level;
private byte level_numberof;
public string taappearance;
public void BulidTa()
{
Ta gunta = new();
Ta fireta = new();
Ta rpgta = new();
gunta.atk = 20;
rpgta.atk = 50;
fireta.atk = 15;
//定义塔的攻击力
fireta.money = 1000;
rpgta.money = 1200;
gunta.money = 500;
//定义塔的金额
gunta.taappearance = "G";
fireta.taappearance = "F";
rpgta.taappearance = "R";
//定义塔的基本属性
if (haveta.Count < 6)
{
WriteLine("请选择你要购买的塔");
WriteLine("1 机枪塔 2喷火塔 3火箭助推榴弹塔");
string a = ReadLine();
switch (a)//选择购买哪个塔
{
case "1":
if (Hero.usemoney >= gunta.money)//察看拥有的金额是否够买这座塔
{
Hero.usemoney -= gunta.money;// 减少钱数
haveta.Add(gunta);//把购买的塔加进haveta列表中
WriteLine($"购买成功,你购买了一座gunta,你还剩{Hero.usemoney}元");
}
break;
case "2":
if (Hero.usemoney >= fireta.money)
{
Hero.usemoney -= fireta.money;
haveta.Add(fireta);
WriteLine($"购买成功,你购买了一座fireta,你还剩{Hero.usemoney}元");
}
break;
case "3":
if (Hero.usemoney >= rpgta.money)
{
Hero.usemoney -= rpgta.money;
haveta.Add(rpgta);
WriteLine($"购买成功,你购买了一座rpgta,你还剩{Hero.usemoney}元");
}
break;
default://默认购买gunta
goto case "1";
}
}
else
{
WriteLine("六个位置已全部被占满");
}
}
public void Shengji()
{
WriteLine("选择你要升级的塔.1 2.3,4,5,6");
string a = ReadLine();
switch (a)
{
case "1":
if (Hero.usemoney > 2000 && haveta[0].level < 2)
{
Hero.usemoney -= 2000;
haveta[0].atk += 30;
haveta[0].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "2":
if (Hero.usemoney > 4000 && haveta[1].level < 2 && level_numberof == 1)
{
Hero.usemoney -= 4000;
haveta[1].atk += 40;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "3":
if (Hero.usemoney > 5000 && haveta[2].level < 2 && level_numberof == 2)
{
Hero.usemoney -= 5000;
haveta[1].atk += 60;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "4":
if (Hero.usemoney > 6000 && haveta[3].level < 2 && level_numberof == 3)
{
Hero.usemoney -= 6000;
haveta[1].atk += 80;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "5":
if (Hero.usemoney > 7000 && haveta[4].level < 2 && level_numberof == 4)
{
Hero.usemoney -= 7000;
haveta[1].atk += 100;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "6":
if (Hero.usemoney > 10000 && haveta[5].level < 2 && level_numberof == 5)
{
Hero.usemoney -= 10000;
haveta[1].atk += 200;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
}
}
public void Atk()
{
switch (haveta.Count)
{
case 1:
if (Monster.brushumonster[0].x>0&& Monster.brushumonster[0].x < 30)
{
Monster.brushumonster[0].hp -= haveta[0].atk;
}
break;
case 2:
if (Monster.brushumonster[0].x > 0 && Monster.brushumonster[0].x < 30)
{
Monster.brushumonster[0].hp -= (haveta[0].atk+=haveta[1].atk);
}
break;
case 3:
if (Monster.brushumonster[0].x>30 && Monster.brushumonster[0].x <50)
{
Monster.brushumonster[0].hp -=haveta[2].atk;
}
break;
case 4:
if (Monster.brushumonster[0].x > 30 && Monster.brushumonster[0].x < 50)
{
Monster.brushumonster[0].hp -= (haveta[2].atk += haveta[3].atk);
}
break;
case 5:
if (Monster.brushumonster[0].x > 50 && Monster.brushumonster[0].x < 90)
{
Monster.brushumonster[0].hp -= haveta[4].atk;
}
break;
case 6:
if (Monster.brushumonster[0].x > 50 && Monster.brushumonster[0].x< 90)
{
Monster.brushumonster[0].hp -= (haveta[4].atk += haveta[5].atk);
}
break;
}
}
}
怪物类:
在这里把y设置为const避免因为误操作改变它的值导致程序错误。
那么让我来介绍一下const吧:
1.一般在防止因为误操作而改变一个重要的,不应改变的值时,我们就会用到const
2.在为一个字段或局部变量添加const关键字后,要为字段或局部变量添加本地变量初始化器。
例如:
class A
{
const int a=12;
const int b;//错误,要提供一个初始值
}
3。使用const会提高效率 ,在编译时会把常量的值替换成常量
4。如果值在定义它的程序集发生变化,并且你没有再跑一次定义了它的程序集的话,其他引用这个常量的程序集的值就不会变
例如:我在A程序集定义了一个常量number的值为12
在B程序集我调用了number.这时我改变A的number的值为0,改变完值后我又没跑过A
那么Bnumber的值依旧还是为12
那么有人会问了,不是还有个叫readonly的关键字跟const差不多么,那为什么不用它呢?
它的名字叫只读字段,从字段这两个字就明白它只能声明在类里面,不可以在方法里面声明
它的特点有很多,例如:
1,你可以把它声明为静态的。使得它可以为类的所有对象共享
2,如果常量的值的类型不为常量所接受时,你可以用只读字段:
class A
{
static Game game;
readonly Game a = game;
const Game b = game;//报错
}
3它可以在构造函数内赋值
4 值可以在运行中计算或加载,对字段的引用都是活动引用
说了这么多,我用const的原因是因为没有第二个程序集。而且y只作为SetCursorPosition的一个不变的参数,并且y需要反复用到,用const则可以提高效率
class Monster
{
public static List<Monster> brushumonster = new();//场上有的怪物列表
private int number_of;
private string appearance;//怪物的外观
public int hp;
public int x=0;
private const int y=14;
public void BrushMonster(Func<Monster> func)//刷怪机制
{
Monster monster = func();
brushumonster.Add(monster);
}
public void Move(List<Monster> monsters)//移动机制
{
void M(int number)
{
SetCursorPosition(monsters[number].x, y);//0,14
Write(monsters[number].appearance);
SetCursorPosition(monsters[number].x++, y);
Write(monsters[number].appearance);
}
for (int i = 0; i <2; i++)
{
M(i);
if (monsters.Count == 1)
{
i = 2;
}
}
if (brushumonster[0].x == 76)
{
//通过再一次覆盖的方法把之前打印出来的怪物覆盖为■或""
//制造出一种怪物尸体消失的假象
SetCursorPosition(x--, y);
Write("A");
monsters.RemoveAt(0);
x = 0;
SetCursorPosition(x, y);
}
if (monsters[0].hp <= 0)
{
Hero.usemoney += 300;
SetCursorPosition(monsters[0].x++, y);
Write(" ");
monsters.RemoveAt(0);
x = 0;
SetCursorPosition(x, y);
}
}//10--15
public Monster Wolf()
{
Monster wolf = new();
wolf.hp = 200;
wolf.appearance = "△";
wolf.x = 3;
return wolf;
}
public Monster Firepeople()
{
Monster firepeople = new();
firepeople.appearance = "▲";
firepeople.hp = 300;
firepeople.x = 0;
return firepeople;
}
public Monster Dinosaur()
{
Monster dinosaur = new();
dinosaur.x = 0;
dinosaur.appearance = "龙";
dinosaur.hp = 100;
return dinosaur;
}
}
而在M这个方法里又用上了一种c#7.0加进去的东西:局部方法
M作为局部方法只能在定义它的方法中访问
在MSDN文档中说明了以下可以使用局部方法
PS:在MSDN中这叫本地函数
在以下地方可以添加局部方法
- 方法(尤其是迭代器方法和异步方法)
- 构造函数
- 属性访问器
- 事件访问器
- 匿名方法
- Lambda 表达式
- 终结
- 其他本地函数
提供任意门:本地函数 - C# 编程指南 | Microsoft Docs
地图类
class Map
{
public void Darwingmap()//绘制地图
{
SetCursorPosition(0,10);
Write("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
SetCursorPosition(0, 15);
Write("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
SetCursorPosition(76, 11);
Write("A");
SetCursorPosition(76, 12);
Write("A");
SetCursorPosition(76, 13);
Write("A");
SetCursorPosition(76, 14);
Write("A");
SetCursorPosition(0,18);
Write("z键来买塔,x键来升级塔。在游玩过程中请按回车使程序运行");
// CursorVisible = tru;
}
public void DarwingTa()
{
switch (Ta.haveta.Count)
{
case 1:
SetCursorPosition(4,9);
Write(Ta.haveta[0].taappearance);
break;
case 2:
SetCursorPosition(4, 16);
Write(Ta.haveta[1].taappearance);
break;
case 3:
SetCursorPosition(40, 9);
Write(Ta.haveta[2].taappearance);
break;
case 4:
SetCursorPosition(40, 16);
Write(Ta.haveta[3].taappearance);
break;
case 5:
SetCursorPosition(60, 9);
Write(Ta.haveta[4].taappearance);
break;
case 6:
SetCursorPosition(60, 16);
Write(Ta.haveta[5].taappearance);
break;
}
}
}
在这里为了介绍委托所以用了委托,其实用个方法就够了
首先c#继承了很多C++的东西,所谓委托其实就是方法指针
那么想要认识委托,我们就要认识一下指针
在内存中,每一块内存都有它自己的地址。指针其实就是存储了某个东西在内存中的地址
在MSDN中,指针的意思为:指针是一个变量,用于存储对象的内存地址
而在<c++高级编程第四版>21页则说明为:可将指针看成指向动态分配堆上内存的一个箭头
而我们的委托则是存储了方法在内存中的地址
委托它是一种类,所以它是一个数据类型。它可以在类,命名空间中声明
它的声明方式为
delegate return-type name(type);
使用委托来间接调用一个方法:
using System;
namespace HelloWorldApplication
{
class A
{
delegate int a();
static void Main(string[] args)
{
A a2=new A();
a a1;
a1=a2.b;
/* Write C# code in this online editor and run it. */
Console.WriteLine(a1());
Console.ReadKey();
}
public int b()
{
int b2=12;
return b2;
}
}
}
我们把方法当作一个参数传递到另一个方法里,这时委托一般带返回值。
常用的几个委托:返回值为void的Action,返回值为TResult的Func<>,Func可以有16个参数,Func的类型取决于最后的那个参数
using System;
namespace HelloWorldApplication
{
class A
{
static void Main(string[] args)
{
A a1=new A();
Func<string,int> func=new Func<string,int>(a1.A2);
a1.ew(func);
}
public int A2(string a)
{
Console.Write(a);
return 12;
}
public void ew(Func<string,int> a)
{
Console.WriteLine(a("Hello,"));
}
}
}
另外委托还有多播
委托还可以实现异步,但是这个东西得跟多线程一起讲才深刻。所以不知道什么时候介绍多线程时再讲吧
全部代码:
using System.Collections.Generic;
using static System.Console;
using System;
using System;
using System.Linq;
using System.IO;
using static System.IO.Directory;
using static System.IO.Path;
using static System.Environment;
class Game
{
private void Win()
{
if(Monster.brushumonster.Count==0)
{
Clear();
WriteLine("你赢了......");
var achievement = Combine(GetFolderPath(SpecialFolder.Personal), "Chengjiu", "Chengjiu01", "Chengjiu");
WriteLine(achievement);
CreateDirectory(achievement);
string a = Combine(achievement, "成就.txt");//创建成就txt 文本文件
StreamWriter text = File.CreateText(a);
text.WriteLine("谢谢你的游玩:)");//写入文本
text.Close();
}
}
public void Lose()
{
Clear();
WriteLine("你输了......");
}
public static void Main(string[] args)
{
Ta ta_Game_Main = new();
Map map_Game_Main = new();
Monster monster_Game_Main = new();
Game game_Game_Main = new();
map_Game_Main.Darwingmap();
Func<Monster> func = new(monster_Game_Main.Wolf);
Func<Monster> func2= new(monster_Game_Main.Firepeople);
Func<Monster> func3 = new(monster_Game_Main.Dinosaur);
Random random = new();
for (int i = 0; i < 10; i++)
{
int randomguai = random.Next(1,4);
switch (randomguai)
{
case 1:
monster_Game_Main.BrushMonster(func: func);
break;
case 2:
monster_Game_Main.BrushMonster(func: func2);
break;
case 3:
monster_Game_Main.BrushMonster(func: func3);
break;
}
}
while (true)
{
string a = ReadLine();
if (a=="z")
{
SetCursorPosition(0, 18);
ta_Game_Main.BulidTa();
map_Game_Main.DarwingTa();
}
if (a == "x")
{
SetCursorPosition(0, 18);
ta_Game_Main.Shengji();
}
if (Monster.brushumonster.Count > 0)
{
ta_Game_Main.Atk();
monster_Game_Main.Move(monsters: Monster.brushumonster);
}
if (Monster.brushumonster.Count == 0)
{
game_Game_Main.Win();
break;
}
if (Monster.brushumonster[0].x==74)
{
game_Game_Main.Lose();
Monster.brushumonster.Clear();
break;
}
}
}
}
class Ta
{
public static List<Ta> haveta = new();
private int atk;
private int money = 0;
public byte level;
private byte level_numberof;
public string taappearance;
public static void A()
{
}
public void BulidTa()
{
Ta gunta = new();
Ta fireta = new();
Ta rpgta = new();
gunta.atk = 20;
rpgta.atk = 50;
fireta.atk = 15;
//定义塔的攻击力
fireta.money = 1000;
rpgta.money = 1200;
gunta.money = 500;
//定义塔的金额
gunta.taappearance = "G";
fireta.taappearance = "F";
rpgta.taappearance = "R";
//定义塔的基本属性
if (haveta.Count < 6)
{
WriteLine("请选择你要购买的塔");
WriteLine("1 机枪塔 2喷火塔 3火箭助推榴弹塔");
string a = ReadLine();
switch (a)//选择购买哪个塔
{
case "1":
if (Hero.usemoney >= gunta.money)//察看拥有的金额是否够买这座塔
{
Hero.usemoney -= gunta.money;// 减少钱数
haveta.Add(gunta);//把购买的塔加进haveta列表中
WriteLine($"购买成功,你购买了一座gunta,你还剩{Hero.usemoney}元");
}
break;
case "2":
if (Hero.usemoney >= fireta.money)
{
Hero.usemoney -= fireta.money;
haveta.Add(fireta);
WriteLine($"购买成功,你购买了一座fireta,你还剩{Hero.usemoney}元");
}
break;
case "3":
if (Hero.usemoney >= rpgta.money)
{
Hero.usemoney -= rpgta.money;
haveta.Add(rpgta);
WriteLine($"购买成功,你购买了一座rpgta,你还剩{Hero.usemoney}元");
}
break;
default://默认购买gunta
goto case "1";
}
}
else
{
WriteLine("六个位置已全部被占满");
}
}
public void Shengji()
{
WriteLine("选择你要升级的塔.1 2.3,4,5,6");
string a = ReadLine();
switch (a)
{
case "1":
if (Hero.usemoney > 2000 && haveta[0].level < 2)
{
Hero.usemoney -= 2000;
haveta[0].atk += 30;
haveta[0].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "2":
if (Hero.usemoney > 4000 && haveta[1].level < 2 && level_numberof == 1)
{
Hero.usemoney -= 4000;
haveta[1].atk += 40;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "3":
if (Hero.usemoney > 5000 && haveta[2].level < 2 && level_numberof == 2)
{
Hero.usemoney -= 5000;
haveta[1].atk += 60;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "4":
if (Hero.usemoney > 6000 && haveta[3].level < 2 && level_numberof == 3)
{
Hero.usemoney -= 6000;
haveta[1].atk += 80;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "5":
if (Hero.usemoney > 7000 && haveta[4].level < 2 && level_numberof == 4)
{
Hero.usemoney -= 7000;
haveta[1].atk += 100;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
case "6":
if (Hero.usemoney > 10000 && haveta[5].level < 2 && level_numberof == 5)
{
Hero.usemoney -= 10000;
haveta[1].atk += 200;
haveta[1].level += 1;
WriteLine($"升级成功,你还剩{Hero.usemoney}元");
level_numberof++;
}
break;
}
}
public void Atk()
{
switch (haveta.Count)
{
case 1:
if (Monster.brushumonster[0].x>0&& Monster.brushumonster[0].x < 30)
{
Monster.brushumonster[0].hp -= haveta[0].atk;
}
break;
case 2:
if (Monster.brushumonster[0].x > 0 && Monster.brushumonster[0].x < 30)
{
Monster.brushumonster[0].hp -= (haveta[0].atk+=haveta[1].atk);
}
break;
case 3:
if (Monster.brushumonster[0].x>30 && Monster.brushumonster[0].x <50)
{
Monster.brushumonster[0].hp -=haveta[2].atk;
}
break;
case 4:
if (Monster.brushumonster[0].x > 30 && Monster.brushumonster[0].x < 50)
{
Monster.brushumonster[0].hp -= (haveta[2].atk += haveta[3].atk);
}
break;
case 5:
if (Monster.brushumonster[0].x > 50 && Monster.brushumonster[0].x < 90)
{
Monster.brushumonster[0].hp -= haveta[4].atk;
}
break;
case 6:
if (Monster.brushumonster[0].x > 50 && Monster.brushumonster[0].x< 90)
{
Monster.brushumonster[0].hp -= (haveta[4].atk += haveta[5].atk);
}
break;
}
}
}
class Hero
{
public static int usemoney=3000;
}
class Monster
{
public static List<Monster> brushumonster = new();//场上有的怪物列表
private int number_of;
private string appearance;//怪物的外观
public int hp;
public int x=0;
private const int y=14;
public void BrushMonster(Func<Monster> func)//刷怪机制
{
Monster monster = func();
brushumonster.Add(monster);
}
public void Move(List<Monster> monsters)//移动机制
{
void M(int number)
{
SetCursorPosition(monsters[number].x, y);//0,14
Write(monsters[number].appearance);
SetCursorPosition(monsters[number].x++, y);
Write(monsters[number].appearance);
}
for (int i = 0; i <2; i++)
{
M(i);
if (monsters.Count == 1)
{
i = 2;
}
}
if (brushumonster[0].x == 76)
{
//通过再一次覆盖的方法把之前打印出来的怪物覆盖为■或""
//制造出一种怪物尸体消失的假象
SetCursorPosition(x--, y);
Write("A");
monsters.RemoveAt(0);
x = 0;
SetCursorPosition(x, y);
}
if (monsters[0].hp <= 0)
{
Hero.usemoney += 300;
SetCursorPosition(monsters[0].x++, y);
Write(" ");
monsters.RemoveAt(0);
x = 0;
SetCursorPosition(x, y);
}
}//10--15
public Monster Wolf()
{
Monster wolf = new();
wolf.hp = 200;
wolf.appearance = "△";
wolf.x = 3;
return wolf;
}
public Monster Firepeople()
{
Monster firepeople = new();
firepeople.appearance = "▲";
firepeople.hp = 300;
firepeople.x = 0;
return firepeople;
}
public Monster Dinosaur()
{
Monster dinosaur = new();
dinosaur.x = 0;
dinosaur.appearance = "龙";
dinosaur.hp = 100;
return dinosaur;
}
}
class Map
{
public void Darwingmap()//绘制地图
{
SetCursorPosition(0,10);
Write("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
SetCursorPosition(0, 15);
Write("■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■");
SetCursorPosition(76, 11);
Write("A");
SetCursorPosition(76, 12);
Write("A");
SetCursorPosition(76, 13);
Write("A");
SetCursorPosition(76, 14);
Write("A");
SetCursorPosition(0,18);
Write("z键来买塔,x键来升级塔。在游玩过程中请按回车使程序运行");
// CursorVisible = tru;
}
public void DarwingTa()
{
switch (Ta.haveta.Count)
{
case 1:
SetCursorPosition(4,9);
Write(Ta.haveta[0].taappearance);
break;
case 2:
SetCursorPosition(4, 16);
Write(Ta.haveta[1].taappearance);
break;
case 3:
SetCursorPosition(40, 9);
Write(Ta.haveta[2].taappearance);
break;
case 4:
SetCursorPosition(40, 16);
Write(Ta.haveta[3].taappearance);
break;
case 5:
SetCursorPosition(60, 9);
Write(Ta.haveta[4].taappearance);
break;
case 6:
SetCursorPosition(60, 16);
Write(Ta.haveta[5].taappearance);
break;
}
}
}
最后介绍一个法国作家:圣●埃克苏佩里。
他这个人你不一定听过,但他写的小王子你也许有所耳闻
除了小王子,他还写过人类的大地,南线邮航
他生于法国里昂,1944年失踪
1994年,他被印在50法郎上