PHPDocument 代码注释规范总结

PHPDocument 代码注释规范

1. 安装phpDocumentor(不推荐命令行安装)
在http://manual.phpdoc.org/下载最新版本的PhpDoc
放在web服务器目录下使得通过浏览器可以访问到
点击files按钮,选择要处理的php文件或文件夹
还可以通过该指定该界面下的Files to ignore来忽略对某些文件的处理。
然后点击output按钮来选择生成文档的存放路径和格式.
最后点击create,phpdocumentor就会自动开始生成文档了。

2.如何写PHP规范注释

所有的文档标记都是在每一行的 * 后面以@开头。如果在一段话的中间出来@的标记,这个标记将会被当做普通内容而被忽略掉。
@access        该标记用于指明关键字的存取权限:private、public或proteced 使用范围:class,function,var,define,module
@author        指明作者
@copyright    指明版权信息
@const        使用范围:define 用来指明php中define的常量
@final            使用范围:class,function,var 指明关键字是一个最终的类、方法、属性,禁止派生、修改。
@global        指明在此函数中引用的全局变量
@name            为关键字指定一个别名。
@package    用于逻辑上将一个或几个关键字分到一组。
@abstrcut    说明当前类是一个抽象类
@param        指明一个函数的参数
@return        指明一个方法或函数的返回值
@static            指明关建字是静态的。
@var            指明变量类型
@version        指明版本信息
@todo            指明应该改进或没有实现的地方
@link            可以通过link指到文档中的任何一个关键字
@ingore        用于在文档中忽略指定的关键字

一些注释规范
a.注释必须是
/**
* XXXXXXX
*/
的形式
b.对于引用了全局变量的函数,必须使用glboal标记。
c.对于变量,必须用var标记其类型(int,string,bool...)
d.函数必须通过param和return标记指明其参数和返回值
e.对于出现两次或两次以上的关键字,要通过ingore忽略掉多余的,只保留一个即可
f.调用了其他函数或类的地方,要使用link或其他标记链接到相应的部分,便于文档的阅读。
g.必要的地方使用非文档性注释(PHPDOC无法识别的关键字前的注释),提高代码易读性。
h.描述性内容尽量简明扼要,尽可能使用短语而非句子。
i.全局变量,静态变量和常量必须用相应标记说明

能够被phpdoc识别的关键字:
Include
Require
include_once
require_once
define
function
global
class

3. 规范注释的php代码 :

<?php
/**
* 文件名(sample2.php)
*
* 功能描述(略)
*
* @author steve <liuzhiqun@facedoing.com>
* @version 1.0
* @package sample2
*/

/**
* 包含文件
*/
include_once 'sample3.php';

/**
* 声明全局变量
* @global integer $GLOBALS['_myvar']
* @name $_myvar
*/
$GLOBALS['_myvar'] = 6;

/**
* 声明全局常量
*/
define('NUM', 6);

/**
* 类名
*
* 类功能描述
*
* @package sample2
* @subpackage classes(如果是父类 就添加)
*/
class myclass {

/**
* 声明普通变量
*
* @accessprivate
* @var integer|string
*/
var $firstvar = 6;

/**
* 创建构造函数 {@link $firstvar}
*/
function myclass() {
$this->firstvar = 7;
}

/**
* 定义函数
*
* 函数功能描述
*
* @global string $_myvar
* @staticvar integer $staticvar
* @param string $param1
* @param string $param2
* @return integer|string
*/
function firstFunc($param1, $param2 = 'optional') {
static $staticvar = 7;
global $_myvar;
return $staticvar;
}
}
?>

25个PHP游戏编程脚本代码

 

本文介绍的脚本易于理解、使用简单并可以快速掌握。

简单的掷骰器

许多游戏和游戏系统都需要骰子。让我们先从简单的部分入手:掷一个六面骰子。实际上,滚动一个六面骰子就是从 1 到 6 之间选择一个随机数字。在 PHP 中,这十分简单:echo rand(1,6);。

