Java小游戏

一、需求

             

 二、思路一

        HP当然是怪物的一个属性成员,而武器是角色的一个属性成员,类型可以使字符串,用于描述目前角色所装备的武器。角色类有一个攻击方法,以被攻击怪物为参数,当实施一次攻击时,攻击方法被调用,而这个方法首先判断当前角色装备了什么武器,然后据此对被攻击怪物的HP进行操作,以产生不同效果

package com.homework.game;public class Monster {//定义怪物名称public String monster_name;//定义怪物血量public int monster_hp;//定义构造方法
//    public Monster(){
//    }//定义有参数的构造方法,主函数中调用此方法可以传递怪物的名称和初始血量public Monster(String name,int hp){//给怪物名称和初始血量赋值this.monster_name = name;this.monster_hp = hp;}
//    //设置怪物的名称
//    public void setMonsterName(String name){
//        this.monster_name = name;
//    }//返回怪物名称public String getMonsterName(){return this.monster_name;}//设置怪物的血量public void setMonsterHp(int hp){this.monster_hp = hp;}
//返回怪物血量public int getMonsterHp(){return this.monster_hp;}
}package com.homework.game;import javax.sound.midi.SoundbankResource;
import java.util.Random;public class Player {//创建玩家名称变量public String player_name;//创建玩家武器变量public String player_weapon;//设置玩家名称方法public void setPlayerName(String name){this.player_name = name;}//获取玩家名称方法public String getPlayerName(){return this.player_name;}//设置玩家武器public void setPlayWeapon(String weapon){this.player_weapon = weapon;}//获取玩家武器public String getPlayerWeapon(){return this.player_weapon;}//玩家攻击方法public void attackMethod(Monster monster){
//        System.out.println(monster.getMonsterHp());
//        System.out.println(this.player_weapon);if (monster.getMonsterHp() > 0){if("木剑".equals(this.player_weapon)){int hp = monster.getMonsterHp();hp = hp - 20;monster.setMonsterHp(hp);if (hp > 0){System.out.println(this.player_name+"用"+this.player_weapon+"打了20HP,"+monster.getMonsterName()+"还剩余"+monster.getMonsterHp()+"血量,可继续攻击");}else {System.out.println(monster.getMonsterName()+"被击杀!!!");return;}}else if("铁剑".equals(this.player_weapon)){if (monster.getMonsterHp() > 0){int hp = monster.getMonsterHp();hp = hp - 50;monster.setMonsterHp(hp);if (hp > 0){System.out.println(this.player_name+"用"+this.player_weapon+"打了50HP,"+monster.getMonsterName()+"还剩余"+monster.getMonsterHp()+"血量,可继续攻击");}else {System.out.println(monster.getMonsterName()+"被击杀!!!");return;}}else {System.out.println(monster.getMonsterName()+"死了,不需要攻击了!!!");return;}}else if("魔剑".equals(this.player_weapon)){if (monster.getMonsterHp() > 0){int random = ((int)(Math.random()*10))+1;int less_hp = (random > 5)?200:100;if (less_hp == 200){System.out.println("暴击了!!!!");}int hp = monster.getMonsterHp();hp = hp - less_hp;monster.setMonsterHp(hp);if (hp > 0){System.out.println(this.player_name+"用"+this.player_weapon+"打了"+less_hp+"HP"+monster.getMonsterName()+"还剩余"+monster.getMonsterHp()+"血量,可继续攻击");}else {System.out.println(monster.getMonsterName()+"被击杀!!!");return;}}}else {System.out.println("没有武器,无法攻击");}}else {System.out.println(monster.getMonsterName()+"死了,无需攻击!!!");}}
}package com.homework.game;import java.util.Scanner;public class TestMain {public static void main(String[] args) {System.out.println("------------------游戏开始------------------");//创建怪物对象Monster monster = new Monster("魔王",500);//创建玩家对象Player player = new Player();//创建两个录入对象Scanner player_name_scanner = new Scanner(System.in);Scanner player_weapon_scanner = new Scanner(System.in);//定义玩家名称变量System.out.println("请输入玩家名称:");String player_name = player_name_scanner.next();while(true){if(monster.getMonsterHp() > 0){System.out.println("请输入武器准备(木剑、铁剑、魔剑):");String player_weapon = player_weapon_scanner.next();player.setPlayerName(player_name);player.setPlayWeapon(player_weapon);player.attackMethod(monster);}else {System.out.println("--------------------You Win----------------------");break;}}}
}

 小结:

计的角色类的攻击方法很长,并且方法中有一个冗长的if…else结构,且每个分支的代码的业务逻辑很相似,只是很少的地方不同。

再者,上述设计思路,违反了O【Open】C【Close】P原则。在这个设计中,如果以后我们增加一个新的武器,如倚天剑,每次攻击损失500HP,那么,我们就要打开角色类,修改攻击方法。而我们的代码应该是对修改关闭的,当有新武器加入的时候,应该使用扩展完成,避免修改已有代码。

一般来说,当一个方法里面出现冗长的if…else或switch…case结构,且每个分支代码业务相似时,往往预示这里应该引入多态性来解决问题。而这里,如果把不同武器攻击看成一个策略,那么引入策略模式(Strategy Pattern)是明智的选择

Tip:OCP原则,即开放关闭原则,指设计应该对扩展开放,对修改关闭。

Tip:策略模式,英文名Strategy Pattern,指定义算法族,分别封装起来,让他们之间可以相互替换,此模式使得算法的变化独立于客户。

三、思路二

        因上述原因,我们重新设计,得到以下思路

 

package com.homework.game2;
//定义一个攻击接口,以怪物作为参数,各类武器实现这个攻击接口
public interface Attack {public void attcak(Monsters monsters);
}package com.homework.game2;
//武器----木剑
public class WoodenSword implements Attack {@Overridepublic void attcak(Monsters monsters) {//通知怪物失去对应血量monsters.bloodLoss(20,"木剑");}
}package com.homework.game2;
//武器----铁剑类
public class IronSword implements Attack{@Overridepublic void attcak(Monsters monsters) {//通知怪物掉血50monsters.bloodLoss(50,"铁剑");}}package com.homework.game2;import javax.sound.midi.SoundbankResource;//武器-----魔剑类
public class MagicSword implements Attack{@Overridepublic void attcak(Monsters monsters) {int random = ((int)(Math.random()*10))+1;if(random > 5){System.out.println("魔剑暴击了,击杀200Hp!!!");monsters.bloodLoss(200,"魔剑");}else {monsters.bloodLoss(100,"魔剑");}}
}package com.homework.game2;
//怪物类
public class Monsters {//定义怪物的名称public String monsters_name;//定义怪物的血量public int monsters_hp;
//    //构造方法,用来创建对象
//    public Monsters(){}
//    //定义怪物的构造方法,在主方法中传入参数,初始化怪物属性public Monsters(String name,int hp){this.monsters_name = name;this.monsters_hp = hp;}
//    //获取怪物名称方法
//    public String getMonstersName(){
//        return this.monsters_name;
//    }
//    //设置怪物血量
//    public void setMonstersHp(int hp){
//        this.monsters_hp = hp;
//    }
//    //获取怪物血量
//    public int getMonsterHp(){
//        return this.monsters_hp;
//    }//怪物掉血的方法,参数  1.掉血量;2.使用的武器Players players =new Players("王也");public void bloodLoss(int hp,String weapon_name){if(this.monsters_hp > 0){this.monsters_hp = this.monsters_hp - hp;if(this.monsters_hp > 0){System.out.println(players.getPlayersName()+"用"+weapon_name+"攻击了"+this.monsters_name+hp+"Hp,剩余"+this.monsters_hp+"Hp,可以继续攻击");}else {System.out.println(this.monsters_name+"死了,无需攻击");}}else {System.out.println(this.monsters_name+"死了,无需攻击");return;}}
}package com.homework.game2;
//玩家类
public class Players {//定义玩家名称public String players_name;//定义玩家武器public Attack players_weapon;//设置玩家构造方法,初始化玩家名称public Players(String name){this.players_name = name;}
//    //设置玩家名称方法
//    public void setPlayersName(String name){
//        this.players_name = name;
//    }//获取玩家名称方法public String getPlayersName(){return this.players_name;}//接口回调 Attack weapon 接口回调变量//设置玩家武器方法,传入接口参数,将变量赋值给this.players_weaponpublic void setPlayersWeapon(Attack weapon){this.players_weapon = weapon;}
//    //获取玩家武器方法
//    public Attack getPlayersWeapon(){
//        return this.players_weapon;
//    }//玩家攻击方法public void player_AttcakMethod(Monsters monsters){this.players_weapon.attcak(monsters);}}package com.homework.game2;public class TestMain {public static void main(String[] args) {//创建怪物对象Monsters monsters = new Monsters("大魔王",200);//创建玩家对象Players players = new Players("王也");players.setPlayersWeapon(new WoodenSword());players.player_AttcakMethod(monsters);players.setPlayersWeapon(new IronSword());players.player_AttcakMethod(monsters);players.setPlayersWeapon(new MagicSword());players.player_AttcakMethod(monsters);}
}

改进后的代码有如下优点:

第一,虽然类的数量增加了,但是每个类中方法的代码都非常短,没有了以前攻击方法那种很长的方法,也没有了冗长的if…else,代码结构变得很清晰。

第二,类的职责更明确了。在第一个设计中,角色不但负责攻击,还负责给怪物减少HP和判断怪物是否已死。这明显不应该是角色的职责,改进后的代码将这两个职责移入怪物内,使得职责明确,提高了类的内聚性。

第三,引入Strategy[策略]模式后,不但消除了重复性代码,更重要的是,使得设计符合了OCP。如果以后要加一个新武器,只要新建一个类,实现武器接口,当角色需要装备这个新武器时,客户代码只要实例化一个新武器类,并赋给角色的武器成员就可以了,已有的角色和怪物代码都不用改动。这样就实现了对扩展开发,对修改关闭

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/86236.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

卷积过程详细讲解

1:单通道卷积 以单通道卷积为例,输入为(1,5,5),分别表示1个通道,宽为5,高为5。假设卷积核大小为3x3,padding0,stride1。 卷积过程如下: 相应的卷积核不断…

怎么在线制作思维导图?分享几个好用的方法和注意事项

思维导图是一种非常有用的工具,它可以帮助我们整理和梳理思路,提高学习和工作效率。现在,越来越多的人开始使用在线工具来制作思维导图,因为它们不仅方便易用,而且可以随时随地进行编辑和共享。本文将介绍几个好用的在…

封装公共el-form表单(记录)

1.公共表单组件 //commonForm.vue <script> import {TEXT,SELECT,PASSWORD,TEXTAREA,RADIO,DATE_PICKER } from /conf/uiTypes import { deepClone } from /utils export default {name: GFormCreator,props: {config: { // title/itemstype: Object,required: true}}…

视频云存储/安防监控视频智能分析网关V3:占道经营功能详解

违规占道经营者经常会在人流量大、车辆集中的道路两旁摆摊&#xff0c;导致公路交通堵塞&#xff0c;给居民出行的造成不便&#xff0c;而且违规占路密集的地方都是交通事故频频发生的区域。 TSINGSEE青犀视频云存储/安防监控视频/AI智能分析网关V3运用视频AI智能分析技术&…

关于 Camera 预览和录像画质不一样的问题分析

1、问题背景 基于之前安卓平台的一个项目&#xff0c;客户有反馈过一个 Camera app 预览的效果&#xff0c;和录像效果不一致的问题。 这里的预览是指打开 Camera app 后直接出图的效果&#xff1b;录像的效果则是指打开 Camera app 开启录像功能&#xff0c;录制一段视频&…

高中信息技术教资考试模拟卷(22下)

2022 年下半年全国教师资格考试模考卷一 &#xff08;高中信息技术&#xff09; 一、单项选择题&#xff08;本大题共 15 小题&#xff0c;每小题 3 分&#xff0c;共 45 分&#xff09; 1.2006 年 10 月 25 日&#xff0c;深圳警方成功解救出一名被网络骗子孙某…

webassembly003 GGML Tensor Library part-1

GGML ggml的函数 可以看到官方示例项目仅依赖于#include "ggml/ggml.h"&#xff0c; #include "common.h"&#xff0c;可以阅读ggml.h获取ggml的使用帮助 函数解释注释ggml_tensor多维张量按行主顺序存储。ggml_tensor结构包含每个维度中元素数&#xf…

【腾讯云 Cloud Studio 实战训练营】从零开始搭建一个数据大屏

文章目录 前言得到什么?使用Cloud Studio登录Cloud Studio登录方式Cloud Studio 功能介绍项目创建配置描述新建工作空间绑定Coding创建仓库绑定coding创建项目项目空间 项目搭建nuxt 脚手架Cloud Studio 安装插件nuxt初始项目预览问题描述 下载Datav 并体验页面结构展示 获取基…

PostgreSQL命令行工具psql常用命令

1. 概述 通常情况下操作数据库使用图形化客户端工具&#xff0c;在实际工作中&#xff0c;生产环境是不允许直接连接数据库主机&#xff0c;只能在跳板机上登录到Linux服务器才能连接数据库服务器&#xff0c;此时就需要使用到命令行工具。psql是PostgreSQL中的一个命令行交互…

SSL证书申请

DV SSL证书申请需要多久&#xff1f; DV SSL证书无需验证所有者资质资料&#xff0c;审核流程相对简单&#xff0c;因此可快速签发。但部分域名信息可能会触发不同等级的安全审查机制&#xff0c;必要时需要人工介入进行审查签发&#xff0c;因此&#xff0c;SSL证书签发时间可…

LC-1267. 统计参与通信的服务器(枚举 + 计数)

1267. 统计参与通信的服务器 中等 这里有一幅服务器分布图&#xff0c;服务器的位置标识在 m * n 的整数矩阵网格 grid 中&#xff0c;1 表示单元格上有服务器&#xff0c;0 表示没有。 如果两台服务器位于同一行或者同一列&#xff0c;我们就认为它们之间可以进行通信。 请…

基于PyTorch深度学习遥感影像地物分类与目标检测、分割及遥感影像问题深度学习优化

我国高分辨率对地观测系统重大专项已全面启动&#xff0c;高空间、高光谱、高时间分辨率和宽地面覆盖于一体的全球天空地一体化立体对地观测网逐步形成&#xff0c;将成为保障国家安全的基础性和战略性资源。未来10年全球每天获取的观测数据将超过10PB&#xff0c;遥感大数据时…