【发布时间】:2021-01-11 20:21:24
【问题描述】:
我正在编写一个 PHP 脚本,用于将小盒子(简单矩形)放置在一个更大的盒子中。为此,我将代码的 Javascript 版本移植到 PHP。
<?php
class Packer
{
private $box;
/**
* Packer constructor.
* @param int $width
* @param int $height
*/
public function __construct(int $width, int $height)
{
$this->box = new Box($width, $height);
}
/**
* @param $blocks
*/
public function fitBlocksIntoBox($blocks)
{
for ($n = 0; $n < sizeof($blocks); $n++) {
$block = $blocks[$n];
$node = $this->findNode($this->box, $block->width, $block->height);
if ($node) {
$block->fitsInBox = $this->splitNode($node, $block->width, $block->height);
}
}
}
/**
* @param $box
* @param $width
* @param $height
* @return Box|null
*/
private function findNode($box, $width, $height)
{
if ($box->used) {
return $this->findNode($box->right, $width, $height) || $this->findNode($box->down, $width, $height);
} else if (($width <= $box->width) && ($height <= $box->height)) {
return $box;
} else {
return null;
}
}
/**
* @param $node
* @param $width
* @param $height
* @return mixed
*/
private function splitNode($node, $width, $height)
{
$node->used = true;
$bW = $node->width;
$bH = $node->height - $height;
$bX = $node->x;
$bY = $node->y + $height;
$node->down = new Box($bW, $bH, $bX, $bY);
$bW = $node->width - $width;
$bH = $node->height;
$bX = $node->x + $width;
$bY = $node->y;
$node->right = new Box($bW, $bH, $bX, $bY);
return $node;
}
}
class Block
{
public $width;
public $height;
public $fitsInBox;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
}
class Box
{
public $x;
public $y;
public $width;
public $height;
public $used;
public $down;
public $right;
public function __construct($width, $height, $x = 0, $y = 0) {
$this->x = $x;
$this->y = $y;
$this->width = $width;
$this->height = $height;
$this->used = false;
$this->right = null;
$this->down = null;
}
}
我这样运行脚本。
<?php
require_once('Packer.php');
require_once('Box.php');
require_once('Block.php');
$blocks = [
new Block(100, 100),
new Block(50, 50),
new Block(50, 50),
new Block(40, 30)
];
$packer = new Packer(900, 1200);
$packer->fitBlocksIntoBox($blocks);
在第一个循环中,脚本完全符合我的预期。它将第一个块放入框中并计算向下和向右两个新框。 第二个循环产生了问题,我不明白为什么会发生。
函数 findNode 将检查盒子是否已被使用。如果是这样,它将检查是否使用了 box-right 或 box-down 并使用此框调用自身。这行得通。在该函数的下一次调用中,它检测到该框未被使用并且该块将适合并返回该框。 结果将存储在函数 fitBlocksIntoBox 中的 $node 中,现在它不再是 Box,结果为 true。
调试第一个循环
调试第二个循环 - 从 findNode 返回
调试第二个循环 - fitBlocksIntoBox if($node)...
我通过 XDebug 运行脚本,它显示 findNode() 按预期返回 Box。 希望有人对我有提示,我在这里做错了什么。 谢谢,蒂莫
【问题讨论】:
-
你试过在 return (a || b) 周围加上括号吗?
-
@limido - 感谢您的提示。我刚刚测试了它,仍然有问题。