我是Objective C的新手,为我的第一个项目翻译了Actionscript 2中的现有代码。我一直在努力保持我的数据结构简单,这对我来说意味着类似C的数组和字符串而不是NS类。我有一堆对象,其中包含单字节数据字符 - 它们是拼字游戏图块,类型为“A”到“Z”。我想创建一个字母值数组,使得键/值对易于在代码中可读和修改。
在AS2中就是这样:
//init
letterScore = new Object({E:1, S:1, I:1, A:2, R:2 ... Z:10});
//assigned in 2dArray:
map[0]="WORD".split();
map[1]="GRID".split();
map[2]="HERE".split();
map[3]="!# @".split();
tile.letter=map[x][y];
//access
if(tile.letter>='A' && tile.letter<='Z'){
wordScore+= letterScore[tile.letter];
}
在目标C中,我已经以类似的方式在地图中定义和读取,我的tile.letter数据类型是char。有没有办法获得一个像char:int配对这样简单的数据类型的关联数组?它可以在一行代码中完成,类似于上面的AS2 init行吗?我正在阅读的书籍建议我必须将值包装为NSNumber,并在char和NSString之间进行转换以访问它们,这看起来很笨拙,但如果我坚持使用类似C的数组,我会失去键的可读性。在Java中,我可以扩展数组类来处理转换,但书中说在Objective C中这是一个坏主意,所以我完全迷失了。
编辑:我认为要避免人们所建议的持续装箱和拆箱(我使用的是这个术语吗?)并保持可读性,我最好的选择是这个可怕的黑客...
#define ASCII_2_ARRAY -65
int letterScore[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z.
然后访问只是
score += letterScore[tile.letter + ASCII_2_ARRAY];
这样做是否有不利之处?
答案 0 :(得分:2)
您可以轻松创建NSDictionary
,并以各种方式使用您的数据进行初始化。输入像
NSDictionary *dict = [[NSDictionary alloc] initWithObjectsAndKeys:
[NSNumber numberWithInt:1], @"A",
...
[NSNumber numberWitHInt:10], @"Z",
nil];
肯定会奏效。访问这个很容易,比如说,提取一个字母的值:
int score = [[dict objectForKey:theLetter] intValue];
其中theLetter
是您正在评分的单词中的一个字母。
一旦你习惯了Objective-C明显的“冗长”,只用几种基本类型就可以做到非常酷。
答案 1 :(得分:2)
NSDictionary
和NSArray
虽然令人讨厌,却是这片树林中的“简单数据结构”。我建议您将tile.letter
更改为NSStrings
。
如果您要使用Obj-C和(我假设)Cocoa,您将不得不习惯NSDictionary
以及它无法处理非对象类型的事实。如Mark所示,NSString
只包含一个字符是没有问题的,您可以输入所需的所有文字NSStrings
。
如果它看起来很有趣,可以把一个“字符”想象成一个长度为1的字符串。这只是有趣的C语言的反转,其中“字符串”只不过是一些串联字符。
回复你的评论:
// Get a random letter from the alphabet
NSString *alphabet = [[NSString alloc] initWithString:@"ABCDEFGHIJKLMNOPQRSTUVWXYZ"];
NSString *letter = [alphabet substringWithRange:NSMakeRange(random() % ALPHABET_LENGTH, 1)];
/ usr / share / dict / words是2.5MB。这是我现在运行的最小Cocoa应用程序的内存占用量的大约10%(预览,没有打开的文档)。三位压缩可以节省半个兆字节。单击按钮使用大致相同;移动窗口会分配更多。您是否测量 NSString
版本的性能?
// Create an NSString with one NSString character
NSString *justOneChar = [NSString stringWithString:@"A"];
// Get a char out of an NSString
char c;
// You can do this if you're sure that the character is ASCII
c = (char)[justOneChar characterAtIndex:0];
// Create an NSString using one char
char c = 'A';
unichar uc = c;
NSString * justOneOtherChar = [NSString stringWithCharacters:&uc length:1];
char oc = (char)[justOneOtherChar characterAtIndex:0];
C字符串也需要以nul结尾。
你也可以让Cocoa处理你的英语词典;看看Dave DeLong的DDFileReader class最初将文本文件放到NSString
中,然后如果需要,写出来并使用NSArray
的{{1}}和-initWithContentsOfFile读取它们:`
答案 2 :(得分:1)
由于
你的问题是请求你使用C数组。您使用
的想法int letterScore[]={0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5};
// A B C D E F G H I J K L M N O P Q R S T U V W X Y Z.
足够好了。
正如您所注意到的,主要问题是将字符映射到数组中的位置。通常,您可以使用预处理器宏,如:
#define CHAR2INDEX(x) (x - 'A')
score += letterScore[CHAR2INDEX(tile.letter)];
我同意初始化数组并不像AS那样,但是,C又是一种尝试尽可能简单有效的不同语言。也就是说,有其他方法可以初始化数组。
首先,您可以使用以下内容:
int letterScore[] = {
['A' - 'A'] = 0,
['B' - 'A'] = 1,
['C' - 'A'] = 2,
…
};
或使用之前的宏
int letterScore[] = {
[CHAR2INDEX('A')] = 0,
[CHAR2INDEX('B')] = 1,
[CHAR2INDEX('C')] = 1,
…
};
如果浪费65 ints
不是问题 - 除非您的目标是严重内存限制的设备,否则不应该这样做 - 您可以拥有一个阵列,其中65个第一个元素未被使用。这会让事情更具可读性。例如:
int letterScore[] = { ['A'] = 0, ['B'] = 1, ['C'] = 2, … };
score += letterScore[tile.letter];