1. 程式人生 > >JAVA 面向物件程式設計練習(一個回合制的戰鬥遊戲:戰士,騎兵,法師,電腦互相攻擊)

JAVA 面向物件程式設計練習(一個回合制的戰鬥遊戲:戰士,騎兵,法師,電腦互相攻擊)

一. 小編有話說

前面一篇文章寫了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個:
 * 遭到攻擊的處理函式
 * 陣亡時的處理函式
 * 對方沒有打中的處理函式
 * 
 * autor:@楊陳菊
 */

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個函式:對方沒有打中的處理函式(重寫)
 * autor:@楊陳菊
 */

//定義戰士子類,繼承父類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個函式:對方沒有打中的處理函式(重寫)
 * autor:@楊陳菊
 */

//定義騎兵子類,繼承父類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個函式:對方沒有打中的處理函式(重寫)
 * autor:@楊陳菊
 */

//定義法師子類,繼承父類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
/*遊戲執行類,main
 * 1個方法:指定命中率
 * 4個物件:戰士,騎兵,法師,電腦
 * 4個變數:角色,對手,對戰雙方,回合數
 * autor:@楊陳菊
 */
 /*
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. 編譯在這裡插入圖片描述
  2. 執行(由於圖片過長,圖中黃色部分為省略戰士 VS 騎兵 在這裡插入圖片描述 戰士 VS 法師 在這裡插入圖片描述 戰士 VS 電腦 在這裡插入圖片描述 騎兵 VS 法師 在這裡插入圖片描述 騎兵 VS 電腦 在這裡插入圖片描述 法師 VS 電腦 在這裡插入圖片描述