1. C++ / Говнокод #27131

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    74. 74
    75. 75
    76. 76
    77. 77
    78. 78
    79. 79
    80. 80
    81. 81
    82. 82
    83. 83
    84. 84
    85. 85
    86. 86
    87. 87
    88. 88
    89. 89
    90. 90
    91. 91
    92. 92
    93. 93
    94. 94
    95. 95
    96. 96
    97. 97
    #include <iostream>
    #include <ctime>
    #include <string>
    #include <random>
    #include <algorithm>
    #include <iomanip> // для ограничения количества вводимых симолов для std::cin
    
    void compUsrWthCmptr(std::string userInput, std::string computerInput)
    {
        std::reverse(userInput.begin(), userInput.end());//  Считаем правильно угаданные позиции
        std::reverse(computerInput.begin(), computerInput.end());
        int guessedPositions{ 0 };
        for (int i = 0; (i < userInput.length()) && (i < computerInput.length()); ++i)
        {
            if (userInput[i] == computerInput[i])
            {
                guessedPositions++;
            }
        }
        std::string::iterator it_userInput;
        std::string::iterator it_computerInput;
        it_userInput = std::unique(userInput.begin(), userInput.end()); // Удаляем повторяющиеся цифры
        userInput.resize(std::distance(userInput.begin(), it_userInput));
        it_computerInput = std::unique(computerInput.begin(), computerInput.end());
        computerInput.resize(std::distance(computerInput.begin(), it_computerInput));
        int guessedDigits{ 0 }; //  Считаем количество правильно угаданных цифр без учета повторяющихся
        for (int i = 0; i < userInput.length(); ++i)
        {
            for (int x = 0; x < computerInput.length(); ++x)
            {
                if (userInput[i] == computerInput[x])
                {
                    guessedDigits++;
                }
            }
        }
        std::cout << "  Угадано: " << guessedDigits << ". Соответствует своим разрядам: " << guessedPositions << std::endl << std::endl;
    };
    void startTheGame()
    {
        int pcsRandomNumber = getRandomNumber(0, 999);      //Загаданое число.
        std::cout << "  Компьютер загадал трехзначное число от 0 до 999!\n" << "  Это: " << pcsRandomNumber << std::endl << std::endl;
        std::string pcNumber{ std::to_string(pcsRandomNumber) };
        bool win = false;
        do
        {
            int usersGuess = getUsersGuess();
            std::string guess{ std::to_string(usersGuess) };
            std::cout << "  Ваш вариант : " << guess << std::endl;
            compUsrWthCmptr(guess, pcNumber);
            if (usersGuess == pcsRandomNumber)
            {
                win = true;
                std::cout << "  *** Вы угадали число " << pcsRandomNumber << "!***\n";
            }
        } while (!win);
    };
    int getUsersGuess()
    {
        while (true) // цикл продолжается до тех пор, пока пользователь не введет корректное значение
        {
            std::cout << "  Введите коректное значение: ";
            int a;
            std::cin >> std::setw(3) >> a;
            if (std::cin.fail()) // если предыдущее извлечение оказалось неудачным,
            {
                std::cin.clear(); // то возвращаем cin в 'обычный' режим работы
                std::cin.ignore(32767, '\n'); // и удаляем значения предыдущего ввода из входного буфера
                std::cout << "  Предыдущее извлечение оказалось неудачным. Попытайтесь еще раз.\n\n";
            }
            else
            {
                if (a >= 1000 || a < 0)
                {
                    std::cin.ignore(32767, '\n'); // удаляем лишние значения
                    std::cout << "  Введенное число вне требуемого диапазонате. Попытайтесь еще раз.\n\n";
                }
                else
                {
                    std::cin.ignore(32767, '\n'); // удаляем лишние значения
                    return a;
                }
            }
        }
    }
    int getRandomNumber(int min, int max)
    {
        return static_cast<int>(rand() % (max - min + 1) + min);
    }
    
    int main()
    {
        setlocale(LC_ALL, "Russian");
        srand(static_cast<unsigned int>(time(0)));
        startTheGame();
        return 0;
    }

    Начинающий говнокодер просит оценить его код. Где/что можно улучшить если возможно. Благодарю
    //Напишите программу реализующую игру «Угадай число».Компьютер загадывает число от 0 до 999 (используйте генерацию случайных чисел),
    //а пользователь угадывает его.На каждом шаге угадывающий делает предположение, а задумавший число — сообщает, сколько цифр из числа угаданы
    //и сколько из угаданных цифр занимают правильные позиции в числе.Например, если задумано число 725 и выдвинуто предположение,
    //что задумано число 523, то угаданы две цифры(5 и 2) и одна из них занимает верную позицию.

    Запостил: radionnazmiev, 25 Ноября 2020

    Комментарии (29) RSS

    • > int getRandomNumber(int min, int max)
      > {
      > return static_cast<int>(rand() % (max - min + 1) + min);
      > }
      Хуевый рандом, распределение будет неравномерным. См. https://govnokod.ru/26014#comment511028

      В крестоговне есть такая хуйня: std::uniform_int_distribution - используй ее.
      Ответить
      • А сишники что делают?
        Ответить
        • Или берут библиотеку, где такая хуйня есть, или пишут велосипед.
          Ответить
        • Ответить
        • Как-то так, если нигде не ошибся на единичку:
          int range = max - min + 1;
          int divisor = RAND_MAX / range;
          while (1) {
              int x = rand();
              if (x < divisor * range)
                  return min + x / divisor;
              // roll again
          }
          Ответить
          • Такой код на RAND_MAX/(RAND_MAX+1)*100 процентов утилизирует диапазон 0..RAND_MAX.
            Для полного счастья надо брать divisor = (RAND_MAX+1) / range, но посчитать без переполнения.

            P.S. Кстати, x / divisor и x % range чем-то отличаются на практике, кроме выдачи разных случайных последовательностей для одного и того же сида?
            Ответить
            • Да одинаково должно быть если у генератора распределение норм. Тут главное -- отбросить "хвост" (roll again). Иначе равномерности никак не добиться.
              Ответить
    • Слищком мало std::, сразу фидно, что нюфаг.
      Ответить
      • Угу.
        - foo.begin();
        + std::begin(foo);
        
        - foo.length();
        + std::distance(std::begin(foo), std::end(foo));
        
        - foo[i];
        + *std::advance(std::begin(foo), i);
        
        - 32767;
        + std::numeric_limits<int16_t>::max;
        Ответить
        • > *
          Фу, питушня! Надо чтоб T std::dereference<T>(T*), по аналогии с std::plus.
          Ответить
    • > int guessedPositions{ 0 };
      Зачем, зачем?
      почему не
      > int guessedPositions = 0;
      ?

      Зачем в крестах придумали столько говноспособов что-то проинициализировать?
      Ответить
      • > Зачем, зачем?
        Чтобы гомоиконность гомогенность: все инициализаторы в одном и том же виде. Я, правда, за «obj{};».
        Ответить
      • потому что в RAII.
        int можно не инициализировать, а непримитивные классы всегда инициализируются.

        прикол есть еще в том, что foo() это нифига не вызов конструктора, а указатель на функцию, но в 11 завезли инициализацию foo{}

        для int есть два способа видимо потому что шаблоны
        Ответить
        • Фигурные скобочки у инта проверяют диапазон для литерала. Круглые и "присваивание" -- нет.
          Ответить
          • ну видимо тоже из за совместимости?
            Ответить
            • Ну тип того, фигурным дали новую сёмантику, а старые оставили как есть.
              Ответить
              • а как жили метушки до 11?
                как поддерживали простые типы и сложные?
                Ответить
                • Круглыми скобочками и "присваиванием" (это тоже вызов конструктора, на самом деле).
                  Ответить
    • Компьютер загадал трехзначное число от 0 до 999!
      Это 265


      Как же я теперь его угадывать буду )))
      Ответить
      • > Это 265
        https://lurkmore.to/265

        > Как же я теперь его угадывать буду )))
        Ну это баг. В качестве воркэраунда можно предварительно заклеить непрозрачной изолентой то место на экране, в котором число выводится.
        Ответить

    Добавить комментарий