«Угадайте номер игры» в C
Только что начал изучать C. Надеюсь, мой код придерживается лучших практик и идиом.
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
int main(void)
{
int iRandomNum;
int iGuess;
srand(time(NULL));
iRandomNum = (rand() % 10);
printf("Guess a number between 1 and 10:");
scanf("%d", &iGuess);
// isdigit function expects a character so the guess value has to be ascii value of the digit character
iGuess += 48;
if (isdigit(iGuess)){
iGuess -=48; // change back to the original value for comparison with random number
if (iGuess == iRandomNum){
printf("You Guessed Correctly\n");
}
else{
printf("The correct answer was %d\n",iRandomNum);
printf("You guessed %d\n",iGuess);
}
}
else{
printf("This is not a digit!\n");
}
}
3 ответа
Я заметил несколько вещей, которые могут помочь вам улучшить ваш код.
Использовать последовательное форматирование
Приведенный код имеет непоследовательный отступ, что затрудняет его чтение и понимание. Выберите стиль и примените его последовательно.
Проверить возвращаемые значения ошибок
Вызов scanf
может завершиться неудачей. Вы можете проверить возвращаемые значения, чтобы убедиться, что у них нет, или ваша программа может сбой (или что еще хуже) при наличии неверного ввода или из-за низких системных ресурсов. Строгая обработка ошибок - это разница между большинством рабочих и программ без ошибок. Вы должны стремиться к последнему.
Не используйте венгерскую нотацию
Префикс каждой переменной с аббревиатурой ее типа обычно называется «венгерской нотацией», и это было когда-то популярно. Даже тогда это была плохая идея. Не загромождайте свой исходный код этим; вместо этого сконцентрируйтесь на определении значимых имен для каждой переменной и выберите подходящие типы. Я бы предложил secretNumber
и userGuess
в этот случай.
Используйте лучший генератор случайных чисел
В настоящее время вы используете
iRandomNum = (rand() % 10);
С этим подходом существует ряд проблем. Наиболее значительная проблема заключается в том, что диапазон, который возвращается (от 0 до 9 включительно), не соответствует тому, что пользователю предлагается угадать («число от 1 до 10»). Во-вторых, это будет генерировать более низкие цифры чаще, чем более высокие - это не равномерное распределение. Другая проблема заключается в том, что младшие разряды генератора случайных чисел не являются особенно случайными, поэтому ни один из них не является результатом. На моей машине есть небольшое, но измеримое смещение к 0 с этим. Подробнее см. этот ответ , но я бы рекомендовал изменить что для
secretNumber = rand() / (RAND_MAX / 10) + 1;
Подумайте о пользователе
Когда кто-то просит меня «Угадать число от 1 до 10», я обычно говорю \ $ е \ $ . (Да, я боюсь, что я такой человек.) Из контекста вашей программы видно, что то, что вы на самом деле имеете в виду, это угадать целое число, и кажется вероятным, что, с технической точки зрения, вы не хотите номера только между 1 и 10, но вы хотите включить 1 и 10 из возможных вариантов. Чтобы более четко передать это, я предлагаю попросить пользователя «угадать целое число от 1 до 10 включительно», но я, вероятно, слишком привык к тому, чтобы быть рядом с инженерами и учеными.
Проверьте свою логику
Если я введу "e"
, как я предполагаю, scanf
, и переменная может быть неинициализирована.
Как сказал Эдвард:
Выберите стиль и примените его последовательно.
Как и в случае с обычным текстом, люди будут разочаровываться в работе с вами и дать отзыв, если написанный вами текст грязный.
Представьте себе:
az wi Normal teXt pepls ~~ DiscourageD w0rking wi you ++ дает обратная связь, если zee teXT y heff vritten is mezzy.
Вот один как пример стиля (от вводного курса CS). В ближайшее время должна быть обновленная версия здесь .
Я также изучаю C
и пытался сделать ваш код совместимым с вышеупомянутым стилем.
Не сейчас ли это на глаз?
/**
* Guessing Game
* Here goes some description...
* .....
*/
#include <stdio.h>
#include <ctype.h>
#include <time.h>
#include <stdlib.h>
int main(void)
{
// Initalize variables
int random_num;
int guess;
// Add comment here
srand(time(NULL));
random_num = (rand() % 10);
// Add comment here
printf("Guess a number between 1 and 10:");
scanf("%d", &guess);
// isdigit function expects a character so the guess value has to be
// ascii value of the digit character
guess += 48;
if (isdigit(guess))
{
// change to the orig value and compare with random_num
guess -= 48;
// Add comment here
if (guess == random_num)
{
printf("You Guessed Correctly\n");
}
else
{
printf("The correct answer was %d\n", random_num);
printf("You guessed %d\n", guess);
}
}
else
{
printf("This is not a digit!\n");
}
}
Напишите, что вы имеете в виду
guess += 48;
if (isdigit(guess)) {
guess -= 48;
Не только упростить код if (isdigit(guess + 48)) {
, но он запутывает две вещи:
-
Что вы хотите добавить ASCII-код символа
0
. Используйте'0'
вместо48
здесь. -
Что вы действительно хотите проверить, находится ли
guess
между 0 и 9, что вы можете сделать гораздо более сжато и с готовностью:if (guess >= 0 && guess <= 9) {
Это эквивалентно (см. ниже) предыдущую проверку, но несогласованный с запрошенным диапазоном номеров «от 1 до 10».
Избегайте вызова неопределенного поведения
справочная страница isdigit(3)
говорит, что входное значение функции
должно иметь значение
unsigned char
илиEOF
[...].
В вашей программе пользователь вашей программы вводит номер, scanf
сохраняет его в переменной guess
, который позже передается isdigit
. Если guess
находится вне диапазона, указанного выше, поведение программы undefined . Теоретически это означает, что функция может выполнять произвольные операции для этих случаев. На практике это означает, что вы не можете полагаться на его возвращаемое значение в этих случаях.
В качестве примера спецификация в руководстве позволяет реализовать isdigit
для урезания своего входного значения до наименее значимых 8 бит ( после проверки на EOF
) и ищет класс символов в таблице длиной 256 (что является разумной и реалистичной реализацией, потому что 256 разные значения unsigned char
); в этом случае входное значение 256 будет преобразовано и затем усечено до (256 + 48)% 256 = 48, которое является кодом ASCII символа цифры, даже если 256 не находится между 0 и 9.