【发布时间】:2013-12-10 17:13:26
【问题描述】:
我一直在尝试为我正在开发的程序编写一些逻辑,但遇到了一些困难。
基本上我在舞台上以编程方式创建的是一个 4x4 网格(16 个块),如下所示:
用户的任务是通过单击块在网格上绘制一个连续的形状,并且它们的形状应该具有没有间隙和没有对角绘制的块,例如以下将是合法的形状:
但是,以下形状不会,并且会以弹出图形的形式向用户抛出错误:
网格的绘制过程与布尔数组形式的网格的 4x4 虚拟表示相关联,如下所示:
public static var ppnRowArray1:Array = [false,false,false,false];
public static var ppnRowArray2:Array = [false,false,false,false];
public static var ppnRowArray3:Array = [false,false,false,false];
public static var ppnRowArray4:Array = [false,false,false,false];
public static var ppnColumnArray:Array = [ppnRowArray1,ppnRowArray2,ppnRowArray3,ppnRowArray4];
当用户单击并选择一个块时,将颜色属性更改为棕色,我的“虚拟网格表示”数组中的相关布尔属性将从 false 变为 true。如果一个情节是非法的,那么这个属性会被改回假,然后用户被邀请再次尝试他们的下一个情节。
我已经设法编写了强制用户绘制合法形状的代码,并在进行非法绘图时进行计算,但我现在需要编写用户从现有块中取消选择块的逻辑合法的形状,使其不连续,这就是我的问题所在。
这是目前的工作解决方案。
//---------------------------------------------------------------------
public static function ppnCountSetCells():int
{
//Count Each 4x4 Grid Cell
var count:int = 0;
for (var row=0; row<=3; row++)
{
for (var col=0; col<=3; col++)
{
if (ppnColumnArray[col][row])
{
count++;
}
}
}
return count;
}
//---------------------------------------------------------------------
public static function ppnBlockValid():Boolean
{
if (ppnCountSetCells() > 1)
{
for (var row=0; row<=3; row++)
{
for (var col=0; col<=3; col++)
{
if (ppnColumnArray[col][row] == true)
{
// Check if we are connected to another set square
var validNeighbours:int = 0;
// Check North
if (row > 0)
{
if (ppnColumnArray[col][row - 1] == true)
{
validNeighbours++;
}
}
// Check South
if (row < 3)
{
if (ppnColumnArray[col][row + 1] == true)
{
validNeighbours++;
}
}
// Check West
if (col > 0)
{
if (ppnColumnArray[col - 1][row] == true)
{
validNeighbours++;
}
}
//-----------------------------------------------------------------------------------------
// Check East
if (col < 3)
{
if (ppnColumnArray[col + 1][row] == true)
{
validNeighbours++;
}
}
//-----------------------------------------------------------------------
if (validNeighbours < 1)
{
return false;
}
//-----------------------------------------------------------------------
}
}
}
}
return true;
}
//---------------------------------------------------------------------
function addBlock(e:MouseEvent):void
{
//trace("You Have Clicked On Grid Block Number: " + e.currentTarget.id);
if (InterfaceButtons.panelOpen == false)
{
//Listen to see if the block click is adjoining and pass back to see if it is valid on the grid
var col:int = (e.currentTarget.id - 1) % 4;
var row:int = (e.currentTarget.id - 1) / 4;
ppnColumnArray[col][row] = true;
addOrRemove = "add";
ppnBlockValid();
//Get the Block Valid Result (True or False) and pass it into a Boolean variable to use later
ppnGridError = ppnBlockValid();
trace("Is This Valid? " + ppnBlockValid());
//----------------------------------------------------------------------------------------------
//Push Blocks Selected into Array
ppnShapeArray[e.currentTarget.id] = true;
trace(ppnShapeArray);
//----------------------------------------------------------------------------------------------
//Add 1 to the block count which directly effects the final outcome depending on ++ or --
ppnBlocksSelected++;
PlantPopNitDesignPlot.ppnPlotMade = false;
//Hide Block to Reveal Brown One
e.currentTarget.alpha = 0;
//-----------------------------------------------------------------------------------------------
//Output an error if one is present on Click based on gridError Boolean Variable
ppnOutputAddError();
if (ppnGridError == false)
{
//Restore the block's alpha property as it isn't allowed to be selected, removing counter by one -- and changing final output accordingly
e.currentTarget.alpha = 1;
ppnBlocksSelected--;
ppnColumnArray[col][row] = false;
ppnShapeArray[e.currentTarget.id] = false;
ppnPopulateTotalSiteUnitsTxt();
}
//Update final total
ppnPopulateTotalSiteUnitsTxt();
//Call again to do dynamic colour font change should total exceed 10
ppnPopulateTotalSiteUnitsTxt();
//Added in to make sure it executes every time if an error is made.
if (ppnGridError == true)
{
e.currentTarget.removeEventListener(MouseEvent.CLICK, addBlock);
e.currentTarget.addEventListener(MouseEvent.CLICK, removeBlock);
}
}
}
function removeBlock(e:MouseEvent):void
{
if (InterfaceButtons.panelOpen == false)
{
var col:int = (e.currentTarget.id - 1) % 4;
var row:int = (e.currentTarget.id - 1) / 4;
ppnColumnArray[col][row] = false;
addOrRemove = "remove";
ppnBlockValid();
ppnGridError = ppnBlockValid();
trace("Is This Removal Valid? " + ppnBlockValid());
//trace("You Have Clicked On Grid Block Number: " + e.currentTarget.id);
e.currentTarget.alpha = 1;
ppnShapeArray[e.currentTarget.id] = false;
//trace("ppnShapeArray - " + ppnShapeArray);
//---------------------------------------------------------------------
ppnBlocksSelected--;
PlantPopNitDesignPlot.ppnPlotMade = false;
//Output an error if one is present on Click based on gridError Boolean Variable
ppnOutputRemoveError();
if (ppnGridError == false)
{
//Restore the block's alpha property as it isn't allowed to be selected, removing counter by one -- and changing final output accordingly
e.currentTarget.alpha = 0;
ppnBlocksSelected--;
ppnColumnArray[col][row] = true;
ppnShapeArray[e.currentTarget.id] = true;
ppnPopulateTotalSiteUnitsTxt();
}
//Update Final Total
ppnPopulateTotalSiteUnitsTxt();
//Call again to do dynamic colour font change should total falls below 10
ppnPopulateTotalSiteUnitsTxt();
//Added in to make sure it executes every time.
if (ppnGridError == true)
{
e.currentTarget.addEventListener(MouseEvent.CLICK, addBlock);
e.currentTarget.removeEventListener(MouseEvent.CLICK, removeBlock);
}
}
}
}
}
//---------------------------------------------------------------------
现在,对于大多数情况,此逻辑在向形状中添加或删除块时会起作用并检测非法绘图,但是最近我发现当形状中有 5 个 > 块时,检测删除错误的逻辑失败某些情况。
当形状不正确时(当块被移除时)被声明为真实和合法的几个例子如下:
我可以看到,我的 'ppnBlockValid():Boolean' 函数中编写的逻辑需要调整以补偿这些输出。似乎您只能删除一个块,前提是相邻块仍连接到其他块。虽然这适用于较小的形状,但理论上较大的形状(例如 5 个或更多块)可以从中间拆分,因此我认为代码需要调整以解决此问题。
但是怎么做呢?对此的任何帮助将不胜感激。
非常感谢,如果您需要我提供任何进一步的信息,请告诉我。
干杯,
乔尔
已编辑
非常感谢您提供增强的代码和解释@dhc 我真的很感激,但我仍然对如何正确实现这一切感到有些困惑。
根据您的以下建议,这是我当前的“ppnBlockValid”功能代码:
public static function ppnBlockValid():Boolean
{
ppnIslands = [];
ppnAddNewIsland = [];
ppnAddToExistingIsland = [];
if (ppnCountSetCells() > 1)
{
for (var row=0; row<=3; row++)
{
for (var col=0; col<=3; col++)
{
if (ppnColumnArray[col][row] == true)
{
var addedToIsland = false;
// Check if we are connected to another set square
var validNeighbours:int = 0;
// Check North
if (row > 0)
{
if (ppnColumnArray[col][row - 1] == true)
{
validNeighbours++;
}
//----------------------------------
//ISLAND CHECK
if (ppnColumnArray[col][row - 1])
{
ppnAddToExistingIsland.push([col,row - 1],[col,row]);
addedToIsland = true;
}
}
// Check South
if (row < 3)
{
if (ppnColumnArray[col][row + 1] == true)
{
validNeighbours++;
}
}
// Check West
if (col > 0)
{
if (ppnColumnArray[col - 1][row] == true)
{
validNeighbours++;
}
//----------------------------------
//ISLAND CHECK
if (ppnColumnArray[col - 1][row])
{
ppnAddToExistingIsland.push([col - 1,row],[col,row]);
addedToIsland = true;
}
}
//-----------------------------------------------------------------------------------------
// Check East
if (col < 3)
{
if (ppnColumnArray[col + 1][row] == true)
{
validNeighbours++;
}
}
//-----------------------------------------------------------------------
if (! addedToIsland)
{
ppnIslands.push([col,row]);
}
//-----------------------------------------------------------------------
if (ppnIslands.length >= 2 && addOrRemove == "remove")
{
trace("TWO ISLANDS HAVE BEEN FORMED AND AN ERROR SHOULD BE OUTPUT");
validNeighbours--;
}
/**/
//return (ppnIslands.length<=1);// 0 islands is valid also!
//-----------------------------------------------------------------------
if (validNeighbours < 1)
{
return false;
}
//-----------------------------------------------------------------------
}
}
}
}
return true;
}
//---------------------------------------------------------------------
我一直使用以下形状作为我的代码实验:
基于上面的代码和示例形状,我当前的跟踪输出是:
ppnIsland = |0,0|,0,2
ppnAddNewIsland =
ppnAddToExistingIsland = 0,0, 1,0, 1,0, 2,0, 2,0, 3,0, 1,0, 1,1, 1,1, 1,2, 0,2, 1,2, 1,2, 2,2, 2,2, 3,2
看起来尽管形状是连续的,但我尝试从您那里解释的代码在块移除之前找到了一个额外的岛,在本例中为“Col: 0, Row: 2”?是这样吗?
如果我尝试删除中间(红色)块,因为 'ppnIsland' 数组包含 > 1 个岛,此代码当然会输出错误,但我认为它没有检测到正确的输出?
我是否需要使用 indexOf 命令交叉引用 'ppnIsland' 和 'ppnAddToExistingIsland' 数组来检查任一元素是否属于现有岛?
乔尔
【问题讨论】:
-
如果您的目标是不创建岛屿,则在存在极地相邻块时进行简单更改以防止块移除可能是不够的。考虑一个 8 块圆圈:移除北单元并不意味着创建两个岛,因为南单元仍然连接两个岛。假设圆圈的北行表示为 ABC,并且您想要移除 B,您可能需要从单元格 A 遍历邻接直到到达 C。只有这样您才能证明有效的块移除。
标签: actionscript-3 flash logic