虽然我确信有很多方法可以保持数组的正确性,但我找到了一种对我来说效果很好的方法。最重要的是,它将大量信息折叠成几个数组,我可以将这些数组解析为 XML 文件或其他存储方法。我将此方法称为我的“索引数组系统”。
实际上有多种方法可以做到这一点:创建少量一维数组,或创建二维(或更高)数组。两者都同样有效,因此请选择最适合您的代码的那个。我只在这里展示一维方法。熟悉数组的人可能会想出如何重写它以使用更高维的数组。
我使用 Actionscript 3,但这种方法几乎适用于任何编程或脚本语言。
在这个例子中,我试图保持不同“活动”的各种“属性”。在这种情况下,我们会说这些属性是 Level、High Score 和 Play Count。我们将这些活动称为弹球、单词搜索、迷宫和记忆。
此方法涉及创建多个数组,每个属性一个数组,并创建保存用于每个活动的整数“键”的常量。
我们将从创建常量开始,作为整数。常量为此工作,因为我们在编译后从不更改它们。我们放入每个常量的值是相应数据将始终存储在数组中的索引。
const pinball:int = 0;
const wordsearch:int = 1;
const maze:int = 2;
const memory:int = 3;
现在,我们创建数组。请记住,数组从零开始计数。由于我们希望能够修改这些值,因此这应该是一个常规变量。
注意,我将数组构造为我们需要的特定长度,并在每个插槽中使用所需数据类型的默认值。我在这里使用了所有整数,但您可以使用几乎任何您需要的数据类型。
var highscore:Array = [0, 0, 0, 0];
var level:Array = [0, 0, 0, 0];
var playcount:Array = [0, 0, 0, 0];
因此,我们为每个属性都有一个一致的“地址”,我们只需要创建四个常量和三个数组,而不是 12 个变量。
现在我们需要创建函数来使用这个系统读取和写入数组。这就是系统真正的魅力所在。如果你想从这个类之外读/写数组,请确保这个函数是在公共范围内编写的。
要创建从数组中获取数据的函数,我们需要两个参数:活动名称和属性名称。我们还想设置此函数以返回任何类型的值。
GOTCHA 警告:在 Actionscript 3 中,这在静态类或函数中不起作用,因为它依赖于“this”关键字。
public function fetchData(act:String, prop:String):*
{
var r:*;
r = this[prop][this[act]];
return r;
}
那段奇怪的代码r = this[prop][this[act]] 只是使用提供的字符串“act”和“prop”作为常量和数组的名称,并将结果值设置为 r。因此,如果您向函数提供参数(“maze”、“highscore”),那么该代码将基本上像r = highscore[2](请记住,this[act] 返回分配给它的整数值。)
写入方法的工作原理基本相同,只是我们需要一个额外的参数,即要写入的数据。这个参数需要能够接受任何
GOTCHA 警告:这个具有严格类型语言的系统的一个显着缺点是您必须记住要写入的数组的数据类型。编译器无法捕获这些类型错误,因此如果您的程序尝试写入错误的值类型,它只会抛出一个致命错误。
解决此问题的一个聪明方法是为不同的数据类型创建不同的函数,因此在参数中传递错误的数据类型将触发编译时错误。
public function writeData(act:String, prop:String, val:*):void
{
this[prop][this[act]] = val;
}
现在,我们还有一个额外的问题。如果我们传递一个不存在的活动或属性名称会发生什么?为了防止这种情况,我们只需要一个函数。
此函数将通过尝试访问提供的常量或变量键来验证它,并捕获由此产生的致命错误,而不是返回 false。如果key有效,则返回true。
function validateName(ID:String):Boolean
{
var checkthis:*
var r:Boolean = true;
try
{
checkthis = this[ID];
}
catch (error:ReferenceError)
{
r = false;
}
return r;
}
现在,我们只需要调整我们的其他两个函数来利用这一点。我们将把函数的代码包装在 if 语句中。
如果其中一个键无效,该函数将不执行任何操作 - 它会静默失败。要解决这个问题,只需在 else 构造中添加一个跟踪(也称为打印)语句或非致命错误。
public function fetchData(act:String, prop:String):*
{
var r:*;
if(validateName(act) && validateName(prop))
{
r = this[prop][this[act]];
return r;
}
}
public function writeData(act:String, prop:String, val:*):void
{
if(validateName(act) && validateName(prop))
{
this[prop][this[act]] = val;
}
}
现在,要使用这些函数,您只需分别使用一行代码。例如,我们会说我们在 GUI 中有一个显示高分的文本对象,称为 txtHighScore。为了示例,我省略了必要的类型转换。
//Get the high score.
txtHighScore.text = fetchData("maze", "highscore");
//Write the new high score.
writeData("maze", "highscore", txtHighScore.text);
我希望您会发现本教程对排序和管理变量很有用。
(后注:您可能可以对字典或数据库做类似的事情,但我更喜欢这种方法的灵活性。)