1

update 1

Building on the previous update, I think I have a better insight into doing this, but I need the answer to this question. In the current for loop there is a variable named tstring. I need to do a something like the following, but it does not work. I get the error Collection expression type 'NSString *' may not respond to countByEnumeratingWithState:objects:count:' How can I fix this for clause?

for (NSUInteger i = 1; i < match.numberOfRanges; ++i)
        {
            NSRange matchedRange = [match rangeAtIndex: i];
            NSString* tstring = [string substringWithRange: matchedRange];
            for (char* suit in tstring){   // error here ********
            NSLog(@"char: %@",suit);}
            NSLog(@"range %lu string: %@", (unsigned long)i, tstring);
        }

update 1

update 0

Here is another approach, that does not require a search, but I still don't have any idea how to accomplish this approach in the context of the for loop.

I need a dictionary like the following schematic representation which associates with each card (2 to Ace) an integer from 0 to 12. (I think I know how to create a dictionary in C; maybe not in objective-c.)

┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬──┬──┬──┐
│0│1│2│3│4│5│6│7│8│9│10│11│12│
├─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼──┼──┼──┤
│2│3│4│5│6│7│8│9│T│J│Q │K │A │
└─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴──┴──┴──┘

I need a struct with four nouns or arrays, I am not sure which, each of length 13 like this. This is similar to the original struct, but now the members are card suits, not players' positions.

struct board { 
int num;
char spade[13]
char heart[13]
char diamond[13]
char club[13]
};

Assuming the following deal of Board number 1,

Q952.652.KJT4.95 T.KQT84.A865.J73 K8763.A7.Q.KQT84 AJ4.J93.9732.A62

I need the following process in the for loop of my code.

   spade[10] = N
   spade[7] = N
   spade[3] = N
   spade[0] = N
   heart[4] = N
   heart[3] = N
   etc.

The question is, "How do you do that processing in a for loop?"

update 0

The following code is working for me but I need to alter it for the purpose described below. My console output (at least, the beginning) is provided below, also. From the output I need to retain results of range 1 and range 4 thru 19 in a special way.

The little table below contains range numbers in a 4 by 4 array with rows labeled Spades, Hearts, Diamonds, Clubs and columns labeled North, East, South, and West. When a Heart is selected, I need to search the contents of row H to determine whether that card is in N,E,S, or W and report the result. Notice that in the table the contents of each cell is a string containing either nothing (is empty) or a set of letters from '23456789TJQKA' and each row has all 13 letters somewhere in it. The numbers in the table just refer to the range number in the current output.

     N  E  S  W    
S    4  8 12 16
H    5  9 13 17
D    6 10 14 18
C    7 11 15 19

I would like to learn how to store the results in anticipation of the search task. Can I create a C struct for which each member contains the integer board number (a number between 1 and 36) and the 4 strings? For example would the struct below work? And if it does, how does one search in such a struct in objective-c? I could also use some help populating the struct in my loop.

struct board { 
int num;
char N[13]
char E[13]
char S[13]
char W[13]
};

Code excerpt follows.

NSRegularExpression *regex = [NSRegularExpression  regularExpressionWithPattern:toMatch options:NSRegularExpressionDotMatchesLineSeparators error:&error];
NSLog(@"pattern length: %lu", (unsigned long)[toMatch length]);
NSUInteger numberOfMatches = [regex numberOfMatchesInString:string options:0 range:NSMakeRange(0, [string length])];
NSLog(@"number of matches: %lu", (unsigned long)numberOfMatches);
for (NSTextCheckingResult* match in [regex matchesInString:string options:NSRegularExpressionDotMatchesLineSeparators range:NSMakeRange(0, [string length])])
{
    NSLog(@"Number of ranges in match: %u", match.numberOfRanges);
    for (NSUInteger i = 0; i < match.numberOfRanges; ++i)
    {
        NSRange matchedRange = [match rangeAtIndex: i];
        NSString* tstring = [string substringWithRange: matchedRange];
        NSLog(@"range %lu string: %@", (unsigned long)i, tstring);
    }
}

