V3ct0r 2,117 Report post Posted August 5, 2018 [C++] Игра "Угадай число!" Привет! В данной статье мы напишем на языке программирования C++ простую игру "Угадай число". Компьютер загадывает натуральное число от 1 до 100 включительно, а игрок в свою очередь должен его отгадать. Если игрок назвал неправильное число, то компьютер дает подсказку: загаданное число больше или меньше числа игрока. Игра продолжается до тех пор, пока игрок не отгадает число. Статья предназначена для начинающих программистов. Код будет выполнен в рамках стандарта C++11, автор будет использовать среду разработки Microsoft Visual Studio Community 2017 (скачать). Код должен успешно компилироваться как под Windows, так и под Linux, то есть является кроссплатформенным. У игры очень простой алгоритм: 1) Компьютер "загадывает" случайное натуральное число от 1 до 100 включительно; 2) Игрок вводит предполагаемое число (ответ) с клавиатуры; 3) Программа сравнивает два числа и выдает результат. 4) Если числа не равны, то "сказать" пользователю больше его ответ или меньше числа, загаданного компьютером. Перейти на шаг 2; 5) Числа равны. Поздравить игрока с победой и перейти на шаг 1. Приступим к реализации игры. Сначала компьютер загадывает случайное натуральное число от 1 до 100. Для этого используется генератор случайных чисел. Для работы с генератором случайных чисел будем применять 2 функции из стандартной библиотеки: srand() и rand(). Функция srand() нужна чтобы задать начало псевдослучайной последовательности чисел, генерируемой функцией rand(). Обычно, в функцию srand() передается текущее системное время. Чтобы получить текущее системное время можно использовать функцию time(). Функция srand() должна вызываться перед вызовом функции rand(), как правило, это делается один раз в начале работы программы. Если этого не сделать, то функция rand() все время будет "отдавать" одинаковые "случайные числа", и наша игра будет загадывать одни и те же числа. // Запускаем генератор случайных чисел std::srand(static_cast<unsigned int>(std::time(nullptr))); Мы инициализировали генератор случайных чисел и теперь можем загадывать число от 1 до 100 с помощью функции rand(). Чтобы загадать очередное число будем использовать следующее выражение: // Загадываем натуральное число // от 1 до 100 int n = (std::rand() % 100) + 1; Функция rand() может возвращать числа от 0 до 32767 включительно. Чтобы преобразовать этот "первичный" интервал в нужный нам интервал от 1 до 100, можно с помощью оператора % взять остаток от деления на 100 у любого числа из первичного интервала и прибавить к нему 1. Например, функция rand() вернула число 256. Остаток от деления на 100 будет равен 56. Прибавляем единицу и получаем число 57, которое и должен будет отгадать игрок: 256 % 100 = 56 56 + 1 = 57 Далее, после того, как компьютер загадал случайное число, просим игрока ввести его предполагаемый ответ: // Ответ игрока int guess = 0; // Просим игрока ввести ответ std::cout << "Введите число:" << std::endl; std::cout << ">> "; std::cin >> guess; С помощью оператора cin получаем целое число с клавиатуры - ответ игрока, и записываем данное число в переменную guess. Будем спрашивать игрока до тех пор, пока он не отгадает число. Для этого воспользуемся циклом do-while (см. ниже). На данном этапе у нас есть два числа: загаданное компьютером и ответ игрока. Осталось их сравнить. Для сравнения двух чисел воспользуемся оператором if и операторами больше (>) - меньше (<): // Ответ игрока int guess = 0; do { /* Тут получаем предполагаемое число (ответ) от игрока с клавиатуры */ // Проверяем ответ if (n > guess) { std::cout << "Не угадал! Моё число больше." << std::endl; } else if (n < guess) { std::cout << "Не угадал! Моё число меньше." << std::endl; } } while (n != guess); Если игрок не угадал число, то выводится соответствующее сообщение и цикл повторяется. В случае, если игрок угадал число, цикл прерывается и выводится сообщение о победе: // Игрок угадал число std::cout << "Верно! Загадать еще число? (Y/N)" << std::endl; std::cout << ">> "; std::cin >> answer; В конце игры можно просто выйти из программы, а можно спросить игрока, хочет ли он чтобы компьютер загадал еще одно число и тем самым продолжить игру. Для этого поместим написанный выше код в цикл do-while (весь лишний код был заменен на комментарии): // Ответ на вопрос "Загадать еще число?" char answer = 0; // Запускаем генератор случайных чисел // Запускаем игровой цикл do { // Загадываем натуральное число // от 1 до 100 do { // Получаем ответ от игрока // Сравниваем ответ игрока с загаднным компьютером числом } while (/* игрок не угадал число */); // Игрок угадал число std::cin >> answer; } while (std::strchr("Nn", answer) == nullptr); В символьную переменную answer записываем ответ игрока с клавиатуры. Предполагается, что игрок введет символ Y (продолжить игру) или символ N (выйти из игры). Далее с помощью функции strchr() ищем введенный символ в строке "Nn". Таким образом, неважно в каком регистре игрок ввел символ: N или n. while (std::strchr("Nn", answer) == nullptr); Если в строке "Nn" не будет найден символ, введенный игроком с клавиатуры, то функция strchr() вернет нулевой указатель (nullptr) и цикл продолжится. Иначе функция вернет указатель на найденный в строке символ и цикл завершится. То есть, если игрок введет символ N или n, то программа завершится. Если он введет любой другой символ, то будет загадано новое число и игра продолжится. После цикла происходит выход из программы - игра закрывается: return 0; Итак, были отмечены все ключевые особенности реализации варианта игры "Угадай число", поэтому далее приведу полный код программы: #include <iostream> #include <limits> #include <ctime> #include <cstdlib> // Точка входа int main(int argc, char *argv[]) { // Ответ на вопрос "Загадать еще число?" char answer = 0; // Поддержка русского языка setlocale(LC_ALL, "Russian"); // Запускаем генератор случайных чисел std::srand(static_cast<unsigned int>(std::time(nullptr))); // Выводим правила игры std::cout << "Игра \"Угадай число\"" << std::endl; std::cout << "Привет! Я загадал число от 1 до 100. Угадай его!" << std::endl << std::endl; // Запускаем игровой цикл do { // Загадываем натуральное число // от 1 до 100 int n = (std::rand() % 100) + 1; // Ответ игрока int guess = 0; do { // Просим игрока ввести ответ std::cout << "Введите число:" << std::endl; std::cout << ">> "; std::cin >> guess; // Проверим, что пользователь ввел число if (std::cin.fail() == true || (guess <= 0 || guess > 100)) { std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); std::cout << "Введите натуральное число от 1 до 100!" << std::endl; continue; } // Проверяем ответ if (n > guess) { std::cout << "Не угадал! Моё число больше." << std::endl; } else if (n < guess) { std::cout << "Не угадал! Моё число меньше." << std::endl; } } while (n != guess); // Игрок угадал число std::cout << "Верно! Загадать еще число? (Y/N)" << std::endl; std::cout << ">> "; std::cin >> answer; } while (std::strchr("Nn", answer) == nullptr); return 0; } При желании Вы можете добавить выбор игроком уровня сложности, например: Легкий уровень - загадывается число в интервале от 1 до 100, неограниченное число попыток; Средний уровень - загадывается число в интервале от 1 до 1000, число попыток 25; Сложный уровень - загадывается число в интервале от 1 до 10000, число попыток 50. Также можно добавить учет очков, набранных игроками. Чем меньше попыток угадать число сделал игрок, тем больше он зарабатывает очков: <Заработанные очки> = max(0, 100 - <Число ходов>) Очки хранить в памяти приложения или в файле: // score.txt Вася 100 Петя 53 Катя 42 Саша 65 Если у Вас есть какие-либо вопросы или замечания, то пишите о них в этой теме! Quote Some useful links / Полезные ссылки Tips for making a topic in 'Questions & Help' / Рекомендации по созданию тем в разделе "Помощь" Server Advertising Section Rules / Правила раздела "Реклама серверов" Available e-mail domains for registration / Допустимые e-mail домены для регистрации User groups / Группы пользователей User ranks / Звания пользователей "Broken" pictures on the forum / "Битые" изображения на форуме Beware of scammers! / Осторожно, мошенники! My developments / Мои разработки Mods for client and server / Моды для клиента и сервера PKOdev.NET website for Tales of Pirates Server / PKOdev.NET веб-обвязка для сервера Пиратии I do not provide any help in private messages and outside the forum. Use 'Questions & Help' section please. Thank you for understanding! Я не оказываю какую-либо помощь в личных сообщениях и вне форума. Пожалуйста, используйте раздел "Пиратия: Помощь". Благодарю за понимание! Share this post Link to post Share on other sites
Stinger 47 Report post Posted August 5, 2018 Как насчёт using namespace std; ? Quote Share this post Link to post Share on other sites
V3ct0r 2,117 Report post Posted August 5, 2018 38 minutes ago, Stinger said: Как насчёт using namespace std; ? Я привык явно указывать пространство имен, это мой стиль, мне так нравится. Становится понятно, что откуда берется, например, запись std::rand() говорит о том, что я использую функцию rand() из стандартной библиотеки, а не из какой-либо другой. Далее такой пример: у меня есть большой проект, в котором я использую ряд библиотек. Я решил использовать using namespace: using namespace foo; using namespace bar; Из библиотеки foo я использую функцию func1(), а из библиотеки bar - функцию func2(). Все замечательно, все работает. Далее, через какое-то время библиотека foo обновляется и в нее добавляется функция func2() - функция с таким же именем, как и в библиотеке bar. В лучшем случае мой код не скомпилируется, а в худшем, если сигнатуры функций совпадают, это приведет к трудноуловимым багам и ошибкам. Потом есть довольно общие названия различных объектов: string, iterator, list и так далее. Эти имена могут использоваться в разных библиотеках в рамках одного и того же проекта. Таким образом, явное указание пространства имен избавляет от потенциальных проблем в будущем. Что касается данной темы, то рассматриваемая программа очень простая и к тому же учебная. Поэтому вполне можно использовать using namespace std. Но все же я советую указывать пространство имен явно. Quote Some useful links / Полезные ссылки Tips for making a topic in 'Questions & Help' / Рекомендации по созданию тем в разделе "Помощь" Server Advertising Section Rules / Правила раздела "Реклама серверов" Available e-mail domains for registration / Допустимые e-mail домены для регистрации User groups / Группы пользователей User ranks / Звания пользователей "Broken" pictures on the forum / "Битые" изображения на форуме Beware of scammers! / Осторожно, мошенники! My developments / Мои разработки Mods for client and server / Моды для клиента и сервера PKOdev.NET website for Tales of Pirates Server / PKOdev.NET веб-обвязка для сервера Пиратии I do not provide any help in private messages and outside the forum. Use 'Questions & Help' section please. Thank you for understanding! Я не оказываю какую-либо помощь в личных сообщениях и вне форума. Пожалуйста, используйте раздел "Пиратия: Помощь". Благодарю за понимание! Share this post Link to post Share on other sites
JustPruss 0 Report post Posted November 25, 2019 ок, а как сделать запись результатов в файл? как не пытался, но на с++ не получается это сделать Quote Share this post Link to post Share on other sites
Graf 210 Report post Posted November 25, 2019 4 часа назад, JustPruss сказал: ок, а как сделать запись результатов в файл? как не пытался, но на с++ не получается это сделать Возможно вам поможет --> https://metanit.com/cpp/tutorial/8.3.php Quote Share this post Link to post Share on other sites
V3ct0r 2,117 Report post Posted November 28, 2019 Привет, @JustPruss! Вот пример кода: // . . . // Число ходов unsigned int n = 10; // Открываем файл moves.txt std::ofstream file("moves.txt", std::ofstream::out); // Проверим, что при открытии файла не возникли ошибки if (file.fail() == true) { // При открытии файла возникла ошибка std::cout << "Не удалось открыть файл moves.txt!" << std::endl; return 1; } // Запишем в файл фразу "Число ходов: ..." file << "Число ходов: " << n; // Закроем файл file.close(); В результате в одной директории с программой будет создан файл "moves.txt" в который будет записано число сделанных ходов (в данном случае 10). Quote Some useful links / Полезные ссылки Tips for making a topic in 'Questions & Help' / Рекомендации по созданию тем в разделе "Помощь" Server Advertising Section Rules / Правила раздела "Реклама серверов" Available e-mail domains for registration / Допустимые e-mail домены для регистрации User groups / Группы пользователей User ranks / Звания пользователей "Broken" pictures on the forum / "Битые" изображения на форуме Beware of scammers! / Осторожно, мошенники! My developments / Мои разработки Mods for client and server / Моды для клиента и сервера PKOdev.NET website for Tales of Pirates Server / PKOdev.NET веб-обвязка для сервера Пиратии I do not provide any help in private messages and outside the forum. Use 'Questions & Help' section please. Thank you for understanding! Я не оказываю какую-либо помощь в личных сообщениях и вне форума. Пожалуйста, используйте раздел "Пиратия: Помощь". Благодарю за понимание! Share this post Link to post Share on other sites
JustPruss 0 Report post Posted November 28, 2019 В 26.11.2019 в 03:57, Graf сказал: Возможно вам поможет --> https://metanit.com/cpp/tutorial/8.3.php спасибо Quote Share this post Link to post Share on other sites
JustPruss 0 Report post Posted November 28, 2019 4 часа назад, V3ct0r сказал: Привет, @JustPruss! Вот пример кода: // . . . // Число ходов unsigned int n = 10; // Открываем файл moves.txt std::ofstream file("moves.txt", std::ofstream::out); // Проверим, что при открытии файла не возникли ошибки if (file.fail() == true) { // При открытии файла возникла ошибка std::cout << "Не удалось открыть файл moves.txt!" << std::endl; return 1; } // Запишем в файл фразу "Число ходов: ..." file << "Число ходов: " << n; // Закроем файл file.close(); В результате в одной директории с программой будет создан файл "moves.txt" в который будет записано число сделанных ходов (в данном случае 10). спасибо большое, очень благодарен за такой пример Quote Share this post Link to post Share on other sites
Максим 0 Report post Posted February 22, 2020 Здравствуйте! Скажите, пожалуйста. А как можно реализовать эту игру в обратном порядке, т.е так , чтобы компьютер отгадывал число задуманное пользователем? Пытался сам, через рандом, но успехов ноль. Quote Share this post Link to post Share on other sites
champ 147 Report post Posted December 18, 2020 On 2/22/2020 at 7:46 AM, Максим said: Здравствуйте! Скажите, пожалуйста. А как можно реализовать эту игру в обратном порядке, т.е так , чтобы компьютер отгадывал число задуманное пользователем? Пытался сам, через рандом, но успехов ноль. А в чем, собственно, смысл? Загадайте число и через цикл заставьте код «угадывать», но задача сама по себе странная, если честно. Quote Share this post Link to post Share on other sites
Кеетти 0 Report post Posted January 29, 2022 А как это програму можно сделать в визуальной среде? помощью двух кнопок и поле для ввода даных Quote Share this post Link to post Share on other sites
V3ct0r 2,117 Report post Posted February 1, 2022 On 1/29/2022 at 8:04 PM, Кеетти said: А как это програму можно сделать в визуальной среде? помощью двух кнопок и поле для ввода даных Добрый день! 1) После запуска программы, например, в конструкторе формы, загадать случайное число и записать его в какую-либо переменную, например A; 2) В обработчике кнопки получать число из поля ввода данных и сравнивать его со значением переменной А. Вывести пользователю соответствующее сообщение по результатам сравнения; 3) Если пользователь угадал число, то загадать новое число и записать его в переменную A; 4) Повторить 2 и 3 пока пользователь не закроет программу. Quote Some useful links / Полезные ссылки Tips for making a topic in 'Questions & Help' / Рекомендации по созданию тем в разделе "Помощь" Server Advertising Section Rules / Правила раздела "Реклама серверов" Available e-mail domains for registration / Допустимые e-mail домены для регистрации User groups / Группы пользователей User ranks / Звания пользователей "Broken" pictures on the forum / "Битые" изображения на форуме Beware of scammers! / Осторожно, мошенники! My developments / Мои разработки Mods for client and server / Моды для клиента и сервера PKOdev.NET website for Tales of Pirates Server / PKOdev.NET веб-обвязка для сервера Пиратии I do not provide any help in private messages and outside the forum. Use 'Questions & Help' section please. Thank you for understanding! Я не оказываю какую-либо помощь в личных сообщениях и вне форума. Пожалуйста, используйте раздел "Пиратия: Помощь". Благодарю за понимание! Share this post Link to post Share on other sites