Необходимо найти логическую ошибку в методе перетасовки карт - PullRequest
0 голосов
/ 04 марта 2011

Я пытаюсь написать метод, который принимает массив целых чисел (0-51, в этом порядке), разрезает его на два отдельных массива (A и B в функции ниже, используя метод cut, который я знаюконечно работает), а затем повторно объединяет два массива, случайным образом выбирая 0, 1 или 2 карты из ДНА или A или B, а затем добавляя их в колоду.

(ps- под "массивом" я имею в виду связанный список, я просто сказал массив, потому что я думал, что это будет концептуально проще)

Это мой код до сих пор, он работает, но естьопределенный уклон, когда дело доходит до места, где карты приземляются.Кто-нибудь может определить мою логическую ошибку?

[code]
void Deck::shuffle(){
    IntList *A = new IntList();
    IntList *B = new IntList();
    cut(A, B);
    IntListNode *aMarker = new IntListNode;
    aMarker = A->getSentinel()->next;
    //cout<< A->getSentinel()->prev->prev->data <<'\n'<<'\n';
    IntListNode *bMarker = new IntListNode;
    bMarker = B->getSentinel()->next;
    //cout<< B->getSentinel()->prev->data;
    deckList.clear();

    srand(time(NULL));
    int randNum = 0, numCards = 0, totalNumCards = 0; 
    bool selector = true, aisDone = false, bisDone = false;

    while(totalNumCards < 52){
        randNum = rand() % 3;
        if(randNum == 0){
            selector = !selector;
            continue;
        }
        numCards = randNum;

        if(!aisDone && !bisDone){
            if(selector){
                for(int i = 0; i < numCards; i++){
                    deckList.push_back(aMarker->data);
                    aMarker = (aMarker->next);
                    if(aMarker == A->getSentinel()){
                        aisDone = true;
                        break;
                    }
                }
                selector = false;
            }else{
                for(int i = 0; i < numCards; i++){
                    deckList.push_back(bMarker->data);
                    bMarker = (bMarker->next);
                    if(bMarker == B->getSentinel()){
                        bisDone = true;
                        break;
                    }
                }
                selector = true;
            }
        }
        if(aisDone && !bisDone){
            for(int i = 0; i < (52 - totalNumCards); i++){
                deckList.push_back(bMarker->data);
                bMarker = (bMarker->next);
                if(bMarker == B->getSentinel()){
                    bisDone = true;
                    break;
                }
            }
            //return;
        }
        if(bisDone && !aisDone){
            for(int i = 0; i < (52 - totalNumCards); i++){
                deckList.push_back(aMarker->data);
                aMarker = (aMarker->next);
                if(aMarker == A->getSentinel()){
                    aisDone = true;
                    break;
                }
            }
            //return;
        }
        totalNumCards += numCards;
    }

    int tempSum = 0;
    IntListNode *tempNode = deckList.head();
    for(int j = 0; j < 52; j++){
        //cout<< (tempNode->data) << '\n';
        tempSum += (tempNode->data);
        tempNode = (tempNode ->next);
    }
    if(tempSum != 1326)
        system("PAUSE");

    return;
}
[/code]

Ответы [ 4 ]

0 голосов
/ 04 марта 2011

Комментарии:

srand(time(NULL));

Его следует вызывать только один раз во время запуска приложения.Это обычно лучше вызывать в main () при запуске.

int randNum = 0, numCards = 0, totalNumCards = 0; 
bool selector = true, aisDone = false, bisDone = false;

Один идентификатор на строку.У каждого написанного стандарта кодирования есть это правило.Это также предотвращает некоторые тонкие ошибки, которые могут появиться при использовании указателей.Привыкайте к этому.

randNum = rand() % 3;

Нижние биты ранда являются наименьшим случайным.

rand Num = rand() / (MAX_RAND / 3.0);

Вопрос:

    if(!aisDone && !bisDone)
    {
         This can execute
         and set one of the above to isDone

         Example:
           Exit state aisDone == false bsiDone == false   // OK
           Exit state aisDone == true  bsiDone == false   // Will run below
           Exit state aisDone == false bsiDone == ture    // Will run below
    }
    if(aisDone && !bisDone)
    {
         Is this allowed to run if the first block above is run?
    }
    if(bisDone && !aisDone)
    {
         Is this allowed to run if the first block above is run?
    }

Остальное слишком сложно иЯ не понимаю.

Я могу придумать более простые приемы, чтобы получить хорошую перетасовку колоды карт:

for(loop = 0 .. 51)
{
    rand = rand(51 - loop);
    swap(loop, loop+rand);
}

Вышеизложенное имитирует случайный выбор карты из колоды Aи положить его на верх колоды B (колода B изначально пуста).Когда цикл завершается, B теперь A (как это было сделано на месте).

Таким образом, каждая карта (из A) имеет одинаковую вероятность размещения в любой позиции в B.

0 голосов
/ 04 марта 2011

Если у вашего инструктора будет мораль научить вас программировать так, как это должно быть сделано, тогда они будут поощрять вас к решению проблемы следующим образом, используя четыре строки кода:

#include<algorithm>
#include<vector>

// ...
std::vector<int> cards;  // fill it in ...
std::random_shuffle(cards.begin(), cards.end());

Использование стандартной библиотеки - это правильный способ ведения дел.Написание кода самостоятельно, когда вы можете решить проблему со стандартной библиотекой, - это неправильный способ ведения дел.Ваш инструктор не учит вас правильно.Если они хотят донести свою точку зрения (скажем, практикуете ли вы с помощью указателей), им следует быть более внимательными при выборе упражнения, которое они вам дают.

В данной речи здесь решение хуже, чем выше, нолучше, чем у вашего инструктора:

  1. 52 раза выполните следующее:

    1. Выберите два случайных не равных целых числа в диапазоне [0,52).
    2. Поменяйте местами значения в массиве, соответствующие этим позициям.
0 голосов
/ 04 марта 2011
  1. Для большинства генераторов случайных чисел младшими битами являются наименьшие случайные биты. Итак, ваша линия

    randNum = rand() % 3;
    

    следует изменить, чтобы получить его значение больше от старшего до среднего битов от rand.

  2. Ваши ожидания могут быть не верными. Я заметил, что вы меняете селектор, если ваше случайное значение равно 0. В сочетании с относительной неслучайностью randNum, это может быть вашей проблемой. Возможно, вам нужно сделать вещи менее случайными, чтобы они казались более случайными, например, менять местами селектор каждый раз в цикле и всегда брать 1 или более карт из выбранной колоды.

0 голосов
/ 04 марта 2011

А как насчет использования std::random_shuffle?Да, он не будет работать для связанного списка, но вы можете изменить его на vector:)

...