[Java教程]17.實戰,趣味猜拳小遊戲

推薦一波我寫的任務管理軟件(持續擴展完善)

主要功能可以每天規劃任務,並查看今天還剩下多少秒,以及總完成率.

CSDN下載:https://download.csdn.net/download/qq_41806966/12545118

需要源碼可以去我的Github:https://github.com/1711680493/Application

裏面的ShendiTaskManager項目

界面圖

 


Java教程專欄:https://blog.csdn.net/qq_41806966/category_9929686.html

hello,I'm shendi

本節將製作一個差不多的猜拳小遊戲.


目錄

功能定義(策劃)

功能實現

主界面

編譯編碼問題解決

運行查看

普通猜拳

貨幣猜拳

挑戰關卡

處理升級

商城

修復一個bug

抽獎

一猜到底

當前屬性

揹包

源碼(所有類)

FingerGuessing 主類

Function功能類

Game遊戲信息類

OutUtils輸出信息類

 Player角色信息類

MyArray之前寫的可變長度數組類,這裏不提供,請如果需要請看之前文章

總結


功能定義(策劃)

我們要完成一個還像樣的猜拳遊戲,當然不能單單隻有猜拳這個功能,那麼簡單就失去了練習的意義了.

首先策劃一下,要做一個像樣的猜拳小遊戲.

我們寫的是控制檯程序(文字遊戲),所以功能的豐富更重要.

首先,我們需要在猜拳玩法的基礎上定義格外的玩法.

  • 主要的玩法,與人機對戰猜拳.
  • 貨幣玩法(*一*,搏一搏,單車變摩托)
    • 默認有100金幣,金幣不可爲負數
  • 關卡玩法(有血量,通過猜拳來攻擊,進行扣血,勝利獲取經驗金幣等,失敗無損失)
    • 通過一定算法 可以無限關卡 越往後越難...
      • 血量=關卡*關卡
      • 攻擊力=取隨機數,區間爲 (0,關卡*關卡]
      • 防禦力=取隨機數,區間爲 [0,關卡*關卡]
    • 戰鬥失敗獎勵少量經驗和金幣,隨機數,區間[0,100]
    • 關卡玩法,回合制,每一回合隨機出攻擊拳,猜中就可攻擊對方
    • 擴展玩法(增加傷害的道具等,有興趣可以自己進行擴展)
  • 屬性機制 默認爲 100 血量,10攻擊,0防禦,1級.
  • 等級玩法(級別越高,血越多,攻擊力越高)
    • 有等級就代表有經驗,所以需要規定經驗算法(經驗上限隨着等級增加而增加)
      • 等級是會變化的,其餘數值不變,所以我們需要根據等級來定義經驗值
      • 經驗值=等級*等級,簡單定義
    • 升級的血量,攻擊力採用隨機數進行增加,區間爲 [0,等級*等級]
  • 商城玩法(用於購買道具,比如道具加血,經驗等)
    • 先將商品都定義好
    • 血藥(自行擴展) 100金幣 加50點
    • 小經驗藥 200金幣 加 50經驗 (在揹包中使用)
    • 中經驗藥 500金幣 加150經驗
    • 大經驗藥 5000金幣 加 2000 經驗
    • (這裏不弄複雜了,就一個裝備一個寵物)
      • 寵物和裝備都有級別,通過商城裏購買升級,對應屬性提高也會增加
      • 寵物裝備購買金幣 默認值 200.
        • 每升一級 = 200 * (級別+1)
        • (寵物)血量和攻擊力 默認爲 100血量,50攻擊力,默認爲1級
          • 每升一級=默認值*級別
        • (裝備)防禦力 默認爲 10(防禦力在被攻擊時計算,有多少防禦力就能抵多少攻擊力),默認1級
          • 每升一級=默認值*級別
  • 抽獎玩法(抽到獎勵還是對戰還是災難?),抽一次200金幣
    • 與我們之前做的擲骰子類似,不過這次我們需要把獎勵都定義出來,然後通過隨機數抽取三個,對應猜拳的三個.
    • 有 挑戰與當前關卡能力一致的,金幣100,金幣300,金幣1000,經驗50,經驗100,經驗150,經驗1000,金幣清零.
  • 寵物,裝備玩法(給自己加屬性,血量,攻擊力,防禦力)
  • 猜到底玩法(一直贏,直到輸,贏得越多,獎勵越高)
  • 角色信息(顯示血量,攻擊力,防禦值,當前裝備,當前寵物,金幣數,等級,經驗值)
  • 揹包機制(查看道具等)

具體就上面這些功能(腦洞大的也可以多搞一點有意思的功能)

上面的功能通俗的就是,人機猜拳(可以選擇金幣模式和非金幣模式)

關卡模式,猜拳,贏了扣血,輸了掉血,血量小於等於0則通關失敗.

通關勝利可以進入下一關,每一關都有對應獎勵.

商店裏有道具可以買,裝備寵物也可以買(需要數組存放自己有的裝備和寵物)


功能實現

我們已經學過了 類 和 對象 以及數組等,相信大家還不能清楚的體會到,和熟練用上,相信通過此實戰可以讓你對此有一個更高的瞭解

主界面

將所有功能列出一個列表供用戶選取

  1. 普通猜拳
  2. 貨幣猜拳
  3. 挑戰關卡
  4. 商城
  5. 抽獎(一次200金幣)
  6. 一猜到底
  7. 當前屬性
  8. 揹包

新建一個 java 文件作爲啓動類,名稱爲 FingerGuessing(猜拳)

先把主界面實現,啥也不想 就是加上一些 System.out.println,和一個掃描器Scanner

我們的程序不是一次性的,別忘記加死循環

現在我們的程序已經可以跑起來了,並且具備讓用戶選擇和退出的功能,但是看起來非常亂.

將代碼優化一下,Scanner放在循環外,輸出語句抽出來變爲方法...

(需要注意,我們main方法是static的,所以我們要想在main裏使用,方法必須也是static的,對象除外(現在不用管,後面學static就明白了))

我們新建一個類,存放輸出語句,作爲輸出語句工具類(OutUtils).

將main方法裏的輸出語句抽取出來成方法放入此類裏(方法不用加 static,因爲我們在main裏使用此對象)

在 main 方法裏改爲持有此類的對象,並調用方法

import java.util.Scanner;

public class FingerGuessing {
	public static void main(String[] args) {
		OutUtils out = new OutUtils();
		Scanner sc = new Scanner(System.in);
		Game:while (true) {
			out.outStartList();
			// 接收用戶的輸入,並執行對應操作
			int input = sc.nextInt();
			switch (input) {
			// 輸入 0 代表退出遊戲,給外層循環命名爲 Game,這裏使用 break Game就跳出外層循環了
			// 因爲代碼量少,所以放在一行,美觀簡潔省空間.
			case 0: break Game;
			case 1:
				
				break;
			case 2:
				
				break;
			case 3:
				
				break;
			case 4:
				
				break;
			case 5:
				
				break;
			case 6:
				
				break;
			case 7:
				
				break;
			case 8:
				
				break;
			// 默認提示重新操作,代碼量少,直接放在同一行
			// (之前講過,每一個分號代表一個語句的結束,加空格是爲了美觀)
			default: System.out.println("沒有此選項,請重新輸入編號!"); break;
			}
		}
	}
}

先測試一下看看寫的代碼有沒有問題(每寫一個功能都要測試一下,不然你寫着寫着有問題然後繼續寫,問題就變得越來越龐大了)


編譯編碼問題解決

遇到了這種問題很容易解決,因爲我的txt文件是UTF-8編碼的,所以我在編譯的時候需要設置一下編碼

可以通過如下的形式獲取到自己的文本文件是什麼編碼的

