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.rhkb.cn/news/107327.html

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

相关文章

31、springboot 配置HTTP服务端口及如何通过WebServer实例动态获取项目中的HTTP端口

配置HTTP服务端口及如何通过WebServer实例动态获取项目中的HTTP端口 ★ 设置HTTP服务端口: - server.port或者SERVER_PORT环境变量——总结来说,其实就是要配置server.port外部配置属性。▲ 同样遵守如下优先级: 这些都是外部配置源&#x…

Android——基本控件下(十七)

1. 文本切换&#xff1a;TextSwitcher 1.1 知识点 &#xff08;1&#xff09;理解TextSwitcher和ViewFactory的使用。 1.2 具体内容 范例&#xff1a;切换显示当前时间 <LinearLayout xmlns:android"http://schemas.android.com/apk/res/android"xmlns:tools&…

嵌入式设备应用开发(发现需求和提升价值)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 很多做技术的同学,都会陷入到技术的窠臼之中。对于如何做具体的产品、实现具体的技术,他们可能很感兴趣。但是做出来的东西做什么用,或者说是有没有竞争力,事实上他们不是很关心…

使用 Transformer 和 Amazon OpenSearch Service 构建基于列的语义搜索引擎

在数据湖中&#xff0c;对于数据清理和注释、架构匹配、数据发现和跨多个数据来源进行分析等许多操作&#xff0c;查找相似的列有着重要的应用。如果不能从多个不同的来源准确查找和分析数据&#xff0c;就会严重拉低效率&#xff0c;不论是数据科学家、医学研究人员、学者&…

无涯教程-PHP - Filtered反序列化

PHP 7引入了Filtered unserialize()函数&#xff0c;以在对不受信任的数据上的对象进行反序列化时提供更好的安全性。 <?phpclass MyClass1 { public $obj1prop; }class MyClass2 {public $obj2prop;}$obj1new MyClass1();$obj1->obj1prop1;$obj2new MyClass2();$obj…

15.live555mediaserver-rtp打包

live555工程代码路径 live555工程在我的gitee下&#xff08;doc下有思维导图、drawio图&#xff09;&#xff1a; live555 https://gitee.com/lure_ai/live555/tree/master 章节目录链接 0.前言——章节目录链接与为何要写这个&#xff1f; https://blog.csdn.net/yhb1206/art…

php插件Workerman聊天室示例

chat.php内容如下 <?php//使用workerman&#xff0c;只需引入这个文件require_once "workerman-4.0/Autoloader.php";//创建服务器&#xff0c;监听3000端口$wsServernew \Workerman\Worker("websocket://127.0.0.1:3000");$wsServer->onConnectfu…

vscode流程图插件使用

vscode流程图插件使用 1.在vscode中点击左下角设置然后选择扩展。 2.在扩展中搜索Draw.io Integration&#xff0c;安装上面第一个插件。 3.安装插件后在工程中创建一个后缀为drawio的文件并且双击打开即可绘制流程图

Zuul:路由网关

话不多说上实战 先建一个子模块 pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://m…

Linux通过libudev获取挂载路径、监控U盘热拔插事件

文章目录 获取挂载路径监控U盘热拔插事件添libudev加库 获取挂载路径 #include <stdio.h> #include <libudev.h> #include <string.h>int main() {struct udev *udev;struct udev_enumerate *enumerate;struct udev_list_entry *devices, *entry;// 创建ude…

软件工程(十五) 行为型设计模式(一)

1、责任链模式 简要说明 通过多个对象处理的请求,减少请求的发送者与接收者之间的耦合。将接受对象链接起来,在链中传递请求,直到有一个对象处理这个请求。 速记关键字 传递职责 类图如下 由类图可以比较容易的看出来,其实就是自己关联自己,形成了一个链,并且自己有…

如何构建多域名HTTPS代理服务器转发

在当今互联网时代&#xff0c;安全可靠的网络访问是至关重要的。本文将介绍如何使用SNI Routing技术来构建多域名HTTPS代理服务器转发&#xff0c;轻松实现多域名的安全访问和数据传输。 SNI代表"Server Name Indication"&#xff0c;是TLS协议的扩展&#xff0c;用于…

STM32 Cubemx配置串口收发

文章目录 前言注意事项Cubemx配置printf重定向修改工程属性修改源码 测试函数 前言 最近学到了串口收发&#xff0c;简单记录一下注意事项。 注意事项 Cubemx配置 以使用USART1为例。 USART1需配置成异步工作模式Asynchronous。 并且需要使能NVIC。 printf重定向 我偏向…

飞天使-k8s基础组件分析-服务与ingress

文章目录 服务的介绍服务代理服务发现连接集群外服务服务发布无头服务 服务&#xff0c;pod和dns的关系端口转发通过expose 暴露应用服务案例INGRESSMetalLB使用参考文档 服务的介绍 服务的作用是啥&#xff1f; 提供外部调用&#xff0c;保证podip的真实性看看服务解决了什么…

鸿鹄工程项目管理系统 Spring Cloud+Spring Boot+前后端分离构建工程项目管理系统 em

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff…

软件工程(八) UML之类图与对象图

1、类图与对象图 1.1、类图与对象图的概念 类图(class diagram)描述一组类、接口、协作和它们之间的关系 对象图(object diagram)描述一组对象及它们之间的关系、对象图描述了在类图中所建立的事物实例的静态快照。 1.2、类图与对象图的区别 类图和对象图基本上是一样…

CSS 属性值计算过程

目录 例子1&#xff0c;确定声明值2&#xff0c;层叠冲突2.1&#xff0c;比较源重要性2.2&#xff0c;比较优先级2.3&#xff0c;比较源次序 3&#xff0c;使用继承4&#xff0c;使用默认值其他 例子 我们来举例说明<h1> 标签最终的样式&#xff1a; <div><h1…

专题-【B树的构建与删除】

构建&#xff1a; 删除&#xff1a; 叶子结点直接删&#xff1b; 非叶结点 找前驱&#xff08;左子树最右边&#xff09;/后继&#xff08;右子树最左边&#xff09;元素覆盖即可&#xff08;满足关键字个数取值范围&#xff09;&#xff1b; 这个更详细 『数据结构与算法』…

Spring Boot(Vue3+ElementPlus+Axios+MyBatisPlus+Spring Boot 前后端分离)【四】

&#x1f600;前言 本篇博文是关于Spring Boot(Vue3ElementPlusAxiosMyBatisPlusSpring Boot 前后端分离)【四】&#xff0c;希望你能够喜欢 &#x1f3e0;个人主页&#xff1a;晨犀主页 &#x1f9d1;个人简介&#xff1a;大家好&#xff0c;我是晨犀&#xff0c;希望我的文章…

opencv/C++ 人脸检测

前言 本文使用的测试资源说明&#xff1a; opencv版本&#xff1a;opencv 4.6.0 人脸检测算法 Haar特征分类器 Haar特征分类器是一个XML文件&#xff0c;描述了人体各个部位的Haar特征值。包括&#xff1a;人脸、眼睛、鼻子、嘴等。 opencv 4.6.0自带的Haar特征分类器&…