阶段项目-宠物小精灵——1

   首先介绍这是用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高手的!嘿嘿嘿

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值