打開文件,另存爲.

一般默認爲不是UTF-8,所以沒有出現這個問題就可以忽略編譯時設置編碼這一步

編譯時 設置編碼命令

javac -encoding 編碼(比如我的UTF-8這裏就UTF-8) java文件


運行查看

看起來不是那麼清晰,我們已經將文本輸出提取出來了,所以我們不用改 main方法裏的內容,直接改另一個類的內容就可以了

加上一些 ----------,就會清晰一點

再次編譯運行

可以通過空格一次編譯多個文件


普通猜拳

這個超級簡單,就是普通猜拳,提示用戶出拳,使用隨機數,0,1,2代表石頭剪刀布,看結果,沒有什麼獎勵懲罰機制.只不過需要用到隨機數

所以我們需要創建Random類,並且將功能實現單獨放到一個方法裏,避免混亂.

新建一個類叫 Function,裏面寫我們的具體實現

我們在類裏面寫好普通猜拳的功能,和創建Random,我們的方法需要接收一個參數(用戶出的拳)

我們把用戶輸入的值都放在main裏取獲取,實際功能在Function內實現.

我們觀察一下上面的代碼,有沒有發現有很多地方是重複的?

輸出的地方出了結果(平局,勝利,失敗)其餘的都是一樣的. 所以我們可以提取出來

做成一個變量存結果,最後輸出結果

 代碼如下

import java.util.Random;

public class Function {
	
	/**
	 * 創建 Random(別忘了導入).
	 */
	Random random = new Random();

	// 定義一個字符串數組,對應 0石頭,1剪刀,2布
	String[] fingerGuessing = {"石頭","剪刀","布"};
	
	/**
	 * 普通猜拳 0石頭,1剪刀,2布
	 */
	public void normalFingerGuessing(int what) {
		// 隨機數獲取人機出拳
		int robot = random.nextInt(3);
		// 優化代碼,去除重複
		String result = "結果";
		// 相同則平,石頭勝剪刀勝布勝石頭
		if (what == robot) {
			result = "平局";
		// 你勝利的所有情況石頭 對手剪刀,剪刀 對手布,布 對手石頭
		} else if ((what == 0 && robot == 1) || (what == 1 && robot == 2) || (what == 2 && robot == 0)) {
			result = "勝利";
		// 沒有平 勝利 只剩下失敗了
		} else {
			result = "失敗";
		}
		System.out.println("----------"+ result +"-----------");
		System.out.println("你出拳爲:" + fingerGuessing[what]);
		System.out.println("對手出拳爲:" + fingerGuessing[robot]);
		System.out.println("------------------------");
	}
	
}

接下來,我們在 main方法裏接收用戶的輸入

現在已經可以完成猜拳了,測試一下

重新編譯修改過的類

運行


貨幣猜拳

後面涉及的東西有點多,什麼金幣,經驗,攻擊力,揹包.

所以我們先寫一個類代表玩家

新建 Player 類

將用戶擁有的屬性都添加到此類

接下來在 main 方法裏提示用戶設置金額 並猜拳

在執行操作前,我們需要提醒用戶當前有多少金幣,我們將方法寫入OutUtils中,方法接收一個角色.

我們需要在Function類裏面新加一個方法執行操作(其實可以將之前普通猜拳的代碼提取出來複用,但是爲了不讓大家混亂就重複操作了)

 main方法的代碼爲

編譯文件(全都重新編譯)

運行測試


挑戰關卡

挑戰勝利和失敗都會獲取一定的金幣和經驗,至於是否能升級...

所以我們要在角色類裏面新增一個增加經驗的方法用於處理是否升級.

處理升級

根據一定的計算來算出是否升級.

升級後隨機添加生命值,攻擊力,代碼如下

	/**
	 * 增加經驗
	 */
	public void addExp(int addExp) {
		// 獲取當前升級所需要的經驗,並判斷添加後是否升級
		int upLevel = level * level;
		// 升級所需經驗 - 當前經驗 小於等於添加的經驗則升級
		while (upLevel - exp <= addExp) {
			// 等級+1,經驗等於添加經驗減去升級剩餘所需經驗
			level++;
			addExp -= upLevel - exp;
			exp = 0;
			// 升級隨機添加血量 攻擊力[0-等級*等級],這裏用到的不會怎麼多 直接使用Math.random.
			health += (int)(Math.random()*100)%upLevel;
			attack += (int)(Math.random()*100)%upLevel;
			upLevel = level * level;
		}
		exp += addExp;
	}

挑戰關卡功能

  • 關卡玩法(有血量,通過猜拳來攻擊,進行扣血,勝利獲取經驗金幣等,失敗無損失)
    • 通過一定算法 可以無限關卡 越往後越難...
      • 血量=關卡*關卡
      • 攻擊力=取隨機數,區間爲 (0,關卡*關卡]
      • 防禦力=取隨機數,區間爲 [0,關卡*關卡]
    • 戰鬥失敗獎勵少量經驗和金幣,隨機數,區間[0,100]
    • 關卡玩法,回合制,每一回合隨機出攻擊拳,猜中就可攻擊對方

因爲有關卡,所以需要一個變量來存儲當前關卡,我們新建一個類來存儲這個變量比較合適,這樣便於擴展,比如增加功能勝利次數,挑戰總次數等

我們新建一個類 Game,作用於遊戲,裏面有關卡變量 level

既然有這麼一個類,那我們就應該將一些關於遊戲方面的放入此類裏,比如通關.

所以有個方法用於通關(也可以在細分一點,可以寫敵人類,每次通過指定方法獲取敵人...)

通關獎勵金幣,經驗,定義規則,100*關卡+隨機數0-100

失敗也有個方法,用於增加金幣經驗

代碼如下

public class Game {
	
	/**
	 * 關卡
	 */
	int level = 1;
	
	/**
	 * 讓指定角色下一關(爲什麼要指定角色? 當然是分配獎勵啦).
	 * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
	 */
	public void upLevel(Player player) {
		// 增加金幣 經驗,計算規則爲 100 * 關卡 + [0-100)
		int addExp = 100 * level + (int)(Math.random() * 100);
		player.addExp(addExp);
		int addMoney = 100 * level + (int)(Math.random() * 100);
		player.money += addMoney;
		System.out.println("**********恭喜你通關了**********");
		System.out.println("獎勵經驗: " + addExp);
		System.out.println("獎勵金幣: " + addMoney);
		System.out.println("****************************");
		level++;
	}
	
	/**
	 * 失敗給予一點獎勵 金幣經驗隨機增加[0,100).
	 */
	public void lose(Player player) {
		// 增加金幣 經驗,計算規則爲 100 * 關卡 + [0-100)
		int addExp = (int)(Math.random() * 100);
		player.addExp(addExp);
		int addMoney = (int)(Math.random() * 100);
		player.money += addMoney;
		System.out.println("**********通關失敗**********");
		System.out.println("增加經驗: " + addExp);
		System.out.println("增加金幣: " + addMoney);
		System.out.println("*************************");
	}
	
}

既然是關卡玩法,一直猜拳,直至某一方血量爲0,所以肯定需要死循環.

我們先要創建 Game類的對象.然後進行具體玩法

OutUtils添加提示代碼

        /**
	 * 關卡模式提示
	 */
	public void outLevelMode(Player player,int enemyHealth,int enemyAttack,int enemyDefence) {
		System.out.println("*********************");
		System.out.print("你的血量: " + player.health);
		System.out.print("\t對方血量: " + enemyHealth);
		System.out.print("\n你的攻擊: " + player.attack);
		System.out.print("\t對方攻擊: " + enemyAttack);
		System.out.print("\n你的防禦: " + player.defence);
		System.out.println("\t對方防禦: " + enemyDefence);
		System.out.println("*********************");
		System.out.println("請出拳 0石頭,1剪刀,2布: ");
	}

