用C#制作塔防游戏

有点简陋,呵呵。

首先一个塔防游戏的主要大类肯定是塔类,怪物类以及地图类了。

塔类代码:

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法郎上

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值