面向对象第二版本

项目---飞机大战

day01

面向对象:OO

面向对象的分析:OOA

面向对象的设计:OOD

面向对象的分析与设计:OOAD---拿高薪

面向对象的编程:OOP----你们以后所参与的


正课:

1.什么是类?什么是对象?

1)现实生活中存在很多很多的对象(东西),基于对象抽出了类

2)对象:软件中真实存在的单个的个体/东西

类:类型,类别,代表一类个体---自己所设计出来的一种数据类型(引用类型)

3)类是对象的模板,对象是类的具体的实例

4)类中包含:

4.1)对象所共有的属性/特征-----成员变量(数据)

4.2)对象所共有的行为/动作------成员方法

5)一个类可以创建多个对象

2.如何创建类?如何创建对象?如何访问成员?

类 对象

月饼模子 月饼

小敌机类---代表所有小敌机

小蜜蜂类---代表所有小蜜蜂


射击游戏需求:

1.所参与的角色:天空、英雄机、大小敌机、子弹、小蜜蜂

2.角色间的关系:

2.1)英雄机发射子弹,分单倍火力和双倍火力。

2.2)子弹射击敌人(小敌机、大敌机、小蜜蜂),若射击到了

2.2.1)子弹直接消失,敌人先爆破再消失

2.2.2)子弹打掉小敌机----玩家得1分

子弹打掉大敌机----玩家得3分

子弹打掉小蜜蜂---英雄机得奖励(1条命或40火力值)

2.3)敌人(小敌机、大敌机、小蜜蜂)可以和英雄机撞,若撞上了:

2.3.1)敌人先爆破再消失

2.3.2)英雄机减1条命,同时清空火力值-----当英雄机命数为0时,游戏结束

2.4)英雄机、大小敌机、子弹、小蜜蜂都在天空上飞


射击游戏第一天:

1.创建了6个对象类,同时创建了一个World窗口类并测试


day02

正课:

1.方法的签名:方法名称+参数列表

2.方法的重载(overload):

1)发生在一个类中,方法名称相同,参数列表不同,方法体不同

2)编译器在编译时,会根据方法的签名自动绑定调用的方法

注意:1.重载与返回值的类型无关!

2.重载与参数名称无关!

3.构造方法:

1)给成员变量赋初值

2)与类同名,没有返回值类型,连void都不允许有

3)创建(new)对象时被自动调用

4)若自己没有定义构造方法,则编译器会默认提供一个无参构造方法;若自己定义了构造方法,则不再默认提供无参构造方法。

5) 构造方法也是可以支持重载的

4.this:指代当前对象,哪个对象调用方法它就代表哪个对象

this的用法:

1)this.成员变量名 --- 访问成员变量(成员变量与局部变量同名时,this不能省略)

2)this.方法名---------调用方法(一般都省略不写)

3)this()---------------调用构造方法

注意: 1.只能用在方法中,方法中访问成员变量之前默认有个this.

2.成员变量和局部变量是可以同名的--用的时候采取的是就近原则

3.当成员变量与局部变量同名时,此时若想访问成员变量,则this不能省略

5.内存管理----------null:由JVM来管理的

1)堆:存储new出来的对象(包括成员变量【类中方法外的变量】)

2)栈:局部变量【方法内部的变量】(包括方法的参数)

3)方法区:class字节码文件(包括方法)

数组也是一个对象----因为数组也是new出来的---凡是new出来的都是对象,统统存放在堆内存中


射击游戏第二天:

1.给6个对象类添加构造方法,并测试


day03

正课:

1.null:表示空,没有指向任何对象

若引用的值为null,则该引用不能再进行任何操作了,否则就发生NullPointerException空指针异常

2.引用类型数组:

3.继承:

1)作用:代码复用

2)通过extends关键字来实现继承

3)超类/父类:派生类所共有的属性和行为

派生类/子类:派生类所特有的属性和行为

4)派生类继承超类后,派生类具有:派生类的+超类的

5)一个超类可以有多个派生类,但是一个派生类有且只能有一个超类

6)继承具有传递性

7)Java规定:构造派生类之前必须先构造超类;

在派生类的构造方法中,若没有调用超类的构造方法,则默认super()调用超类的无参构造

