ساخت بازی حدس کلمه با پایتون؛ پروژه کامل Hangman با random و Set

🗓 آخرین بهروزرسانی:
ساخت بازی حدس کلمه با پایتون یا Hangman یکی از پروژههای کلاسیک و بسیار مفید برای تمرین منطق برنامهنویسی است. در این پروژه، برنامه یک کلمه را بهصورت تصادفی انتخاب میکند و کاربر باید با حدسزدن حروف، کلمه را قبل از تمامشدن فرصتها پیدا کند. در ظاهر ساده است، اما پشت این بازی مفاهیم مهمی مثل رشتهها، Set، حلقه while، شرطها، تابعها، اعتبارسنجی ورودی و انتخاب تصادفی قرار دارد.
این مقاله دهمین پروژه فاز اول دسته تمرین و پروژههای پایتون است. اگر پروژههای قبلی مثل بازی حدس عدد با پایتون و آزمون چهارگزینهای با پایتون را انجام داده باشید، ساختار کلی بازیهای تعاملی برایتان آشنا خواهد بود.
در این پروژه چه چیزی میسازیم؟
- انتخاب تصادفی کلمه از بانک کلمات
- نمایش حروف کشفشده و مخفیکردن بقیه حروف
- دریافت یک حرف از کاربر
- جلوگیری از ورود مقدار نامعتبر
- جلوگیری از حدس تکراری
- ثبت حروف درست و اشتباه
- نمایش تعداد فرصتهای باقیمانده
- نمایش مرحلههای Hangman بهصورت ASCII
- تشخیص برد و باخت
- امکان خروج از بازی
- امکان اجرای دوباره بازی
پیشنیازهای پروژه
این پروژه به هیچ کتابخانه خارجی نیاز ندارد. فقط از ماژول استاندارد random استفاده میکنیم. آشنایی با تابع input در پایتون، حلقه while و Set در پایتون کمک میکند منطق کد را راحتتر درک کنید.
یک فایل با نام زیر بسازید:
hangman.pyسپس اجرا کنید:
python hangman.pyمرحله اول: ساخت بانک کلمات
برای شروع، یک لیست از کلمات انگلیسی مرتبط با برنامهنویسی میسازیم:
WORDS = [
"python",
"function",
"variable",
"string",
"dictionary",
"module",
"exception",
"object",
"class",
"loop",
]استفاده از لیست باعث میشود افزودن یا حذف کلمات ساده باشد. بعداً میتوانید این بانک را از فایل متنی یا JSON بارگذاری کنید.
مرحله دوم: انتخاب تصادفی کلمه
برای انتخاب یک عضو تصادفی از لیست از random.choice() استفاده میکنیم:
import random
def choose_word():
return random.choice(WORDS)هر بار که یک دور جدید بازی آغاز میشود، یکی از کلمات لیست انتخاب خواهد شد.
مرحله سوم: نگهداری حروف حدسزدهشده با Set
برای ذخیره حروف حدسزدهشده از Set استفاده میکنیم:
guessed_letters = set()دلیل انتخاب Set این است که اعضای تکراری را نگه نمیدارد و بررسی وجود یک حرف در آن ساده است. اگر کاربر حرف a را دوباره وارد کند، میتوانیم سریع تشخیص دهیم که قبلاً حدس زده شده است.
مرحله چهارم: نمایش کلمه مخفی
در ابتدای بازی هیچ حرفی مشخص نیست. برای هر حرفی که هنوز حدس زده نشده، زیرخط نمایش میدهیم:
def display_word(
word,
guessed_letters,
):
return " ".join(
letter
if letter in guessed_letters
else "_"
for letter in word
)اگر کلمه python باشد و کاربر حروف p و o را پیدا کرده باشد، خروجی به شکل زیر است:
p _ _ _ o _مرحله پنجم: ساخت مراحل Hangman
برای هر اشتباه یک مرحله از شکل بازی را نمایش میدهیم. تعداد مرحلهها تعیین میکند کاربر چند اشتباه مجاز دارد.
HANGMAN_STAGES = [
r"""
+---+
| |
|
|
|
|
=========
""",
r"""
+---+
| |
O |
|
|
|
=========
""",
r"""
+---+
| |
O |
| |
|
|
=========
""",
r"""
+---+
| |
O |
/| |
|
|
=========
""",
r"""
+---+
| |
O |
/|\ |
|
|
=========
""",
r"""
+---+
| |
O |
/|\ |
/ |
|
=========
""",
r"""
+---+
| |
O |
/|\ |
/ \ |
|
=========
""",
]
MAX_WRONG = len(HANGMAN_STAGES) - 1بهجای نوشتن عدد ۶ بهصورت ثابت، مقدار فرصتها را از تعداد Stageها محاسبه میکنیم. در نتیجه اگر بعداً شکل دیگری اضافه شود، منطق بازی هم خودکار با آن هماهنگ میشود.
مرحله ششم: دریافت حرف معتبر
ورودی کاربر باید فقط یک حرف انگلیسی باشد. همچنین نباید اجازه دهیم یک حرف چند بار حدس زده شود.
def get_guess(guessed_letters):
while True:
guess = input(
"یک حرف انگلیسی وارد کنید "
"(0 برای خروج): "
).strip().lower()
if guess == "0":
return None
if (
len(guess) != 1
or not ("a" <= guess <= "z")
):
print(
"فقط یک حرف انگلیسی از a تا z وارد کنید."
)
continue
if guess in guessed_letters:
print(
"این حرف را قبلاً حدس زدهاید."
)
continue
return guessاستفاده از strip() فاصلههای اضافی را حذف میکند و lower() باعث میشود حروف بزرگ و کوچک تفاوتی نداشته باشند.
مرحله هفتم: تشخیص برد
برای برد، باید تمام حروف کلمه داخل مجموعه حروف حدسزدهشده باشند.
def has_won(
word,
guessed_letters,
):
return set(word).issubset(
guessed_letters
)این بخش یکی از کاربردهای خوب Set در پروژه واقعی است. set(word) حروف یکتای کلمه را میسازد و issubset() بررسی میکند همه آنها حدس زده شدهاند یا نه.
مرحله هشتم: نمایش حروف اشتباه
def wrong_letters(
word,
guessed_letters,
):
return sorted(
letter
for letter in guessed_letters
if letter not in word
)نمایش حروف اشتباه به کاربر کمک میکند دوباره همان مسیر را تکرار نکند و وضعیت بازی را بهتر ببیند.
ساخت حلقه اصلی یک دور بازی
def play_round():
word = choose_word()
guessed_letters = set()
wrong_count = 0
while (
wrong_count < MAX_WRONG
and not has_won(
word,
guessed_letters,
)
):
print(
HANGMAN_STAGES[wrong_count]
)
print(
"کلمه:",
display_word(
word,
guessed_letters,
),
)
mistakes = wrong_letters(
word,
guessed_letters,
)
if mistakes:
print(
"حروف اشتباه:",
", ".join(mistakes),
)
print(
"فرصت باقیمانده:",
MAX_WRONG - wrong_count,
)
guess = get_guess(
guessed_letters
)
if guess is None:
print(
"بازی توسط کاربر متوقف شد."
)
return None
guessed_letters.add(guess)
if guess in word:
print("حدس درست بود.")
else:
wrong_count += 1
print(
"این حرف در کلمه نیست."
)تشخیص پایان بازی
پس از خروج از حلقه، یا کاربر کلمه را کامل پیدا کرده یا تعداد اشتباهها به سقف رسیده است.
print(
HANGMAN_STAGES[wrong_count]
)
print("کلمه:", word)
if has_won(
word,
guessed_letters,
):
print(
"تبریک! شما برنده شدید."
)
return True
print("فرصتها تمام شد.")
return Falseکد کامل بازی Hangman با پایتون
import random
WORDS = [
"python",
"function",
"variable",
"string",
"dictionary",
"module",
"exception",
"object",
"class",
"loop",
]
HANGMAN_STAGES = [
r"""
+---+
| |
|
|
|
|
=========
""",
r"""
+---+
| |
O |
|
|
|
=========
""",
r"""
+---+
| |
O |
| |
|
|
=========
""",
r"""
+---+
| |
O |
/| |
|
|
=========
""",
r"""
+---+
| |
O |
/|\ |
|
|
=========
""",
r"""
+---+
| |
O |
/|\ |
/ |
|
=========
""",
r"""
+---+
| |
O |
/|\ |
/ \ |
|
=========
""",
]
MAX_WRONG = len(HANGMAN_STAGES) - 1
def choose_word():
return random.choice(WORDS)
def display_word(
word,
guessed_letters,
):
return " ".join(
letter
if letter in guessed_letters
else "_"
for letter in word
)
def wrong_letters(
word,
guessed_letters,
):
return sorted(
letter
for letter in guessed_letters
if letter not in word
)
def get_guess(guessed_letters):
while True:
guess = input(
"یک حرف انگلیسی وارد کنید "
"(0 برای خروج): "
).strip().lower()
if guess == "0":
return None
if (
len(guess) != 1
or not ("a" <= guess <= "z")
):
print(
"فقط یک حرف انگلیسی "
"از a تا z وارد کنید."
)
continue
if guess in guessed_letters:
print(
"این حرف را قبلاً حدس زدهاید."
)
continue
return guess
def has_won(
word,
guessed_letters,
):
return set(word).issubset(
guessed_letters
)
def play_round():
word = choose_word()
guessed_letters = set()
wrong_count = 0
while (
wrong_count < MAX_WRONG
and not has_won(
word,
guessed_letters,
)
):
print(
HANGMAN_STAGES[wrong_count]
)
print(
"کلمه:",
display_word(
word,
guessed_letters,
),
)
mistakes = wrong_letters(
word,
guessed_letters,
)
if mistakes:
print(
"حروف اشتباه:",
", ".join(mistakes),
)
print(
"فرصت باقیمانده:",
MAX_WRONG - wrong_count,
)
guess = get_guess(
guessed_letters
)
if guess is None:
print(
"بازی توسط کاربر متوقف شد."
)
return None
guessed_letters.add(guess)
if guess in word:
print("حدس درست بود.")
else:
wrong_count += 1
print(
"این حرف در کلمه نیست."
)
print(
HANGMAN_STAGES[wrong_count]
)
print("کلمه:", word)
if has_won(
word,
guessed_letters,
):
print(
"تبریک! شما برنده شدید."
)
return True
print("فرصتها تمام شد.")
return False
def main():
print(
"=== بازی حدس کلمه Hangman "
"با پایتون ==="
)
while True:
result = play_round()
if result is None:
break
again = input(
"\nدوباره بازی کنیم؟ "
"(بله/خیر): "
).strip().lower()
if again not in {
"بله",
"yes",
"y",
}:
print("بازی پایان یافت.")
break
if __name__ == "__main__":
main()نمونه اجرای بازی
=== بازی حدس کلمه Hangman با پایتون ===
کلمه: _ _ _ _ _ _
فرصت باقیمانده: 6
یک حرف انگلیسی وارد کنید: p
حدس درست بود.
کلمه: p _ _ _ _ _چرا از Set استفاده کردیم؟
اگر حروف حدسزدهشده را در یک List نگه داریم، بازی همچنان کار میکند، اما Set برای این مسئله مناسبتر است. چون تکرار ندارد و هدف ما فقط دانستن این است که یک حرف قبلاً وارد شده یا نه. همین پروژه نمونه خوبی برای درک تفاوت List و Set است.
اشتباههای رایج در ساخت Hangman
کمکردن فرصت برای حدس تکراری
اگر کاربر حرفی را قبلاً وارد کرده باشد، نباید دوباره جریمه شود. ابتدا باید تکراریبودن ورودی بررسی شود و بعد سراغ درست یا غلط بودن آن برویم.
استفاده از یک رشته برای نگهداری تمام حدسها
استفاده از رشته ممکن است ممکن باشد، اما Set برای بررسی عضویت و جلوگیری از تکرار خواناتر است.
مقایسه حروف بزرگ و کوچک
بدون lower()، حروف P و p دو مقدار متفاوت خواهند بود. بهتر است ورودی را قبل از پردازش Normalize کنیم.
نوشتن تمام منطق داخل main
تفکیک کد به توابع choose_word، display_word، get_guess و play_round باعث میشود پروژه قابل تست و توسعه باشد.
چطور پروژه را حرفهایتر کنیم؟
- سطح سختی: برای Easy، Medium و Hard تعداد فرصتها و طول کلمات را تغییر دهید.
- دستهبندی کلمات: کلمات Python، Web، Database و General را جدا کنید.
- خواندن کلمات از فایل: بانک کلمات را از فایل متنی بارگذاری کنید.
- ذخیره امتیاز: تعداد برد و باخت را داخل JSON ثبت کنید.
- راهنما یا Hint: برای هر کلمه یک توضیح کوتاه تعریف کنید.
- حدس کل کلمه: علاوه بر حرف، امکان واردکردن پاسخ کامل را اضافه کنید.
- نسخه فارسی: بانک کلمات فارسی بسازید و اعتبارسنجی حروف را متناسب با فارسی تغییر دهید.
- نسخه GUI: با Tkinter بازی را از ترمینال به رابط گرافیکی منتقل کنید.
تمرین پیشنهادی
بانک کلمات را از کد خارج کنید و داخل فایل words.txt قرار دهید. سپس هنگام اجرای برنامه، فایل را بخوانید، خطهای خالی را حذف کنید و یکی از کلمات را با random.choice() انتخاب کنید. این تمرین ترکیب خوبی از پروژه Hangman با مباحث فایل در پایتون است.
بعد از Hangman میتوانید یک بازی گرافیکی بسازید؛ آموزش بازی مار با پایتون و Pygame قدمبهقدم همین کار را انجام میدهد. فهرست کامل پروژهها بهترتیب سطح در ۳۲ پروژه پایتون از مبتدی تا پیشرفته آمده است.
این پروژه چه مفاهیمی را تمرین میدهد؟
- ماژول random
- random.choice
- رشتهها و پیمایش حروف
- List و Set
- Set Membership
- حلقه while
- شرطهای چندمرحلهای
- تابعها و مقدار بازگشتی
- input و اعتبارسنجی ورودی
- List Comprehension و Generator Expression
- ASCII Art
- مدیریت State در یک بازی
جمعبندی
در این آموزش یک بازی کامل حدس کلمه یا Hangman با پایتون ساختیم. برنامه از یک بانک کلمات، کلمهای تصادفی انتخاب میکند، حروف واردشده را داخل Set نگه میدارد، حدسهای تکراری را رد میکند، کلمه مخفی را مرحلهبهمرحله نمایش میدهد و با توجه به تعداد اشتباهها برد یا باخت را تشخیص میدهد.
مهمترین ارزش این پروژه در ترکیب چند مفهوم پایه در یک منطق واقعی است. بعد از اجرای نسخه اصلی، پیشنهاد میشود قابلیت سطح سختی یا بارگذاری کلمات از فایل را اضافه کنید تا پروژه از یک تمرین ساده به یک بازی قابل توسعه تبدیل شود.
📌 همچنین بخوانید: تمرین پایتون با جواب، ساخت بازی با پایتون و Pygame و ساخت ربات با پایتون