在许多情况下,这基本上很简单。但是在处理机率游戏时,我们需要一些更好的实现。PHP 提供了更好的随机数字生成器:mt_rand()。在不深入研究两者差别的情况下,可以认为 mt_rand 是一个更快、更好的随机数字生成器:echo mt_rand(1,6);。如果把该随机数字生成器放入函数中,则效果会更好。

清单 1. 使用 mt_rand() 随机数字生成器函数

  function roll () {

  return mt_rand(1,6);

  }

  echo roll();



然后可以把需要滚动的骰子类型作为参数传递给函数。

清单 2. 将骰子类型作为参数传递

  function roll ($sides) {

  return mt_rand(1,$sides);

  }

  echo roll(6);  // roll a six-sided die

  echo roll(10);  // roll a ten-sided die

  echo roll(20);  // roll a twenty-sided die



从这里开始,我们可以继续根据需要一次滚动多个骰子,返回结果数组;也可以一次性滚动多个不同类型的骰子。但是大多数任务都可以使用这个简单的脚本。

随机名称生成器

如果正在运行游戏、编写故事或者一次性创建大批字符,有时会疲于应付不断出现的新名字。让我们看一看可用于解决此问题的一个简单随机名称生成器。首先,让我们创建两个简单数组 — 一个用于名字,一个用于姓氏。

清单 3. 名字和姓氏的两个简单数组

  $male = array(

  "William",

  "Henry",

  "Filbert",

  "John",

  "Pat",

  );

  $last = array(

  "Smith",

  "Jones",

  "Winkler",

  "Cooper",

  "Cline",

  );



然后就可以从每个数组中选择一个随机元素:echo $male[array_rand($male)] . ' ' . $last[array_rand($last)];。要一次性提取多个名称,只需混合数组并根据需要提取。

清单 4. 混合名称数组

  shuffle($male);

  shuffle($last);

  for ($i = 0; $i <= 3; $i++) {

  echo $male[$i] . ' ' . $last[$i];

  }



基于此基本概念,我们可以创建保存名字和姓氏的文本文件。如果在文本文件的每一行中存放一个名字,则可以轻松地用换行符分隔文件内容以构建源代码数组。清单 5. 创建名称的文本文件

  $male = explode('\n', file_get_contents('names.female.txt'));

  $last = explode('\n', file_get_contents('names.last.txt'));

构建或查找一些好的名字文件(代码归档 中附带了一些文件),此后我们绝不再需要为名字烦恼。

场景生成器

利用构建名字生成器使用的相同基本原理,我们可以构建场景生成器。此生成器不但在角色扮演游戏中十分有用,而且在需要用到伪随机环境集合(可用于角色扮演、即兴创作、写作等情况)的情况下也十分有用。我最喜欢的游戏之一,Paranoia 在其 GM Pack 中包括了 “任务混合器(mission blender)”。任务混合器可用于在快速滚动骰子时整合完整任务。让我们整合自己的场景生成器。

考虑以下场景:您醒来后发现自己迷失于丛林中。您知道自己必须赶去纽约,但是不知道原因。您可以听到附近的狗叫声及清晰的敌方搜寻者的声音。您浑身发冷、不住颤抖,而且没有武器。该场景中的每一句话都介绍场景的特定方面:

“您醒来后发现自己迷失于丛林中” — 这句话将建立设置。

“您知道自己必须赶去纽约” — 这句话将描述目标。

“您可以听到狗叫声” — 这句话将介绍敌人。

“您浑身发冷、不住颤抖,而且没有武器” — 这句话将添加复杂度。

就像创建名字和姓氏的文本文件一样,首先分别创建设置、目标、敌人和复杂度的文本文件。代码归档中附带了样例文件。在拥有这些文件后,生成场景的代码与生成名称的代码基本相同。

清单 6. 生成场景

  $settings = explode("\n", file_get_contents('scenario.settings.txt'));

  $objectives = explode("\n", file_get_contents('scenario.objectives.txt'));

  $antagonists = explode("\n", file_get_contents('scenario.antagonists.txt'));

  $complicati**** = explode("\n", file_get_contents('scenario.complicati****.txt'));

  shuffle($settings);

  shuffle($objectives);

  shuffle($antagonists);

  shuffle($complicati****);

  echo $settings[0] . ' ' . $objectives[0] . ' ' . $antagonists[0] . ' '

  . $complicati****[0] . "<br />\n";



