6

我只是在尝试自学如何使用正则表达式,如果这对某些人来说似乎微不足道,我很抱歉。

我正在制作一个小婴儿床脚本。它使用一副标准的扑克牌,我使用CDHS(梅花、方块、红心、黑桃)作为花色,使用A2..9TJQK(ace、2...9、10、jack、queen、king)作为等级。

我有一个变量$hand,它是一个偶数长度的卡片串。例如,S2HA3D分别是黑桃 2、红桃 A 和方块 3。请注意,花色和等级可以是任意一种。

我正在使用:

preg_match_all("/[2-9ATJQK][CDHS]|[CDHS][2-9ATJQK]/i", $hand, $result);

找到所有的牌,但这会按照找到的顺序返回花色和等级。

我的问题是,无论给出的顺序如何,我怎样才能使结果为每张卡排在第一位。我希望我已经清楚地表达了这一点。

4

4 回答 4

3

一种方法是将命名捕获与允许使用相同名称的 J 修饰符一起使用。

$pattern = '~(?J)(?<rk>[2-9ATJQK])?(?<su>[CDHS])(?(1)|(?<rk>[2-9ATJQK]))~i';

preg_match_all($pattern, $hand, $matches, PREG_SET_ORDER);

foreach($matches as $match) {
    $result .= $match['rk'] . $match['su'];
}
echo $result;

或者使用 preg_replace 更简单:

$result = preg_replace('~([2-9ATJQK])?([SCHD])(?(1)|([2-9ATJQK]))~i', '$2$1$3', $hand);
于 2013-06-27T16:44:24.230 回答
3

我不认为你可以做到这一点preg_match

此函数旨在匹配字符串,而不是操纵它们。但是,您可以preg_replace在第二遍中执行:

preg_match_all("/[2-9ATJQK][CDHS]|[CDHS][2-9ATJQK]/i", $hand, $rawResult);
$normalisedResult = preg_replace('/([CDHS])([2-9ATJQK])/i', "$2$1", $rawResult[0]);

如果您想知道$1$2是对第一个参数中括号标识的组的反向引用preg_replace()

于 2013-06-27T16:49:10.103 回答
1

编辑:一开始我没有正确理解你的问题。这是您需要做的,您需要进行 2 个正则表达式调用,例如:

/([CDHS])([A2-9TJQK])/i

然后:

/([A2-9TJQK])([CDHS])/i

尝试制作一个可以保存第一组值和第二组值的变量。然后要获得正确的排名,您需要使用第二种模式切换它们...

如果我错了,请纠正我,但你不能用一个正则表达式来做到这一点。

于 2013-06-27T16:23:08.660 回答
0

我会使用正则表达式来匹配所有对,然后有一些逻辑将等级重新排序为第一。这就是我的意思(未经测试)

$grades = array(2,3,4,5,6,7,8,9,'A','T','J','Q','K');

preg_match_all('/((C|D|H|S)[2-9ATJQK]{1})|([2-9ATJQK]{1}(C|D|H|S))/i', $subject, $result, PREG_PATTERN_ORDER);
for ($i = 0; $i < count($result[0]); $i++) {

    if (in_array($result[0][$i][0], $grades)) {
        echo ($result[0][$i]);
    }
    else {
        echo (strrev($result[0][$i]));      
    }

}
于 2013-06-27T16:43:12.403 回答