策略模式实战 - 猜拳游戏

**可以整体的替换一套算法,这就是策略模式。**这样对于同一个问题,可以有多种解决方案——算法实现的时候,可以通过策略模式来非常方便的进行算法的整体替换,而各种算法是独立封装好的,不用修改其内部逻辑。

具体的实战,下面给出一个经典案例——“猜拳游戏”。该示例来自于【日】结城浩的《图解设计模式》,策略算法做了一些简化调整。

“石头剪刀布”的游戏每轮出什么样的手势,可以遵循一定的策略。比如可以按照下面两种策略来出手势:

  1. 看上一轮自己出的手势,如果赢了,继续用上一轮出的手势;否则出任意的手势
  2. 看上一轮对方出的手势
    1. 如果赢了,就出和上一轮不一样的手势;
    2. 如果上一轮平了(比如出的剪刀),本轮就出石头;
    3. 如果上一轮输了,本轮就出上一轮和对方一样的手势

文章目录

    • 整体类图设计
    • 出手势策略接口
    • 手势类
    • 玩家类
    • 策略实现类
    • 测试类

整体类图设计

在这里插入图片描述

出手势策略接口

因此抽象出一个出手势的策略接口:

/*** Java小卷带你轻松高效学编程,一对一辅导加q1372569394*/
package com.juan.java.designpattern.strategy;/**** @author Java小卷* @date 2024-12-04 14:16* @since 1.0*/
public interface Strategy {/*** 下一回合出手势的方法* @author Java小卷* @date 2024/12/5 14:04* @return 出的手势* @since 1.0*/Hand nextHand();/*** 仔细考虑上一轮的结果,作为下一轮出手势的策略的依据* @author Java小卷* @date 2024/12/5 14:07* @param result 上一轮的结果 0-打平 1-胜 -1-负* @param other 上一轮对方的手势* @since 1.0*/void study(int result, Hand other);}

在这里插入图片描述

手势类

封装了手势具体信息和比手势的方法。

在这里插入图片描述

这里会维护3个公开的静态常量来分别维护“石头、剪刀、布”的手势数值。

/** 出的石头 */
public static final int HANDVALUE_STONE = 0;
/** 出的剪刀 */
public static final int HANDVALUE_SCISSORS = 1;
/** 出的布 */
public static final int HANDVALUE_PAPER = 2;

为方便对三种手势对象的获取,这里的手势值和三种手势对象的数组的索引值保持一致。

Hand类中维护一个私有的静态数组常量,初始化3个手势对象:

/** 初始化三种手势:石头、剪刀、布 */
private static final Hand[] HANDS = {new Hand(HANDVALUE_STONE),new Hand(HANDVALUE_SCISSORS),new Hand(HANDVALUE_PAPER)
};

同时维护一个对应手势名称的静态数组常量:

/** 描述出的手势的名称数组 */
private static final String[] HAND_NAMES = {"石头", "剪刀", "布"};

提供一个代表所出的手势值的成员变量,并提供相应的构造方法完成其初始化,注意Hand类不能在外部实例化,只能在内部维护,因此用private修饰:

/** 出的当前手势值 */
private final int handValue;/** 私有的带有手势值的构造 */
private Hand(int handValue) {this.handValue = handValue;
}

提供几个获取手势信息的方法:

/*** 根据手势值获取对应的手势对象* @param handValue 手势值* @return 对应的手势对象*/
public static Hand getHand(int handValue) {return HANDS[handValue];
}/*** 返回当前实例的手势名称* @author Java小卷* @date 2024/12/4 10:57* @return 手势名称* @since 1.0
*/
@Override
public String toString() {return HAND_NAMES[handValue];
}/*** 获取手势数值* @author Java小卷* @date 2024/12/5 15:14* @return int 手势数值* @since 1.0
*/
public int getHandValue() {return handValue;
}

提供比较手势的方法

