JAVA 面向对象编程练习(一个回合制的战斗游戏:战士,骑兵,法师,电脑互相攻击)

版权声明:本文为博主原创,未经允许不得转载 https://blog.csdn.net/Yangchenju/article/details/82917558

一. 小编有话说

前面一篇文章写了JAVA面向对象编程的思想,本文主要展示关于面向对象编程的实例(一个回合制的战斗游戏:战士,骑兵,法师,电脑互相攻击),小编的基础暂时薄弱,如此一来有助于更深入的理解和灵活的运用,以及打下坚实的基础。

二. 游戏的要求

  1. 定义一个描述战斗单位的类,此类必须包含以下成员变量:名称,生命值,攻击力,防御力,命中率。此类还必须包含以下成员方法:遭到攻击时的处理函数,阵亡时的处理函数。自行设计生命值,攻击力,防御力,命中率之间的关系。请自行设计各处理函数被执行时的提示信息。

  2. 此游戏中存在多种战斗角色,每种角色都是由要求1所定义的类派生出来的子类。每种角色类除了继承自父类的成员变量和函数之外,可以增加一些成员变量和成员函数,例如增加防御这一动作的处理函数。
    战斗角色例:
    战士,生命高,普通攻击敌人,攻击力中,防御力高
    骑兵,生命中,普通攻击敌人,攻击力高,防御力高
    法师,生命极低,法术攻击敌人,攻击力极高,防御力低

  3. 此游戏采用回合制,人对人或人对电脑。每个角色对象依次顺序被使用,游戏操作者通过选菜单的方式操作角色对象的攻击、攻击谁、防御等等动作。游戏以某方全体阵亡而结束。

  4. 游戏必须具有完备的提示信息,例如每个回合都要提示轮到那方的那名角色对象行动,每个回合菜单之前都必须显示敌我双方每一个角色对象的各种参数值,并且每个回合必须重新刷新显示屏幕上的提示内容等。

三. 编程前的准备

  1. 按上面的描述,该有5个.java文件:
  • 1个父类文件:GameUtil.java
  • 3个子类文件:Soilder.javaCavalry.javaMagian.java
  • 1个含执行入口的文件:GameStart.java
  1. 角色及其成员变量的设置
角色 生命值 攻击力 防御力 命中率
战士 100 10 12 80%
骑兵 80 10 12 70%
法师 50 20 5 75%
电脑 80 15 5 75%

四. 代码及详细注释

  1. GameUtil.java
/*描述战斗单位的类(父类)
 * 父类初始化值为电脑
 * 成员变量(5个):名称,生命值,攻击力,防御力,命中率
 * 方法函数3个:
 * 遭到攻击的处理函数
 * 阵亡时的处理函数
 * 对方没有打中的处理函数
 * 
 * author:@杨陈菊
 */

public class GameUtil {
	String name = "电脑";            //名称
	int life = 80;                  //生命值
	int attack = 15;                //攻击力
	int defend = 5;                 //防御力
	double hr = 0.75 ;              //命中率
	public int getLife() {
		return life;
	}
	public void setLife(int life) {
		this.life = life;
	}
	public int getAttack() {
		return attack;
	}
	public void setAttack(int attack) {
		this.attack = attack;
	}
	public int getDefend() {
		return defend;
	}
	public void setDefend(int defend) {
		this.defend = defend;
	}
	public double getHr() {
		return hr;
	}
	public void setHr(double hr) {
		this.hr = hr;
	}
	//遭到攻击时的处理函数
	public void fangyu(int attack) {
		int hurt = 0;              //受到的伤害
		int residue_life;          //剩余生命值
		if (die()) {               //调用下面的阵亡处理函数
			if(attack>defend) {    //对手攻击力大于自身防御力则受到伤害,否则受伤值为0
				hurt = attack-defend;
			}else {
				hurt = 0;
			}
				residue_life = life - hurt;         //每回合计算剩余生命值
				System.out.println(this.name+"做出了防御,受到"+hurt+"点伤害!");//打印受到多少伤害
				if(residue_life<0)
					residue_life = 0;
				System.out.println("还剩"+residue_life+"点生命值");   //打印剩余生命值
				life = residue_life;         //当前生命值
		}else {
			
		}
	}
	//阵亡时的处理函数,返回一个布尔值,代表是否死亡
	public boolean die() {
		boolean flag=true;    //初始化,代表活着
		if (life <= 0) {       //生命值小于等于0则阵亡
			System.out.println(this.name+"阵亡,游戏结束!");
			flag = false;
		}
		return flag;    //返回生存状态
	}
	//没有打中,躲开的处理函数
	public void dodge() {
		System.out.println("没有击中,"+this.name+"躲过一劫!");
	}
}

  1. Soilder.java