在派生类的构造中,若自己调用了超类的构造,则不再默认提供

4.super:指代当前对象的超类对象/父类对象

super的用法:

4.1)super.成员变量名-----------访问超类的成员变量

4.2)super.方法名----------------访问超类的方法

4.3)super.()------------------访问超类的构造方法


射击游戏第三天:

1.设计小敌机数组、大敌机数组、小蜜蜂数组、子弹数组,并测试

2.设计FlyingObject超类/父类,6个对象类作为其子类/派生类继承该类

3.在FlyingObject设计2个构造方法,6个对象类分别调用


day04

正课:

1.引用类型变量之间划等号:

1)指向同一个对象

2)通过一个引用对数据的修改会影响另一个引用对数据的访问

例子:我出差,我留一把备用钥匙给我弟弟妹妹,结果他们整来一堆狐朋狗友来我家一顿霍霍;我回家后看到的是我出差前收拾好的景象还是给我霍霍完的?

基本类型变量之间划等号:

1)赋值

2)对一个变量的修改不会影响另一个变量

例子:身份证复印件,我拿着身份证原件,别人拿着我的复印件,无论怎么改,怎么坏我,对我有影响吗?

2.向上造型:

1)超类型的引用指向了派生类的对象

2)能点出什么,看引用的类型【编译看左边】


射击游戏第四天:

1.将小敌机数组、大敌机数组和小蜜蜂数组,组合成为FlyingObject数组,并测试


day05

正课:

1.方法的重写(override):重新写、覆盖

1)发生在父子类中,方法名相同,参数列表相同,但方法体不同

2)重写方法被调用时,看对象的类型(new的是谁就是谁在调用)。【运行看右边】

3)重写需遵循“两同两小一大”原则:---了解,一般情况都是一模一样的

3.1)两同:

3.1.1)方法名相同

3.1.2)参数列表相同

3.2)两小:

3.2.1)派生类方法的返回值类型小于或等于超类方法的

3.2.2)派生类方法抛出的异常小于或等于超类方法的

3.3)一大:

3.3.1)派生类方法的访问权限大于或等于超类方法的

2.重写与重载的区别---------常见面试题

2.1)重写(override):

2.1.1)发生在父子类中/超类和派生类中/具有继承关系的两个类中,方法名相同,参数列表相同,方法体不同/方法内部逻辑不同。

2.1.2)遵循“运行期绑定”,看对象的类型来绑定方法(看具体的指向类型,即=右边,运行看右边)

2.2)重载(overload):

2.2.1)发生在一个类中,方法名相同,参数列表不同,方法体不同。【仅仅只有方法名相同,其他一律不相同】

2.2.2)遵循“编译期间绑定”,看参数/引用的类型来绑定方法【对象能不能通过.来调用方法,即在编译期间,要想语法不报错,先看的是=左边的引用类型中是否存在该方法;若存在,则编译通过。在运行时,再去根据你所传入的参数去具体执行方法,可能是父类中的方法/也可能是子类中重写的方法。】

3.package:

1)作用:避免类的命名冲突

2)包名可以有层次结构类的全称:包名.类名

3)同包中的类不能同名,不同包中的类可以同名

4)建议:包名所有字母都小写

import:

1)同包中的类可以直接访问,不同包中的类不能直接访问;若想访问只有如下两种方式:

1.1)先import声明类再访问类---建议

1.2)类的全称--------------------不建议

4.访问控制修饰符:---数据(变量)私有化(private),行为(方法)公开化(public)

1)public:公共的,任何类

2)private:私有的,本类

3)protected:受保护的,本类、派生类和同包类

4)默认的:什么都不写,本类,同包类

说明:

1)类的访问修饰权限只能是public和默认的

2)类中成员的访问权限上述皆可

5.final:最终的,不可改变的,单独应用机率低

1)修饰变量:变量不能被改变

2)修饰方法:方法不能被重写

3)修饰类:类不能被继承


射击游戏第五天:

1.在6个对象类中重写step()移动方法

2.给类中成员添加访问权限控制修饰符

3.画窗口:----在World类中

1)导包:javax.swing.JFrame+JPanel

2)设计World类--继承JPanel类

3)复制粘贴代码


Day06

正课:

1.static:静态的

1)静态变量:

1.1)由static修饰