在main方法裏代碼如下

import java.util.Random;
import java.util.Scanner;

public class FingerGuessing {
	public static void main(String[] args) {
		// 文本輸出工具類
		OutUtils out = new OutUtils();
		// 方法處理類
		Function fun = new Function();
		// 角色
		Player player = new Player();
		// 遊戲類
		Game game = new Game();
		
		Scanner sc = new Scanner(System.in);
		Random random = new Random();
		
		Game:while (true) {
			out.outStartList();
			// 接收用戶的輸入,並執行對應操作
			int input = sc.nextInt();
			switch (input) {
			// 輸入 0 代表退出遊戲,給外層循環命名爲 Game,這裏使用 break Game就跳出外層循環了
			// 因爲代碼量少,所以放在一行,美觀簡潔省空間.
			case 0: break Game;
			// 普通猜拳
			case 1:
				System.out.println("請出拳: 0石頭,1剪刀,2布");
				input = sc.nextInt();
				fun.normalFingerGuessing(input);
				break;
			// 貨幣猜拳
			case 2:
				out.outPlayerMoney(player);
				System.out.println("請輸入你要猜的金額:");
				int moneyInput = sc.nextInt();
				System.out.println("請出拳: 0石頭,1剪刀,2布");
				input = sc.nextInt();
				fun.moneyFingerGuessing(player,moneyInput,input);
				break;
			// 挑戰關卡
			case 3:
				System.out.println("-----你當前挑戰的關卡是 " + game.level);
				// 將對方的屬性創造出來,就三個,血量攻擊力防禦力
				// 血量=關卡*關卡,攻擊力=隨機數,攻擊力=隨機數(0,關卡*關卡],防禦力=隨機數[0,關卡*關卡]
				int enemyHealth = game.level * game.level;
				int enemyAttack = random.nextInt(enemyHealth)+1;
				int enemyDefence = random.nextInt(enemyHealth);
				// 將自己血量記住,通關成功/失敗後進行復原
				int playerHealth = player.health;
				while (true) {
					// 提示,代碼量大且固定,放入OutUtils中
					out.outLevelMode(player,enemyHealth,enemyAttack,enemyDefence);
					// 獲取用戶輸入的拳
					input = sc.nextInt();
					// 獲取當前攻擊拳 和對手出的拳,這部分操作不能封裝到Function類了,因爲敵人的三個變量都不是對象(引用類型)
					// 所以傳遞過去就算進行改變,我們這裏的仍然不會改變
					// 在 Function 裏提供一個功能 將數字變爲拳(裏面有數組)
					int enemy = random.nextInt(3);
					int attackFinger = random.nextInt(3);
					System.out.println("攻擊拳爲: " + fun.getFG(attackFinger));
					// 判斷你輸入的是否中了,中了則扣對方血,同時判斷對方是否中了
					System.out.println("你出拳爲: "+ fun.getFG(input));
					if (input == attackFinger) {
						// 扣血量爲 自己的攻擊力 - 對方防禦力,傷害最少爲1滴血(負數就加血了,不能這樣)
						int delHealth = player.attack - enemyDefence;
						delHealth = delHealth <= 0 ? 1 : delHealth;
						enemyHealth -= delHealth;
						System.out.println("你造成傷害: " + delHealth);
					}
					System.out.println("敵人出拳: "+ fun.getFG(enemy));
					if (enemy == attackFinger) {
						int delHealth = enemyAttack - player.defence;
						delHealth = delHealth <= 0 ? 1 : delHealth;
						player.health -= delHealth;
						System.out.println("你被攻擊了,扣血: " + delHealth);
					}
					// 判斷結果,有三種可能,第一種你沒血了,第二種敵人沒血了,第三種都沒血了(都沒血了肯定是你失敗啦)
					if (player.health <= 0) {
						game.lose(player);
						// 別忘記將生命值復原
						player.health = playerHealth;
						break;
					} else if (enemyHealth <= 0) {
						game.upLevel(player);
						player.health = playerHealth;
						break;
					}
				}
				break;
			// 商城
			case 4:
				
				break;
			// 抽獎
			case 5:
				
				break;
			// 一猜到底
			case 6:
				
				break;
			// 當前屬性
			case 7:
				
				break;
			// 揹包
			case 8:
				
				break;
			// 默認提示重新操作,代碼量少,直接放在同一行
			// (之前講過,每一個分號代表一個語句的結束,加空格是爲了美觀)
			default: System.out.println("沒有此選項,請重新輸入編號!"); break;
			}
		}
	}
}

重新編譯,測試一下


商城

  • 商城玩法(用於購買道具,比如道具加血,經驗等)
    • 小經驗藥 200金幣 加 50經驗 (在揹包中使用)
    • 中經驗藥 500金幣 加150經驗
    • 大經驗藥 5000金幣 加 2000 經驗
    • (這裏不弄複雜了,就一個裝備一個寵物)
      • 寵物和裝備都有級別,通過商城裏購買升級,對應屬性提高也會增加
      • 寵物裝備購買金幣 默認值 200.
        • 每升一級 = 200 * (級別+1)
        • (寵物)血量和攻擊力 默認爲 100血量,50攻擊力,默認爲1級
          • 每升一級=默認值*級別
        • (裝備)防禦力 默認爲 10(防禦力在被攻擊時計算,有多少防禦力就能抵多少攻擊力),默認1級
          • 每升一級=默認值*級別

這個比較簡單,購買商品後存入數組裏,我們之前寫過一個可變長度的數組,使用字符串類型的數組就可以滿足當前需求

我們道具的話還需要記錄數量,因爲是字符串,我們可以將字符串拆分一下獲取到想要的東西.

格式爲: 類型|數量(這裏的| 是或者的那個符號)

將之前我們寫的可變數組類複製過來(class文件就行了),也可以自己重新手寫,

在 Player 裏新增這個類的對象,用於代表當前揹包

剩下的只要將購買的商品存入揹包就行了

以及有此物品 數量+1.

並且涉及到寵物和裝備(直接使用Player類就可以了)

我們添加提示

	/**
	 * 商店提示
	 */
	public void outShop(Player player) {
		System.out.println("*********************");
		System.out.println("你的金幣: " + player.money);
		System.out.println("---------------------");
		System.out.println("0.返回");
		System.out.println("1.小經驗藥 200金幣 加 50經驗");
		System.out.println("2.中經驗藥 500金幣 加150經驗");
		System.out.println("3.大經驗藥 5000金幣 加 2000 經驗");
		if (player.pet == null) {
			System.out.println("4.寵物購買 200金幣.100血量,50攻擊力");
		} else {
			System.out.println("4.寵物購買"+ player.pet.level +") "+(200*player.pet.level+1) 
					+"金幣.血量: "+ (100 * player.pet.level)
					+",攻擊力: "+ (50 * player.pet.level));
		}
		if (player.equip == null) {
			System.out.println("5.裝備購買 200金幣.10防禦力");
		} else {
			System.out.println("5.裝備購買("+ player.equip.level +") "+ (200*player.equip.level+1) +"金幣.防禦力: "+ (10 * player.equip.level));
		}
		System.out.println("*********************");
		System.out.println("請輸入:");
	}

剩下的就是購買了,購買寵物和裝備的時候直接將屬性加上去