/*描述战士的类(子类)
 * 成员变量(5个):名称,生命值,攻击力,防御力,命中率
 * 1个函数:对方没有打中的处理函数(重写)
 * author:@杨陈菊
 */

//定义战士子类,继承父类GameUtil
public class Soilder extends GameUtil {
	
	public Soilder() {
		//初始化5个变量
		name = "战士";
		life = 100;
		attack = 10;
		defend = 12;
		hr = 0.7;
	}
	@Override
	public void dodge() {
		System.out.println(this.name+"一个后空翻,躲过一劫!");
	}
}

  1. Cavalry.java
/*描述骑兵的类(子类)
 * 成员变量(5个):名称,生命值,攻击力,防御力,命中率
 * 1个函数:对方没有打中的处理函数(重写)
 * author:@杨陈菊
 */

//定义骑兵子类,继承父类GameUtil
public class Cavalry extends GameUtil {

	public Cavalry() {
		//初始化骑士属性
		name ="骑兵";
		life = 80;
		attack = 15;
		defend = 12;
		hr = 0.75;
	}
	@Override
	public void dodge() {
		System.out.println(this.name+"身体一俯,逃过对方的攻击!");
	}
}

  1. Magian.java
/*描述法师的类(子类)
 * 成员变量(5个):名称,生命值,攻击力,防御力,命中率
 * 1个函数:对方没有打中的处理函数(重写)
 * author:@杨陈菊
 */

//定义法师子类,继承父类GameUtil
public class Magian extends GameUtil {

	public Magian() {
		//初始化战法师属性
		name = "法师";
		life = 50;
		attack = 25;
		defend = 5;
		hr = 0.75;
	}
	@Override
	public void dodge() {
		System.out.println(this.name+"轻轻一挥手,避开了对反的攻击!");
	}
}

  1. GameStart.java
    指定命中率详见我的另一篇文章:JAVA产生指定概率的随机数
/*游戏执行类,main
 * 1个方法:指定命中率
 * 4个对象:战士,骑兵,法师,电脑
 * 4个变量:角色,对手,对战双方,回合数
 * 1个函数:产生指定的命中率
 * author:@杨陈菊
 */
 /*
import GameUtil;   //引入父类(描述战斗单元的类)
import Soilder;    //引入战士的类
import Cavalry;    //引入骑兵的类
import Magian;     //引入法师的类
*/
import java.util.Random;//引入Random类
import java.util.Scanner;//导入java.util包下的Scanner类,以读取来自System.in的输入

public class GameStart {

