«Угадайте номер игры» в 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");
 }
 }
11 голосов | спросил ChrisIkeokwu 24 FebruaryEurope/MoscowbFri, 24 Feb 2017 20:10:59 +0300000000pmFri, 24 Feb 2017 20:10:59 +030017 2017, 20:10:59

3 ответа


13

Я заметил несколько вещей, которые могут помочь вам улучшить ваш код.

Использовать последовательное форматирование

Приведенный код имеет непоследовательный отступ, что затрудняет его чтение и понимание. Выберите стиль и примените его последовательно.

Проверить возвращаемые значения ошибок

Вызов 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, и переменная может быть неинициализирована.

ответил Edward 24 FebruaryEurope/MoscowbFri, 24 Feb 2017 21:21:01 +0300000000pmFri, 24 Feb 2017 21:21:01 +030017 2017, 21:21:01
7

Как сказал Эдвард:

  

Выберите стиль и примените его последовательно.

Как и в случае с обычным текстом, люди будут разочаровываться в работе с вами и дать отзыв, если написанный вами текст грязный.

Представьте себе:

  

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");
    }
}
ответил snoram 24 FebruaryEurope/MoscowbFri, 24 Feb 2017 23:38:40 +0300000000pmFri, 24 Feb 2017 23:38:40 +030017 2017, 23:38:40
5

Напишите, что вы имеете в виду

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.

ответил David Foerster 25 FebruaryEurope/MoscowbSat, 25 Feb 2017 05:44:20 +0300000000amSat, 25 Feb 2017 05:44:20 +030017 2017, 05:44:20

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132