1.2)属于类的,存储在方法区中,只有一份

1.3)常常通过类名点来访问

1.4)何时用:所有对象所共享的数据(图片、音频、视频等)

2)静态方法:

2.1)由static修饰

2.2)属于类的,存储在方法区中,只有一份

2.3)常常通过类名点来访问

2.4)静态方法中没有隐式的this传递,所以静态方法中不能直接访问实例成员

2.5)何时用:方法的操作与对象无关

3)静态块/静态代码块:

3.1)由static修饰

3.2)在类被加载期间自动执行,因为类只被加载依次,所以静态块只执行一次

3.3)何时用:初始化/加载静态资源(图片、音频、视频等)

2.static final:静态常量,应用率高

1)必须声明同时初始化

2)通过类名点来访问,不能被改变

3)建议:常量名所有字母都大写,多个单词之间用_分隔

4)编译器在编译时会将常量直接替换成为具体的值,效率高

5)何时用:数据永远不变,并且经常使用

3.抽象方法:

1)由abstract修饰

2)只有方法的定义,没有具体的实现(连{}都没有)

4.抽象类:

1)由abstract修饰

2)包含抽象方法的类必须是抽象类

3)抽象类不能被实例化(不能new对象)

4)抽象类是需要被继承的,派生类:---换言之,一个类是抽象类就不可能没有子类,虽然语法层面可以,但是实际开发中这么做是毫无意义的!

4.1)重写抽象类中的所有抽象方法---变不完整为完整

4.2)也声明为抽象类---仅仅语法层面,实际开发中不可能这么干!

常见面试题:

1.派生类反正需要重写,那么抽象方法可否在超类中删除?若不能,为什么?存在的意义?

1.答:当使用多态对象【向上造型】时,通过超类/父类的引用能够点出来【访问】--但是最终具体调用的还是派生类重写之后的方法----【编译看左边,运行看右边】

2.不设计成抽象方法,就设计为普通方法,为什么不可以?设计抽象方法的意义?

2.答:java中,方法可以被重写,也可以不被重写。若把step()设计为普通方法,则派生类中可以重写也可以不重写;这样就达不到统一管理的效果了,设计为抽象方法,在语法层面就强制了我们所有的派生类必须重写该方法,这是一种开发规范目的为了加限制、作统一管理。

5)抽象类的意义:

5.1)封装派生类所共有的属性和行为-----代码复用

5.2)为所有派生类提供统一的类型-------向上造型

5.3)可以包含抽象方法,为所有派生类提供统一的入口

派生类的具体实现不同,但入口是一致的

但是要注意一下这种情况:以该项目为例:

FlyingObject f;//正确,因为FlyingObject是一个类,类就是一个数据类型,只要是数据类型就能够声明变量。

FlyingObject[] fs = new FlyingObject[3];//正确,FlyingObject是一个数据类型,只要是数据类型就能声明该数据类型的数组对象。---创建FlyingObject数组对象

new FlyingObject();//错误,抽象类不能被实例化----这是在创建FlyingObject对象!!!区分!


射击游戏第六天:

1.设计Images图片工具类来准备图片

2.设计窗口的宽和高为常量,适当地方做修改

3.设计超类中的step()为抽象方法,从而引发超类也要跟着改为抽象类


Day07

正课:

1.成员内部类:了解即可,应用率极低

1)类中套类,外面的称为外部类Outer,里面的称为内部类Inner

2)内部类通常只服务于外部类,对外不具备可见性

3)内部类对象通常是在外部类中创建的

4)内部类中可以直接访问外部类的成员(包括私有的)---想象你家的房间

在内部类中有个隐式的引用指向了创建它的外部类对象。


射击游戏第七天:

1.画对象:

1)想画对象得需要先获取对象的图片,每个对象都能获取图片,意味获取图片为对象的共有行为,所以将获取图片的方法设计在超类中,每个对象获取图片的行为都是不一样的,所以设计为抽象方法。---具体步骤:

1.1)在FlyingObject中,设计抽象方法getImage()用于获取对象的图片

2)获取图片时,需要去考虑对象的状态,因为在不同状态下获取图片的方式是不同的;每个对象都有状态,意味着状态为对象所共有的属性,所以设计在超类中,状态一般都是固定的,所以都设计为常量,同时设计一个state变量来表示当前的状态。----具体实现步骤:

2.1)在FlyingObject中,设计三个常量LIFE、DEAD、REMOVE,设计state变量表示当前状态。

2.2)状态有了,还需要判断状态,每个对象都得进行判断,意味着判断状态为共有行为,所以也要设计在超类中,每个对象判断状态的方式都是一样的,所以设计为普通方法即可。---具体的实现步骤:

--在FlyingObject中设计isLife()、isDead()和isRemove()来判断对象的状态。

不考虑爆破的话,两种状态:

1.活着的:

2.死了的:

考虑爆破的话,三种状态:

1.活着的:

2.死了的:(没有死彻底,还要爆破)

3.删除的:

3)重写getImage()获取图片

3.1)天空Sky,直接返回sky图片即可 state==LIFE

3.2)子弹Bullet:

3.2.1)若活着的,直接返回bullet图片即可

3.2.2)若死了的,直接删除(不返回图片)

3.3)英雄机Hero:

3.3.1)若活着的,直接返回heros[0]和heros[1]的来回切换

3.4)小敌机Airplane:

3.4.1)若活着的,直接返回airs[0]和airs[1]的来回切换

3.4.2)若死了的,返回airs[2]到airs[5]的轮换,5后删除(不返回图片)

3.5)大敌机BigAirplane:

3.5.1)若活着的,直接返回bairs[0]和bairs[1]的来回切换

3.5.2)若死了的,返回bairs[2]到bairs[5]的轮换,5后删除(不返回图片)

3.6)小蜜蜂Bee:

3.6.1)若活着的,直接返回bees[0]和bees[1]的来回切换

3.6.2)若死了的,返回bees[2]到bees[5]的轮换,5后删除(不返回图片)

4)图片有了就可以开画了,需要往窗口上画,所以在窗口World类中重写paint()方法实现画对象。

步骤: 1.抽象方法getImage()获取图片

2.准备状态常量、判断状态

3.重写getImage()方法

4.在World类中重写paint()


day08

正课:

理论知识:

1.匿名内部类:

1)若想创建一个类的对象,并且对象只被创建一次;此时该类不必命名,称为匿名内部类---优点:代码结构更加简洁

2)问:内部类有独立的.class字节码文件吗?----常见面试题

答:有


项目功能实现:

1.敌人入场:---------------定时发生的

敌人对象是由窗口产生的,所以将创建敌人行为设计在窗口World类中

2.子弹入场:---------------定时发生的

子弹对象是由英雄机发射出来的,所以将创建子弹的行为设计在英雄机Hero类中

3.飞行物移动:-------------定时发生的

飞行物移动是所有派生类所共有的行为,所以将飞行物移动的行为设计在超类FlyingObject类中

定时器:Timer

timer.schedule(TimerTask,long,long);---计划表方法

第一个10:程序启动到第一次触发的时间间隔

第二个10:第一次触发到第二次触发的时间间隔(上下两次的间隔)

举例:现在晚上7点整---定闹钟(每天早上7点的闹钟)

timer.schedule(A,12小时的毫秒数【从现在晚7点到明天早上7点要12小时】,24小时的毫秒数【以后每次上下两次的时间就是一天24h】);

TimerTask它是一个抽象类,是不能new对象的,其内部包含抽象方法run,在run中执行需要定时的任务。--类似线程中的run方法。

线程:

业务功能的实现套路:

1.先写行为:

1.1)若为派生类所特有的行为,就将方法设计在特定的类中

1.2)若为派生类所共有的行为,就将方法设计在超类中

2.窗口调用:

2.1)定时触发的,在定时器中调用

2.2)事件触发的,在监听器中调用

paint属于多线程并发,当我们生成敌人对象后,发现看不到。这是因为我们刚开始调用paint时,还没有生成任何敌人对象,而paint方法我们只调用了一次。

解决:再次调用;

paint的调用方式:

1.Frame.setVisible(true);

2.直接调用repaint()


射击游戏第八天:

1.敌人入场:

1)敌人对象是由窗口产生的,所以在World窗口类中设计nextOne()方法,来生成敌人对象

2)敌人入场为定时发生的,所以nextOne()方法要由定时器调用。在run中调用enterAction()实现敌人入场。