Sample output follows.

2013-02-04 16:24:06.583 [71684:11303] string length: 22365
2013-02-04 16:24:06.591 [71684:11303] pattern length: 347
2013-02-04 16:24:06.602 [71684:11303] number of matches: 36
2013-02-04 16:24:06.613 [71684:11303] Number of ranges in match: 20
2013-02-04 16:24:06.613 [71684:11303] range 0 string:
[Board "1"]
[West ""]
[North ""]
[East ""]
[South ""]
[Dealer "N"]
[Vulnerable "None"]
[Deal "N:Q952.652.KJT4.95 T.KQT84.A865.J73 K8763.A7.Q.KQT84 AJ4.J93.9732.A62"]
2013-02-04 16:24:06.613 [71684:11303] range 1 string: 1
2013-02-04 16:24:06.613 [71684:11303] range 2 string: N
2013-02-04 16:24:06.614 [71684:11303] range 3 string: None
2013-02-04 16:24:06.614 [71684:11303] range 4 string: Q952
2013-02-04 16:24:06.614 [71684:11303] range 5 string: 652
2013-02-04 16:24:06.614 [71684:11303] range 6 string: KJT4
2013-02-04 16:24:06.614 [71684:11303] range 7 string: 95
2013-02-04 16:24:06.614 [71684:11303] range 8 string: T
2013-02-04 16:24:06.614 [71684:11303] range 9 string: KQT84
2013-02-04 16:24:06.614 [71684:11303] range 10 string: A865
2013-02-04 16:24:06.615 [71684:11303] range 11 string: J73
2013-02-04 16:24:06.615 [71684:11303] range 12 string: K8763
2013-02-04 16:24:06.615 [71684:11303] range 13 string: A7
2013-02-04 16:24:06.615 [71684:11303] range 14 string: Q
2013-02-04 16:24:06.615 [71684:11303] range 15 string: KQT84
2013-02-04 16:24:06.616 [71684:11303] range 16 string: AJ4
2013-02-04 16:24:06.616 [71684:11303] range 17 string: J93
2013-02-04 16:24:06.616 [71684:11303] range 18 string: 9732
2013-02-04 16:24:06.616 [71684:11303] range 19 string: A62
4

1 回答 1

0

我觉得这个问题与“我该如何做 X?”相去甚远。并开始非常接近“请为我做X”。也就是说,昨晚我确实考虑了一会儿,我有一些想法要分享,这些想法可能对你有所帮助。

首先,是的,这可以用任意数量的 C 结构来建模。您已经探索了其中的几个。您尚未提出的一种想法是使用位图来表示手。一副牌中有 52 张牌;存储手牌的一种方法是使用 64 位整数,并使 52 位对应于一副牌中的牌。如果设置了对应于特定卡片的位,则一手牌包含特定卡片。然后搜索这些手就变成了一个简单的按位与运算。您甚至可以通过界面获得创意,并使用 Cunion将底层表示设为 64 位类型,同时允许对子集(如花色或位置)进行结构化访问,或许可以通过说每个花色对应于底层类型的 16 位来实现。

也就是说,考虑到这里数据集的大小,遇到性能问题的方法相对较少,在仔细研究了一下之后,我开始觉得努力寻找最好的或“最快速搜索的”数据结构构成过早的优化。即使你把这个应用程序的数据模型变成了一个完全成熟的 Objective-C 对象图,包括棋盘类、每个位置、每只手,甚至每张牌的对象实例,你仍然在解决一个“恒定大小”的问题(有一个“恒定时间”表现的机会。)IIUC,一副牌中永远不会有超过 52 张牌,也不会超过 4 个位置,也不会超过 36 个棋盘。这是一个非常受约束的问题。如果您打算导入数以万计的此类游戏,然后查询所有这些游戏,

