首先介绍这是用java编写的宠物小精灵图形化界面,由于内容较多分为三节。
下面是游戏的全流程图
这是所有项目的所有类
首先,我先把类分别拷贝上来,展示他的内容。
这是物品显示接口,让子类继承他的方法
package com;
/**
* 物品显示接口
*/
public interface DisplayItem {
/**
* 获取物品信息
* @return
*/
String getItemInformation();
}
接下来是物品类,作用就是是所有游戏物品的抽象父类,它继承DisplayITem接口,为所有子类提供名称和关卡等级基础属性,discovery控制物品是否可见,没有被探索就是显示物品图案
package com.item;
import com.DisplayItem;
/**
* 物品
* 核心作用:所有游戏物品的抽象基类
* 关键特性:
* 1.discovery标志位控制物品是否可见(未探索显示物品图案)
* 2.未所有子类提供名称和关卡等级基础属性
*/
public abstract class Item implements DisplayItem {
protected String name;
protected int levelNumber;
public int getLevelNumber() {
return levelNumber;
}
/**
* 是否被探索
*/
protected boolean discovery = false;
public Item(String name) {
this.name = name;
}
public Item(String name, int levelNumber) {
this.name = name;
this.levelNumber = levelNumber;
}
public String getName() {
return name;
}
public void setDiscovery(boolean discovery) {
this.discovery = discovery;
}
}
这是药品类(HP)
继承ITem,功能就是恢复精灵生命值的消耗品
package com.item;
public class HP extends Item{
private int count;
public HP(int levelNumber,int count) {
super("天山雪莲", levelNumber);
this.count = count;
}
/**
* 是使用药品可以回复血量
* @return
*/
public int use(){
count--;
return levelNumber * 500;
}
/**
* 获取药品数量
*/
public int getCount() {
return count;
}
/**
* 堆叠药瓶
* @param count
*/
public void addCount(int count){
if (count > 0) {
this.count += count; // 将新数量累加到当前药品数量
}
}
/**
* 检测药品是否可以被摧毁
* @return
*/
public boolean canDestroy(){
return count == 0;
}
@Override
public String getItemInformation() {
return name;
}
}
这是传送门类(Portar)
功能:切换关卡的入口,分下一关和上一关,显示逻辑为探索就是黑正方形,右箭头是下一关,左箭头上一关。
package com.item;
public class Portar extends Item{
/**
* 是否通往下一关
*/
private boolean next;
public Portar(boolean next) {
super("传送门");
this.next = next;
}
public boolean isNext() {
return next;
}
@Override
public String getItemInformation() {
if(discovery){
return next ? "→" : "←";
}
return "■"; }
}
这是宝箱类(Treasure)
功能:地图上的可交互物品,开启后获得随机奖励,关键方法是open调用Tools.getRandomItem();生成物品。
显示逻辑:未探索和探索随便找了两个
package com.item;
import com.util.Tools;
/**
* 宝箱
*/
public class Treasure extends Item{
public Treasure(int levelNumber) {
super("宝箱", levelNumber);
}
/**
* 开启宝箱能够获得一个物品
* @return
*/
public Item open(){
return Tools.getRandomItem(levelNumber);
}
@Override
public String getItemInformation() {
return discovery ? "۞" : "■";
}
}
这是工具类(Tools)
功能:提供通用工具方法(输入处理、随机数生成、延迟)
核心方法:
getInputChar():从控制台获取单个字符,顺便确保输入有效性
getRandomNumber():生成指定的随机数字
getRandomItem():随机生成(精灵、装备、药品)
物品掉落概率
“药品” : 60
“装备” : 30
“精灵” : 10
package com.util;
import com.item.HP;
import com.item.Item;
import com.item.equipment.*;
import com.item.pokemon.Bikachu;
import com.item.pokemon.Bulbasaur;
import com.item.pokemon.Charmander;
import com.item.pokemon.Jolteon;
import java.util.Random;
import java.util.Scanner;
/**
* 工具类
*/
public class Tools {
/**
* 随机数对象
*/
private static final Random RANDOM = new Random();
/**
* 输入对象
*/
private static final Scanner SCANNER = new Scanner(System.in);
/**
* 从控制台获取一个字符
* @return
*/
public static char getInputChar(){
while (true){
String input = SCANNER.next().trim();//trim()方法会去掉输入字符串首尾的空白字符。
/**
* 若长度不为 1,就会输出错误提示"输出错误,请重新输",
* 然后继续下一次循环,等待用户重新输入。
* 若长度为 1,就会返回该字符串的第一个字符
* (也就是唯一的字符),此时方法执行结束。
*/
if(input.length() != 1)
{
System.out.println("输出错误,请重新输");
}else{
return input.charAt(0);
}
}
}
/**
* 从控制台获取给定范围内的数字
* @param min
* @param max
* @return
*/
public static int getInputNumber(int min,int max){
while (true){
if(SCANNER.hasNext()){
int num = SCANNER.nextInt();
if(num >= min && num <= max){
return num;
}else
{
System.out.println("输入错误,请输入" + min + "~" + max + "之间的整数");
}
}else{
System.out.println("输入错误,请输入" + min + "~" + max + "之间的整数");
}
}
}
/**
* 延迟给定时间
* 作用:让当前线程休眠指定的毫秒数,暂停程序执行。
* 参数:time(长整型),表示休眠的毫秒数(例如 300L 表示 300 毫秒)。
* 异常处理:捕获并打印 InterruptedException(当线程在休眠期间被中断时抛出)。
* @param time
*/
public static void lazy(long time){
try {
Thread.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 获取给定范围内的随机数
* @param min 最大值
* @param max 最小值
* @param levelNumber 关卡编号
* @return
*/
public static int getRandomNumber(int min,int max,int levelNumber){
int diff = (max - min) * levelNumber;
return RANDOM.nextInt(diff) + min * levelNumber;
}
/**
* 获取给定范围内的随机数
* @param min
* @param max
* @return
*/
public static int getRandomNumber(int min,int max){
return getRandomNumber(min,max,1);
}
/**
* 获取给定范围内的随机数
* @param max
* @return
*/
public static int getRandomNumber(int max){
return getRandomNumber(0,max);
}
public static Item getRandomItem(int levelNumber){
//取[0,10)范围内的随机数
int number = Tools.getRandomNumber(10);
if(number == 0)//获得宠物小精灵,比例初级中级高级究极:80:15:4:1
{
int rate = Tools.getRandomNumber(100);
if(rate == 0){//究极宠物小精灵=>比卡丘
return new Bikachu();
}else if(rate <= 4)//高级宠物小精灵=>小火龙
{
return new Charmander();
}else if(rate <= 20)//中级宠物雷精灵
{
return new Jolteon();
}
else{//初级宠物小精灵
return new Bulbasaur();
}
}
else if(number <= 3)//获得装备
{//比例 武器项链戒指手镯头盔铠甲护腰鞋子:=3:5:8:8:19:19:19:19
int rate = Tools.getRandomNumber(100);
if(rate < 3){//武器
return new Weapon(levelNumber);
}
else if(rate < 8)//项链
{
return new Necklace(levelNumber);
}else if(rate<16)//戒指
{
return new Ring(levelNumber);
}
else if(rate < 24)
{//手镯
return new Bracelet(levelNumber);
}else if(rate < 43)
{//头盔
return new Helmet(levelNumber);
}else if(rate < 62)
{//铠甲
return new Armor(levelNumber);
}else if(rate < 81)//护腿
{
return new Leggings(levelNumber);
}else {
return new Shoe(levelNumber);
}
}
else {//获得药品
return new HP(levelNumber,10);
}
}
}
这是关卡系统(Level)
功能:管理关卡层级关系(前后关系)关联关卡编号和地图
关键属性:
number:关卡编号
preLevel / nextLevel:前后关卡
map:当前关卡地图,new出来一个LevelMap实例
核心逻辑:通过preLevel / nextLevel实现关卡切换
package com.level;
/**
* 关卡系统
* 管理关卡编号,前后关卡引用
* 包含LevelMap
*/
public class Level {
/**
* 关卡编号
*/
private int number;
/**
* 关卡地图
*/
private LevelMap map;
private Level prevLevel;
private Level nextLevel;
public Level(Level prevLevel,int number, Level nextLevel) {
this.number = number;
this.prevLevel = prevLevel;
this.nextLevel = nextLevel;
this.map = new LevelMap(number);
}
public int getNumber() {
return number;
}
public LevelMap getMap() {
return map;
}
public Level getPrevLevel() {
return prevLevel;
}
public void setPrevLevel(Level prevLevel) {
this.prevLevel = prevLevel;
}
public Level getNextLevel() {
return nextLevel;
}
public void setNextLevel(Level nextLevel) {
this.nextLevel = nextLevel;
}
}
这是关卡地图(LevelMap)
功能:管理游戏地图9*9网格,生成地图元素,处理冒险家移动和位置查询
关键属性:items[9][9]:存储地图上的所有物品(DisplayItem)
currentRow/currentCol:记录冒险家当前位置
核心方法:
generate()方法按照比例生成地图元素(宝箱:怪物:传送门:39:39:1),第一关第一个位置是冒险家,第二个位置初始为低级怪物,其他关卡第一个位置为传送门,第二个位置为冒险家。
getPositionItem(char direct):根据方向WASD获取目标位置的物品。
move(char direct):移动冒险家位置,处理非法移动提示
show():绘制地图界面
package com.level;
import com.Adventurer;
import com.DisplayItem;
import com.item.Portar;
import com.item.Treasure;
import com.item.monster.*;
import com.util.Tools;
/**
* 关卡地图
*/
public class LevelMap {
/**
* 关卡编号
*/
private int number;
/**
* 地图上的物品 9*9
*/
private final DisplayItem[][] items = new DisplayItem[9][9];
/**
* 记录冒险家在地图中的位置
*/
private int currentRow,currentCol;
public LevelMap(int number) {
this.number = number;
generate();
}
/**
* 生成地图 => 宝箱:怪物:传送门 = 39:39:1
* 第一个位置和第二个位置不能使用
*/
private void generate(){
if(number == 1)//表示第一关卡
{
//第二个位置为初级怪物象牙猪
items[0][1] = new Mamoswine(number);
items[0][0] = new Mamoswine(number);
}else{//其他关卡
//第一个位置为返回上一层的传送门
items[0][0] = new Portar(false);
items[0][1] = new Portar(false);
}
//记录生成的宝箱数量
int generatedTreasure = 0;
//记录生成的怪物数量
int generatedMonster1 = 0;//记录生成的初级怪物数量
int generatedMonster2 = 0;//记录生成的中级怪物数量
int generatedMonster3 = 0;//记录生成的高级怪物数量
int generatedMonster4 = 0;//记录生成的究极级怪物数量
//记录生成的传送门数量
int generatedPortal = 0;
//第0个和第1个位置已经取到了,所以从2到81生成
while (generatedTreasure < 39
|| (generatedMonster1 + generatedMonster2 + generatedMonster3 +generatedMonster4) < 39
|| generatedPortal == 0)
{
//获取随机坐标
int index = Tools.getRandomNumber(2,81);
//计算行和列
int row = index / items[0].length;//行
int col = index % items[0].length;//列
//目标位置已经有物品存在
if(items[row][col] != null) continue;//不为null,直接进入下一次循环
//获取一个随机数
int rate = Tools.getRandomNumber(79);
if(rate == 0)//传送门
{
if(generatedPortal == 1) continue;
items[row][col] = new Portar(true);
generatedPortal += 1;
}
else if(rate < 40)//宝箱
{
if(generatedTreasure == 39) continue;
items[row][col] = new Treasure(1);
generatedTreasure += 1;
}
else//怪物 初级:中级:高级:究极 = 18:12:6:3
{
int num = Tools.getRandomNumber(39);
if(num < 3)//究极怪物
{
if(generatedMonster4 == 3) continue;
items[row][col] = new Moltres(number);
generatedMonster4 += 1;
}else if(num < 9)//高级怪物
{
if(generatedMonster3 == 6)continue;
items[row][col] = new Ramoraid(number);
generatedMonster3 += 1;
}
else if(num < 21)//中级怪物
{
if(generatedMonster2 == 12)continue;
items[row][col] = new CattleMonster(number);
generatedMonster2 += 1;
}
else
{
if(generatedMonster1 == 18) continue;
items[row][col] = new Mamoswine(number);
generatedMonster1 += 1;
}
}
}
}
/**
* 获取给定方法位置的物品信息
* @param direct 方向
* 这段代码通过方向判断→坐标调整→边界检查→获取物品的流程,
* 实现了根据方向查询目标位置物品的功能。
* 返回类型为 DisplayItem 是因为地图中所有物品都实现了该接口,
* 保证了代码的通用性和扩展性。
* @return
*/
public DisplayItem getPositionItem(char direct){
int targetRow = currentRow,targetCol = currentCol;
switch (direct){
case 'W'://向上
if(targetRow == 0){
return null;
}
targetRow -= 1;
break;
case 'A'://向左
if(targetCol == 0){
return null;
}
targetCol -= 1;
break;
case 'S'://向下
if(targetRow == items.length - 1)
{
return null;
}
targetRow += 1;
break;
case 'D'://向右
if(targetCol == items[currentRow].length - 1)
{
return null;
}
targetCol += 1;
break;
}
return items[targetRow][targetCol];
}
/**
* 向给定方向移动冒险家的位置
* @param direct
*/
public void move(char direct){
int oldRow = currentRow,oldCol = currentCol;
//获取冒险家
DisplayItem adventurer = items[oldRow][oldCol];
switch (direct){
case 'W'://向上
if(currentRow == 0){
System.err.println("非法移动");
Tools.lazy(300L);
return;
}
currentRow -= 1;
break;
case 'A'://向左
if(currentCol == 0){
System.err.println("非法移动");
Tools.lazy(300L);
return;
}
currentCol -= 1;
break;
case 'S'://向下
if(currentRow == items.length - 1)
{
System.err.println("非法移动");
Tools.lazy(300L);
return;
}
currentRow += 1;
break;
case 'D'://向右
if(currentCol == items[currentRow].length - 1)
{
System.err.println("非法移动");
Tools.lazy(300L);
return;
}
currentCol += 1;
break;
}
//冒险家新的位置
items[currentRow][currentCol] = adventurer;
//原来的位置就不在存在物品了
items[oldRow][oldCol] = null;
}
/**
* 添加冒险家
* @param adventurer
*/
public void addAdventure(Adventurer adventurer){
currentRow = 0;
if(number == 1)//如果是第一关
{
currentCol = 0;
}
else {
currentCol = 1;
}
items[currentRow][currentCol] = adventurer;
}
/**
* 展示地图
*/
public void show(){
System.out.println("宠物小精灵第" + number + "关");
for(int i=0;i<items.length;i++)
{
String line1 = "", line2 = "";
for(int j=0;j<items[i].length;j++)
{
String info = " ";
if(items[i][j] != null){
info = items[i][j].getItemInformation();
}
if(i==0)//第一行
{
if(j == 0)//第一列
{
line1 += "┌───";
line2 += "│ " + info +" ";
}else if(j == items[i].length-1)
{
line1 += "┬───┐";
line2 += "│ " + info + " │";
}
else{
line1 += "┬───";
line2 += "│ " + info + " ";
}
}
else {
if(j == 0){//第一列
line1 += "├───";
line2 += "│ " + info + " ";
}
else if(j == items[i].length - 1)
{
line1 += "┼───┤";
line2 += "│ " + info + " │";
}
else
{
line1 += "┼───";
line2 += "│ " + info + " ";
}
}
}
System.out.println(line1);
System.out.println(line2);
}
String lastLine = "";//最后一格网格线
for(int i=0;i<items[0].length;i++)
{
if(i==0){//第一列
lastLine += "└───";
}else if(i == items[0].length - 1){//最后一列
lastLine += "┴───┘";
}else{
lastLine += "┴───";
}
}
System.out.println(lastLine);
}
}
以上就是部分类的实现,接下来请见第2节和第3节(冒险家类、怪物类、小精灵类、装备类、启动类)
感谢大家观看!我一定会成为java高手的!嘿嘿嘿