首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >生成随机的“模式锁定”数字序列

生成随机的“模式锁定”数字序列
EN

Stack Overflow用户
提问于 2017-10-21 15:34:14
回答 3查看 323关注 0票数 6

今天,我的朋友提出了一个我仍然无法解决的挑战:“在PHP中生成一个随机数字序列”

这些数字被安排为拨号垫/模式锁,由3行3列的1-9键组成:

代码语言:javascript
运行
复制
 ---------------------------
|                           |
|     1       2      3      |
|                           |
|     4       5      6      |
|                           |
|     7       8      9      |
|                           |
 ---------------------------

现在,在给定长度的情况下,我们必须使用以下条件生成给定长度的随机、非重复的数字序列:

  1. 生成的序列应该遵循特定的方向/模式,仅通过相邻的数字(可能是对角线),例如(长度:8),12569874: 1 2 4 5 6 7 8 9
  2. 第一行的数字不应该跟在第三行的数字后面,反之亦然。列也是如此。例如,1不能后面跟着8,6不能后面跟着4。
  3. 可以很容易地从android模式锁定系统中猜出更多的标准。

下面是一些为长度9: 12369874/5、142536987等和长度= 6: 987532等生成的示例序列

我试着用rand()做这件事

代码语言:javascript
运行
复制
  $chars = "123456789";
  $length = 9;
  $clen   = strlen( $chars )-1;
  $id  = '';

  for ($i = 0; $i < $length; $i++) {
      $id .= $chars[mt_rand(0,$clen)];
  }
  return ($id);

但还是没有运气..。

我怎样才能解决这个问题?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-10-21 16:59:01

有一些限制,但这需要你去解决。我只在拿到薪水的时候才处理头痛:)

代码语言:javascript
运行
复制
<pre>
<?php

// Keypad
$grid = [
    ['1', '2', '3'],
    ['4', '5', '6'],
    ['7', '8', '9'],
];

// Sequence Target Length
$target_length = 5;

// Place to store the Keypad sequence
$points = [];

// Starting Point
$x = rand(0, 2);
$y = rand(0, 2);

// Run through the process until we have the sequence at the desired length
while (count($points) < $target_length):

    // Check if the grid keypad entry has been used
    if ($grid[$x][$y]):
        // Hasn't been used, so stire it
        $points[] = $grid[$x][$y]; 
        // Mark it used 
        $grid[$x][$y] = NULL;
    endif;

    // Sanity Check, imagine if you will,.... target length of 9, and you hit 6 5 2 1,  You'll vault off into the twilight zone without this
    if ((!$grid[$x + 1][$y]) && (!$grid[$x][$y + 1]) && (!$grid[$x - 1][$y]) && (!$grid[$x][$y - 1])):
        // We have no where to go
        break;
    endif;

    // Start looking for possible values 
    do {
        $test_x = $x;
        $test_y = $y;
        $dir = rand(0, 3);

        switch ($dir):
            case (0):
                $test_y--; // Up
                break;
            case (1):
                $test_x++; // Right
                break;
            case (2):
                $test_y++; // Down
                break;
            case (3):
                $test_x--; // Left
                break;
        endswitch;
        // Optional Gibberish 
        echo "Moving from {$x}, {$y} to {$test_x}, {$test_y} --> " . (($grid[$test_x][$test_y] === NULL) ? 'FAILED' : 'OK!') . '<br>';

        // Keep going until we find a valid direction
    } while ($grid[$test_x][$test_y] === NULL);

    // assign the new coords
    $x = $test_x;
    $y = $test_y;

    // repeat
endwhile;

// report
echo implode('-', $points) . "\n";

?>
</pre>
票数 3
EN

Stack Overflow用户

发布于 2017-10-21 21:36:06

以下是适用这些规则的解决方案:

  • 路径只能步到相邻的单元,即相邻的单元,包括对角线。
  • 路径不能包含同一单元格两次。

下面的算法对添加到序列中的每个数字使用递归。每当序列被“卡住”时,就会发生回溯,并尝试另一条路径。如果没有更多的替代方案,回溯将继续进行。

如果给定长度在1至9之间,则保证返回给定长度的路径:

代码语言:javascript
运行
复制
function randomSequence($len) {
    if ($len < 1 || $len > 9) return []; // No results
    $row = [null, 1, 1, 1, 2, 2, 2, 3, 3, 3];
    $col = [null, 1, 2, 3, 1, 2, 3, 1, 2, 3];
    $neighbors = [[], [2, 4, 5],       [1, 4, 5, 6, 3],          [2, 5, 6],
                      [1, 2, 5, 7, 8], [1, 2, 3, 4, 6, 7, 8, 9], [2, 3, 5, 8, 9],
                      [4, 5, 8],       [4, 5, 6, 7, 9],          [5, 6, 8]];
    // Shuffle the neighbor lists to implement the randomness:
    foreach ($neighbors as &$nodes) shuffle($nodes);

    $recurse = function ($seq) use (&$len, &$row, &$col, &$neighbors, &$recurse) {
        if (count($seq) >= $len) return $seq; // found solution
        $last = end($seq);
        echo "try " . json_encode(array_keys($seq)) . "\n";
        foreach ($neighbors[$last] as $next) {
            if (isset($seq[$next])) continue; // Skip if digit already used
            $result = $recurse($seq + [$next => $next]);
            if (is_array($result)) return $result;
        }
    };
    $choice = rand(1, 9);
    return array_keys($recurse([$choice => $choice]));
}

echo "result: " . json_encode(randomSequence(9)) . "\n";

看到它在repl.it上运行

票数 2
EN

Stack Overflow用户

发布于 2017-10-21 16:21:46

下面是一个如下所示的矩阵的伪代码示例:

代码语言:javascript
运行
复制
1 2
3 4

# Get which other numbers are "legal moves" from each number.
adjacency = {
    1: [2, 3],
    2: [1, 4],
    3: [1, 4],
    4: [2, 3]
}

# Get the length of code required.
n = 8
# Start at a random position;
pos = rand(keys(adjacency))
result = []
while (n > 0)
    n -= 1
    newpos = rand(adjacency[pos])
    result[] = newpos
    pos = newpos
print(result.join(', '))

如果您的矩阵将很大或将发生变化,您可能希望编写一些代码来生成adjaceny,而不是硬编码它。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46864907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档