/*** 手势对战方法* @author Java小卷* @date 2024/12/4 10:42* @param hand 对方出的手势* @return int 0-平局 1-胜 -1-负* @since 1.0
*/
private int fight(Hand hand) {// 自身比较无意义,但这里也记为平局if (this == hand) {return 0;} else if ((this.handValue + 1) % 3 == hand.handValue) {// 游戏规则:石头>剪刀>布>石头// 因此,只要按照数组的顺序,当前手势的下一个元素与对方手势相等,就认为自己赢了return 1;} else {// 其他情况都是判负return -1;}
}/*** 对外提供的判断赢了方法* @author Java小卷* @date 2024/12/4 10:55* @param hand 对方手势* @return boolean* @since 1.0
*/
public boolean isStrongThan(Hand hand) {return this.fight(hand) == 1;
}

玩家类

Player类在策略模式的类设计中,作为Context,由它负责设置和切换策略并调用策略的行为。

该玩家类除了namestrategy属性外,还包含了全局的状态信息(比赛总轮数、胜的轮数、败的轮数)。另外提供了调用策略对象完成出手势的方法以及对一轮比赛结果处理的方法。

在这里插入图片描述

策略实现类

正如前面一开始介绍的出手势的两种实现策略,这里提供两种具体的实现:

/*** Java小卷带你轻松高效学编程,一对一辅导加q1372569394*/
package com.juan.java.designpattern.strategy.impl;import .../**** @author Java小卷* @date 2024-12-04 14:21* @since 1.0*/
public class WinningStrategy implements Strategy {private final Random random;private int prevResult;private Hand prevHand;public WinningStrategy() {random = new Random();}@Overridepublic Hand nextHand() {// 前一轮不胜,则随意出if (prevResult != 1) {prevHand = Hand.getHand(random.nextInt(3));}// 否则出上一轮的手势return prevHand;}@Overridepublic void study(int result, Hand other) {this.prevResult = result;}
}
/*** Java小卷带你轻松高效学编程,一对一辅导加q1372569394*/
package com.juan.java.designpattern.strategy.impl;import .../**** @author Java小卷* @date 2024-12-04 15:38* @since 1.0*/
public class SmartStrategy implements Strategy {private final Random random;private int prevResult = 1;private Hand prevOtherHand;public SmartStrategy() {this.random = new Random();}@Overridepublic Hand nextHand() {// 如果前一轮平,则出比它大的if (prevResult == 0) {return Hand.getHand(Math.floorMod(prevOtherHand.getHandValue() - 1, 3));} else if (prevResult == -1) {// 输了则出和对方一样的return Hand.getHand(prevOtherHand.getHandValue());} else {// 赢了,则出不一样的if (prevOtherHand == null) {return Hand.getHand(random.nextInt(3));} else {Hand prevHand = Hand.getHand(Math.floorMod(prevOtherHand.getHandValue() - 1, 3));// 出和prevHand不一样的随机手势return Hand.getHand(Math.floorMod(prevHand.getHandValue() + random.nextInt(2) + 1, 3));}}}@Overridepublic void study(int result, Hand other) {this.prevResult = result;this.prevOtherHand = other;}
}

测试类

/*** Java小卷带你轻松高效学编程,一对一辅导加q1372569394*/
package com.juan.java.designpattern.strategy;import .../**** @author Java小卷* @date 2024-12-04 14:46* @since 1.0*/
public class Main {public static void main(String[] args) {Player player1 = new Player("糖宝", new WinningStrategy());Player player2 = new Player("小卷", new SmartStrategy());// 比赛10轮for (int i = 0; i < 10; i++) {Hand hand1 = player1.nextHand();Hand hand2 = player2.nextHand();if (hand1.isStrongThan(hand2)) {System.out.println("胜者: " + player1);player1.win(hand2);player2.lose(hand1);} else if (hand2.isStrongThan(hand1)) {System.out.println("胜者: " + player2);player2.win(hand1);player1.lose(hand2);} else {System.out.println("打平...");player1.even(hand2);player2.even(hand1);}}System.out.println("最终结果:");System.out.println(player1);System.out.println(player2);}}

程序输出:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

漫画之家Spring Boot:漫画资源的个性化推荐

4 系统设计 4.1系统设计主要功能 通过市场调研及咨询研究&#xff0c;了解了用户及管理者的使用需求&#xff0c;于是制定了管理员和用户等模块。功能结构图如下所示&#xff1a; 图4-1系统功能结构图 4.2数据库设计 4.2.1数据库设计规范 数据可设计要遵循职责分离原则&#…

C++:AVL树

文章目录 一、AVL树的概念二、AVL树的实现1、AVL树的节点2、 AVL的插入的过程3、平衡因子的更新 三、旋转1、右单旋2、左单旋3、右左双旋4、右左双旋 四、AVL树平衡检测五、AVL树查找 一、AVL树的概念 二、AVL树的实现 1、AVL树的节点 key,vaule的二叉搜索树&#xff0c;需要…

Vscode插件 :用于生成文件头部注释和函数注释

最近找到了一个好用的vscode生成注释的插件----koroFileHeader 1.在拓展中搜索&#xff0c;并且安装 2.找到setting.json 设置模板 点击ctrlp(windows and linus),commandp(mac) 输入 > Open Settings 点击第一个选项 并且用以下代码进行覆盖 // 头部注释 "file…

知从科技闪耀汽车智能底盘大会:共探软件安全新篇章

在汽车科技蓬勃发展的浪潮中&#xff0c;智能底盘技术正成为引领行业变革的关键力量。11月27日-28日&#xff0c;盖世汽车 2024 第四届汽车智能底盘大会盛大召开&#xff0c;上海知从科技有限公司受邀出席此次盛会&#xff0c;与众多汽车领域的精英齐聚一堂&#xff0c;共话智能…

LabVIEW密码保护与反编译的安全性分析

在LabVIEW中&#xff0c;密码保护是一种常见的源代码保护手段&#xff0c;但其安全性并不高&#xff0c;尤其是在面对专业反编译工具时。理论上&#xff0c;所有软件的反编译都是可能的&#xff0c;尽管反编译不一定恢复完全的源代码&#xff0c;但足以提取程序的核心功能和算法…

ABAP 类与对象 EXCEPTIONS与RAISE

文章目录 ABAP 类与对象 EXCEPTIONS与RAISE系统示例代码执行结果RAISE的系统文档测试 ABAP 类与对象 EXCEPTIONS与RAISE 系统示例 代码 CLASS cls DEFINITION.PUBLIC SECTION.CLASS-METHODS meth EXCEPTIONS exc. ENDCLASS.CLASS cls IMPLEMENTATION.METHOD meth....RAISE ex…

接第二部分 Advanced Learning Algorithms

接第二部分 Advanced Learning Algorithms 文章目录 接第二部分 Advanced Learning AlgorithmsMachine learning development process(机器学习开发的迭代)Iterative loop of ML development错误分析(error analysis)添加数据(Adding data)迁移学习&#xff1a;使用其他任务中的…

AI新动向:豆包文生图升级,文心一言领先市场

在今日的AI资讯中&#xff0c;我们关注到了几个重要的行业动态&#xff0c;其中包括字节跳动AI助手豆包的功能升级&#xff0c;以及百度文心一言在生成式AI市场的领先地位。 字节跳动旗下的智能AI助手豆包近期对其文生图能力进行了显著提升&#xff0c;用户现在可以通过一键操…

力扣54.螺旋矩阵

题目描述 题目链接54. 螺旋矩阵 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,2,3],[4,5,6],[7,8,9]] 输出&#xff1a;[1,2,3,6,9,8,7,4,5]示例 2&#xff1a;…

【第 1 章 初识 C 语言】1.10 - 1.11 本书的组织结构、本书的约定

目录 1.10 本书的组织结构 1.11 本书约定 1.11.1 字体 1.11.2 程序输出 特殊的击键 本书使用的系统 读者的系统 1.11.3 特殊元素 1.10 本书的组织结构 本书采用多种方式编排内容&#xff0c;其中最直接的方法是介绍 A 主题的所有内容、介绍 B 主题的所有内容&#xff0…

# 06_Python基础到实战一飞冲天(三)-python面向对象(六)--类属性和类方法和单例

06_Python基础到实战一飞冲天&#xff08;三&#xff09;-python面向对象&#xff08;六&#xff09;–类属性和类方法和单例 一、类属性-05-使用对象名类属性赋值语句会创建实例属性 1、使用对象名访问类属性的问题注意 如果使用 对象.类属性 值 赋值语句&#xff0c;只会…

【目标跟踪】DUT Anti-UAV数据集详细介绍

DUT Anti-UAV数据集是大连理工大学的团队公开的数据集&#xff08;DUT是他们学校的简称&#xff09;&#xff0c;其中包括了两个子数据集&#xff1a;目标检测和目标跟踪&#xff08;也就是说&#xff0c;目标检测和目标跟踪都可以用这个数据集&#xff09;。该数据集为可见光模…

★ 数据结构 ★ 排序

Ciallo&#xff5e;(∠・ω< )⌒☆ ~ 今天&#xff0c;我将和大家一起学习数据结构中的各种排序~ ​❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️ 澄岚主页&#xff1a;椎名澄嵐-CSDN博客 数据结构专栏&#xff1a;https://blog.csdn.net/2302_80328146/categ…

c语言基础三:运算符和表达式

一、常用的运算符分类 运算符类型 作用 算术运算符 用于处理四则运算 赋值运算符 用于将表达式的值赋给变量 比较运算符 用于表达式的比较&#xff0c;并返回一个真值或假值 逻辑运算符 用于根据表达式的值返回真值或假值 位运算符 用于处理数据的位运算 s…

如何通过金蝶云星空高效集成销售出库单

金蝶云星空数据集成案例分享&#xff1a;销售出库单-&#xff08;分销&京东&唯品&虚拟除外&#xff09;手表汇总 在企业信息化系统中&#xff0c;数据的高效流转和准确对接是业务运作的关键。本文将聚焦于一个具体的系统对接集成案例&#xff0c;即如何将金蝶云星…

【SKFramework框架核心模块】3-4、事件模块

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享QQ群&#xff1a;398291828小红书小破站 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【Unity3D框架】SKFramework框架完全教程《全…

鸿蒙分享:添加模块,修改app名称图标

新建公共模块common 在entry的oh-package.json5添加dependencies&#xff0c;引入common模块 "dependencies": {"common": "file:../common" } 修改app名称&#xff1a; common--src--resources--string.json 新增&#xff1a; {"name&q…

逆向攻防世界CTF系列48-Signin.md

逆向攻防世界CTF系列48-Signin.md 直接定位 输入&#xff0c;然后跟踪96A 一个整数一个余数你会发现这是把输入字符变成两个分开的十六进制存储起来&#xff0c;比如输入字符 ‘1’ &#xff0c;它的整数是49&#xff0c;49除16的整数是3&#xff0c;余数是1&#xff0c;在byt…

最新版Chrome谷歌加载ActiveX控件之金格iWebOffice2015控件

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX控件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持Chrome、Firefo…

Lakehouse 架构下的元数据“大一统”管理深度解析

在湖仓一体&#xff08;Lakehouse&#xff09;出现之前&#xff0c;数据仓库和数据湖堪称数据领域的两大“顶流”。打个比方&#xff0c;要是把数据仓库比作一座大型图书馆&#xff0c;那其中的数据就如同馆内藏书&#xff0c;需要按照规范放好&#xff0c;借阅者只需依照类别索…