我在零矩阵中有工作功能 flood-fill sa 封闭区域,递归,给定区域内的X和Y.
class Game
{
Bitmap image;
public Game(Bitmap image)
{
this.image = image;
}
}
...
Bitmap tempConvert;
...
tempConvert = new Bitmap(100, 100);
games.Add(new Game(tempConvert));
tempConvert.Dispose();
因为我递归调用此函数超过 1 时间,所以我不能只返回该函数。我最后还得回来。因此,我必须通过引用传递矩阵,如您所见。否则它将无法工作。
如何更改此代码,以便按值传递矩阵,函数将返回新的充满洪水的矩阵?
谢谢!
答案 0 :(得分:1)
如果更改函数以将数组作为参数,修改并返回,则实际上可以避免使用引用。你所要做的就是记住当你递归地调用它时:
import UIKit
import Foundation
class CollectionViewController: UICollectionViewController, UICollectionViewDataSource, UICollectionViewDelegate, UIGestureRecognizerDelegate {
var name = [String]()
var originalCenter: CGPoint!
var animator: UIDynamicAnimator!
override func viewDidLoad() {
super.viewDidLoad()
let width = CGRectGetWidth(collectionView!.frame)
let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: width, height: width + (width / 3))
name = ["DAN", "DANIELA", "MIRABELA", "ANGELA", "CARTOCEA", "FANDOSAN"]
}
override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return name.count
}
override func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("cell", forIndexPath: indexPath) as! UICollectionViewCell
originalCenter = cell.center
animator = UIDynamicAnimator(referenceView: cell)
let names = cell.viewWithTag(1) as! UILabel
names.text = name[indexPath.row]
let panLeftRight: UIGestureRecognizer = UIPanGestureRecognizer(target: self, action: "handlePan:")
panLeftRight.delegate = self
cell.addGestureRecognizer(panLeftRight)
return cell
}
func handlePan(sender: UIPanGestureRecognizer) {
let translation = sender.translationInView(self.view)
let location = sender.locationInView(self.view)
var widthForPan = CGRectGetWidth(collectionView!.frame)
sender.setTranslation(CGPoint(), inView: self.view)
switch sender.state {
case .Began:
if let view = sender.view {
view.center = CGPoint(x:view.center.x, y:view.center.y)
}
case .Changed:
if let view = sender.view {
view.center = CGPoint(x:view.center.x + translation.x,
y:view.center.y)
}
case .Ended:
UIView.animateWithDuration(0.4) {
if let revine = sender.view {
revine.center = CGPoint(x: translation.x + widthForPan / 2, y: revine.center.y)
}
print(self.originalCenter)
print(widthForPan)
}
default:
if let view = sender.view {
view.center = CGPoint(x:view.center.x,
y:view.center.y)
}
sender.setTranslation(CGPointZero, inView: self.view)
}
}
}
<强>更新强>
正如@Daniel评论的那样,在执行函数期间,每次执行function MatrixFloodFill(array $matrix, $x, $y)
{
if($matrix[$x][$y] == 0) {
// Modify the matrix
$matrix[$x][$y] = 1;
// Pass the modified matrix to the recursive call and ...
// ... store the value it returns (a modified copy of the matrix)
$matrix = MatrixFloodFill($matrix, $x+1, $y);
// ... do the same again and again ...
$matrix = MatrixFloodFill($matrix, $x-1, $y);
$matrix = MatrixFloodFill($matrix, $x, $y+1);
$matrix = MatrixFloodFill($matrix, $x, $y-1);
}
// Return the modified matrix
return $matrix;
}
块时,行if
都会生成矩阵的新副本。只保留最后一个这样的副本(它由函数的最顶层调用返回,并且可能由调用代码保存在变量中),所有其他副本都被销毁。
执行函数期间创建的副本数等于修改的元素数(最多为矩阵中元素的总数)。如果这个数字很大,那么脚本会花费大量的处理时间来创建许多副本并丢弃所有副本,但最后一个副本。
通过值传递矩阵的唯一优点是代码清洁度和可测试性(顺便说一下,这不是一件小事)。但是,如果将原始函数(使用引用)标记为实现细节(此处的语言对您没有帮助,您可以在函数的文档中解释这一点),则可以保持可测试性和清洁性,编写一个包装函数来获取矩阵值,调用引用函数,然后返回更新的矩阵,只使用包装函数(它是公共接口)。
更好的是,您应该将数据和代码嵌入到类中。它还应该存储矩阵的维度(你发布的代码不检查它们,递归永远不会停止;我假设发布的代码是一个最小的例子,真实的代码正确处理矩阵的维度。)
答案 1 :(得分:1)
axiac发布了一个问题的答案,该答案产生了一个递归函数,该函数不通过引用取矩阵。这样可行,但效率低得多。
我建议你保留原来的方法,然后添加另一个包装器:
function MatrixFloodFillRef(&$matrix, $x, $y)
{
if($matrix[$x][$y] == 0)
{
$matrix[$x][$y] = 1;
MatrixFloodFillRef($matrix, $x+1, $y);
MatrixFloodFillRef($matrix, $x-1, $y);
MatrixFloodFillRef($matrix, $x, $y+1);
MatrixFloodFillRef($matrix, $x, $y-1);
}
return $matrix;
}
function MatrixFloodFill($matrix, $x, $y)
{
MatrixFloodFillRef($matrix, $x, $y);
return $matrix;
}