購買物品先要判斷是否存在,存在則在原物品基礎上+1

	/**
	 * 判斷物品在揹包內是否存在
	 * 存在返回此物品對應下標,不存在返回-1
	 */
	public int exists(MyArray arr,String name) {
		for (int i = 0;i < arr.getSize();i++) {
			String s = (String)arr.get(i);
			// contains方法是判斷有沒有這個子串
			// 例如我是 abcd,ab就是我的子串,bc,bd都是,ad則不是
			// 就是判斷有沒有這個字符串
			if (s.contains(name)) {
				return i;
			}
		}
		return -1;
	}

main 方法裏代碼如下

			// 商城
			case 4:
				out.outShop(player);
				input = sc.nextInt();
				switch (input) {
				case 0: break;
				// 小經驗藥水 購買之前先看看有沒有,有則數量+1
				// 判斷有沒有的方法寫進 Function 類裏
				case 1:
					// 金幣是否足夠
					if (player.money < 200) {
						System.out.println("金幣不足!");
						break;
					} else {
						player.money -= 200;
					}
					
					int num = fun.exists(player.bag,"小經驗藥水");
					if (num == -1) {
						player.bag.add("小經驗藥水|1");
					} else {
						String s = (String)player.bag.get(num);
						// 使用 Integer.parseInt() 可以將字符串轉換爲數字
						// split是將字符串按照某個字符來拆分,因爲|是特殊字符,所以我們需要用\轉義,\也是特殊字符,所以我們需要用\將\轉義...
						player.bag.set(num,"小經驗藥水|" + (Integer.parseInt(s.split("\\|")[1])+1));
					}
					break;
					// 中經驗藥水
					case 2:
						if (player.money < 500) {
							System.out.println("金幣不足!");
							break;
						} else {
							player.money -= 500;
						}
						
						num = fun.exists(player.bag,"中經驗藥水");
						if (num == -1) {
							player.bag.add("中經驗藥水|1");
						} else {
							String s = (String)player.bag.get(num);
							// 使用 Integer.parseInt() 可以將字符串轉換爲數字
							player.bag.set(num,"中經驗藥水|" + (Integer.parseInt(s.split("\\|")[1])+1));
						}
						break;
						// 大經驗藥水
					case 3:
						if (player.money < 5000) {
							System.out.println("金幣不足!");
							break;
						} else {
							player.money -= 5000;
						}
						
						num = fun.exists(player.bag,"大經驗藥水");
						if (num == -1) {
							player.bag.add("大經驗藥水|1");
						} else {
							String s = (String)player.bag.get(num);
							// 使用 Integer.parseInt() 可以將字符串轉換爲數字
							player.bag.set(num,"大經驗藥水|" + (Integer.parseInt(s.split("\\|")[1])+1));
						}
						break;
					case 4:
						if (player.pet == null) {
							if (player.money < 200) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= 200;
								player.pet = new Player();
								player.pet.attack = 50;
								player.health += player.pet.health;
								player.attack += player.pet.attack;
							}
						} else {
							if (player.money < (200*player.pet.level+1)) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= (200*player.pet.level+1);
								player.pet.level++;
								player.pet.health = (100 * player.pet.level);
								player.pet.attack = (50 * player.pet.level);
								player.health += player.pet.health - (100 * (player.pet.level -1));
								player.attack += player.pet.attack - (100 * (player.pet.level -1));;
							}
						}
						break;
					case 5:
						if (player.equip == null) {
							if (player.money < 200) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= 200;
								player.equip = new Player();
								player.equip.defence = 10;
								player.defence += player.equip.defence;
							}
						} else {
							if (player.money < (200*player.equip.level+1)) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= (200*player.equip.level+1);
								player.equip.level++;
								player.equip.defence = (10 * player.equip.level);
								player.defence += player.equip.defence - (10 * (player.equip.level -1));;
							}
						}
						break;
				default: break;
				}
				break;

運行測試,能跑起來就代表應該沒問題


修復一個bug

發現一個bug 具體是我們在進行關卡模式的時候,升級無法將血量上限增加(因爲我們在執行操作前將血量保存,執行完將血量恢復)

修復,在Player裏新加了一個屬性用於恢復血量,並且升級設置也使用此變量.

Player類的增加經驗方法也要改

	/**
	 * 增加經驗
	 */
	public void addExp(int addExp) {
		// 獲取當前升級所需要的經驗,並判斷添加後是否升級
		int upLevel = level * level;
		// 升級所需經驗 - 當前經驗 小於等於添加的經驗則升級
		while (upLevel - exp <= addExp) {
			// 等級+1,經驗等於添加經驗減去升級剩餘所需經驗
			level++;
			addExp -= upLevel - exp;
			exp = 0;
			// 升級隨機添加血量 攻擊力[0-等級*等級],這裏用到的不會怎麼多 直接使用Math.random.
			defaultHealth += (int)(Math.random()*100)%upLevel;
			health += defaultHealth;
			attack += (int)(Math.random()*100)%upLevel;
			upLevel = level * level;
		}
		exp += addExp;
	}

判斷結果的地方也要改

上面商城購買寵物的地方也要加一句,將默認上限生命值設置

					case 4:
						if (player.pet == null) {
							if (player.money < 200) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= 200;
								player.pet = new Player();
								player.pet.attack = 50;
								player.health += player.pet.health;
								player.defaultHealth = player.health;
								player.attack += player.pet.attack;
							}
						} else {
							if (player.money < (200*player.pet.level+1)) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= (200*player.pet.level+1);
								player.pet.level++;
								player.pet.health = (100 * player.pet.level);
								player.pet.attack = (50 * player.pet.level);
								player.health += player.pet.health - (100 * (player.pet.level -1));
								player.defaultHealth = player.health;
								player.attack += player.pet.attack - (100 * (player.pet.level -1));;
							}
						}
						break;

抽獎

  • 抽獎玩法(抽到獎勵還是對戰還是災難?),抽一次200金幣
    • 與我們之前做的擲骰子類似,不過這次我們需要把獎勵都定義出來,然後通過隨機數抽取三個,對應猜拳的三個.
    • 有 挑戰與當前關卡能力一致的(暫不做),金幣100,金幣300,金幣1000,經驗50,經驗100,經驗150,經驗1000,金幣清零.

我們先創建一個數組(在Function類裏),用於存放我們的獎勵.

// 抽獎的所有物品
String[] luck = {"金幣100","金幣300","金幣1000","經驗50","經驗100","經驗150","經驗1000","金幣清零"};
	

創建三個變量,執行三次隨機數 0-7,接收用戶輸入的猜拳,並返回三個之間的一個

代碼量有點多,並且相對獨立,所以我們放到Function類裏

	/**
	 * 幸運抽獎
	 */
	public void playLuck(Player player,int input) {
		// 先判斷有沒有足夠金幣
		if (player.money < 200) {
			System.out.println("抽獎需要200金幣,你的金幣不夠!");
			return;
		}
		
		int one = random.nextInt(8);
		int two = random.nextInt(8);
		int three = random.nextInt(8);
		System.out.println("********幸運物品********");
		System.out.println("石頭: " + luck[one]);
		System.out.println("剪刀: " + luck[two]);
		System.out.println("布: " + luck[three]);
		System.out.println("*********************");
		System.out.println("你出的幸運拳爲: " + fingerGuessing[input]);
		// 將用戶輸入改到獎勵下標,用於獲取指定獎勵
		input = input == 0 ? one : input == 1 ? two : three;
		System.out.println("恭喜你獲得了: " + luck[input]);
		
		switch (input) {
		// 金幣100
		case 0: player.money += 100; break;
		// 金幣300
		case 1: player.money += 300; break;
		// 金幣1000
		case 2: player.money += 1000; break;
		// 經驗50
		case 3: player.addExp(50); break;
		// 經驗100
		case 4: player.addExp(100); break;
		// 經驗150
		case 5: player.addExp(150); break;
		// 經驗1000
		case 6: player.addExp(1000); break;
		// 金幣清零
		case 7: player.money = 0; break;
		}
	}

