Loyiha: «Sonni top» o'yini

Endi o'rganganlarimizni birlashtirib, to'liq dastur — kichik o'yin yasaymiz. Kompyuter 1 dan 100 gacha son o'ylaydi, siz esa uni topishga harakat qilasiz. Har bir taxmindan keyin kompyuter «kattaroq» yoki «kichikroq» deb maslahat beradi.

Bu loyihada

  • Katta vazifani kichik qadamlarga bo'lish
  • random, while, if/elif/else va try/except ni birga ishlatish
  • Dasturni funksiyalarga ajratish
  • Har bir qadamdan keyin dasturni sinab ko'rish odati

Har bir qadamni avval o'zingiz yozishga harakat qiling, keyin bizning variantga qarang. Bu yerdagi muharrirlarda o'yinni haqiqatan o'ynash mumkin — javoblarni natija oynasidagi maydonga yozasiz.

0-qadam: reja

Kod yozishdan oldin algoritmni so'z bilan tuzib olamiz («Dastur va algoritm» darsini eslang):

  1. Kompyuter 1 dan 100 gacha tasodifiy son o'ylaydi.
  2. Foydalanuvchidan taxmin so'raladi.
  3. Agar taxmin to'g'ri bo'lsa — tabriklaymiz va o'yin tugaydi.
  4. Aks holda «kattaroq» yoki «kichikroq» deb aytamiz va 2-qadamga qaytamiz.

Reja tayyor. Unda takrorlash (2–4-qadamlar) va shart (3–4-qadamlar) borligini ko'ryapsizmi? Endi uni bo'laklab kodga aylantiramiz.

1-qadam: bitta taxmin

Eng oddiy versiyadan boshlaymiz: kompyuter son o'ylaydi, biz bitta taxmin qilamiz.

import random

sir = random.randint(1, 100)
taxmin = int(input("Taxminingiz: "))

if taxmin == sir:
    print("Topdingiz!")
elif taxmin < sir:
    print("Men kattaroq son o'yladim.")
else:
    print("Men kichikroq son o'yladim.")

Ishlayapti, lekin bitta urinish juda kam. Sinab ko'rish paytida sirni bilish uchun vaqtincha print(sir) qo'shib qo'yish mumkin — dasturchilar shunday qilishadi. Faqat oxirida uni o'chirishni unutmang!

2-qadam: topguncha takrorlash

Necha marta urinish kerakligi oldindan noma'lum — demak, while kerak (10-dars):

import random

sir = random.randint(1, 100)
taxmin = 0

while taxmin != sir:
    taxmin = int(input("Taxminingiz: "))
    if taxmin < sir:
        print("Kattaroq.")
    elif taxmin > sir:
        print("Kichikroq.")

print("Barakalla, topdingiz!")

Sikldan oldin taxmin = 0 yozdik: shart birinchi marta tekshirilganda taxmin mavjud bo'lishi kerak, 0 esa hech qachon sir son bo'lmaydi.

3-qadam: urinishlarni sanash

O'yinchi necha urinishda topganini bilish qiziq. Hisoblagich qo'shamiz:

import random

sir = random.randint(1, 100)
taxmin = 0
urinishlar = 0

while taxmin != sir:
    taxmin = int(input("Taxminingiz: "))
    urinishlar += 1
    if taxmin < sir:
        print("Kattaroq.")
    elif taxmin > sir:
        print("Kichikroq.")

print(f"Barakalla! {urinishlar} ta urinishda topdingiz.")

4-qadam: xato kiritishdan himoya

O'yinchi tasodifan harf yoki 500 deb yozsa-chi? Hozir harf yozilsa, dastur ValueError bilan to'xtab qoladi. Sonni so'rashni alohida funksiyaga chiqaramiz va unda barcha tekshiruvlarni qilamiz (15- va 17-darslar):

def son_sora(eng_kichik, eng_katta):
    """Foydalanuvchidan oraliqdagi butun sonni so'raydi."""
    while True:
        try:
            son = int(input(f"Taxminingiz ({eng_kichik}-{eng_katta}): "))
        except ValueError:
            print("Iltimos, butun son kiriting.")
            continue
        if eng_kichik <= son <= eng_katta:
            return son
        print(f"Son {eng_kichik} dan {eng_katta} gacha bo'lishi kerak.")

# Funksiyani alohida sinab ko'ramiz
x = son_sora(1, 100)
print("Qabul qilindi:", x)
Taxminingiz (1-100): salom
Iltimos, butun son kiriting.
Taxminingiz (1-100): 500
Son 1 dan 100 gacha bo'lishi kerak.
Taxminingiz (1-100): 42
Qabul qilindi: 42