设计一个enterAction方法,其中:

2.1)先定义一个计数变量

2.2)数组扩容

2.3)将生成的对象存入到数组中

2.子弹入场:

1)子弹是由英雄机发射出来的,所以在Hero中设计shoot()生成子弹对象

2)子弹入场为定时发生,所以在run()中调用shootAction()实现子弹入场

3)在shootAction中:

3.1)每15*10ms,获取子弹数组对象bs,bullets扩容,将bs追加到bullets的末尾

3.飞行物移动:

1)飞行物移动为派生类所共有的行为,所以在超类FlyingObject中设计抽象step()移动,派生类中重写

2)飞行物移动为定时发生的,所以在run中调用stepAction()实现飞行物移动。

在stepAction中:

天空动、遍历敌人敌人动,遍历子弹子弹动


Day09

正课:

1.接口:


射击游戏第九天:

1.英雄机随着鼠标移动:

1)英雄机随着鼠标移动为英雄机特有的行为,所以在Hero类中设计moveTo()来实现英雄机随着鼠标移动

2)英雄机随着鼠标移动---事件触发的(swing相关)--了解;所以在侦听器中重写mouseMoved()鼠标移动事件

在mouseMoved()中:

获取鼠标的x和y坐标,调用Hero类对象的moveTo()方法,实现随鼠标移动

2.1)swing中的事件:

2.1.1)事件:发生了一件事

事件 处理

鼠标点击 启动状态改为运行状态

鼠标移动 英雄机随着鼠标移动

鼠标移出 运行状态改为暂停状态

鼠标移入 暂停状态改为运行状态

2.1.2)事件处理:事件发生后做的操作

2.1.3)侦听器:不需要掌握 MouseAdapter

2.1.3.1)有一个侦听器对象

2.1.3.2)把侦听器装到面板上去

程序的状态:

1)启动状态(车打着火了)

2)运行状态(车正常行驶)

3)暂停状态(红灯停车等待)

4)游戏结束(停车熄火拔钥匙)

2.解决运行时间长卡的问题,内存溢出-----删除越界的敌人和子弹

1)在FlyingObject类中设计outOfBounds()检测敌人是否越界,在Bullet中重写outOfBounds()检测子弹是否越界

2)删除越界的敌人和子弹为定时发生的,所以在run中调用outOfBoundsAction()删除越界的敌人和子弹

在outOfBoundsAction()中:

声明不越界敌人/子弹数组,遍历enemies/bullets数组,判断若不越界,则将对象装到不越界数组中,最后将不越界数组复制到原数组中

3.设计接口:

1)接口是一种引用数据类型

2)由interface定义

3)只能包含常量和抽象方法---jdk8之后,可以有普通方法,但是必须前面有default修饰

4)接口不能被实例化

5)接口是需要被实现的,实现类:必须重写所有抽象方法

6)一个类可以实现多个接口【干爹可以有多个】,用逗号分隔;若既要继承又要实现时,应该先继承后实现。【先管亲爹再管干爹!】

7)接口可以继承接口

接口的好处:

扩展:

软件的设计规则:

1.将派生类所共有的属性和行为,抽取到超类中----抽共性

2.所有派生类的行为都一样,设计为普通方法

所有派生类的行为都不一样,设计为抽象方法

3.将部分派生类共有的行为,抽到接口中

接口是对继承单根型的扩展

接口实现了代码的松耦合,增加了开发的灵活性。----实现多继承

举例子:子弹射击敌人

子弹射击敌人,若打中了:

1.打掉小敌机,玩家得1分

2.打掉大敌机,玩家得3分

3.打掉小蜜蜂,英雄机得奖励(1条命或40火力值)

得分行为是小敌机和大敌机所共有的

得奖励行为是小蜜蜂和大黄蜂所共有的


day10

射击游戏第十天:

1.敌人与子弹的碰撞:

1)在FlyingObject中设计hit()检测敌人与子弹的碰撞、goDead()飞行物去死

在Hero中设计addLife()增命、addFire()增加火力值

2)敌人与子弹的碰撞是定时发生的,所以在run()中调用bulletBangAction()实现敌人与子弹的碰撞

在bulletBangAction()中:

2.1)遍历子弹和敌人,判断类型award还是enemy