接下來在main方法裏只需要接收用戶輸入就行了.

重新編譯 運行測試


一猜到底

無限猜,只要不輸,功能相對獨立,實際操作寫Function類裏

通過一個變量存當前勝利多少次,最後通過算法計算得出獎勵

金幣和金幣=關卡<<關卡+隨機數0-100

使用位移則可以看到成倍增加...

在Function類中已經有類似功能,我們只要複製一下稍微改改就ok了

勝利返回0,平局返回1,失敗返回2

	/**
	 * 無限猜拳 0石頭,1剪刀,2布.
	 * 返回0代表勝利 1平局 2失敗.
	 * num參數是勝利的次數.
	 */
	public int wxfingerGuessing(int what,int num) {
		// 隨機數獲取人機出拳
		int robot = random.nextInt(3);
		// 優化代碼,去除重複
		String result = "結果";
		int r = 2;
		// 相同則平,石頭勝剪刀勝布勝石頭
		if (what == robot) {
			result = "平局";
			r = 1;
		// 你勝利的所有情況石頭 對手剪刀,剪刀 對手布,布 對手石頭
		} else if ((what == 0 && robot == 1) || (what == 1 && robot == 2) || (what == 2 && robot == 0)) {
			result = "勝利";
			r = 0;
		// 沒有平 勝利 只剩下失敗了
		} else {
			result = "失敗";
		}
		System.out.println("---------"+ result + num + "----------");
		System.out.println("你出拳爲:" + fingerGuessing[what]);
		System.out.println("對手出拳爲:" + fingerGuessing[robot]);
		System.out.println("------------------------");
		return r;
	}

在main裏調用

			// 一猜到底
			case 6:
				// 無限猜,當然是死循環 記錄當前勝利次數
				int win = 0;
				while (true) {
					System.out.println("請出拳 0石頭,1剪刀,2布: ");
					input = sc.nextInt();
					int r = fun.wxfingerGuessing(input,win);
					// 勝利 繼續
					if (r == 0) {
						win++;
					//平局 繼續 不加勝利次數
					} else if (r == 1) {
						continue;
					// 失敗 計算獎勵
					} else {
						int winNum = win<<win;
						int addMoney = winNum + random.nextInt(100);
						int addExp = winNum + random.nextInt(100);
						player.money += addMoney;
						player.addExp(addExp);
						System.out.println("%%%%%%%%%%%%%%%%%%");
						System.out.println("擊敗對手: " + win);
						System.out.println("增加了金幣: " + addMoney);
						System.out.println("增加了經驗: " + addExp);
						System.out.println("%%%%%%%%%%%%%%%%%%");
						break;
					}
				}
				break;

重新編譯測試


當前屬性

經過製作了以上功能後,這個功能就簡單了起來(直接獲取Player類裏的屬性打印到控制檯)

既然是輸出的功能,我們有一個類專門做這個,OutUtils類.

但是我不準備放在OutUtils類裏,我們來學習一個新方法,toString方法

每一個類都有 toString方法,我們使用System.out.println,其實打印的就是這個對象的toString方法

toString是Object類的方法,萬物皆Object,所以---所有類都有toString方法,後面詳細介紹

我們現在就實現,直接輸出player對象來獲取此角色的信息

在Player類裏新建一個方法叫 toString(),大小寫不能錯,必須一模一樣

方法有返回值 String,我們只需要返回我們想要的字符串,打印這個對象就可以看到了

所以我們在Player類裏增加代碼如下

	public String toString() {
		// 創建一個String用於存儲我們需要的字符串格式
		// 這裏 \r\n 是換行,因爲在不同操作系統下換行符不同(有用\r的,有用\n的),所以直接使用\r\n
		String str = "@@@@@@@@@@@@@@@@@@@@@\r\n";
		str += "生命值: " + health;
		str += "\r\n攻擊力: " + attack;
		str += "\r\n防禦力: " + defence;
		str += "\r\n等級: " + level;
		str += "\r\n經驗值: " + exp;
		str += "\r\n下一級所需經驗: " + (level*level - exp);
		str += "\r\n金幣: " + money;
		// 有寵物/裝備則顯示 不然不顯示
		// \t 等於一個tab鍵,這樣看起來會有級別的感覺
		if (pet != null) {
			str += "\r\n寵物: \r\n\t血量" + pet.health;
			str += "\r\n\t攻擊力" + pet.attack;
		}
		// 只有一個語句可以省略 {} 太長就別省略了 不好看.
		if (equip != null) str += "\r\n裝備: \r\n\t防禦力" + equip.defence;
		str += "\r\n@@@@@@@@@@@@@@@@@@@@@";
		return str;
	}

在 main方法裏直接調用就ok了

重新編譯,運行測試


揹包

這是最後一個功能,我們揹包裏有經驗藥水,所以需要提供一個使用的功能(目前揹包裏的物品都可以使用)

我們直接在OutUtils方法裏添一個功能遍歷我們的MyArray類顯示出我們的道具列表,然後接受用戶輸入來執行使用/返回

	/**
	 * 輸出當前揹包內物品
	 */
	public void outBag(Player player) {
		// 這是引用對象,我們這麼做沒有創建新的東西,就是做了個指針指向bag.
		MyArray arr = player.bag;
		int size = arr.getSize();
		System.out.println("$$$$$$$$$揹包$$$$$$$$$");
		for (int i = 0;i < size;i++) {
			System.out.println(i + ":" + arr.get(i));
		}
		System.out.println("$$$$$$$$$$$$$$$$$$$$$");
		System.out.println("請輸入編號直接使用,輸入-1返回");
	}

main方法代碼如下

			// 揹包
			case 8:
				out.outBag(player);
				input = sc.nextInt();
				// 0則退出,否則直接使用編號對應的物品,要先看有沒有這個物品
				if (input != -1 && player.bag.getSize() > input) {
					// 獲取到對應物品,然後 switch判斷執行
					String what = (String)player.bag.get(input);
					// 我們的數據是 名稱|數量,根據|拆分得到一個字符串數組,0下標就是名稱,1就是數量
					String[] whats = what.split("\\|");
					String name = whats[0];
					int num = Integer.parseInt(whats[1]);
					switch (name) {
					// 小的加50,中的150,大的2000
					case "小經驗藥水": player.addExp(50); break;
					case "中經驗藥水": player.addExp(150); break;
					case "大經驗藥水": player.addExp(2000); break;
					}
					// 用完後數量 - 1,沒有數量則去掉此物品
					if (num <= 1) {
						player.bag.del(input);
					} else {
						num--;
						player.bag.set(input,name+"|"+num);
					}
				}
				break;

重新編譯測試

至此,這麼個小遊戲就做好了

源碼(所有類)

FingerGuessing 主類

import java.util.Random;
import java.util.Scanner;