E'tibor bering: funksiyani o'yinga qo'shishdan oldin uni alohida sinab ko'rdik. Kichik bo'laklarni alohida tekshirish — xatolarni erta topishning eng yaxshi usuli.

5-qadam: urinishlar chegarasi

Cheksiz urinish bilan o'yin juda oson. Qiziqroq bo'lishi uchun 7 ta urinish beramiz. Urinishlar soni ma'lum bo'lgani uchun endi for qulayroq (11-dars), topilganda esa return bilan funksiyadan chiqamiz:

def oyin(urinishlar_soni=7):
    sir = random.randint(1, 100)
    print("Men 1 dan 100 gacha son o'yladim. Topa olasizmi?")
    for urinish in range(1, urinishlar_soni + 1):
        taxmin = son_sora(1, 100)
        if taxmin == sir:
            print(f"Barakalla! {urinish}-urinishda topdingiz!")
            return True
        if taxmin < sir:
            print("Kattaroq.", end=" ")
        else:
            print("Kichikroq.", end=" ")
        print(f"Qolgan urinishlar: {urinishlar_soni - urinish}")
    print(f"Urinishlar tugadi. Men {sir} sonini o'ylagan edim.")
    return False

Funksiya o'yinchi yutsa True, yutqazsa False qaytaradi — bu keyingi qadamda g'alabalarni sanash uchun kerak bo'ladi.

6-qadam: to'liq o'yin

Hammasini birlashtiramiz va «Yana o'ynaysizmi?» savolini qo'shamiz. Mana tayyor dastur — o'ynab ko'ring!

import random


def son_sora(eng_kichik, eng_katta):
    """Foydalanuvchidan oraliqdagi butun sonni so'raydi."""
    while True:
        try:
            son = int(input(f"Taxminingiz ({eng_kichik}-{eng_katta}): "))
        except ValueError:
            print("Iltimos, butun son kiriting.")
            continue
        if eng_kichik <= son <= eng_katta:
            return son
        print(f"Son {eng_kichik} dan {eng_katta} gacha bo'lishi kerak.")


def oyin(urinishlar_soni=7):
    """Bitta o'yin. Yutilsa True, yutqazilsa False qaytaradi."""
    sir = random.randint(1, 100)
    print("Men 1 dan 100 gacha son o'yladim. Topa olasizmi?")
    for urinish in range(1, urinishlar_soni + 1):
        taxmin = son_sora(1, 100)
        if taxmin == sir:
            print(f"Barakalla! {urinish}-urinishda topdingiz!")
            return True
        if taxmin < sir:
            print("Kattaroq.", end=" ")
        else:
            print("Kichikroq.", end=" ")
        print(f"Qolgan urinishlar: {urinishlar_soni - urinish}")
    print(f"Urinishlar tugadi. Men {sir} sonini o'ylagan edim.")
    return False


def asosiy():
    oyinlar = 0
    galabalar = 0
    while True:
        oyinlar += 1
        if oyin():
            galabalar += 1
        javob = input("Yana o'ynaysizmi? (ha/yo'q): ").strip().lower()
        if javob != "ha":
            break
    print(f"O'yinlar: {oyinlar}, g'alabalar: {galabalar}. Xayr!")


asosiy()

Dasturning tuzilishiga e'tibor bering: uchta funksiya, har biri o'z ishini qiladi. son_sora() — kiritishni, oyin() — bitta o'yinni, asosiy() — butun jarayonni boshqaradi. Bunday dasturni o'qish, tuzatish va kengaytirish oson.

Sir: 7 ta urinish doim yetadi

Agar to'g'ri strategiya bilan o'ynasangiz, 1 dan 100 gacha istalgan sonni 7 urinishda topish mumkin. Har safar qolgan oraliqning o'rtasini ayting: 50 → keyin 25 yoki 75 → va hokazo. Har bir javob oraliqni ikki baravar qisqartiradi: 100 → 50 → 25 → 13 → 7 → 4 → 2 → 1. 2⁷ = 128, bu esa 100 dan katta.

Bu usul ikkilik qidiruv (inglizcha binary search) deyiladi va dasturlashdagi eng muhim algoritmlardan biri. Keling, kompyuterning o'zi shu usulda sirni topsin:

sir = 73
past, yuqori = 1, 100
urinish = 0

