【问题标题】:Poker code cleanup modification from book...not quite right书中的扑克代码清理修改......不太正确
【发布时间】:2009-06-15 18:08:28
【问题描述】:

阅读更多书籍示例-这是一个部分扑克程序- 本段涉及直手....

首先给出的 - 只有相关部分......如果需要,将提供完整的代码......

int suits[5]; //index 1..4- value start at 1
int values[14]; //index 1..13- value same as rank, A = 1, K = 13

cin.get(rankCh);
switch (toUpper(rankCh)) {
case 'A': values = 1; break;
case '2': values = 2; break;
case '3': values = 3; break;
case '4': values = 4; break;
case '5': values = 5; break;
case '6': values = 6; break;
case '7': values = 7; break;
case '8': values = 8; break;
case '9': values = 9; break;
case 'T': values = 10; break;
case 'J': values = 11; break;
case 'Q': values = 12; break;
case 'K': values = 13; break;
default:
badCard = true;
}

其他功能:

bool isFlush(int suits[]) {
    for(i = 1; i <= 4; i++)
        if (suits[i] == 5)       //5 here is Number of Cards 
            return true;
    return false;
}

是的,我知道数组声明,但这就是它的定义方式——在文本中很好地证明了它......从 1 开始编号 我希望我的直手现在可以同时处理 Ace 高和低 - 因为上面定义的 A 是低...

两个版本:第一个似乎不确定正确的低 A...

代码

bool isStraight(int values[]) //Version one only straight- low aces only
{
    int count = 0;

    for (i = 1; i <= 13; i++) {
        if (values[i] != 1) {
            count++;
        } else
            count = 0;

        if (count == 5) //5 is NUMCARDS
            return true;
    }
    return false;
}

现在这是我需要一些建议的地方:拥有一个处理高低 ace 的函数:

bool isStraight(int values[]) //Version handles both high and low
{
    int count = 0;

    for (i = 1; i <= 13; i++) {
        if (values[i] != 1) {
            count++;
            // if(i == 1 && values[1] != 0) //Check for high and low
            // count++;
        } else
            count = 0;

        if (count == 5) //5 is NUMCARDS
            return true;
    }
    return false;
}

我在 cmets 中拥有的东西能同时处理高低 ace 吗...

由于 i = 1 表示为 ace,并且不确定哪些 values[1] 是正确的,应该是 values[13] 还是什么...可能类似于

if (i == 1)
   values[13] //not sure... 

建议-

  • 不希望进行大规模更改 - 只是对我拥有的内容进行细微更改...我不想通过蛮力进行排序或解决,即喜欢 values[1] == 1 && values [2] ==1 you明白这一点 - 文本已经这样做了,但我正试图以这种方式重写它......

谢谢...希望我能完成我想要的修改...