我们可以通过添加新文本文件向场景中添加元素,也可能希望添加多重复杂度。添加到基本文本文件中的内容越多,场景随时间的变化就越多。

牌组创建器(Deck builder)和装备(shuffler)

如果您要玩纸牌并且要处理与纸牌相关的脚本,我们需要用装备中的工具整合一副牌组构建器。首先,让我们构建一副标准纸牌。需要构建两个数组 — 一个用于保存同花色的组牌,而另一个用于保存牌面。如果稍后需要添加新组牌或牌类型,则这样做将获得很好的灵活性。

清单 7. 构建一副标准扑克牌

  $suits = array (

  "Spades", "Hearts", "Clubs", "Diamonds"

  );

  $faces = array (

  "Two", "Three", "Four", "Five", "Six", "Seven", "Eight",

  "Nine", "Ten", "Jack", "Queen", "King", "Ace"

  );



然后构建一副牌数组来保存所有纸牌值。只需使用一对 foreach 循环即可完成此操作。

清单 8. 构建一副牌数组

  $deck = array();

  foreach ($suits as $suit) {

  foreach ($faces as $face) {

  $deck[] = array ("face"=>$face, "suit"=>$suit);

  }

  }



在构建了一副扑克牌数组后,我们可以轻松地洗牌并随机抽出一张牌。

清单 9. 洗牌并随机抽出一张牌

  shuffle($deck);

  $card = array_shift($deck);

  echo $card['face'] . ' of ' . $card['suit'];



现在,我们就获得了抽取多副牌或构建多层牌盒(multideck shoe)的捷径。

胜率计算器:发牌

由于构建扑克牌时会分别跟踪每张牌的牌面和花色,因此可以通过编程方式利用这副牌来计算得到特定牌的几率。首先每只手分别抽出五张牌。

清单 10. 每只手抽出五张牌

  $hands = array(1 => array(), 2=>array());

  for ($i = 0; $i < 5; $i++) {

  $hands[1][] = implode(" of ", array_shift($deck));

  $hands[2][] = implode(" of ", array_shift($deck));

  }



然后可以查看这副牌,看看剩余多少张牌以及抽到特定牌的机率是多少。查看剩余的牌数十分简单。只需要计算 $deck 数组中包含的元素数。要获得抽到特定牌的机率,我们需要一个函数来遍历整副牌并估算其余牌以查看是否匹配。清单 11. 计算抽到特定牌的几率

  function calculate_odds($draw, $deck) {

  $remaining = count($deck);

  $odds = 0;

  foreach ($deck as $card) {

  if (  ($draw['face'] == $card['face'] && $draw['suit'] ==

  $card['suit'] ) ||

  ($draw['face'] == '' && $draw['suit'] == $card['suit'] ) ||

  ($draw['face'] == $card['face'] && $draw['suit'] == '' ) ) {

  $odds++;

  }

  }

  return $odds . ' in ' $remaining;

  }



现在可以选出尝试抽出的牌。为了简单起见,传入看上去类似某张牌的数组。我们可以查找特定的一张牌。

清单 12. 查找指定的一张牌

  $draw = array('face' => 'Ace', 'suit' => 'Spades');

  echo implode(" of ", $draw) . ' : ' . calculate_odds($draw, $deck);



或者可以查找指定牌面或花色的牌。

清单 13. 查找指定牌面或花色的牌

  $draw = array('face' => '', 'suit' => 'Spades');

  $draw = array('face' => 'Ace', 'suit' => '');



简单的扑克发牌器

现在已经得到牌组构建器和一些工具,可以帮助计算出抽出特定卡的机率,我们可以整合一个真正简单的发牌器来进行发牌。出于本例的目的,我们将构建一个可以抽出五张牌的发牌器。发牌器将从整副牌中提供五张牌。使用数字指定需要放弃哪些牌,并且发牌器将用一副牌中的其他牌替换这些牌。我们无需指定发牌限制或特殊规则,但是您可能会发现这些是非常有益的个人经验。