	public static void main(String[] args) {
		Soilder soilder = new Soilder();    //创建一个战士对象
		Cavalry cavalry = new Cavalry();    //创建一个骑兵对象
		Magian magain = new Magian();       //创建一个法师对象
		GameUtil computer = new GameUtil(); //创建一个电脑对象
		Scanner input=new Scanner(System.in);//创建一个Scanner对象input
		//声明变量
		String role = "";    //声明变量cole,用于获取从控制台输入角色
		String opponent = "";//声明变量opponent,用于获取从控制台选择的对手
		String battle="";    //声明变量battle,用于选择对战过程
		int number = 0;      //用于记录回合数
		//提示玩家进行选择
		System.out.println("请选择一个角色,并输入角色编号:");
		System.out.println("A:战士");
		System.out.println("B:骑士");
		System.out.println("C:法师");
		role = input.nextLine();//获取玩家输入的角色选择
		System.out.println("请选择一个对手,并输入对手编号:");
		System.out.println("A:战士");
		System.out.println("B:骑士");
		System.out.println("C:法师");
		System.out.println("D:电脑");
		opponent = input.nextLine();//获取玩家选择的对手
		//角色和对手不能相同
		if(role.equals(opponent)) {//字符串之间的比较
			System.out.println("角色和对手不能相同,请重新选择对手:");
			opponent = input.nextLine();//重新获取从控制台选择的对手
		}
		//System.out.println(soilder.getAttack());
		/*
		 * 选择对战对象
		 */
		battle = role + opponent;  //用于对战双方角色限定
		switch(battle) {
			//战士对电脑
			case "AD": {
				System.out.println("");                   //空一行
				System.out.println("战士 VS 电脑");
				//int number = 0;       //用于记录回合数
				while(computer.die() && soilder.die()) {  //双方都活着,循环继续
					number++;            //循环一次自增1,表示回合数
					System.out.println("第"+number+"回合:");//每回合输出回合数
					if(mingZhong(soilder.getHr())==1) {    //战士打中电脑
						computer.fangyu(soilder.getAttack());//电脑做出防御
					}else {
						computer.dodge();//战士没有打中电脑,调用父类躲闪函数
					}
					if(mingZhong(computer.getHr())==1 && computer.getLife() > 0) {//电脑还活着,并且电脑打中了战士
						soilder.fangyu(computer.getAttack());      //战士做出防御
					}
					if(mingZhong(computer.getHr())==0 && computer.getLife() > 0) { //电脑还活着,但没有打中战士
						soilder.dodge();           //调用Soilder子类重写的躲闪函数
					}
				}
				break;
			}
			//骑兵对电脑
			case "BD":{
				System.out.println("");
				System.out.println("骑兵 vs 电脑");
				while(computer.die() && cavalry.die()) {   //双方都活着,循环继续
					number++;       //循环一次自增1,表示回合数
					System.out.println("第"+number+"回合:");//每回合输出回合数
					if(mingZhong(cavalry.getHr())==1) {    //骑骑兵打中电脑
						computer.fangyu(cavalry.getAttack());//电脑防御
					}else {
						computer.dodge();     //骑兵没有打中电脑,调用父类躲闪函数函数
					}
					if(mingZhong(computer.getHr())==1 && computer.getLife() > 0) {//电脑活着,打中骑兵
						cavalry.fangyu(computer.getAttack());    //骑兵防御
					}
					if(mingZhong(computer.getHr())==0 && computer.getLife() > 0) {//电脑活着,没有打中骑兵
						cavalry.dodge();      //调用Cavalry子类重写的躲闪函数
					}
				}
				break;
			}
			//法师对电脑
			case "CD":{
				System.out.println("");
				System.out.println("法师 vs 电脑");
				while(computer.die() && magain.die()) {      //双方都活着,循环继续
					number++;         //循环一次自增1,表示回合数
					System.out.println("第"+number+"回合:");  //每回合输出回合数
					if(mingZhong(magain.getHr())==1) {        //法师打中电脑
						computer.fangyu(magain.getAttack());  //电脑防御
					}else {
						computer.dodge();      //法师没有打中电脑,调用父类躲闪函数函数
					}
					if(mingZhong(computer.getHr())==1 && computer.getLife() > 0) {//电脑活着,打中法师
						magain.fangyu(computer.getAttack());    //法师防御
					}
					if(mingZhong(computer.getHr())==0 && computer.getLife() > 0) {//电脑活着,没有打中法师
						magain.dodge();    //调用Magain子类重写的躲闪函数
					}
				}
				break;
			}
			//战士对骑兵
			case "AB":{
				System.out.println("");
				System.out.println("战士 vs 骑兵");
				while(cavalry.die() && soilder.die()) {     //双方都活着,循环继续
					number++;   //循环一次自增1,表示回合数
					System.out.println("第"+number+"回合:");//每回合输出回合数
					if(mingZhong(soilder.getHr())==1) {    //战士打中骑兵
						cavalry.fangyu(soilder.getAttack());//骑兵防御
					}else {
						cavalry.dodge();  //战士没有打中骑兵,调用Cavalry子类重写的躲闪函数
					}
					if(mingZhong(cavalry.getHr())==1 && cavalry.getLife() > 0) {//骑兵当前生命值大于0(即活着),并且打中战士
						soilder.fangyu(cavalry.getAttack());    //战士防御
					}
					if(mingZhong(cavalry.getHr())==0 && cavalry.getLife() > 0) {//骑兵活着,没有打中战士
						soilder.dodge();   //调用Soilder子类重写的躲闪函数
					}
				}
				break;
			}
			//战士会法师
			case "AC":{
				System.out.println("");
				System.out.println("战士 vs 法师");
				while(magain.die() && soilder.die()) {     //双方活着,循环继续
					number++;    //循环一次自增1,表示回合数
					System.out.println("第"+number+"回合:");//每回合输出回合数
					if(mingZhong(soilder.getHr())==1) {     //战士打中法师
						magain.fangyu(soilder.getAttack());//法师防御
					}else {
						magain.dodge();   //战士没有打中法师,调用Magain子类重写的躲闪函数
					}
					if(mingZhong(magain.getHr())==1 && magain.getLife() > 0) {//法师活着,打中战士
						soilder.fangyu(magain.getAttack()); //战士防御
					}
					if(mingZhong(magain.getHr())==0 && magain.getLife() > 0) {//法师活着。未打中战士
						soilder.dodge();    //调用Soilder子类重写的躲闪函数
					}
				}
				break;
			}
			//骑兵对法师
			case "BC":{
				System.out.println("");
				System.out.println("骑兵 vs 法师");
				while(magain.die() && cavalry.die()) {     //双方或者,循环继续
					number++;   //循环一次自增1,表示回合数
					System.out.println("第"+number+"回合:");//每回合输出回合数
					if(mingZhong(cavalry.getHr())==1) {     //骑兵打中法师
						magain.fangyu(cavalry.getAttack());  //法师防御
					}else {
						magain.dodge();  //骑兵为打中骑兵,调用Magain子类重写的躲闪函数
					}
					if(mingZhong(magain.getHr())==1 && magain.getLife() > 0) {//法师活着,打中骑兵
						cavalry.fangyu(magain.getAttack());    //骑兵防御
					}
					if(mingZhong(magain.getHr())==0 && magain.getLife() > 0) { //法师活着,为打中骑兵
						cavalry.dodge();     //调用Cavalry子类重写的躲闪函数
					}
				}
				break;
			}
		}	
	}
	//实现指定命中率的函数
	public static int mingZhong(double hr) {
		Random r = new Random();
		int flag=0;//意味着,不攻击
		//随机产生[0;1],0出现的概率为hr,1出现的概率为1-hr
		int a = r.nextInt(100);//随机产生[0,100)的整数,每个数字出现的概率为1%
		if(a<(int) (hr*100)){ //前hr*100个数字的区间,代表的几率
			flag=1;//意味着攻击
		}else{
			flag=0;
		}
		return flag;
	}
}

五. 结果

  1. 编译

在这里插入图片描述

  1. 执行(由于图片过长,图中黄色部分为省略
    战士 VS 骑兵
    在这里插入图片描述
    战士 VS 法师
    在这里插入图片描述
    战士 VS 电脑
    在这里插入图片描述
    骑兵 VS 法师
    在这里插入图片描述
    骑兵 VS 电脑
    在这里插入图片描述
    法师 VS 电脑
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Yangchenju/article/details/82917558