【问题讨论】:

    标签: c++ c


    【解决方案1】:

    编辑:我想我会先直接回答你的问题。让我们首先弄清楚原始算法是如何工作的。基本上它从 1 循环到 13,每次在该插槽中看到一张卡时,它都会增加计数。如果有任何东西破坏了序列,它会重置计数器。最后,如果计数器达到 5,你就有了顺子。

    我不能说你的解决方案是否可行,我说试试看。但是,对原始版本的简单快速补丁可能会是这样的:

    //Version handles both high and low
    bool isStraight(int values[]) {
        int count = 0;
    
        for (i = 1; i <= 13; i++) {
            if (values[i] != 1) {
                    count++;
            } else
                    count = 0;
    
            if (count == 5) //5 is NUMCARDS
                    return true;
        }
    
            // handle ace high.
            if(count == 4 && values[1] != 0) {
                return true;
            }
    
        return false;
    }
    

    基本上它的作用是说“如果我们已经连续有 4 张,并且我们刚刚查看了最后一张牌(循环结束),然后检查是否有 A,如果是,我们确实有顺子是王牌高牌”。

    原始答案: 我认为处理 ace 高低最简单的方法是让“get rank”函数有两种模式,一种返回高 ace,另一种返回低 ace。然后只需计算每种情况的手值并取更好的。

    另外,你的排名可能更简单:-P。

    int get_rank(char card) {
        static const char *cards = "A23456789TJQK";
        char *p = strchr(cards, toupper(card));
        if(p) {
            return (p - cards) + 1; 
        } else {
            return -1;
        }
    }
    

    所以如果你想要一个有 ace_high 或 ace_low 的 get_rank,你可以这样做:

    int get_rank(char card, bool ace_high) {
        static const char *cards_high = "23456789TJQKA";
        static const char *cards_low = "A23456789TJQK";
    
        const char *cards = ace_high ? cards_high : cards_low;
    
        char *p = strchr(cards, toupper(card));
        if(p) {
            return (p - cards) + 1; 
        } else {
            return -1;
        }
    }
    

    编辑:

    为了好玩,我制作了一个快速而肮脏的程序来检测顺子(处理高和低 A)。它相当简单,但可以更短(另请注意,这些数组没有尝试缓冲安全,生产质量的东西应该使用更安全的东西,例如std::vector

    #include <algorithm>
    #include <iostream>
    #include <cstring>
    
    int get_rank(char card, bool ace_high) {
        static const char *cards_high = "23456789TJQKA";
        static const char *cards_low = "A23456789TJQK";
        const char *cards = ace_high ? cards_high : cards_low;
    
        char *p = strchr(cards, toupper(card));
        if(p) {
            return (p - cards) + 1; 
        } else {
            return -1;
        }
    }
    
    bool is_rank_less_low(int card1, int card2) {
        return get_rank(card1, false) < get_rank(card2, false);
    }
    
    bool is_rank_less_high(int card1, int card2) {
        return get_rank(card1, true) < get_rank(card2, true);
    }
    
    bool is_straight(int hand[], bool ace_high) {
    
        std::sort(hand, hand + 5, ace_high ? is_rank_less_high : is_rank_less_low);
        int rank = get_rank(hand[0], ace_high);
        for(int i = 1; i < 5; ++i) {
            int new_rank = get_rank(hand[i], ace_high);
            if(new_rank != rank + 1) {
                return false;
            }
            rank = new_rank;
        }
        return true;
    }
    
    bool is_straight(int hand[]) {
        return is_straight(hand, false) || is_straight(hand, true);
    }
    
    int main() {
        int hand1[5] = { 'T', 'J', 'Q', 'K', 'A' };
        int hand2[5] = { 'A', '2', '3', '4', '5' };
        std::cout << is_straight(hand1) << std::endl;
        std::cout << is_straight(hand2) << std::endl;
    }
    

    【讨论】:

    • count的值只有在递增时才检查,并不是每次都循环。
    • 虽然你是,但这是一个很小的优化。检查在哪里,因为那是它在原始代码中的位置。
    【解决方案2】:

    可以通过更改最终测试来找到存在 A 高顺子的情况:

    if (count == 5 || count == 4 && values[1] == 1) // 2nd case handles ace-high straight
        return true;
    

    这是一种特殊情况,所以必须分开处理。

    【讨论】:

    • 关闭,但不完全正确。如果他们有这样的东西,那将返回 true:A,3,4,5,6(注 4 与 ace 连续)。如果您查看我最近的答案,它对此有一个变体,它确实有效(基本上它会执行相同的检查 after 循环是否完成,因为如果循环刚刚结束并且我们的计数为 4 , 那么这意味着我们有 T,J,Q,K)。
    • 我不同意。当 i == 7 时计数将恢复为 0,因此在 [~9],T,J,Q,K 的情况下它只会是 4
    • 哦,该死,我没看到它在 for 循环中。
    猜你喜欢
    • 2013-01-25
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 2021-04-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多