public class FingerGuessing {
	public static void main(String[] args) {
		// 文本輸出工具類
		OutUtils out = new OutUtils();
		// 方法處理類
		Function fun = new Function();
		// 角色
		Player player = new Player();
		// 遊戲類
		Game game = new Game();
		
		Scanner sc = new Scanner(System.in);
		Random random = new Random();
		
		Game:while (true) {
			out.outStartList();
			// 接收用戶的輸入,並執行對應操作
			int input = sc.nextInt();
			switch (input) {
			// 輸入 0 代表退出遊戲,給外層循環命名爲 Game,這裏使用 break Game就跳出外層循環了
			// 因爲代碼量少,所以放在一行,美觀簡潔省空間.
			case 0: break Game;
			// 普通猜拳
			case 1:
				System.out.println("請出拳: 0石頭,1剪刀,2布");
				input = sc.nextInt();
				fun.normalFingerGuessing(input);
				break;
			// 貨幣猜拳
			case 2:
				out.outPlayerMoney(player);
				System.out.println("請輸入你要猜的金額:");
				int moneyInput = sc.nextInt();
				System.out.println("請出拳: 0石頭,1剪刀,2布");
				input = sc.nextInt();
				fun.moneyFingerGuessing(player,moneyInput,input);
				break;
			// 挑戰關卡
			case 3:
				System.out.println("-----你當前挑戰的關卡是 " + game.level);
				// 將對方的屬性創造出來,就三個,血量攻擊力防禦力
				// 血量=關卡*關卡,攻擊力=隨機數,攻擊力=隨機數(0,關卡*關卡],防禦力=隨機數[0,關卡*關卡]
				int enemyHealth = game.level * game.level;
				int enemyAttack = random.nextInt(enemyHealth)+1;
				int enemyDefence = random.nextInt(enemyHealth);
				while (true) {
					// 提示,代碼量大且固定,放入OutUtils中
					out.outLevelMode(player,enemyHealth,enemyAttack,enemyDefence);
					// 獲取用戶輸入的拳
					input = sc.nextInt();
					// 獲取當前攻擊拳 和對手出的拳,這部分操作不能封裝到Function類了,因爲敵人的三個變量都不是對象(引用類型)
					// 所以傳遞過去就算進行改變,我們這裏的仍然不會改變
					// 在 Function 裏提供一個功能 將數字變爲拳(裏面有數組)
					int enemy = random.nextInt(3);
					int attackFinger = random.nextInt(3);
					System.out.println("攻擊拳爲: " + fun.getFG(attackFinger));
					// 判斷你輸入的是否中了,中了則扣對方血,同時判斷對方是否中了
					System.out.println("你出拳爲: "+ fun.getFG(input));
					if (input == attackFinger) {
						// 扣血量爲 自己的攻擊力 - 對方防禦力,傷害最少爲1滴血(負數就加血了,不能這樣)
						int delHealth = player.attack - enemyDefence;
						delHealth = delHealth <= 0 ? 1 : delHealth;
						enemyHealth -= delHealth;
						System.out.println("你造成傷害: " + delHealth);
					}
					System.out.println("敵人出拳: "+ fun.getFG(enemy));
					if (enemy == attackFinger) {
						int delHealth = enemyAttack - player.defence;
						delHealth = delHealth <= 0 ? 1 : delHealth;
						player.health -= delHealth;
						System.out.println("你被攻擊了,扣血: " + delHealth);
					}
					// 判斷結果,有三種可能,第一種你沒血了,第二種敵人沒血了,第三種都沒血了(都沒血了肯定是你失敗啦)
					if (player.health <= 0) {
						game.lose(player);
						// 別忘記將生命值復原
						player.health = player.defaultHealth;
						break;
					} else if (enemyHealth <= 0) {
						game.upLevel(player);
						player.health = player.defaultHealth;
						break;
					}
				}
				break;
			// 商城
			case 4:
				out.outShop(player);
				input = sc.nextInt();
				switch (input) {
				case 0: break;
				// 小經驗藥水 購買之前先看看有沒有,有則數量+1
				// 判斷有沒有的方法寫進 Function 類裏
				case 1:
					// 金幣是否足夠
					if (player.money < 200) {
						System.out.println("金幣不足!");
						break;
					} else {
						player.money -= 200;
					}
					
					int num = fun.exists(player.bag,"小經驗藥水");
					if (num == -1) {
						player.bag.add("小經驗藥水|1");
					} else {
						String s = (String)player.bag.get(num);
						// 使用 Integer.parseInt() 可以將字符串轉換爲數字
						// split是將字符串按照某個字符來拆分,因爲|是特殊字符,所以我們需要用\轉義,\也是特殊字符,所以我們需要用\將\轉義...
						player.bag.set(num,"小經驗藥水|" + (Integer.parseInt(s.split("\\|")[1])+1));
					}
					break;
					// 中經驗藥水
					case 2:
						if (player.money < 500) {
							System.out.println("金幣不足!");
							break;
						} else {
							player.money -= 500;
						}
						
						num = fun.exists(player.bag,"中經驗藥水");
						if (num == -1) {
							player.bag.add("中經驗藥水|1");
						} else {
							String s = (String)player.bag.get(num);
							// 使用 Integer.parseInt() 可以將字符串轉換爲數字
							player.bag.set(num,"中經驗藥水|" + (Integer.parseInt(s.split("\\|")[1])+1));
						}
						break;
						// 大經驗藥水
					case 3:
						if (player.money < 5000) {
							System.out.println("金幣不足!");
							break;
						} else {
							player.money -= 5000;
						}
						
						num = fun.exists(player.bag,"大經驗藥水");
						if (num == -1) {
							player.bag.add("大經驗藥水|1");
						} else {
							String s = (String)player.bag.get(num);
							// 使用 Integer.parseInt() 可以將字符串轉換爲數字
							player.bag.set(num,"大經驗藥水|" + (Integer.parseInt(s.split("\\|")[1])+1));
						}
						break;
					case 4:
						if (player.pet == null) {
							if (player.money < 200) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= 200;
								player.pet = new Player();
								player.pet.attack = 50;
								player.health += player.pet.health;
								player.defaultHealth = player.health;
								player.attack += player.pet.attack;
							}
						} else {
							if (player.money < (200*player.pet.level+1)) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= (200*player.pet.level+1);
								player.pet.level++;
								player.pet.health = (100 * player.pet.level);
								player.pet.attack = (50 * player.pet.level);
								player.health += player.pet.health - (100 * (player.pet.level -1));
								player.defaultHealth = player.health;
								player.attack += player.pet.attack - (100 * (player.pet.level -1));;
							}
						}
						break;
					case 5:
						if (player.equip == null) {
							if (player.money < 200) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= 200;
								player.equip = new Player();
								player.equip.defence = 10;
								player.defence += player.equip.defence;
							}
						} else {
							if (player.money < (200*player.equip.level+1)) {
								System.out.println("金幣不足!");
								break;
							} else {
								player.money -= (200*player.equip.level+1);
								player.equip.level++;
								player.equip.defence = (10 * player.equip.level);
								player.defence += player.equip.defence - (10 * (player.equip.level -1));;
							}
						}
						break;
				default: break;
				}
				break;
			// 抽獎
			case 5:
				System.out.println("請出拳 0石頭,1剪刀,2布: ");
				input = sc.nextInt();
				fun.playLuck(player,input);
				break;
			// 一猜到底
			case 6:
				// 無限猜,當然是死循環 記錄當前勝利次數
				int win = 0;
				while (true) {
					System.out.println("請出拳 0石頭,1剪刀,2布: ");
					input = sc.nextInt();
					int r = fun.wxfingerGuessing(input,win);
					// 勝利 繼續
					if (r == 0) {
						win++;
					//平局 繼續 不加勝利次數
					} else if (r == 1) {
						continue;
					// 失敗 計算獎勵
					} else {
						int winNum = win<<win;
						int addMoney = winNum + random.nextInt(100);
						int addExp = winNum + random.nextInt(100);
						player.money += addMoney;
						player.addExp(addExp);
						System.out.println("%%%%%%%%%%%%%%%%%%");
						System.out.println("擊敗對手: " + win);
						System.out.println("增加了金幣: " + addMoney);
						System.out.println("增加了經驗: " + addExp);
						System.out.println("%%%%%%%%%%%%%%%%%%");
						break;
					}
				}
				break;
			// 當前屬性
			case 7:
				System.out.println(player);
				break;
			// 揹包
			case 8:
				out.outBag(player);
				input = sc.nextInt();
				// 0則退出,否則直接使用編號對應的物品,要先看有沒有這個物品
				if (input != -1 && player.bag.getSize() > input) {
					// 獲取到對應物品,然後 switch判斷執行
					String what = (String)player.bag.get(input);
					// 我們的數據是 名稱|數量,根據|拆分得到一個字符串數組,0下標就是名稱,1就是數量
					String[] whats = what.split("\\|");
					String name = whats[0];
					int num = Integer.parseInt(whats[1]);
					switch (name) {
					// 小的加50,中的150,大的2000
					case "小經驗藥水": player.addExp(50); break;
					case "中經驗藥水": player.addExp(150); break;
					case "大經驗藥水": player.addExp(2000); break;
					}
					// 用完後數量 - 1,沒有數量則去掉此物品
					if (num <= 1) {
						player.bag.del(input);
					} else {
						num--;
						player.bag.set(input,name+"|"+num);
					}
				}
				break;
			// 默認提示重新操作,代碼量少,直接放在同一行
			// (之前講過,每一個分號代表一個語句的結束,加空格是爲了美觀)
			default: System.out.println("沒有此選項,請重新輸入編號!"); break;
			}
		}
	}
}