接下来,我建议在解析行内容时放弃使用正则表达式[Deal "..."]。你能用正则表达式吗?当然。但是将带引号的字符串作为 a const char*(请参阅-[NSString UTF8String])然后按顺序遍历字符会更简单:第一个字符是[NSEW]并标识第一个位置(可能需要存储在您的结构中,但到目前为止还没有)。然后一个无用:的忽略。然后开始阅读黑桃牌。当你击中一个.增量西装。当你击中一个<space>增量的位置。你可以使用正则表达式来提取这些部分,但是简单的方法要简单得多,我建议使用它。(我应该提到,考虑到上下文,这种更简单的方法也快得多,但我认为仅出于性能选择这种方法将是不成熟的优化。所以,不要为了性能而选择这种方法,选择它是为了简单!)

最后,我觉得我应该提一下,虽然我的 2 分钟 google-fu 未能找到任何好的开源 C PBN 读取实现(以及模型数据结构),但我发现真的很难相信有一个没有。我的搜索有点复杂,因为“桥”是一个超载的英文单词。我可能会建议您多了解一下,看看您是否可以找到一个成熟的开源实现来按原样使用或作为灵感使用,而不是自己动手。

编辑:

我写了一个潜在的循环来填充你建议的结构:

// Your structure, but as a typedef for clarity.
typedef struct {
    int num;
    char spade[13];
    char heart[13];
    char diamond[13];
    char club[13];
} board;

// The quoted string in the [Deal "..."] line; you already know how to get this.
NSString* dealString = @"N:A8.J762.KQ742.98 KQ53.K93.A85.T52 J97.A8.J963.J743 T642.QT54.T.AKQ6";

// Set up some arrays to use as maps between ints and chars...
// ...for positions:
const char* const positionIntToCharMap = "NESW";
int positionCharToIntMap['Z'] = { 0 };
for (int i = 0, len = (int)strlen(positionIntToCharMap); i < len; ++i) positionCharToIntMap[positionIntToCharMap[i]] = i;

// and cards:
const char* const cardIntToCharMap = "23456789TJQKA";
int cardCharToIntMap['Z'] = { 0 };
for (int i = 0, len = (int)strlen(cardIntToCharMap); i < len; ++i) cardCharToIntMap[cardIntToCharMap[i]] = i;

// and suits:
const char* const suitIntToCharMap = "SHDC";
int suitCharToIntMap['Z'] = { 0 }; 
for (int i = 0, len = (int)strlen(suitIntToCharMap); i < len; ++i) suitCharToIntMap[suitIntToCharMap[i]] = i;

const char* dealCString = [dealString UTF8String];
const size_t dealCStringLen = strlen(dealCString);

board thisBoard = { 0 }; 

if (dealCStringLen)
{
    char suit = 'S'; // start with spades
    char pos = dealCString[0]; // first character is starting position

    for (off_t i = 1; i < dealCStringLen; ++i)
    {
        if (dealCString[i] == ':')
        {
            continue;
        }
        else if (dealCString[i] == '.') // advance the suit
        {
            const int currentSuitInt = suitCharToIntMap[suit];
            const int nextSuitInt = (currentSuitInt + 1) % 4;
            suit = suitIntToCharMap[ nextSuitInt ];
        }
        else if (dealCString[i] == ' ') // advance the position and reset the suit
        {
            const int currentPosInt = positionCharToIntMap[pos];
            const int nextPosInt = (currentPosInt + 1) % 4;
            pos = positionIntToCharMap[ nextPosInt ];
            suit = 'S';
        }
        else // read the card
        {
            const char charForCard = dealCString[i];
            const int intForCard = cardCharToIntMap[charForCard];

            // Mark the current position in the appropriate array.
            if (suit == 'S')
            {
                thisBoard.spade[intForCard] = pos;
            }
            else if (suit == 'H')
            {
                thisBoard.heart[intForCard] = pos;
            }
            else if (suit == 'D')
            {
                thisBoard.diamond[intForCard] = pos;
            }
            else if (suit == 'C')
            {
                thisBoard.club[intForCard] = pos;
            }
        }
    }
}

// thisBoard is now populated.

我希望这有帮助。

于 2013-02-05T14:42:58.523 回答