- 浏览: 842369 次
- 性别:
- 来自: 南京
-
文章分类
最新评论
-
xieye:
jetty插件有好几个版本,1.6,1.7,1.8
我选的是用 ...
tapestry入门(翻译)3 导入项目到eclipse -
xieye:
还有,
注:第2部分时,需要先安装jetty,我自己在安装过程 ...
tapestry入门(翻译)3 导入项目到eclipse -
xieye:
说明一下:实际使用中,导入时我并没有错误。2、我把eclips ...
tapestry入门(翻译)3 导入项目到eclipse -
xieye:
其实还是有一些先决条件的。1是外部环境,2是进步是阶段性的(意 ...
(转载文章)如何愉悦起来:一位精神治疗师的见解 -
mandy_yanzi:
我都已经饿7天了坚持为了我的衣衣
身体健康的问题
本文改自《设计模式-java语言中的应用》中的策略模式章节。作者:结城 浩(日本)
简单的说,策略模式就是算法替换,用不同的类实现不同的算法。
难点:需要根据算法设计出不同的方法,参数等。
程序示例
这里的程序是计算机游戏“剪刀石头布”。
猜拳时的策略有两种方法。第一种方法有点笨,“猜赢之后继续出同样的招式”(WinningStrategy),第2种方法则是“从上一次出的招式,以概率分配方式求出下一个招式的几率”(ProbStrategy)。
类一览表。
Hand:表示猜拳手势的类
HandStrategyInterface:表示猜拳战略的接口
Player:表示玩猜拳的游戏者的类
WinningStratrgy:策略1,表示猜赢之后继续出同样招式的战略的类
ProbStratrgy:策略2,表示根据上一次出的招式以概率计算出下一个招式的类。
Main:执行主类
代码在附件。
Hand.php
HandStrategyInterface.php
Player.php
WinningStrategy.php
ProbStrategy.php
Main.php
运行结果示例:
代码在附件。
简单的说,策略模式就是算法替换,用不同的类实现不同的算法。
难点:需要根据算法设计出不同的方法,参数等。
程序示例
这里的程序是计算机游戏“剪刀石头布”。
猜拳时的策略有两种方法。第一种方法有点笨,“猜赢之后继续出同样的招式”(WinningStrategy),第2种方法则是“从上一次出的招式,以概率分配方式求出下一个招式的几率”(ProbStrategy)。
类一览表。
Hand:表示猜拳手势的类
HandStrategyInterface:表示猜拳战略的接口
Player:表示玩猜拳的游戏者的类
WinningStratrgy:策略1,表示猜赢之后继续出同样招式的战略的类
ProbStratrgy:策略2,表示根据上一次出的招式以概率计算出下一个招式的类。
Main:执行主类
代码在附件。
Hand.php
<?php /** * 手势类 * * @author 结城 浩 */ class Hand { public static $HANDVALUE_GUU = 0; //表示石头的值 public static $HANDVALUE_CHO = 1; //表示剪刀的值 public static $HANDVALUE_PAA = 2; //表示布的值 private static $name_arr = array('石头', '剪刀', '布'); /** * 手势的值 * * @var int */ private $handValue; /** * 私有构造方法 * * @param int $handvalue 手势的值 */ private function __construct($handvalue) { $this->handValue = $handvalue; } /** * 该方法实现单例数组,里面存放3个对象 * * @return array 对象数组 */ public static function getHandArr() { static $hand_arr = array(); if (!$hand_arr) { $hand_arr = array( new Hand(self::$HANDVALUE_GUU), new Hand(self::$HANDVALUE_CHO), new Hand(self::$HANDVALUE_PAA), ); } return $hand_arr; } /** * 外部调用,获取一个手势对象 * * @param int $handvalue 手势的值 * @return Hand 一个手势对象 */ public static function getHand($handvalue) { $hand = self::getHandArr(); return $hand[$handvalue]; } /** * 判断是否战胜另一个手势 * * @param Hand $h 另一个手势对象 * @param boolean */ public function isStrongerThan(Hand $h) { return $this->fight($h) == 1; } /** * 判断是否输给另一个手势 * * @param Hand $h 另一个手势对象 * @param boolean */ public function isWeakerThan(Hand $h) { return $this->fight($n) == -1; } /** * 与另一个手势判断输赢 * * @param Hand $h 另一个手势对象 * @return int 胜为1 ,负为-1,平局为0 */ private function fight(Hand $h) { if ($this->handValue == $h->handValue) { return 0; } elseif (($this->handValue + 1) % 3 == $h->handValue) { return 1; } else { return -1; } } /** * 字符串显示 */ function __toString() { return self::$name_arr[$this->handValue]; } }
HandStrategyInterface.php
<?php /** * 手势策略接口 */ interface HandStrategyInterface { /** * 得到下一个手势 */ public function nextHand(); /** * 策略的智能学习 */ public function study($win); }
Player.php
<?php require_once 'HandStrategyInterface.php'; /** * 游戏者类 * * @author 结城 浩 */ class Player { /** * 游戏者名称 * * @var string */ private $name; /** * 私有策略对象 * * @var HandStrategyInterface */ private $strategy; /** * 总胜利次数 * * @var int */ private $wincount; /** * 总失败次数 * * @var int */ private $losecount; /** * 总游戏次数 * * @var int */ private $gamecount; /** * 构造方法 * * @param string $name 游戏者名称 * @param HandStrategyInterface $strategy 策略对象 */ function __construct($name, HandStrategyInterface $strategy) { $this->name = $name; $this->strategy = $strategy; $this->wincount = $this->losecount = $this->gamecount = 0; } /** * 根据策略返回游戏者的下一个手势 * * @return Hand 游戏者的下一个手势 */ public function nextHand() { $hand = $this->strategy->nextHand(); echo $this->name . ":" . $hand ."<br>"; return $hand; } /** * 胜利后的处理 */ public function win() { $this->strategy->study(true); $this->wincount++; $this->gamecount++; } /** * 失败后的处理 */ public function lose() { $this->strategy->study(false); $this->losecount++; $this->gamecount++; } /** * 平局后的处理 */ public function even() { $this->gamecount++; } /** * 魔术方法显示游戏者信息 * * @return string */ function __toString() { return '[' . $this->name . ':' . $this->gamecount . ' games, ' . $this->wincount . ' win, ' . $this->losecount . ' lose]'; } }
WinningStrategy.php
<?php require_once 'Hand.php'; require_once 'HandStrategyInterface.php'; /** * 简单策略类 * * 这是第一个策略,非常简单,如果赢了,就继续同一个手势,如果输了,随机出手势。 * * @author 结城 浩 */ class WinningStrategy implements HandStrategyInterface { /** * 与该策略算法有关的变量 * * @var boolean */ private $won = false; /** * 上一个手势 * * @var Hand */ private $prevhand; public function __construct() { } /** * 策略的算法核心。 * * 如果赢,就继续相同的手势,输则随机产生一个。 * * @return Hand */ public function nextHand() { if (!$this->won) { $this->prevhand = Hand::getHand(mt_rand(0, 2)); } return $this->prevhand; } /** * 学习方法,只记住当前的输赢结果 * * @param boolean 输赢结果 */ public function study($win) { $this->won = $win; } }
ProbStrategy.php
<?php require_once 'Hand.php'; require_once 'HandStrategyInterface.php'; /** * 复杂策略类 * * 这是第二个策略,虽然下一次的手势都是由随机数决定,不过它会参考之前的输赢记录,机动性的更改手势的出现几率。 * history字段是一份列出过去输赢记录的表格,用来计算几率。history是一个int类型的2维数组,各下标的含义是 * history[上一次的手势][下一次的手势] * 这个表达式的值越大,则代表之前获胜的几率越高。用实际的数据可能会更清楚一点。 * 这个作战策略的前提是对手的出拳方式也有另一种Pattern。 * * @author 结城 浩 */ class ProbStrategy implements HandStrategyInterface { /** * 前面手势的值,统计用 * * @var int */ private $prevHandValue = 0; /** * 后面手势的值,统计用 * * @var int */ private $currentHandValue = 0; /** * 存放历史数据的数组 * * history[0][0] 石头之后出石头的不败(获胜或平手)次数。 * history[0][1] 石头之后出剪刀的不败(获胜或平手)次数。 * history[0][2] 石头之后出布的不败(获胜或平手)次数。 * history[1][0] 剪刀之后出石头的不败(获胜或平手)次数。 * history[1][1] 剪刀之后出剪刀的不败(获胜或平手)次数。 * history[1][2] 剪刀之后出布的不败(获胜或平手)次数。 * history[2][0] 布之后出石头的不败(获胜或平手)次数。 * history[2][1] 布之后出剪刀的不败(获胜或平手)次数。 * history[2][2] 布之后出布的不败(获胜或平手)次数。 * * @var array 二维数组 */ private $history = array( array(1, 1, 1), array(1, 1, 1), array(1, 1, 1), ); public function __construct() { } /** * 算法核心 * * 根据历史数据,计算出某一个手势的下一个手势的3个概率(比如6:4:13),然后 * 也不一定就是那个最大概率的手势,而是依然根据概率得到下一个手势。 */ public function nextHand() { $bet = mt_rand(0, $this->getSum($this->currentHandValue) - 1); $handvalue = 0; if ($bet < $this->history[$this->currentHandValue][0]) { $handvalue = 0; } elseif ($bet < ($this->history[$this->currentHandValue][0] + $this->history[$this->currentHandValue][1]) ) { $handvalue = 1; } else { $handvalue = 2; } $this->prevHandValue = $this->currentHandValue; $this->currentHandValue = $handvalue; $hand = Hand::getHand($handvalue); return $hand; } /** * 从历史数据中得到某一个手势的次数之和,算概率用的 * * @param int $hv * @return int */ private function getSum($hv) { $sum = 0; for ($i = 0; $i < 3; $i++) { $sum += $this->history[$hv][$i]; } return $sum; } /** * 该策略的学习就是把结果记入统计数据里。 * * @param boolean $win 本次的输赢结果 */ public function study($win) { if ($win) { $this->history[$this->prevHandValue][$this->currentHandValue]++; } else { $this->history[$this->prevHandValue][($this->currentHandValue + 1) % 3]++; $this->history[$this->prevHandValue][($this->currentHandValue + 2) % 3]++; } } }
Main.php
<?php require_once 'Hand.php'; require_once 'WinningStrategy.php'; require_once 'ProbStrategy.php'; require_once 'Player.php'; /** * 执行主类 * * 使用方法,把这几个类一起拷贝到web服务器的docment_root路径下,然后 * http://localhost/Main.php * * @author 结城 浩 */ class Main { public static function run() { //得到两个游戏者,策略不同 $player1 = new Player('张三', new WinningStrategy()); $player2 = new Player('李四', new ProbStrategy()); //1000次运算,得到结果,并不停的输出。 for ($i = 0; $i < 1000; $i++) { $nextHand1 = $player1->nextHand(); $nextHand2 = $player2->nextHand(); if ($nextHand1->isStrongerThan($nextHand2)) { $player1->win(); $player2->lose(); self::echoinfo('胜利者: ' . $player1); } elseif ($nextHand2->isStrongerThan($nextHand1)) { $player1->lose(); $player2->win(); self::echoinfo('胜利者: ' . $player2); } else { $player1->even(); $player2->even(); self::echoinfo('平手。 '); } self::echoinfo(' '); } //统计 self::echoinfo('======================= 低调滴分割线 ======================='); self::echoinfo($player1); self::echoinfo($player2); } /** * 只是一个便利的输出换行 * * @param string $s 待输出信息 * @return string 加了换行后的输出 */ public static function echoinfo($s) { echo $s . "<br />\n"; } } //执行 Main::run();
运行结果示例:

代码在附件。
发表评论
-
召唤神龙 - 安装 centos 8, php 8, mysql 8, laravel 8 的整套 php 运行环境
2020-11-27 16:26 739本文编写时间:2020-11-27 传说集齐龙珠可以召唤神 ... -
centos8 使用阿里镜像快速安装php7.4套件
2020-11-15 00:48 908centos8 使用阿里镜像快速安装php7.4套件 本文只 ... -
centos7 使用阿里镜像快速安装php7.4套件
2020-11-15 00:32 1296本文只考虑centos7 今日 2020-11-16 rem ... -
composer常用命令
2020-11-05 14:46 1516列出当前全局配置 composer config -l -g ... -
期待centos8+php8 + mysql8 + laravel8,8888
2020-10-29 19:24 554期待centos8+php8 + mysql8 目前主要使用 ... -
ubuntu 安装 php7.4以及各类插件
2020-10-24 13:20 1168ubuntu 安装 php7.4以及各类插件 安装系统 最近 ... -
宝塔定义站点
2020-02-24 10:41 2宝塔定义站点。 1111111111111111111111 ... -
让php-fpm以root账号运行
2020-02-19 21:41 839一般来说,我们没有这种需求,但是当需要时, 可以让php-fp ... -
将代码部署到coding.net
2020-01-10 14:20 676coding.net 是一个git仓库,有免费有收费。 首先 ... -
php部署工具deployer技巧 - vendor目录创建
2020-01-06 12:06 940deployer是个好东西,可是每次都composer ,其实 ... -
自定义redis多个实例
2020-01-04 01:17 663假如多个项目部署到同一台服务器,有时会被redis的各项目前缀 ... -
推荐使用php的部署工具 deployer
2020-01-03 16:48 952php部署代码可以使用 https://deployer.or ... -
使用composer 类库 cachetool 清除opcache 的缓存
2020-01-03 16:38 983php的生产服务器上,需要把opche打开。 但有时,会被缓 ... -
laravel容器学习体会
2019-12-31 15:11 696根据文档与实测结果 假设我在app下建一个Services目 ... -
phalcon 自定义超强日志类
2019-12-18 10:00 846phalcon自带的日志文件类,有两个麻烦之处。 1、路径不能 ... -
自定义后台的使用
2019-12-18 05:22 432如果自己写后台,保存用户的表单请求值 所有的情况如下: 1 ... -
phalcon 自定义事件使用的多种方式
2019-12-16 20:43 786方法1:官方文档的方式。 这是控制器: public ... -
phalcon对控制器返回值的使用以输出json
2019-12-16 19:17 857在phalcon里,控制器的Action的方法的返回值没啥用。 ... -
phalcon数据库DB使用实例
2019-12-12 17:12 719整理了一下phalcon的db使用,写了个demo。 ... -
php-redis5.0降级成php-redis4.3
2019-08-22 00:01 903最新版本的php的redis插件,版本是5.0 但是可能会有 ...
相关推荐
### 设计模式——简单工厂模式解析与应用实例 #### 一、简单工厂模式概述 简单工厂模式(Simple Factory Pattern)是一种常用的创建型设计模式。它提供了一种方式来封装对象的创建过程,使得整个系统更加灵活,...
装饰者模式是软件设计模式中的一种结构型模式,它的主要目的是动态地给对象添加新的功能,而无需修改原有代码。在Java中,装饰者模式通常通过继承和组合来实现,它提供了一种比继承更灵活的方式来扩展对象的功能。...
例题简单的阐述了Java工厂模式的概念,有利于读者更好地了解Java工厂模式
C#是一种广泛应用的面向对象的编程语言,它支持多种设计模式,其中包括策略模式。策略模式是一种行为设计模式,允许我们在运行时根据需要改变一个对象的行为。 策略模式的核心思想是定义一系列的算法,并将每一个...
本资料包"设计模式例题 C#版"包含了C#实现的设计模式示例代码,所有代码均经过调试,确保功能正确,易于理解。 一、单例模式(Singleton) 单例模式确保一个类只有一个实例,并提供全局访问点。在C#中,可以通过...
《Java设计模式》是刘伟老师撰写的经典教材,它为Java程序员深入理解和应用设计模式提供了极佳的学习资源。设计模式作为软件工程中解决特定问题的典型方案,是每一个有志于成为高级开发者的程序员不可或缺的知识储备...
《C++程序设计-清华大学-郑莉-例题源代码》是针对郑莉教授主编的《C++程序设计》一书中的例题所编写的源代码集合。这本书是中国计算机科学教育领域的重要教材,旨在帮助学生深入理解C++编程语言,掌握程序设计的...
《E-R图转换成关系模式规则与例题》 在数据库设计中,E-R图(实体-关系图)是一种常用的概念建模工具,用于描述实体、属性和实体之间的关系。将其转换为关系模式是数据库实现的关键步骤。以下是E-R图转换成关系模式...
在给定的压缩包文件中,我们可以看到涉及到九种基本的设计模式,它们分别是:组合模式(Composite)、策略模式(Strategy)、外观模式(Facade)、观察者模式(Observer)以及单例模式(Singleton)。接下来,我们将...
7. **例题解析**:"例题-GPSS"可能包含一系列实际问题的解决方案,例如,模拟一个简单的生产线,研究其瓶颈、优化调度策略,或者模拟交通流量,分析交通拥堵情况等。通过这些例题,学习者可以深入理解GPSS的应用和...
这里通过分析提供的例题,我们可以深入探讨几个关键的知识点: 1. **信号量机制**:信号量是一种用于实现进程间同步和互斥的工具。题目中提到的信号量S,其值的含义是: - 当S.value>0时,表示有S个资源可用。 - ...
以“156-例题-IO系统例题1”为例,我们将深入探讨磁盘块空闲状态管理,磁盘的旋转速度,以及磁盘替换为Flash半导体存储器的相关问题。 首先,我们来说明如何进行磁盘块空闲状态的管理。磁盘块空闲状态管理是文件...
压缩包中的"MATLAB程序设计与应用-刘卫国-例题源程序(DOC)"文档,很可能是包含了书中所有例题的MATLAB代码,这为读者提供了亲自动手实践的机会,是学习和提高MATLAB技能的重要资源。读者可以通过运行和修改这些源...
这个压缩包“C语言程序设计”--例题源代码.zip包含了丰富的教学资料,特别是各种例题的源代码,是学习和理解C语言语法、逻辑控制以及算法设计的宝贵资源。 1. **C语言基础** C语言是一种中级语言,它的语法简洁...
数据库原理---例题
《吉林大学软件设计模式PPT例题》是一个深入学习和实践设计模式的宝贵资源,它包含了一系列可直接在IDEA(IntelliJ IDEA)中运行的例题。设计模式是软件工程中的重要概念,它是一种在特定情境下解决常见问题的最佳...
一、VHDL程序设计约定 语句结构描述中方括号“[ ]”内的内容为可选内容。 对于VHDL的编译器和综合器来说,程序文字的大小写是不加区分的。 程序中的注释使用双横线“- -”。 源程序命名与实体同名(MAX+plus Ⅱ...
面向对象程序设计(Java)第十章例题代码-J7chapte10面向对象程序设计(Java)第十章例题代码-J7chapte10面向对象程序设计(Java)第十章例题代码-J7chapte10面向对象程序设计(Java)第十章例题代码-J7chapte10面向...
设计模式一(单子、工厂、策略模式)练习 1. 假设现在要设计一个贩卖各类书籍的电子商务网站的购物车系统。对所有的教材类图书 实行每本一元的折扣;对连环画类图书提供每本 7%的促销折扣;而对非教材类的计算 机...