Function功能類

import java.util.Random;

public class Function {
	
	/**
	 * 創建 Random(別忘了導入).
	 */
	Random random = new Random();

	// 定義一個字符串數組,對應 0石頭,1剪刀,2布
	String[] fingerGuessing = {"石頭","剪刀","布"};
	
	// 抽獎的所有物品
	String[] luck = {"金幣100","金幣300","金幣1000","經驗50","經驗100","經驗150","經驗1000","金幣清零"};
	
	/**
	 * 普通猜拳 0石頭,1剪刀,2布
	 */
	public void normalFingerGuessing(int what) {
		// 隨機數獲取人機出拳
		int robot = random.nextInt(3);
		// 優化代碼,去除重複
		String result = "結果";
		// 相同則平,石頭勝剪刀勝布勝石頭
		if (what == robot) {
			result = "平局";
		// 你勝利的所有情況石頭 對手剪刀,剪刀 對手布,布 對手石頭
		} else if ((what == 0 && robot == 1) || (what == 1 && robot == 2) || (what == 2 && robot == 0)) {
			result = "勝利";
		// 沒有平 勝利 只剩下失敗了
		} else {
			result = "失敗";
		}
		System.out.println("----------"+ result +"-----------");
		System.out.println("你出拳爲:" + fingerGuessing[what]);
		System.out.println("對手出拳爲:" + fingerGuessing[robot]);
		System.out.println("------------------------");
	}
	
	/**
	 * 貨幣猜拳
	 */
	public void moneyFingerGuessing(Player player,int money,int what) {
		// 金幣不夠則不允許操作
		if (player.money < money) {
			System.out.println("您的金幣不足!");
			// 之前講過 return就是不執行後面的代碼了直接返回
			return;
		}
		
		// 隨機數獲取人機出拳
		int robot = random.nextInt(3);
		// 相同則平,石頭勝剪刀勝布勝石頭
		if (what == robot) {
			System.out.println("----------平局-----------");
			System.out.println("你出拳爲:" + fingerGuessing[what]);
			System.out.println("對手出拳爲:" + fingerGuessing[robot]);
			System.out.println("------------------------");
		// 你勝利的所有情況石頭 對手剪刀,剪刀 對手布,布 對手石頭
		} else if ((what == 0 && robot == 1) || (what == 1 && robot == 2) || (what == 2 && robot == 0)) {
			player.money += money;
			System.out.println("----------勝利-----------");
			System.out.println("你出拳爲:" + fingerGuessing[what]);
			System.out.println("對手出拳爲:" + fingerGuessing[robot]);
			System.out.println("你贏取了: " + money);
			System.out.println("------------------------");
		// 沒有平 勝利 只剩下失敗了
		} else {
			player.money -= money;
			System.out.println("----------失敗-----------");
			System.out.println("你出拳爲:" + fingerGuessing[what]);
			System.out.println("對手出拳爲:" + fingerGuessing[robot]);
			System.out.println("你失去了: " + money);
			System.out.println("------------------------");
		}
	}
	
	/**
	 * 獲取當前拳頭,根據數字
	 */
	public String getFG(int input) {
		return fingerGuessing[input];
	}
	
	/**
	 * 判斷物品在揹包內是否存在
	 * 存在返回此物品對應下標,不存在返回-1
	 */
	public int exists(MyArray arr,String name) {
		for (int i = 0;i < arr.getSize();i++) {
			String s = (String)arr.get(i);
			// contains方法是判斷有沒有這個子串
			// 例如我是 abcd,ab就是我的子串,bc,bd都是,ad則不是
			// 就是判斷有沒有這個字符串
			if (s.contains(name)) {
				return i;
			}
		}
		return -1;
	}
	
	/**
	 * 幸運抽獎
	 */
	public void playLuck(Player player,int input) {
		// 先判斷有沒有足夠金幣
		if (player.money < 200) {
			System.out.println("抽獎需要200金幣,你的金幣不夠!");
			return;
		}
		
		int one = random.nextInt(8);
		int two = random.nextInt(8);
		int three = random.nextInt(8);
		System.out.println("********幸運物品********");
		System.out.println("石頭: " + luck[one]);
		System.out.println("剪刀: " + luck[two]);
		System.out.println("布: " + luck[three]);
		System.out.println("*********************");
		System.out.println("你出的幸運拳爲: " + fingerGuessing[input]);
		// 將用戶輸入改到獎勵下標,用於獲取指定獎勵
		input = input == 0 ? one : input == 1 ? two : three;
		System.out.println("恭喜你獲得了: " + luck[input]);
		
		switch (input) {
		// 金幣100
		case 0: player.money += 100; break;
		// 金幣300
		case 1: player.money += 300; break;
		// 金幣1000
		case 2: player.money += 1000; break;
		// 經驗50
		case 3: player.addExp(50); break;
		// 經驗100
		case 4: player.addExp(100); break;
		// 經驗150
		case 5: player.addExp(150); break;
		// 經驗1000
		case 6: player.addExp(1000); break;
		// 金幣清零
		case 7: player.money = 0; break;
		}
	}
	
	/**
	 * 無限猜拳 0石頭,1剪刀,2布.
	 * 返回0代表勝利 1平局 2失敗.
	 * num參數是勝利的次數.
	 */
	public int wxfingerGuessing(int what,int num) {
		// 隨機數獲取人機出拳
		int robot = random.nextInt(3);
		// 優化代碼,去除重複
		String result = "結果";
		int r = 2;
		// 相同則平,石頭勝剪刀勝布勝石頭
		if (what == robot) {
			result = "平局";
			r = 1;
		// 你勝利的所有情況石頭 對手剪刀,剪刀 對手布,布 對手石頭
		} else if ((what == 0 && robot == 1) || (what == 1 && robot == 2) || (what == 2 && robot == 0)) {
			result = "勝利";
			r = 0;
		// 沒有平 勝利 只剩下失敗了
		} else {
			result = "失敗";
		}
		System.out.println("---------"+ result + num + "----------");
		System.out.println("你出拳爲:" + fingerGuessing[what]);
		System.out.println("對手出拳爲:" + fingerGuessing[robot]);
		System.out.println("------------------------");
		return r;
	}
	
}

Game遊戲信息類

public class Game {
	
	/**
	 * 關卡
	 */
	int level = 1;
	