如上一节所示,生成并洗牌,然后每只手五张牌。按数组索引显示这些牌,以便可以指定返回哪些牌。您可以使用表示要替换哪些牌的复选框来完成此操作



清单 14. 使用复选框表示要替换的牌

  foreach ($hand as $index =>$card) {

  echo "<input type='checkbox' name='card[" . $index . "]'>

  " . $card['face'] . ' of ' . $card['suit'] . "<br />";

  }



然后,计算输入 array $_POST['card'],查看哪些牌已被选择用于替换。

清单 15. 计算输入

  $i = 0;

  while ($i < 5) {

  if (isset($_POST['card'][$i])) {

  $hand[$i] = array_shift($deck);

  }

  }



使用此脚本,您可以尝试找到处理特定一组牌的最佳方法。

Hangman 游戏

Hangman 实质上是一款猜字游戏。给定单词的长度,我们使用有限的几次机会猜这个单词。如果猜出了出现在该单词中的一个字母,则填充该字母出现的所有位置。在猜错若干次(通常为六次)后,您就输了比赛。要构建一个简陋的 hangman 游戏,我们需要从单词列表开始。现在,让我们把单词列表制作成一个简单的数组。

清单 16. 创建单词列表

  $words = array (

  "giants",

  "triangle",

  "particle",

  "birdhouse",

  "minimum",

  "flood"

  );



使用前面介绍的技术,我们可以把这些单词移动到外部单词列表文本文件中,然后根据需要导入。

在得到单词列表后,需要随机选出一个单词,将每个字母显示为空,然后开始猜测。我们需要在每次进行猜测时跟踪正确和错误的猜测。只需序列化猜测数组并在每次猜测时传递它们,就可实现跟踪目的。如果需要阻止人们通过查看页面源代码侥幸猜对,则需要执行一些更安全的操作。

构建数组以保存字母和正确/错误的猜测。对于正确的猜测,我们将用字母作为键并用句点作为值填充数组。清单 17. 构建保存字母和猜测结果的数组

  $letters = array('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',

  'p','q','r','s','t','u','v','w','x','y','z');

  $right = array_fill_keys($letters, '.');

  $wrong = array();



现在需要一些代码来评估猜测并在完成猜字游戏的过程中显示该单词。

清单 18. 评估猜测并显示进度

  if (stristr($word, $guess)) {

  $show = '';

  $right[$guess] = $guess;

  $wordletters = str_split($word);

  foreach ($wordletters as $letter) {

  $show .= $right[$letter];

  }

  } else {

  $show = '';

  $wrong[$guess] = $guess;

  if (count($wrong) == 6) {

  $show = $word;

  } else {

  foreach ($wordletters as $letter) {

  $show .= $right[$letter];

  }

  }

  }



在源代码归档 中,可以看到如何序列化猜测数组并将该数组从一次猜测传递到另一次猜测中。

纵横字谜助手

我知道这样做不合适,但是有时在玩纵横拼字谜时,您不得不费劲地找出以 C 开头并以 T 结尾、包含五个字母的单词。使用为 Hangman 游戏构建的相同单词列表,我们可以轻松地搜索符合某个模式的单词。首先,找到一种传输单词的方法。为了简单起见,用句点替换缺少的字母:$guess = "c...t";。由于正则表达式将把句点处理为单个字符,因此我们可以轻松地遍历单词列表以查找匹配。

清单 19. 遍历单词列表

  foreach ($words as $word) {

  if (preg_match("/^" . $_POST['guess'] . "$/",$word)) {

  echo $word . "<br />\n";

  }

  }



根据单词列表的质量及猜测的准确度,我们应当能够得到合理的单词列表以用于可能的匹配。您必须自己决定 “表示 ‘不按规则玩’ 的由五个字母组成的单词” 的谜底是 “chest” 还是 “cheat”。

米德里比斯

米德里比斯是一款文字游戏,玩家在游戏中得到一个简短的故事并用同一类型的不同单词替换主要类型的单词,从而创建同一个故事的更无聊的新版本。阅读以下文本:“I was walking in the park when I found a lake. I jumped in and swallowed too much water. I had to go to the hospital.” 开始用其他单词标记替换单词类型。开始和结束标记带有下划线用于阻止意外的字符串匹配。