while True:
    urinish += 1
    taxmin = (past + yuqori) // 2
    print(f"{urinish}-urinish: {taxmin}", end=" → ")
    if taxmin == sir:
        print("topildi!")
        break
    elif taxmin < sir:
        print("kattaroq")
        past = taxmin + 1
    else:
        print("kichikroq")
        yuqori = taxmin - 1
1-urinish: 50 → kattaroq
2-urinish: 75 → kichikroq
3-urinish: 62 → kattaroq
4-urinish: 68 → kattaroq
5-urinish: 71 → kattaroq
6-urinish: 73 → topildi!

sir ni 1 dan 100 gacha istalgan songa o'zgartirib ko'ring — urinishlar hech qachon 7 dan oshmaydi. Telefon kitobidan ism qidirganda ham aslida shunday qilamiz: kitobni o'rtasidan ochib, kerakli harf oldinda yoki keyinda ekaniga qaraymiz.

O'yinni yaxshilash g'oyalari

Dastur tayyor, lekin uni yanada qiziqarli qilish mumkin. Quyidagilardan birini o'zingiz qo'shib ko'ring:

  1. Qiyinlik darajasi. O'yin boshida «oson» (1–50, 10 urinish), «o'rta» (1–100, 7 urinish) yoki «qiyin» (1–1000, 10 urinish) darajasini tanlash.
  2. Issiq-sovuq. Taxmin sirga 5 tagacha yaqin bo'lsa «Juda issiq!», 15 tagacha — «Iliq», aks holda «Sovuq» deb aytish.
  3. Eng yaxshi natija. Bir necha o'yin davomida eng kam urinishlar sonini eslab qolish.
  4. Rollarni almashtirish. Siz son o'ylaysiz, kompyuter esa ikkilik qidiruv bilan topadi. Siz faqat «katta», «kichik» yoki «topding» deb javob berasiz.

Mashq Issiq-sovuq

2-g'oyani amalga oshiring: maslahat(taxmin, sir) funksiyasini yozing. Farq 5 gacha bo'lsa — Juda issiq!, 15 gacha — Iliq, aks holda — Sovuq qaytarsin.

def maslahat(taxmin, sir):
    pass

print(maslahat(48, 50))
print(maslahat(40, 50))
print(maslahat(10, 50))
Ishora

Farq manfiy bo'lishi ham mumkin. abs(taxmin - sir) uni musbat qiladi.

Yechimni ko'rish
def maslahat(taxmin, sir):
    farq = abs(taxmin - sir)
    if farq <= 5:
        return "Juda issiq!"
    if farq <= 15:
        return "Iliq"
    return "Sovuq"

print(maslahat(48, 50))
print(maslahat(40, 50))
print(maslahat(10, 50))

O'zingizni sinang

Nima uchun 2-qadamda sikldan oldin taxmin = 0 yozildi?

  1. O'yinni qiyinlashtirish uchun
  2. while sharti birinchi marta tekshirilganda taxmin mavjud bo'lishi uchun
  3. Sir sonni 0 ga tenglash uchun
  4. Bu shart emas, shunchaki odat

To'g'ri. Aks holda NameError chiqardi.

Ikkilik qidiruv bilan 1 dan 1000 gacha sonni topish uchun eng ko'pi bilan nechta urinish kerak?

  1. 100
  2. 500
  3. 10
  4. 1000

To'g'ri. 2¹⁰ = 1024 > 1000. Har bir urinish oraliqni ikki baravar qisqartiradi.

Dasturni nima uchun son_sora(), oyin() va asosiy() funksiyalariga ajratdik?

  1. Har bir qism bitta ishni bajarsa, dasturni tushunish, sinash va o'zgartirish oson bo'ladi
  2. Python funksiyasiz dasturni ishga tushirmaydi
  3. Funksiyalar dasturni tezlashtiradi
  4. Faqat chiroy uchun

To'g'ri. Masalan, son_sora() ni boshqa o'yinda ham o'zgartirmasdan ishlatish mumkin.

Xulosa

  • Loyiha avval so'z bilan rejalashtiriladi, keyin kichik qadamlar bilan quriladi.
  • Har bir qadamdan keyin dastur ishga tushirilib, sinab ko'riladi.
  • Kiritishni tekshirish alohida funksiyaga chiqarildi va alohida sinaldi.
  • Tayyor dastur bitta ishni bajaradigan funksiyalardan tuzilgan.
  • Ikkilik qidiruv — har qadamda oraliqni ikkiga bo'lish — juda tez ishlaydigan algoritm.