2.2)判断是否活着并且是否撞击上了

2.2.1)若撞上了:

2.2.1.1)敌人去死,子弹去死

2.2.1.2)若被撞的是小敌机-------玩家得1分

若被撞的是大敌机------玩家得3分

若被撞的是小蜜蜂------英雄机得1条命/40火力值

若被撞的是大黄蜂-----英雄机得2条命/80火力值

碰撞是谁的行为----敌人的还是子弹的?---皆可

2.画分,命和关卡:

1)在Hero中添加分、命属性的getter,获取英雄机的命数和当前得分

2)在World类的paint()中,画上即可


正课:

1.多态:

1)意义:

1.1)同一类型的引用,在指向不同的对象时,有不同的实现---行为的多态:cut()、step()、getImage()...

1.2)同一个对象,被造型为不同的类型时,有不同的功能-----对象的多态:你我他水

2)向上造型:

2.1)超类型的引用指向派生类的对象

2.2)能造型成为的数据类型有:超类+所实现的接口

2.3)能点出来什么,看引用的类型【编译看左边】

3)强制类型转换,成功的条件只有两种:

3.1)引用所指向的对象,就是该类型

3.2)引用所指向的对象,实现了该接口或继承了该类

4)强转时若不符合如上两个条件,则发生ClassCastException类型转换异常

建议:强转之前先通过instanceof来判断引用的对象是否是该类型


Day11

正课:

1.内存管理:

由JVM来管理的

1)堆:

1.1)存储所有new出来的对象(包括实例变量)

1.2)垃圾:没有任何引用所指向的对象

垃圾回收器(GC):不定时到堆内存中清扫垃圾,回收过程是透明的,隐式的(看不到);不一定一发现垃圾就立即回收,通过调用System.gc()可以建议虚拟机尽快来调度GC来回收。--想象你去酒店,打扫房间的阿姨(GC),System.gc()相当你忍无可忍给前台打电话,让阿姨尽快来打扫房间。

1.3)内存泄露:不再使用的内存没有被及时地回收,严重的泄露会导致系统的崩溃

建议:不再使用的对象及时将引用设置为null

1.4)实例变量的声明周期:

创建(new)对象时存在堆内存中,对象被回收时一并被回收

2)栈:

2.1)存储正在调用的方法中的局部变量(包括方法的参数)

2.2)调用对象时会在栈中为该对象分配一块对应的栈帧,栈帧中存储方法中的局部变量(包括方法参数);当方法调用结束时,栈帧被清除,局部变量(包括方法参数)一并被清除

3)方法区:

面向对象总结:


射击游戏第十一天(最后一天):

1.英雄机与敌人的碰撞:

1)借用FlyingObject中的hit()碰撞检测、参数类型决定了和谁撞、goDead()去死

在Hero中设计substractLife()减命、clearFire()清空火力值

2)敌人与英雄机的碰撞为定时发生的,所以在run()中调用heroBangAction()实现英雄机与敌人撞

在heroBangAction()中:

遍历敌人得敌人,判断都活着并且撞上了:

敌人去死,英雄机减命并清空火力值

2.检测游戏结束:

1)借助于Hero的getLife()获取当前英雄机的命数

2)检测游戏是否结束也为定时发生的,所以在run()中调用checkGameOverAction()检测游戏结束

在checkGameOverAction()中:

当英雄机的命数<=0时,表示游戏结束,则

3.添加游戏暂停、运行状态---补充鼠标事件

4.画状态:

1)在World中设计START、RUNNING、PAUSE、GAME_OVER四种状态,同时设计sate变量表示当前状态,默认为START启动状态。在Imagaes中设计start、pause、gameover三个状态图,在static块中赋值;在World类的paint()中设计在不同的状态下画不同的图片。

2)设计run()中那一堆action,仅仅在运行状态时运行;设计英雄机随鼠标移动,仅仅在运行状态时执行。

3)重写mouseCliked()鼠标点击:启动状态时变运行状态,游戏结束状态时,先清理战场后变启动状态。

重写mouseExited()鼠标移出:运行变暂停

重写mouseEntered()鼠标移入:暂停变运行

若撞上了:

1.敌人去死

2.英雄机减1条命,同时火力值清零

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Y特奈特

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值