清单 20. 用单词标记替换单词类型

  $text = "I was _VERB_ing in the _PLACE_ when I found a _NOUN_.

  I _VERB_ed in, and _VERB_ed too much _NOUN_.  I had to go to the _PLACE_.";



接下来,创建几个基本单词列表。对于本例,我们也不会做得太复杂。

清单 21. 创建几个基本单词列表

  $verbs = array('pump', 'jump', 'walk', 'swallow', 'crawl', 'wail', 'roll');

  $places = array('park', 'hospital', 'arctic', 'ocean', 'grocery', 'basement',

  'attic', 'sewer');

  $nouns = array('water', 'lake', 'spit', 'foot', 'worm',

  'dirt', 'river', 'wankel rotary engine');



现在可以重复地评估文本来根据需要替换标记。

清单 22. 评估文本

  while (preg_match("/(_VERB_)|(_PLACE_)|(_NOUN_)/", $text, $matches)) {

  switch ($matches[0]) {

  case '_VERB_' :

  shuffle($verbs);

  $text = preg_replace($matches[0], current($verbs), $text, 1);

  break;

  case '_PLACE_' :

  shuffle($places);

  $text = preg_replace($matches[0], current($places), $text, 1);

  break;

  case '_NOUN_' :

  shuffle($nouns);

  $text = preg_replace($matches[0], current($nouns), $text, 1);

  break;

  }

  }

  echo $text;



很明显,这是一个简单而粗糙的示例。单词列表越精确,并且花在基本文本上的时间越多,结果就越好。我们已经使用了文本文件创建名称列表及基本单词列表。使用相同原则,我们可以创建按类型划分的单词列表并使用这些单词列表创建更加变化多端的米德里比斯游戏。乐透机

全部选中乐透的六个正确号码 —— 退一步说 —— 在统计学上是不可能的。不过,许多人仍然花钱去玩,而且如果您喜欢号码,则查看趋势图可能很有趣。让我们构建一个脚本,该脚本将允许跟踪赢奖号码并在列表中提供选择次数最少的 6 个号码。

(免责声明:这不会帮助您中乐透奖,因此请不要花钱购买奖券。这只是为了娱乐)。

把赢奖的乐透选择保存到文本文件中。用逗号分隔各个号码并把每组号码放在单独一行中。使用换行符分隔文件内容并使用逗号分隔行后,可以得到类似清单 23 的内容。

清单 23. 把选择的赢奖乐透保存到文本文件中

  $picks = array(

  array('6', '10', '18', '21', '34', '40'),

  array('2', '8', '13', '22', '30', '39'),

  array('3', '9', '14', '25', '31', '35'),

  array('11', '12', '16', '24', '36', '37'),

  array('4', '7', '17', '26', '32', '33')

  );



很明显,这不足以成为绘制统计数据的基本文件。但是它是一个开端,并且足以演示基本原理。

设置一个基本数组以保存选择范围。例如,如果选择 1 到 40 之间(例如,$numbers = array_fill(1,40,0);)的号码,则遍历我们的选择,递增相应的匹配值。

清单 24. 遍历选择

  foreach ($picks as $pick) {

  foreach ($pick as $number) {

  $numbers[$number]++;

  }

  }



最后,根据值将号码排序。此操作应当会把最少选择的号码放在数组的前部。

清单 25. 根据值将号码排序

  asort($numbers);

  $pick = array_slice($numbers,0,6,true);

  echo implode(',', array_keys($pick));



通过有规律地向包含中奖号码列表的文本文件添加实际的乐透中奖号码,可以发现选号的长期趋势。查看某些号码的出现频率十分有趣。

 

Windows 服务器配置 RamDisk

 

给 Windows 服务器增加 RamDisk以前在 IIS 6 的 PHP 最佳配置一文中提到过 RamDisk,后来在那篇文章的留言里,就看到有人问关于 RamDisk 的事。正好那几天转移服务器,需要重新配置这个东西,发现这个东西确实挺难找的,所以在这里写下来,一来可以方便自己以后的工作,二来可以方便跟我有相同需求的朋友们。

 

