重温了黑马的这个小程序
首先介绍一下:相当于一个小游戏,你打我一下,我打你一下;中间经历一些来回,最终根据血量的大小来判断谁输谁赢,实话讲黑马整个课在这个之前的题目没有什么难度,这个不难,但有很多小知识点忘记,以此文总结一下。
知识点梳理
1、拿到这个题目的时候需要先思考,和前面的都写在单独一个类中的有什么区别?如果全部写在一个类,所有功能(角色属性、攻击逻辑、游戏流程)可能集中在一个类中,导致代码冗长,难以实现复杂的游戏系统(如继承、多态),如不同角色的特殊技能。
2、所以要分离主类(GameTest)和业务类(Role),继续思考如何界定里面?
3、大方向是:先写业务类(里面的多个角色实例(如乔峰、摩智)均可复用)
- 首先先带着数据类型和公私有去定义角色的属性(名字、血量、性别、状态...)
- 然后就是利用快捷键(Fn+Alt+insert去调出无参和全参的构造函数<初始化对象>及getset方法)
- 最基本的处理完成后,就要思考自定义方法了(attack)和(showRoleInfo)。
4、对于set和get方法
set 方法:用于修改成员变量的值,需要参数,因为 set 方法的目的是设置成员变量的值,所以它需要一个参数来接收新的值。
- 比较特殊的是face,这个对象得随机生成,构造函数中也不同于其他属性那样直接赋值 this.某=某,它需要在set里面修改。
- 具体操作也是利用随机索引,调用提前在类中定义的描述男女两长相数组的索引,注意不要忘记写 this.某 = 数组名 [ 随机产生的索引 ] 。
public void setFace(char gender) {Random r = new Random();//长相是随机的if(gender=='男'){int index = r.nextInt(boyfaces.length);this.face = boyfaces[index];}else if(gender=='女'){int index = r.nextInt(girlfaces.length);this.face = girlfaces[index];}else {this.face = "非男非女";}}
get 方法:用于读取成员变量的值。
5、第一个自定义方法attack,目的是实现一个角色对另一个角色的攻击行为,需要一个 role 类型的参数来表示被攻击的角色。
- role.getName():获取被攻击角色的名字
- this.getName():获取当前攻击角色的名字,this是方法的调用者(在gametest中调用)
public void attack(Role role){//随机攻击效果Random r1 = new Random();int index = r1.nextInt(attack_esc.length);String kongfu = attack_esc[index];//输出一个攻击的效果System.out.printf(kongfu,this.getName(),role.getName());System.out.println("");//造成的随机伤害Random r = new Random();int hurt = r.nextInt(20)+1;//修改一下挨揍人的血量int remainBlood = role.getBlood()-hurt;//剩余血量remainBlood = remainBlood<0?0:remainBlood; //验证剩余的血量role.setBlood(remainBlood);if(remainBlood>90){System.out.printf(injureds_esc[0],role.getName());}else if(remainBlood>60){System.out.printf(injureds_esc[1],role.getName());}else {System.out.printf(injureds_esc[2],role.getName());}System.out.println("");// //this是方法的调用者
// System.out.println(this.getName()+"打了"+role.getName()
// +"一下,造成了"+hurt+"伤害,"+"\n"+
// role.getName()+"还剩"+remainBlood+"血量");}
- 想要实现随机攻击效果,首先需要在方法之前写一个字符串数组,想要生动形象的调用名词就需要使用到 printf(允许你按照指定的格式输出文本),在方法中使用随机索引来调用一个攻击效果。System.out.printf (随机攻击的数组名,第一个% this.getName(),第二个% role.getName());
- 同样的想要输出一个受伤描述,这个是根据剩余血量的大小(在方法中定义的变量)来决定的,输出是也是使用 printf。System.out.printf ( 被攻击状态名 [数组中第几个值根据血量大小],role.getName());
格式说明符 | 作用 | 示例 |
---|---|---|
%d | 格式化整数 | int num = 10; |
%s | 格式化字符串 | String str = "hello"; |
%f | 格式化浮点数 | double d = 3.14159; |
%c | 格式化字符 | char c = 'A'; |
%b | 格式化布尔值 | boolean b = true; |
6、第二个方法showRoleInfo,不需要参数,因为它只操作当前对象自身的属性,不需要外部输入,调用的时候只需要写出对应的get返回值即可。
7、写完业务类的属性、并对属性的构造函数和对应方法写完之后,就要写一个test类,这个类的目的是作为程序入口,负责创建角色、控制游戏流程,不涉及角色内部实现。两个类的两者职责分离,修改其中一个不会影响另一个。
8、在test类中,首先主要对应上一个类中的构造函数创建角色 上一个类名 r1 = new 上一个类名(逗号隔开分别传入构造函数中的参数);
9、在该类中可以利用上面构造的角色名调另一个类中的方法 调用者对象.方法名(方法参数),如果在调用方法中有对应的限制比如是否小于了0。
全部代码
Role类:
import java.util.Random;public class Role {private String name;private int blood;private char gender;private String face;String[] boyfaces = {"风流倜傥","气宇轩昂","相貌英俊"};String[] girlfaces = {"风华正茂","清秀","身材较好"};//攻击描述String[] attack_esc = {"%s用牛角尖刺中%s","%s用小刀砍中%s","%s用小棒打中%s"};//受伤描述String[] injureds_esc = {"结果%s被攻击,","结果%s被打倒","结果%s被打中"};public Role(String name, int blood, char gender) {this.name = name;this.blood = blood;this.gender = gender;//随机长相setFace(gender);}public Role() { }public char getGender() {return gender;}public void setGender(char gender) {this.gender = gender;}//get 方法:用于读取成员变量的值。public String getFace() {return face;}//set 方法:用于修改成员变量的值。//set 方法需要参数:因为 set 方法的目的是设置成员变量的值,所以它需要一个参数来接收新的值。public void setFace(char gender) {Random r = new Random();//长相是随机的if(gender=='男'){int index = r.nextInt(boyfaces.length);this.face = boyfaces[index];}else if(gender=='女'){int index = r.nextInt(girlfaces.length);this.face = girlfaces[index];}else {this.face = "非男非女";}}public String[] getBoyfaces() {return boyfaces;}public void setBoyfaces(String[] boyfaces) {this.boyfaces = boyfaces;}public String[] getGirlfaces() {return girlfaces;}public void setGirlfaces(String[] girlfaces) {this.girlfaces = girlfaces;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getBlood() {return blood;}public void setBlood(int blood) {this.blood = blood;}//定义一个方法用于攻击别人,方法需要一个Role参数:因为需要指定攻击的目标角色。//role.getName():获取被攻击角色的名字。//this.getName():获取当前攻击角色的名字。// this是方法的调用者即 this.getName// role也就是参数,是挨揍的人即 role.getNamepublic void attack(Role role){//随机攻击效果Random r1 = new Random();int index = r1.nextInt(attack_esc.length);String kongfu = attack_esc[index];//输出一个攻击的效果System.out.printf(kongfu,this.getName(),role.getName());System.out.println("");//造成的随机伤害Random r = new Random();int hurt = r.nextInt(20)+1;//修改一下挨揍人的血量int remainBlood = role.getBlood()-hurt;//剩余血量//验证剩余的血量remainBlood = remainBlood<0?0:remainBlood;//修改挨揍人的血量role.setBlood(remainBlood);if(remainBlood>90){System.out.printf(injureds_esc[0],role.getName());}else if(remainBlood>60){System.out.printf(injureds_esc[1],role.getName());}else {System.out.printf(injureds_esc[2],role.getName());}System.out.println("");// //this是方法的调用者
// System.out.println(this.getName()+"打了"+role.getName()
// +"一下,造成了"+hurt+"伤害,"+"\n"+
// role.getName()+"还剩"+remainBlood+"血量");}
//showRoleInfo 方法不需要参数:因为它只操作当前对象自身的属性,不需要外部输入。public void showRoleInfo(){System.out.println("姓名为:"+getName());System.out.println("血量为:"+getBlood());System.out.println("性别为:"+getGender());System.out.println("长相为:"+getFace());}
}
GameTest类:
public class GameTest {public static void main(String[] args) {Role r1 = new Role("乔峰",100,'男');Role r2 = new Role("摩智",100,'男');//展示角色信息r1.showRoleInfo();r2.showRoleInfo();//不知道要打击多少轮,所有要用whilewhile (true){r1.attack(r2);//判断一下剩余血量if (r2.getBlood()==0){System.out.println(r1.getName()+" ko "+r2.getName());break;}r2.attack(r1);if(r1.getBlood()==0){System.out.println(r2.getName()+" ko "+r1.getName());break;}}}
}