[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之前写的可变长度数组类,这里不提供,请如果需要请看之前文章

总结

勤思考,勤练习,这个实战可以看出你之前学习的稳不稳固,如果你做起来感觉到困难或者有地方不能理解,请在评论区留言,共同进步!

猜你喜欢

转载自blog.csdn.net/qq_41806966/article/details/106909295