۱۳ - ۱۴تمرین‌های فصل

منطقِ بازی

ممکنه موقعِ بازی کردنِ داربازی متوجه یه چیزهای عجیبی شده باشین:

  • با این که لغات ممکنه ۹ حرف داشته باشن، فقط میشه ۷ حرف رو حدس زد؛

  • بازی بعد از ۷ حدس تموم میشه، چه درست باشن چه غلط؛

  • اگه حدسِ هفتم کلمه رو کامل کنه، پیغام باخت میده؛

  • لغاتِ عجیبی انتخاب می‌کنه که اصلاً به نظر نمیرسه تو دیکشنری باشن.

    اینها با داربازی ِ واقعی همخونی ندارن. مثلاً فقط حدس‌های اشتباه باید شمارش بشن، حدس‌های درست محدودیت ندارن. تغییرِ بازی به نحوی که فقط تعداد حدس‌های مجاز بیشتر بشن، یا لغات کوتاه‌تری انتخاب بشن (یا هر دو) کار سختی نیست.

    کار بهتر، و یه کم پیچیده‌تر که برای این تمرین پیشنهاد می‌کنیم، اینه که مثل داربازی ِ واقعی، کاری کنین که فقط حدس‌های غلط شمارده بشن.

    تغییرِ کُد

    ۱.

    رمزنگارها: ماژول ِ رمزنگارهای سزار و ویژنر که قبلاً نوشته بودین رو باز کنین، و طوری تغییرشون بدین که با ورودیِ کاربر کار کنن.

    ۲.

    اینجا یه بلوک ِ کُدِ خیلی ساده نوشتیم. دقت کنید با ‏‎forever‎‏ این کُد تا بینهایت تکرار میشه. اول تو REPL بارگذاری و امتحان‌ش کنین. بعد هم با توجه به مطالبِ فصل، کاری کنین که بعد از یه جوابِ ‏‎False‎‏، با موفقیت از برنامه خارج شه.

    import Control.Monad
    
    palindrome :: IO ()
    palindrome = forever $ do
      line1 <- getLine
      case (line1 == reverse line1) of
        True -> putStrLn "It's a palindrome!"
        False -> putStrLn "Nope!"

    ۳.

    اگه تابعِ ‏‎palindrome‎‏ رو به جمله‌ای مثلِ ‏‎“Madam I’m Adam”‎‏ اعمال کنین، جوابِ منفی می‌گیرین. تغییرِ این تابع طوری که روی جملات هم کار کنه شاملِ چند مرحله میشه. شاید لازم بشه چندتا از مثال‌های فصل رو دوره کنین؛ وارد کردنِ ‏‎Data.Char‎‏ به خاطرِ تابعِ ‏‎toLower‎‏ هم ممکنه لازم باشه. خوش بگذره.

    ۴.

    بدونِ تغییرِ کُدِ زیر:

    type Name = String
    type Age = Integer
    
    data Person = Person Name Age deriving Show
    data PersonInvalid =
        NameEmpty
      | AgeTooLow
      | PersonInvalidUnknown String
      deriving (Eq, Show)
    
    mkPerson :: Name
             -> Age
             -> Either PersonInvalid Person
    mkPerson name age
      | name /= "" && age > 0 =
          Right $ Person name age
      | name == "" = Left NameEmpty
      | not (age > 0) = Left AgeTooLow
      | otherwise =
          Left $ PersonInvalidUnknown $
            "Name was: " ++ show name ++
            " Age was: " ++ show age

    تابعِ زیر رو تعریف کنین:

    gimmePerson :: IO ()
    gimmePerson = undefined

    از اونجا که تایپِ ‏‎IO ()‎‏ اطلاعاتِ زیادی نمیده... کاری که باید انجام بده رو توضیح میدیم:

    a)

    باید با یه prompt، اسم و سن ِ کاربر رو بپُرسه.

    b)

    بعد توسطِ اسم و سنی که کاربر وارد کرد، تلاش کنه یه مقدارِ ‏‎Person‎‏ درست کنه. برای ‏‎Age‎‏ به تابعِ ‏‎read‎‏ احتیاج دارین، چون ‏‎Integer‎‏ ِه و ‏‎String‎‏ نیست.

    c)

    اگه تونست با موفقیت یه ‏‎Person‎‏ درست کنه، یه پیغام مثلِ ‏‎“Yay! Successfully got a person:”‎‏ به همراهِ مشخصاتِ ‏‎Person‎‏ ای که که درست کرد رو چاپ کنه.

    d)

    اگر هم به خطا خورد، با یه پیغام بگه مشکل کجا بوده.