网上能找到的 RamDisk 程序大都不能支持 Windows 2003,而且许多都是收费软件。原来我用的也是一个试用版的软件,虽然没有功能限制和时间限制,但是总会在随机的某个时间弹出提示框,让人很不爽,而且还不是很稳定。于是这次找了一个免费的却更好的 RamDisk 软件。这个支持 Windows 2000 以上的系统,包括 Windows 2003。

 

这里主要以 IIS 为例来讲。

 

首先用 lyh728 做到 RamDisk 的 GUI 前端来安装 RamDisk 驱动。直接双击 ramdisk.exe 然后点击 install ramdisk 按钮就可以了。然后你可以调整盘符和磁盘大小。RamDisk 的盘符默认是 R:,因为我的服务器只有一个软驱 A:,所以我把 RamDisk 的盘符设为了 B:,主要是为了保证这个盘符不会变。RamDisk 上一般放的都是临时性质的文件,比如 IE 的缓存、IIS 的压缩页面缓存、临时文件夹、PHP 的 Sessions 文件等。这些内容在服务器重启以后就没有了。我给我的服务器分了 256M 的内存作 RamDisk,实际上我发现用不了这么多,目前也只占了 20 多兆的空间而已,所以如果你的内存本来就不是很多的话,分 32M 作 RamDisk 给服务器我觉得基本上就足够了,不放心的话,也可以多给它一点空间,比如 64M 或者 128M。但是默认的 RamDisk 是格式化成 FAT 格式的,并且已经建好了一个 TEMP 文件夹。你会发现这个文件夹在服务器重启后,依然存在。你甚至会发现,你即使将 RamDisk 重新格式化为 NTFS 格式,再重启后,仍然会变为 FAT 格式,并且还有那个 TEMP 文件夹。原因在于默认的安装已经把这个配置写到注册表里了。如果想修改的话,需要用里面的 rdutil 这个工具。

 

首先安装完 RamDisk,并调整好盘符和大小后,什么也别做。尤其是不要急着把 IE 的缓存目录改到 RamDisk 上,否则 RamDisk 会被锁定,以至于不能在被修改保存。

 

然后格式化 RamDisk

 

FORMAT /FS:NTFS /Q /V:RamDisk /A:512 B:

其中 /FS: 后面指定的是文件系统,/A: 后面是一个单元块的大小,因为 RamDisk 上保存的大都是小文件,因此指定 512 字节比较合适。B: 是盘符。

 

接下来把 NTFS 的日志大小设到最小(2M)

 

CHKDSK /L:2048 R:

否则,会因为太大而无法压缩到注册表中。

 

在接下来你就可以在上面建文件夹了,比如 Temp、Sessions、Upload Temp Files、IIS Temporary Compressed Files 等。目录不要建太多,够用就行了。比如 Temp 是用来保存系统临时文件的,Sessions 可以保存 PHP 的 Session 文件,Upload Temp Files 可以保存 PHP 上传的临时文件,IIS Temporary Compressed Files 可以保存 IIS 的临时压缩文件。当然这些目录你还要给予足够的权限,比如需要让 IIS(包括用 IIS 发布的 PHP 程序)访问的目录,就需要给 IIS_WPG 用户组或者 IUSR_HOSTNAME 用户足够的权限。注意,这里也不要给 IE 建立缓存目录,即使你想让 IE 缓存也使用 RamDisk,因为当你设置 IE 的缓存到 RamDisk 的时候,IE 会自动建立这个目录的。

 

好了,做完这步后,先不要急着把这些目录用起来,先把这个文件系统和目录结构保存到注册表:

 

rdutil B: registry

好了,如果你看到保存成功的提示,就大功告成了。重启一下试试看,你会发现重新启动后,你的 RamDisk 将会保持你设置的文件系统格式,以及目录和相应的权限。

 

现在你就可以把系统的 Temp 目录、IIS 的压缩文件缓存、IE 缓存、PHP Session 文件目录、PHP 临时上传目录统统设置到 RamDisk 上了。