	/**
	 * 讓指定角色下一關(爲什麼要指定角色? 當然是分配獎勵啦).
	 * @author Shendi <a href='tencent://AddContact/?fromId=45&fromSubId=1&subcmd=all&uin=1711680493'>QQ</a>
	 */
	public void upLevel(Player player) {
		// 增加金幣 經驗,計算規則爲 100 * 關卡 + [0-100)
		int addExp = 100 * level + (int)(Math.random() * 100);
		player.addExp(addExp);
		int addMoney = 100 * level + (int)(Math.random() * 100);
		player.money += addMoney;
		System.out.println("**********恭喜你通關了**********");
		System.out.println("獎勵經驗: " + addExp);
		System.out.println("獎勵金幣: " + addMoney);
		System.out.println("****************************");
		level++;
	}
	
	/**
	 * 失敗給予一點獎勵 金幣經驗隨機增加[0,100).
	 */
	public void lose(Player player) {
		// 增加金幣 經驗,計算規則爲 100 * 關卡 + [0-100)
		int addExp = (int)(Math.random() * 100);
		player.addExp(addExp);
		int addMoney = (int)(Math.random() * 100);
		player.money += addMoney;
		System.out.println("**********通關失敗**********");
		System.out.println("增加經驗: " + addExp);
		System.out.println("增加金幣: " + addMoney);
		System.out.println("*************************");
	}
	
}

OutUtils輸出信息類

/**
 * 用於輸出操作的工具類
 */
public class OutUtils {
	
	/**
	 * 輸出剛開始的列表提示.
	 */
	public void outStartList() {
		System.out.println("--------------------------");
		System.out.println("猜拳小遊戲,請選擇:");
		System.out.println("0.退出");
		System.out.println("1.普通猜拳");
		System.out.println("2.貨幣猜拳");
		System.out.println("3.挑戰關卡");
		System.out.println("4.商城");
		System.out.println("5.抽獎(一次200金幣)");
		System.out.println("6.一猜到底");
		System.out.println("7.當前屬性");
		System.out.println("8.揹包");
		System.out.println("--------------------------");
	}
	
	/**
	 * 輸出用戶當前金幣數
	 */
	public void outPlayerMoney(Player player) {
		System.out.println("*********************");
		System.out.println("您當前金幣剩餘: " + player.money);
		System.out.println("*********************");
	}
	
	/**
	 * 關卡模式提示
	 */
	public void outLevelMode(Player player,int enemyHealth,int enemyAttack,int enemyDefence) {
		System.out.println("*********************");
		System.out.print("你的血量: " + player.health);
		System.out.print("\t對方血量: " + enemyHealth);
		System.out.print("\n你的攻擊: " + player.attack);
		System.out.print("\t對方攻擊: " + enemyAttack);
		System.out.print("\n你的防禦: " + player.defence);
		System.out.println("\t對方防禦: " + enemyDefence);
		System.out.println("*********************");
		System.out.println("請出拳 0石頭,1剪刀,2布: ");
	}
	
	/**
	 * 商店提示
	 */
	public void outShop(Player player) {
		System.out.println("*********************");
		System.out.println("你的金幣: " + player.money);
		System.out.println("---------------------");
		System.out.println("0.返回");
		System.out.println("1.小經驗藥 200金幣 加 50經驗");
		System.out.println("2.中經驗藥 500金幣 加150經驗");
		System.out.println("3.大經驗藥 5000金幣 加 2000 經驗");
		if (player.pet == null) {
			System.out.println("4.寵物購買 200金幣.100血量,50攻擊力");
		} else {
			System.out.println("4.寵物購買"+ player.pet.level +") "+(200*player.pet.level+1) 
					+"金幣.血量: "+ (100 * player.pet.level)
					+",攻擊力: "+ (50 * player.pet.level));
		}
		if (player.equip == null) {
			System.out.println("5.裝備購買 200金幣.10防禦力");
		} else {
			System.out.println("5.裝備購買("+ player.equip.level +") "+ (200*player.equip.level+1) +"金幣.防禦力: "+ (10 * player.equip.level));
		}
		System.out.println("*********************");
		System.out.println("請輸入:");
	}
	
	/**
	 * 輸出當前揹包內物品
	 */
	public void outBag(Player player) {
		// 這是引用對象,我們這麼做沒有創建新的東西,就是做了個指針指向bag.
		MyArray arr = player.bag;
		int size = arr.getSize();
		System.out.println("$$$$$$$$$揹包$$$$$$$$$");
		for (int i = 0;i < size;i++) {
			System.out.println(i + ":" + arr.get(i));
		}
		System.out.println("$$$$$$$$$$$$$$$$$$$$$");
		System.out.println("請輸入編號直接使用,輸入-1返回");
	}
	
}

 Player角色信息類


public class Player {
	/**
	 * 生命值 默認100
	 */
	int health = 100;
	
	/**
	 * 生命上限,扣血不會扣這個,用於事後恢復
	 */
	int defaultHealth = health;
	
	/**
	 * 攻擊力 默認10
	 */
	int attack = 10;
	
	/**
	 * 防禦力
	 */
	int defence = 0;
	
	/**
	 * 級別 默認爲1
	 */
	int level = 1;
	
	/**
	 * 經驗值
	 */
	int exp = 0;
	
	/**
	 * 金幣
	 */
	int money = 100;
	
	/**
	 * 揹包
	 */
	MyArray bag = new MyArray();
	
	/**
	 * 寵物
	 */
	Player pet;
	
	/**
	 * 裝備
	 */
	Player equip;
	
	/**
	 * 增加經驗
	 */
	public void addExp(int addExp) {
		// 獲取當前升級所需要的經驗,並判斷添加後是否升級
		int upLevel = level * level;
		// 升級所需經驗 - 當前經驗 小於等於添加的經驗則升級
		while (upLevel - exp <= addExp) {
			// 等級+1,經驗等於添加經驗減去升級剩餘所需經驗
			level++;
			addExp -= upLevel - exp;
			exp = 0;
			// 升級隨機添加血量 攻擊力[0-等級*等級],這裏用到的不會怎麼多 直接使用Math.random.
			defaultHealth += (int)(Math.random()*100)%upLevel;
			health += defaultHealth;
			attack += (int)(Math.random()*100)%upLevel;
			upLevel = level * level;
		}
		exp += addExp;
	}
	
	public String toString() {
		// 創建一個String用於存儲我們需要的字符串格式
		// 這裏 \r\n 是換行,因爲在不同操作系統下換行符不同(有用\r的,有用\n的),所以直接使用\r\n
		String str = "@@@@@@@@@@@@@@@@@@@@@\r\n";
		str += "生命值: " + health;
		str += "\r\n攻擊力: " + attack;
		str += "\r\n防禦力: " + defence;
		str += "\r\n等級: " + level;
		str += "\r\n經驗值: " + exp;
		str += "\r\n下一級所需經驗: " + (level*level - exp);
		str += "\r\n金幣: " + money;
		// 有寵物/裝備則顯示 不然不顯示
		// \t 等於一個tab鍵,這樣看起來會有級別的感覺
		if (pet != null) {
			str += "\r\n寵物: \r\n\t血量" + pet.health;
			str += "\r\n\t攻擊力" + pet.attack;
		}
		// 只有一個語句可以省略 {} 太長就別省略了 不好看.
		if (equip != null) str += "\r\n裝備: \r\n\t防禦力" + equip.defence;
		str += "\r\n@@@@@@@@@@@@@@@@@@@@@";
		return str;
	}
	
}

MyArray之前寫的可變長度數組類,這裏不提供,請如果需要請看之前文章

總結

勤思考,勤練習,這個實戰可以看出你之前學習的穩不穩固,如果你做起來感覺到困難或者有地方不能理解,請在評論區留言,共同進步!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章