PythonPython · Chapterبەش 12 · Lectureوانە 12.2

Project: A Word-Scramble Gameپڕۆژیلە: یاریی پیتە تێکەڵەکان

Build a complete word game, Mixed Letters, step by step: word lists, random.shuffle(), functions that return values, input validation, a play-again loop, a clean quit with Ctrl+C, and tests with a fixed random seed.

یارییەکی وشەی تەواو، پیتە تێکەڵەکان، هەنگاو بە هەنگاو دروست بکە: وشە، ⁦random.shuffle()⁩، دەگەڕێننەوە، ، بۆ دووبارە یاریکردن، وەستانی ئارام بە ⁦Ctrl+C⁩ و تاقیکردنەوە بە جێگیر.

26 min read26 خولەک خوێندنەوە · 23 stepsهەنگاو

What you will learnچی فێر دەبیت

  • Plan a program with a scenario, a flowchart and a list of functions before writing code.
  • Scramble a word with list(), random.shuffle() and join(), and avoid the two usual shuffle mistakes.
  • Validate the player's input with loops and small checking functions.
  • Join functions, return values (including None and tuples) and loops into one complete program.
  • Test a program that uses random numbers with a fixed seed and assert.
  • پێش نووسینی کۆد، بە ، و لیستی پلانی دابنێیت.
  • وشەیەک بە ⁦list()⁩، ⁦random.shuffle()⁩ و ⁦join()⁩ تێکەڵ بکەیت و خۆت لە دوو هەڵە باوەکەی تێکەڵکردن بپارێزیت.
  • یاریزان بە و پشکنین پشتڕاست بکەیتەوە.
  • ، (لەوانە None و ) و لە یەک تەواودا کۆ بکەیتەوە.
  • کە بەکار دەهێنێت بە جێگیر و assert تاقی بکەیتەوە.

The project: Mixed Lettersپڕۆژیلەکە: پیتە تێکەڵەکان

You now know the main building blocks of Python: strings, loops, functions, lists and dictionaries. In this project you put them together in one complete program: a word game called Mixed Letters.

ئێستا بەردە سەرەکییەکانی دەناسیت: ، ، ، و . لەم هەموویان لە یەک تەواودا کۆ دەکەیتەوە: یارییەکی وشە بە ناوی ⁦Mixed Letters⁩ (پیتە تێکەڵەکان).

  • The computer picks a word and shows its letters in a mixed order, for example o y h n t p.
  • You have 3 tries to type the real word (python).
  • Right on the first try: 3 points; second try: 2 points; third try: 1 point.
  • After a wrong try you get a hint: the first letters of the word.
  • A guess with the wrong length or with other letters is not counted as a try.
  • One game has 5 different words. Then the game asks: play again?
  • Type quit at any time to stop.
  • وشەیەک هەڵدەبژێرێت و پیتەکانی بە ڕیزێکی تێکەڵ پیشان دەدات، بۆ نموونە o y h n t p.
  • 3 هەوڵت هەیە بۆ نووسینی وشە ڕاستەقینەکە (python).
  • ڕاست لە هەوڵی یەکەمدا: 3 خاڵ؛ هەوڵی دووەم: 2 خاڵ؛ هەوڵی سێیەم: 1 خاڵ.
  • دوای هەوڵێکی هەڵە سەرەداوێک وەردەگریت: پیتە سەرەتاییەکانی وشەکە.
  • وەڵامێک کە درێژییەکەی هەڵە بێت یان پیتی تری تێدا بێت وەک هەوڵ ناژمێردرێت.
  • هەر یارییەک 5 وشەی جیاوازی هەیە. پاشان یارییەکە دەپرسێت: دووبارە یاری دەکەیتەوە؟
  • هەر کاتێک quit بنووسە بۆ وەستان.
One round of the finished gameگەڕێک لە یارییە تەواوکراوەکە
Letters: o o p l
Your guess: pool
Not this one. Hint: it starts with l
Tries left: 2
Your guess: loop
Correct! +2 points

We build the game in small steps. Each step is a short program that you can run and test before you go on.

یارییەکە بە هەنگاوی بچووک دروست دەکەین. هەر هەنگاوێک کورتە کە دەتوانیت پێش ئەوەی بڕۆیتە پێشەوە جێبەجێی بکەیت و تاقی بکەیتەوە.

Quick checkپشکنینی خێراIn Mixed Letters, which guess does not use up one of your 3 tries?لە یاریی پیتە تێکەڵەکاندا، کام وەڵام یەکێک لە 3 هەوڵەکەت ناسووتێنێت؟

The project: Mixed Lettersپڕۆژیلەکە: پیتە تێکەڵەکان

Anagrams and scrambled wordsanagram و وشەی تێکەڵکراو

An anagram is a word made by putting the letters of another word in a new order: listen → silent, loop → pool. Word games with letter tiles are built on this idea: you move the same letters around until a word appears.

anagram وشەیەکە کە بە ڕیزکردنەوەی پیتەکانی وشەیەکی تر دروست دەبێت: listen ← silent، loop ← pool. یارییە وشەییەکانی تەختەی پیت لەسەر ئەم بیرۆکەیە دروست کراون: هەمان پیتەکان دەجووڵێنیت تا وشەیەک دەردەکەوێت.

Our game does the opposite. It scrambles a word: it mixes the letters at random, so the result is usually not a real word (oyhntp). Your job is to find the original word again.

یارییەکەی ئێمە پێچەوانەکەی دەکات. وشەیەک تێکەڵ دەکات: پیتەکانی بە هەڵکەوت تێکەڵ دەکات، بۆیە ئەنجامەکە زۆرجار وشەیەکی ڕاستەقینە نییە (oyhntp). کاری تۆ ئەوەیە وشە بنەڕەتییەکە بدۆزیتەوە.

Quick checkپشکنینی خێراWhich pair is an anagram?کام جووت anagramـە؟

What the project practisesپڕۆژیلەکە ڕاهێنان لەسەر چی دەکات

A small game uses almost everything you learned in this course. The table shows which tool does which job; each link goes back to the lesson that teaches it.

یارییەکی بچووک نزیکەی هەموو ئەو شتانە بەکار دەهێنێت کە لەم کۆرسەدا فێری بوویت. خشتەکە پیشان دەدات کام ئامراز کام کار دەکات؛ هەر دەتباتەوە بۆ ئەو وانەیەی فێری دەکات.

Job in the gameکار لە یارییەکەداPython toolئامرازی PythonLearn it inفێربوون لە
Choose words at randomهەڵبژاردنی وشە بە هەڵکەوتrandom.sample()Lesson: Modulesوانەی مۆدیوڵەکان
Keep the wordsهەڵگرتنی وشەکانa list of strings Lesson: Listsوانەی لیستەکان
Mix letters, read guessesتێکەڵکردنی پیت، خوێندنەوەی وەڵامlist(), .join(), .strip(), .lower()Lesson: Stringsوانەی زنجیرەنووسەکان
Repeat tries and gamesدووبارەکردنەوەی هەوڵ و یاریwhile, for, continue, breakLesson: whileوانەی خولی while
Split the work into partsدابەشکردنی کار بۆ بەشەکانdef, return, NoneLesson: Functionsوانەی کردارەکان
Accept only good inputوەرگرتنی تەنها دروستwhile True + returnLesson: Validationوانەی پشتڕاستکردنەوە
Menu choices, two resultsهەڵبژاردنەکانی ، دوو ئەنجامdict, tupleLesson: Dictionariesوانەی فەرهەنگەکان
Stop cleanly on Ctrl+Cوەستانی ئارام بە ⁦Ctrl+C⁩try / exceptLesson: Exceptionsوانەی هەڵاوێردەکان
Quick checkپشکنینی خێراWhich module gives the game its random choices?کام هەڵبژاردنە هەڵکەوتییەکان بە یارییەکە دەدات؟

Plan before you codeپێش کۆدنووسین پلان دابنێ

Good projects start on paper. The planning method from Algorithms and flowcharts works here too: first a short scenario (the story of the program), then a flowchart, then the list of functions, and only then code.

لەسەر کاغەز دەست پێ دەکەن. ڕێگای پلاندانانی وانەی ئەلگۆریزمەکان و هێڵکارییەکانی ڕەوت لێرەشدا کار دەکات: سەرەتا کورت (چیرۆکی )، پاشان ، پاشان لیستی و ئینجا کۆد.

Quick checkپشکنینی خێراWhat should you write first when you plan a project?کاتێک پلانی دادەنێیت، پێش هەموو شتێک چی بنووسیت؟

Plan before you codeپێش کۆدنووسین پلان دابنێ

A flowchart of one roundهێڵکارییەکی ڕەوت بۆ یەک گەڕ

The flowchart shows one round: one word, up to 3 tries. It uses the standard symbols: an oval for start and end, a rectangle for a step, a parallelogram for input and output, and a diamond for a yes/no question.

یەک گەڕ پیشان دەدات: یەک وشە، تا 3 هەوڵ. بەکار دەهێنێت: هێلکەیی بۆ دەستپێک و کۆتایی، لاکێشە بۆ هەنگاوێک، لاکێشەی لار بۆ و ، ئەڵماسی بۆ پرسیارێکی بەڵێ/نەخێر.

Flowchart of one round. Start a round; scramble the word, show its letters and set tries to 0. Decision: tries < 3? If no, show the word and return 0. If yes, read the guess. Decision: is the guess quit? If yes, return None. If no, decision: a fair guess (length and letters)? If no, explain the problem, which is not counted as a try, and go back to the tries test. If yes, add 1 to tries. Decision: guess equals word? If yes, show Correct with points = 4 − tries and return the points. If no, give a hint with the first letters if a try is left, and go back to the tries test.هێڵکاریی ڕەوتی یەک گەڕ. دەستپێکی گەڕێک؛ وشەکە تێکەڵ بکە، پیتەکانی پیشان بدە و tries بکە بە 0. بڕیار: tries < 3؟ ئەگەر نەخێر، وشەکە پیشان بدە و 0 بگەڕێنەرەوە. ئەگەر بەڵێ، وەڵامەکە وەربگرە. بڕیار: وەڵامەکە quitـە؟ ئەگەر بەڵێ، None بگەڕێنەرەوە. ئەگەر نەخێر، بڕیار: وەڵامێکی ڕەوایە (درێژی و پیتەکان)؟ ئەگەر نەخێر، کێشەکە ڕوون بکەرەوە (وەک هەوڵ ناژمێردرێت) و بگەڕێوە بۆ پشکنینی tries. ئەگەر بەڵێ، 1 بخەرە سەر tries. بڕیار: وەڵام یەکسانە بە وشە؟ ئەگەر بەڵێ، «ڕاستە» پیشان بدە بە points = 4 − tries و خاڵەکان بگەڕێنەرەوە. ئەگەر نەخێر، ئەگەر هەوڵ مابێت سەرەداوێک بە پیتە سەرەتاییەکان بدە و بگەڕێوە بۆ پشکنینی tries.
One round of Mixed Letters as a flowchart with standard symbolsگەڕێکی پیتە تێکەڵەکان وەک بە CêIT

Look at the two arrows that go back up: they are the loop. The unfair-guess path goes back without changing tries, so it costs nothing. Every path that leaves the loop ends in a return: 0, None or the points.

سەیری ئەو دوو تیرە بکە کە بۆ سەرەوە دەگەڕێنەوە: ئەوان . ڕێگای وەڵامی ناڕەوا بەبێ گۆڕینی tries دەگەڕێتەوە، بۆیە هیچی تێ ناچێت. هەموو ڕێگایەک کە لە دەردەچێت بە returnـێک کۆتایی دێت: 0، None یان خاڵەکان.

Quick checkپشکنینی خێراIn the flowchart, what happens after an unfair guess such as lop for loop?لە ، دوای وەڵامێکی ناڕەوای وەک lop بۆ loop چی ڕوودەدات؟

Plan before you codeپێش کۆدنووسین پلان دابنێ

Split the game into functionsدابەشکردنی یارییەکە بۆ کردارەکان

Next, list the jobs and give each job its own function. A function that does one job is easy to read, to test and to change.

دواتر کارەکان بنووسە و هەر کارێک خۆی بدەرێ. کە یەک کار دەکات خوێندنەوە، تاقیکردنەوە و گۆڕینی ئاسانە.

A tree of seven functions. main() runs games until the player stops and prints the best score. It calls choose_word_list(), which asks for 1 or 2 and returns a list of words; play_game(words), which plays 5 words, adds the points and returns score and player_quit; and ask_yes_no(question), which asks until y or n and returns True or False. play_game calls play_round(word), which plays one word and returns the points, or None to quit. play_round calls scramble(word), which returns the mixed word, and guess_problem(guess, word), which returns a message or an empty string.دارێکی حەوت کردار. main() یارییەکان دەکات تا یاریزان دەوەستێت و باشترین خاڵ چاپ دەکات. بانگی choose_word_list() دەکات، کە داوای 1 یان 2 دەکات و لیستێکی وشە دەگەڕێنێتەوە؛ play_game(words)، کە یاری بە 5 وشە دەکات، خاڵەکان کۆ دەکاتەوە و score و player_quit دەگەڕێنێتەوە؛ و ask_yes_no(question)، کە دەپرسێت تا y یان n دێت و True یان False دەگەڕێنێتەوە. play_game بانگی play_round(word) دەکات، کە یاری بە یەک وشە دەکات و خاڵەکان، یان None بۆ وەستان، دەگەڕێنێتەوە. play_round بانگی scramble(word) دەکات (وشە تێکەڵکراوەکە دەگەڕێنێتەوە) و بانگی guess_problem(guess, word) دەکات (پەیامێک یان زنجیرەنووسەیەکی بەتاڵ دەگەڕێنێتەوە).
Who calls whom, and what each function gives backکێ بانگی کێ دەکات و هەر چی دەگەڕێنێتەوەCêIT

Information travels through parameters and return values, never through global variables. play_round() returns its points and play_game() adds them up in its own local variable score. This keeps each function independent: you can test play_round() alone.

زانیاری لە ڕێگەی و دەگوازرێتەوە، هەرگیز لە ڕێگەی نا. play_round() خاڵەکانی دەگەڕێنێتەوە و play_game() لە خۆیدا بە ناوی score کۆیان دەکاتەوە. ئەمە هەر سەربەخۆ دەهێڵێتەوە: دەتوانیت play_round() بە تەنها تاقی بکەیتەوە.

Quick checkپشکنینی خێراHow does play_game() learn how many points one word gave?play_game() چۆن دەزانێت یەک وشە چەند خاڵی دا؟

Step 1: the word listsهەنگاوی 1: لیستەکانی وشە

The words live in two lists of strings. Their names are written in CAPITALS: in Python this tells other programmers that the value is a constant — set once at the top and never changed. The Kurdish words show that Python strings hold any Unicode letter.

وشەکان لە دوو دەژین. ناوەکانیان بە پیتی گەورە نووسراون: لە Pythonـدا ئەمە بە تر دەڵێت کە : یەک جار لە سەرەوە دادەنرێت و هەرگیز ناگۆڕێت. وشە کوردییەکان پیشان دەدەن کە هەر پیتێکی هەڵدەگرن.

Word lists and two random toolsلیستەکانی وشە و دوو ئامرازی هەڵکەوتstep1_lists.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
import random

PROGRAMMING_WORDS = ["python", "variable", "function", "string", "loop",
                     "list", "index", "random", "integer", "keyboard"]
KURDISH_WORDS = ["کتێب", "قوتابخانە", "چایخانە", "بازاڕ", "باران",
                 "پاسکیل", "مامۆستا", "خوێندکار", "زستان", "کۆمپیوتەر"]

print(len(PROGRAMMING_WORDS), "programming words")
print(len(KURDISH_WORDS), "Kurdish words")
print(list("کتێب"), len("کتێب"))
print("One random word:", random.choice(PROGRAMMING_WORDS))
print("Three different words:", random.sample(PROGRAMMING_WORDS, 3))
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3-6

Two constants. A long list may continue on the next line inside the brackets.

دوو . درێژ دەتوانێت لە ناو کەوانەکاندا لە دێڕی داهاتوودا بەردەوام بێت.

Lineدێڕی 10

list("کتێب") splits a Kurdish word into its 4 letters. Each Sorani letter is one character.

list("کتێب") وشەیەکی کوردی دەکات بە 4 پیتەکەی. هەر پیتێکی سۆرانی یەک .

Lineدێڕی 11

random.choice() returns one item.

random.choice() یەک دەگەڕێنێتەوە.

Lineدێڕی 12

random.sample(list, 3) returns 3 different items in a new list.

random.sample(list, 3) 3 جیاواز لە نوێدا دەگەڕێنێتەوە.

Why sample() and not choice() five times? choice() can pick the same word twice in one game; sample() never does.

بۆچی sample() و نەک پێنج جار choice()؟ choice() دەتوانێت لە یەک یاریدا هەمان وشە دوو جار هەڵبژێرێت؛ sample() هەرگیز وا ناکات.

Quick checkپشکنینی خێراYou need 5 different words from a list. Which call is right?پێویستت بە 5 وشەی جیاوازە لە . کام بانگکردن دروستە؟

Step 2: shuffling lettersهەنگاوی 2: تێکەڵکردنی پیتەکان

A string cannot be changed (it is immutable), so we cannot mix its letters in place. The trick has three moves: turn the word into a list of letters, shuffle the list, then join the letters back into a new string.

ناگۆڕدرێت ()، بۆیە ناتوانین پیتەکانی لە شوێنی خۆیدا تێکەڵ بکەین. فێڵەکە سێ جووڵەیە: وشەکە بکە بە لە پیت، تێکەڵ بکە، پاشان پیتەکان بلکێنەوە بە نوێ.

Animation with six letter tiles. The tiles p y t h o n show the hidden word. letters = list(word) makes a list of them. random.shuffle(letters) moves the tiles to new places: o y h n t p, which the player sees. The player types python, the program checks guess == word, the tiles slide back to p y t h o n and the text says Correct! +3 points.
Animation with six letter tiles. The tiles p y t h o n show the hidden word. letters = list(word) makes a list of them. random.shuffle(letters) moves the tiles to new places: o y h n t p, which the player sees. The player types python, the program checks guess == word, the tiles slide back to p y t h o n and the text says Correct! +3 points.
From word to list, shuffled, then guessedلە وشەوە بۆ ، تێکەڵکراو، پاشان دۆزراوەCêIT
list → shuffle → joinlist → shuffle → join: سێ جووڵەstep2_shuffle.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
import random

word = "python"
letters = list(word)        # a list of one-letter strings
print(letters)
random.shuffle(letters)     # mixes the list itself, in place
print(letters)
mixed = "".join(letters)    # glue the letters back into one string
print(mixed)
print(word)                 # the original string is unchanged
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 4

list(word) makes a new list with one letter in each place.

list(word) نوێ دروست دەکات کە لە هەر شوێنێکدا پیتێکی تێدایە.

Lineدێڕی 6

shuffle() changes the list itself and returns None.

shuffle() خودی دەگۆڕێت و None دەگەڕێنێتەوە.

Lineدێڕی 8

"".join(letters) glues the letters with nothing ("") between them.

"".join(letters) پیتەکان بە هیچ ("") لە نێوانیاندا پێکەوە دەلکێنێت.

Name cards on the teacher's deskکارتی ناو لەسەر مێزی مامۆستا

A name painted on the classroom wall cannot be rearranged — like a string. To mix the letters, the teacher writes each letter on its own card (a list), shuffles the cards on the desk, then copies them in their new order onto a fresh sheet (a new string).

ناوێک کە لەسەر دیواری پۆل بۆیاخ کراوە ناتوانرێت ڕیزی بگۆڕدرێت؛ وەک . بۆ تێکەڵکردنی پیتەکان، مامۆستا هەر پیتێک لەسەر کارتێکی جیا دەنووسێت ()، کارتەکان لەسەر مێزەکە تێکەڵ دەکات، پاشان بە ڕیزە نوێکەیان لەسەر پەڕەیەکی نوێ دەینووسێتەوە ( نوێ).

Where the analogy stops workingسنووری ئەم نموونەیە

Real cards can get lost; shuffle() always keeps exactly the same letters, only their order changes.

کارتی ڕاستەقینە لەوانەیە ون ببن؛ shuffle() هەمیشە ڕێک هەمان پیتەکان دەهێڵێتەوە، تەنها ڕیزەکەیان دەگۆڕێت.

Quick checkپشکنینی خێراAfter random.shuffle(letters), where are the mixed letters?دوای random.shuffle(letters)، پیتە تێکەڵکراوەکان لە کوێن؟

Generate random numbers in Python 🎲Bro Code · Englishئینگلیزی · 148K viewsبینین · 3.4K likesلایک · Partبەشی 3:32–4:32 (ofلە 8:02)

The random module's main tools: random(), randint(), choice() and shuffle(), shown with dice, rock-paper-scissors and a deck of cards.

ئامرازە سەرەکییەکانی random: random()، randint()، choice() و shuffle()، بە نموونەی بەردەزار، بەرد-کاغەز-مقەست و دەستەیەک کارتی یاری.

Watch 3:32–4:32: random.shuffle() mixes a list of cards in place, as the game mixes a list of letters.

لە ⁦3:32⁩ تا ⁦4:32⁩ سەیر بکە: random.shuffle() کارت لە شوێنی خۆیدا تێکەڵ دەکات، وەک چۆن یارییەکە پیت تێکەڵ دەکات.

Step 2: shuffling lettersهەنگاوی 2: تێکەڵکردنی پیتەکان

Two shuffle mistakesدوو هەڵەی تێکەڵکردن

Mistake 1: keeping the return value. shuffle() returns None. If you write letters = random.shuffle(letters), the list is shuffled and then thrown away, and letters becomes None.

هەڵەی 1: هەڵگرتنی . shuffle() None دەگەڕێنێتەوە. ئەگەر بنووسیت letters = random.shuffle(letters)، تێکەڵ دەکرێت و پاشان فڕێ دەدرێت و letters دەبێت بە None.

mistake_none.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
import random

letters = list("python")
letters = random.shuffle(letters)   # WRONG: shuffle() returns None
print(letters)
print("".join(letters))

Mistake 2: shuffling the string. shuffle() needs something it can change. A string is immutable, so Python stops with a TypeError.

هەڵەی 2: تێکەڵکردنی . shuffle() پێویستی بە شتێکە بتوانێت بیگۆڕێت. ، بۆیە بە TypeError دەوەستێت.

mistake_str.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
import random

random.shuffle("python")    # WRONG: a string cannot be changed
Quick checkپشکنینی خێراWhat does print(random.shuffle([1, 2, 3])) print?print(random.shuffle([1, 2, 3])) چی چاپ دەکات؟

Step 3: the scramble() functionهەنگاوی 3: کرداری ⁦scramble()⁩

Now wrap the three moves in a function. One detail matters: a shuffle can, by chance, give the original order back. Showing loop as the puzzle for loop would spoil the round, so the function shuffles again until the result is different.

ئێستا سێ جووڵەکە لە ناو دابنێ. وردەکارییەک گرنگە: تێکەڵکردن دەتوانێت بە هەڵکەوت ڕیزە بنەڕەتییەکە بگەڕێنێتەوە. پیشاندانی loop وەک مەتەڵ بۆ loop گەڕەکە تێک دەدات، بۆیە دووبارە تێکەڵ دەکات تا ئەنجامەکە جیاواز دەبێت.

A word in, a mixed word outوشەیەک دێتە ژوورەوە، وشەیەکی تێکەڵ دەچێتە دەرەوەstep3_scramble.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
import random


def scramble(word):
    """Return the letters of word in a new random order."""
    if len(set(word)) < 2:          # "aa" can never look different
        return word
    letters = list(word)
    while True:
        random.shuffle(letters)
        mixed = "".join(letters)
        if mixed != word:           # never show the answer itself
            return mixed


for word in ["loop", "loop", "loop", "کتێب", "aa"]:
    print(word, "->", scramble(word))
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 6-7

Guard: set(word) keeps each letter once. A word like aa has only one different letter and can never look different, so the loop below would run for ever.

پاسەوان: set(word) هەر پیتێک یەک جار دەهێڵێتەوە. وشەیەکی وەک aa تەنها یەک پیتی جیاوازی هەیە و هەرگیز جیاواز دەرناکەوێت، بۆیە خوارەوە بۆ هەمیشە کار دەکات.

Lineدێڕی 9-13

Shuffle, join, test. return leaves the loop and the function together.

تێکەڵکردن، لکاندن، پشکنین. return لە و پێکەوە دەردەچێت.

Lineدێڕی 16

Five test calls. Each call gives its own random order.

پێنج بانگکردنی تاقیکردنەوە. هەر بانگکردنێک ڕیزی هەڵکەوتیی خۆی دەدات.

The three calls with loop gave three different mixes, none of them loop itself. Two calls may give the same mix by chance: we only promise that the mix is never the word.

سێ بانگکردنەکەی loop سێ تێکەڵی جیاوازیان دا و هیچیان خودی loop نییە. دەشێت دوو بانگکردن بە هەڵکەوت هەمان تێکەڵ بدەن: تەنها بەڵێن دەدەین کە تێکەڵەکە هەرگیز خودی وشەکە نەبێت.

Quick checkپشکنینی خێراWhy does scramble() shuffle inside a while True loop?بۆچی scramble() لە ناو while Trueـدا تێکەڵ دەکات؟

Step 4: checking a guessهەنگاوی 4: پشکنینی وەڵامێک

Players make typing mistakes. Before we count a guess as a try, we check that it is fair: the right length and exactly the letters shown. This is input validation: never trust input until you have checked it.

یاریزانان هەڵەی تایپکردن دەکەن. پێش ئەوەی وەڵامێک وەک هەوڵ بژمێرین، دەپشکنین کە ڕەوایە: درێژیی دروست و ڕێک ئەو پیتانەی پیشان دراون. ئەمە ـە: هەرگیز متمانە بە مەکە تا نەیپشکنیت.

A function that explains what is wrongکردارێک کە ڕوون دەکاتەوە چی هەڵەیەstep4_check.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
def guess_problem(guess, word):
    """Return why guess is not a fair try, or "" if it is fine."""
    if len(guess) != len(word):
        return f"Please type exactly {len(word)} letters."
    if sorted(guess) != sorted(word):
        return "Please use only the letters shown."
    return ""


word = "loop"
for guess in ["lop", "loops", "lope", "pool", "loop"]:
    problem = guess_problem(guess, word)
    if problem:                     # a non-empty string counts as True
        print(guess, "->", problem)
    else:
        print(guess, "-> a fair try")
print(sorted("pool"), sorted("loop"))
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3-4

Wrong length: return a message that says how many letters are needed.

درێژیی هەڵە: پەیامێک بگەڕێنەرەوە کە دەڵێت چەند پیت پێویستە.

Lineدێڕی 5-6

sorted() puts the letters of a string in order in a new list. Two words use the same letters exactly when their sorted lists are equal.

sorted() پیتەکانی لە نوێدا ڕیز دەکات. دوو وشە ڕێک هەمان پیتەکانیان هەیە کاتێک یەکسانن.

Lineدێڕی 7

An empty string means “no problem”.

بەتاڵ واتە «هیچ کێشەیەک نییە».

Lineدێڕی 13

In an if, a non-empty string counts as true and "" as false.

لە ifـدا نابەتاڵ وەک ڕاست و "" وەک هەڵە دەژمێردرێت.

pool is a fair try for loop (same letters), even though it is the wrong word. lope is not fair: it has an e that was never shown.

pool بۆ loop هەوڵێکی ڕەوایە (هەمان پیت)، هەرچەندە وشە هەڵەکەیە. lope ڕەوا نییە: eـی تێدایە کە هەرگیز پیشان نەدراوە.

Quick checkپشکنینی خێراThe word is list. Which guess does guess_problem() call fair?وشەکە listـە. guess_problem() کام وەڵام بە ڕەوا دادەنێت؟

Step 5: one roundهەنگاوی 5: یەک گەڕ

play_round() follows the flowchart. Put it below scramble() and guess_problem() and add two test calls at the bottom.

play_round() شوێنی دەکەوێت. لە خوار scramble() و guess_problem() دایبنێ و دوو بانگکردنی تاقیکردنەوە لە خوارەوە زیاد بکە.

One word, up to three triesیەک وشە، تا سێ هەوڵstep5_round.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
MAX_TRIES = 3      # tries for each word


def play_round(word):
    """Play one word. Return the points (0-3), or None to quit."""
    print("\nLetters:", " ".join(scramble(word)))
    tries = 0
    while tries < MAX_TRIES:
        guess = input("Your guess: ").strip().lower()
        if guess == "quit":
            return None
        problem = guess_problem(guess, word)
        if problem:
            print(problem)          # an unfair guess costs no try
            continue
        tries += 1
        if guess == word:
            points = MAX_TRIES + 1 - tries
            print(f"Correct! +{points} points")
            return points
        if tries < MAX_TRIES:
            print(f"Not this one. Hint: it starts with {word[:tries]}")
            print(f"Tries left: {MAX_TRIES - tries}")
    print(f"Out of tries. The word was {word}.")
    return 0


print("Points:", play_round("string"))
print("Points:", play_round("loop"))
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 1

One constant for the number of tries. Change it here and the whole round follows.

یەک بۆ ژمارەی هەوڵەکان. لێرە بیگۆڕە و هەموو گەڕەکە شوێنی دەکەوێت.

Lineدێڕی 9

Clean the guess at once: no spaces at the ends, small letters only.

یەکسەر وەڵامەکە پاک بکەرەوە: بێ لە سەرەکاندا، تەنها پیتی بچووک.

Lineدێڕی 10-11

quit ends the round with None, a value that means “no points: stop”.

quit گەڕەکە بە None کۆتایی پێ دەهێنێت، بە واتای «هیچ خاڵێک نییە: بوەستە».

Lineدێڕی 13-15

An unfair guess: explain and continue — back to the loop test without counting a try.

وەڵامێکی ناڕەوا: ڕوونی بکەرەوە و continue — گەڕانەوە بۆ پشکنینی بەبێ ژماردنی هەوڵ.

Lineدێڕی 17-20

Points: 3 on try 1, 2 on try 2, 1 on try 3.

خاڵ: 3 لە هەوڵی 1، 2 لە هەوڵی 2، 1 لە هەوڵی 3.

Lineدێڕی 22

word[:tries] is a slice: 1 letter after the first wrong try, 2 letters after the second.

word[:tries] : دوای یەکەم هەوڵی هەڵە 1 پیت، دوای دووەم 2 پیت.

Lineدێڕی 24-25

The loop ended because all tries are used: show the word and give 0 points.

کۆتایی هات چونکە هەموو هەوڵەکان بەکار هاتوون: وشەکە پیشان بدە و 0 خاڵ بدە.

Quick checkپشکنینی خێراThe word is loop. The player types lop, then pool, then LOOP. How many points?وشەکە loopـە. یاریزان سەرەتا lop، پاشان pool، پاشان LOOP دەنووسێت. چەند خاڵ؟

Step 5: one roundهەنگاوی 5: یەک گەڕ

Returning None to say “quit”گەڕاندنەوەی None بۆ وتنی «وەستان»

A function can return only one thing, but that thing can carry meaning. play_round() returns a number of points (0 to 3) or None. None cannot be confused with a real score, while 0 could: 0 points is a normal result after three wrong tries.

تەنها دەتوانێت یەک شت بگەڕێنێتەوە، بەڵام ئەو شتە دەتوانێت واتای هەبێت. play_round() ژمارەیەک خاڵ (⁦0⁩ تا ⁦3⁩) یان None دەگەڕێنێتەوە. None لەگەڵ خاڵێکی ڕاستەقینە تێکەڵ نابێت، بەڵام 0 تێکەڵ دەبێت: 0 خاڵ دوای سێ هەوڵی هەڵە ئەنجامێکی ئاساییە.

The caller checks it with is None: if points is None:. You met None in Return values.

بە is None دەیپشکنێت: if points is None:. پێشتر Noneـت لە نرخە گەڕاوەکان بینی.

Quick checkپشکنینی خێراWhy does play_round() return None for quit instead of 0?بۆچی play_round() بۆ quit لە جیاتی 0 None دەگەڕێنێتەوە؟

Step 6: a whole gameهەنگاوی 6: یارییەکی تەواو

A game is 5 rounds with 5 different words. play_game() adds up the points in a local variable and gives back two results: the score, and whether the player typed quit.

یارییەک 5 گەڕە بە 5 وشەی جیاواز. play_game() خاڵەکان لە کۆ دەکاتەوە و دوو ئەنجام دەگەڕێنێتەوە: خاڵەکان و ئەوەی ئایا یاریزان quitـی نووسیوە.

Five rounds and a totalپێنج گەڕ و کۆیەکmixed_letters.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
def play_game(words):
    """Play ROUNDS different words. Return (score, player_quit)."""
    score = 0
    for word in random.sample(words, ROUNDS):   # no word twice
        points = play_round(word)
        if points is None:
            return score, True
        score += points
    return score, False
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 4

random.sample() picks ROUNDS different words, so no word comes twice.

random.sample() ROUNDS وشەی جیاواز هەڵدەبژێرێت، بۆیە هیچ وشەیەک دوو جار نایەت.

Lineدێڕی 6-7

The player quit: stop at once and report it.

یاریزان وەستا: یەکسەر بوەستە و ڕاپۆرتی بکە.

Lineدێڕی 8

An accumulator: each round's points are added to score.

: خاڵی هەر گەڕێک دەخرێتە سەر score.

Lineدێڕی 9

return score, False returns a tuple of two values.

return score, False لە دوو دەگەڕێنێتەوە.

The caller unpacks the tuple into two names: score, player_quit = play_game(words). Tuples and unpacking are explained in Tuples, sets and dictionaries.

دەکاتەوە بۆ دوو ناو: score, player_quit = play_game(words). و کردنەوەیان لە تاپڵەکان، کۆمەڵەکان و فەرهەنگەکان ڕوون کراونەتەوە.

Quick checkپشکنینی خێراWhat does play_game() return when the player finishes all 5 words with 3+2+3+0+23 + 2 + 3 + 0 + 2 points?کاتێک یاریزان هەر 5 وشەکە بە 3+2+3+0+23 + 2 + 3 + 0 + 2 خاڵ تەواو دەکات، play_game() چی دەگەڕێنێتەوە؟

Step 7: questions that accept only good answersهەنگاوی 7: پرسیار کە تەنها وەڵامی دروست وەردەگرێت

Two more questions need validation: which word list, and “play again?”. Both use the same pattern from the while loop: ask inside while True, return when the answer is good, explain and ask again when it is not.

دوو پرسیاری تر پێویستیان بە هەیە: کام وشە و «دووبارە یاری دەکەیتەوە؟». هەردووکیان هەمان شێوازی خولی while بەکار دەهێنن: لە ناو while True بپرسە، کاتێک وەڵامەکە باش بوو return بکە، کاتێک باش نەبوو ڕوونی بکەرەوە و دووبارە بپرسە.

Two validation loopsدوو خولی پشتڕاستکردنەوەmixed_letters.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
def choose_word_list():
    """Ask until the player types 1 or 2; return that word list."""
    while True:
        choice = input("1 = programming words, 2 = Kurdish words: ").strip()
        if choice in WORD_LISTS:
            return WORD_LISTS[choice]
        print("Please type 1 or 2.")


def ask_yes_no(question):
    """Ask until the answer is yes or no; return True for yes."""
    while True:
        answer = input(question).strip().lower()
        if answer in ("y", "yes"):
            return True
        if answer in ("n", "no"):
            return False
        print("Please answer y or n.")
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 5

choice in WORD_LISTS checks the dictionary's keys: only "1" and "2" pass.

choice in WORD_LISTS دەپشکنێت: تەنها "1" و "2" تێدەپەڕن.

Lineدێڕی 6

The key gives its list. return also ends the loop.

خۆی دەدات. return کۆتایی پێ دەهێنێت.

Lineدێڕی 14-17

Two accepted spellings for each answer; anything else is explained on line 18.

بۆ هەر وەڵامێک دوو شێوەی نووسین قبووڵ دەکرێت؛ هەر شتێکی تر لە دێڕی ⁦18⁩دا ڕوون دەکرێتەوە.

Using a dictionary for the menu means that a third word list needs only one new line in WORD_LISTS (and new prompt text) — no new if.

بەکارهێنانی بۆ هەڵبژاردنەکان واتە وشەی سێیەم تەنها یەک دێڕی نوێی لە WORD_LISTSـدا پێویستە (و دەقی پرسیاری نوێ) — هیچ ifـێکی نوێ نا.

Quick checkپشکنینی خێراThe player answers Yes (capital Y, a space at the end). What does ask_yes_no() return?یاریزان وەڵامی Yes دەداتەوە (Yـی گەورە، لە کۆتاییدا). ask_yes_no() چی دەگەڕێنێتەوە؟

Step 8: main() and playing againهەنگاوی ⁦8: main()⁩ و دووبارە یاریکردن

main() connects everything. One pass of its while True loop is one game. The best score lives in main(), so it survives from game to game.

main() هەموو شتێک پێکەوە دەبەستێت. هەر while Trueـەکەی یەک یارییە. باشترین خاڵ لە main()ـدا دەژی، بۆیە لە یارییەکەوە بۆ یارییەکی تر دەمێنێتەوە.

The main loop and a clean exitخولە سەرەکییەکە و دەرچوونێکی ئارامmixed_letters.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
def main():
    print("=== Mixed Letters ===")
    print(f"Unmix {ROUNDS} words. You have {MAX_TRIES} tries for each word.")
    print("Type quit at any time to stop.")
    best = 0
    while True:                     # one pass of this loop = one game
        words = choose_word_list()
        score, player_quit = play_game(words)
        print(f"\nScore: {score} out of {ROUNDS * MAX_TRIES}")
        if score > best:
            best = score
            print("New best score today!")
        if player_quit or not ask_yes_no("Play again? (y/n): "):
            break
    print(f"Best score: {best}. Goodbye!")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:       # the player pressed Ctrl+C
        print("\nGame stopped. Goodbye!")
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 6-8

One game: choose a list, play it, unpack the two results.

یەک یاری: هەڵبژێرە، یاری پێ بکە، دوو ئەنجامەکە بکەرەوە.

Lineدێڕی 10-12

Keep the highest score so far.

بەرزترین خاڵ تا ئێستا هەڵبگرە.

Lineدێڕی 13-14

Stop if the player typed quit, or answered no. Thanks to or, the question is not asked after quit.

ئەگەر یاریزان quitـی نووسی یان وەڵامی نەخێری دایەوە بوەستە. بە هۆی or، دوای quit پرسیارەکە ناکرێت.

Lineدێڕی 18

Run main() only when this file is run, not when another file imports it (the tests below need that).

main() تەنها کاتێک جێبەجێ بکە کە ئەم جێبەجێ دەکرێت، نەک کاتێک تر importـی دەکات (تاقیکردنەوەکانی خوارەوە ئەمەیان پێویستە).

Lineدێڕی 19-22

Ctrl+C raises KeyboardInterrupt. We catch it and say goodbye instead of showing a traceback.

⁦Ctrl+C⁩ KeyboardInterrupt دروست دەکات. دەیگرین و لە جیاتی پیشاندانی ماڵئاوایی دەکەین.

When the player presses Ctrl+C, the terminal shows ^C and our except block prints the goodbye line:

کاتێک یاریزان ⁦Ctrl+C⁩ دادەگرێت، ^C پیشان دەدات و بلۆکی exceptـەکەمان دێڕی ماڵئاوایی چاپ دەکات:

Ctrl+C at the first question (real terminal run)⁦Ctrl+C⁩ لە یەکەم پرسیاردا (جێبەجێکردنی ڕاستەقینە لە تێرمیناڵدا)
=== Mixed Letters ===
Unmix 5 words. You have 3 tries for each word.
Type quit at any time to stop.
1 = programming words, 2 = Kurdish words: ^C
Game stopped. Goodbye!
Quick checkپشکنینی خێراWhy is the best score kept in main() and not in play_game()?بۆچی باشترین خاڵ لە main()ـدا هەڵدەگیرێت نەک لە play_game()ـدا؟

The complete programبەرنامە تەواوەکە

Here is the whole game in one file, mixed_letters.py (110 lines). Read it from the bottom up: main() calls the others, and each helper does one job.

ئەمە هەموو یارییەکەیە لە یەک ، mixed_letters.py (⁦110⁩ دێڕ). لە خوارەوە بۆ سەرەوە بیخوێنەرەوە: main() بانگی ئەوانی تر دەکات و هەر یاریدەدەرێک یەک کار دەکات.

Mixed Letters — the whole gameپیتە تێکەڵەکان — هەموو یارییەکەmixed_letters.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
import random

MAX_TRIES = 3      # tries for each word
ROUNDS = 5         # words in one game

PROGRAMMING_WORDS = ["python", "variable", "function", "string", "loop",
                     "list", "index", "random", "integer", "keyboard"]
KURDISH_WORDS = ["کتێب", "قوتابخانە", "چایخانە", "بازاڕ", "باران",
                 "پاسکیل", "مامۆستا", "خوێندکار", "زستان", "کۆمپیوتەر"]
WORD_LISTS = {"1": PROGRAMMING_WORDS, "2": KURDISH_WORDS}


def scramble(word):
    """Return the letters of word in a new random order."""
    if len(set(word)) < 2:          # "aa" can never look different
        return word
    letters = list(word)
    while True:
        random.shuffle(letters)     # mixes the list in place
        mixed = "".join(letters)
        if mixed != word:           # never show the answer itself
            return mixed


def guess_problem(guess, word):
    """Return why guess is not a fair try, or "" if it is fine."""
    if len(guess) != len(word):
        return f"Please type exactly {len(word)} letters."
    if sorted(guess) != sorted(word):
        return "Please use only the letters shown."
    return ""


def play_round(word):
    """Play one word. Return the points (0-3), or None to quit."""
    print("\nLetters:", " ".join(scramble(word)))
    tries = 0
    while tries < MAX_TRIES:
        guess = input("Your guess: ").strip().lower()
        if guess == "quit":
            return None
        problem = guess_problem(guess, word)
        if problem:
            print(problem)          # an unfair guess costs no try
            continue
        tries += 1
        if guess == word:
            points = MAX_TRIES + 1 - tries
            print(f"Correct! +{points} points")
            return points
        if tries < MAX_TRIES:
            print(f"Not this one. Hint: it starts with {word[:tries]}")
            print(f"Tries left: {MAX_TRIES - tries}")
    print(f"Out of tries. The word was {word}.")
    return 0


def play_game(words):
    """Play ROUNDS different words. Return (score, player_quit)."""
    score = 0
    for word in random.sample(words, ROUNDS):   # no word twice
        points = play_round(word)
        if points is None:
            return score, True
        score += points
    return score, False


def choose_word_list():
    """Ask until the player types 1 or 2; return that word list."""
    while True:
        choice = input("1 = programming words, 2 = Kurdish words: ").strip()
        if choice in WORD_LISTS:
            return WORD_LISTS[choice]
        print("Please type 1 or 2.")


def ask_yes_no(question):
    """Ask until the answer is yes or no; return True for yes."""
    while True:
        answer = input(question).strip().lower()
        if answer in ("y", "yes"):
            return True
        if answer in ("n", "no"):
            return False
        print("Please answer y or n.")


def main():
    print("=== Mixed Letters ===")
    print(f"Unmix {ROUNDS} words. You have {MAX_TRIES} tries for each word.")
    print("Type quit at any time to stop.")
    best = 0
    while True:                     # one pass of this loop = one game
        words = choose_word_list()
        score, player_quit = play_game(words)
        print(f"\nScore: {score} out of {ROUNDS * MAX_TRIES}")
        if score > best:
            best = score
            print("New best score today!")
        if player_quit or not ask_yes_no("Play again? (y/n): "):
            break
    print(f"Best score: {best}. Goodbye!")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:       # the player pressed Ctrl+C
        print("\nGame stopped. Goodbye!")
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3-10

Settings and word lists: constants, written in capitals.

و وشە: ، بە پیتی گەورە نووسراون.

Lineدێڕی 13-31

Two small helpers that never talk to the player: easy to test.

دوو یاریدەدەری بچووک کە هەرگیز قسە لەگەڵ یاریزان ناکەن: تاقیکردنەوەیان ئاسانە.

Lineدێڕی 34-66

One round and one game.

یەک گەڕ و یەک یاری.

Lineدێڕی 69-86

Two validation loops.

دوو .

Lineدێڕی 89-110

The main loop, the __main__ guard and the Ctrl+C exit.

، پاسەوانی __main__ و دەرچوون بە ⁦Ctrl+C⁩.

In this run you can follow every rule: the menu rejects 3; pool costs a try and gives the hint l; varible (7 letters) costs nothing; list is lost after three fair tries; the score is 3+2+3+0+2=103 + 2 + 3 + 0 + 2 = 10; and maybe is not accepted as an answer.

لەم جێبەجێکردنەدا دەتوانیت هەموو یاساکان ببینیت: هەڵبژاردنەکە 3 ڕەت دەکاتەوە؛ pool هەوڵێک دەسووتێنێت و سەرەداوی l دەدات؛ varible (⁦7⁩ پیت) هیچی تێ ناچێت؛ list دوای سێ هەوڵی ڕەوا دەدۆڕێت؛ کۆی خاڵەکان: 3+2+3+0+2=103 + 2 + 3 + 0 + 2 = 10؛ و maybe وەک وەڵام قبووڵ ناکرێت.

Quick checkپشکنینی خێراIn the sample run, why did the round with list give 0 points?لە نموونەی جێبەجێکردنەکەدا، بۆچی گەڕەکەی list 0 خاڵی دا؟

The complete programبەرنامە تەواوەکە

Playing with Kurdish wordsیاریکردن بە وشەی کوردی

Choose list 2 and the same code plays with Kurdish words. Nothing in the program is English-only: list(), shuffle(), sorted() and len() work on any Unicode letters.

2 هەڵبژێرە و هەمان کۆد بە وشەی کوردی یاری دەکات. هیچ شتێک لە تەنها بۆ ئینگلیزی نییە: list()، shuffle()، sorted() و len() لەسەر هەر پیتێکی کار دەکەن.

Sample run with Kurdish wordsنموونەی جێبەجێکردن بە وشەی کوردی
=== Mixed Letters ===
Unmix 5 words. You have 3 tries for each word.
Type quit at any time to stop.
1 = programming words, 2 = Kurdish words: 2

Letters: ا ز ا ڕ ب
Your guess: بازار
Please use only the letters shown.
Your guess: بازاڕ
Correct! +3 points

Letters: ل پ س ک ا ی
Your guess: quit

Score: 3 out of 15
New best score today!
Best score: 3. Goodbye!

The first guess was refused: بازار was typed with ر instead of ڕ. For Python these are two different characters (code points 1585 and 1685), so the guess does not use the letters shown. Careful spelling matters to a computer! See Kurdish letters in comparisons.

یەکەم وەڵام ڕەت کرایەوە: بازار بە ر لە جیاتی ڕ نووسرا. بۆ ئەمانە دوو جیاوازن ( ⁦1585⁩ و ⁦1685⁩)، بۆیە وەڵامەکە ئەو پیتانە بەکار ناهێنێت کە پیشان دراون. ڕێنووسی ورد بۆ گرنگە! بڕوانە پیتە کوردییەکان لە بەراوردکردندا.

Quick checkپشکنینی خێراWhy was بازار refused for the word بازاڕ?بۆچی بازار بۆ وشەی بازاڕ ڕەت کرایەوە؟

Testing a program that uses randomتاقیکردنەوەی بەرنامەیەک کە هەڵکەوت بەکار دەهێنێت

How do you test a program whose output changes every run? Two tools help. First, random.seed() fixes the starting point of the random-number generator: with the same seed, the same “random” results come again. Second, assert checks a fact and stops the program if it is false.

چۆن تاقی دەکەیتەوە کە لە هەر جێبەجێکردنێکدا دەگۆڕێت؟ دوو ئامراز یارمەتی دەدەن. یەکەم، random.seed() خاڵی دەستپێکی دروستکەری جێگیر دەکات: بە هەمان ، هەمان ئەنجامە «هەڵکەوتییەکان» دووبارە دێنەوە. دووەم، assert ڕاستییەک دەپشکنێت و ئەگەر هەڵە بوو دەوەستێنێت.

Automatic checks for the two helpersپشکنینی خۆکار بۆ دوو یاریدەدەرەکەtest_mixed_letters.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
import random

from mixed_letters import guess_problem, scramble

random.seed(2026)                    # fix the "random" numbers
print(scramble("python"), scramble("python"))
random.seed(2026)                    # same seed again ...
print(scramble("python"), scramble("python"))   # ... same letters again

for word in ["python", "loop", "کتێب"]:
    mixed = scramble(word)
    assert mixed != word                     # never the answer itself
    assert sorted(mixed) == sorted(word)     # the same letters
assert guess_problem("pool", "loop") == ""
assert guess_problem("lop", "loop") != ""
assert guess_problem("lope", "loop") != ""
print("All tests passed.")
Explain the codeڕوونکردنەوەی کۆدەکە
Lineدێڕی 3

Save this file next to mixed_letters.py. Importing works because main() is guarded by if __name__ == "__main__": — the game does not start.

ئەم لە تەنیشت mixed_letters.py هەڵبگرە. import کار دەکات چونکە main() بە if __name__ == "__main__": پارێزراوە — یارییەکە دەست پێ ناکات.

Lineدێڕی 5-8

Same seed, same results: both lines print the same two mixes.

هەمان ، هەمان ئەنجام: هەردوو دێڕ هەمان دوو تێکەڵ چاپ دەکەن.

Lineدێڕی 10-13

Facts that must be true for any word: never the word itself, always the same letters.

ڕاستییەک کە دەبێت بۆ هەموو وشەیەک ڕاست بێت: هەرگیز خودی وشەکە نا، هەمیشە هەمان پیتەکان.

If a fact is false, assert raises an AssertionError and shows the line. Here a wrong claim is tested on purpose:

ئەگەر ڕاستییەک هەڵە بێت، assert AssertionError دروست دەکات و دێڕەکە پیشان دەدات. لێرەدا بە ئەنقەست بانگەشەیەکی هەڵە تاقی دەکرێتەوە:

test_fail.pyPYTHONType in a terminalلە تێرمیناڵدا بینووسە
from mixed_letters import guess_problem

assert guess_problem("lope", "loop") == ""   # this claim is false
print("All tests passed.")
Quick checkپشکنینی خێراWhat does random.seed(2026) do?random.seed(2026) چی دەکات؟

Why Is "random.seed()" So Important In Python?Indently · Englishئینگلیزی · 42K viewsبینین · 1.1K likesلایک

What random.seed() does: the same seed gives the same 'random' numbers every run, which makes programs easy to test.

random.seed() چی دەکات: هەمان لە هەموو جێبەجێکردنێکدا هەمان دەدات، ئەمەش ئاسان دەکات.

Whole video (2:44): what random.seed() does and why the same seed gives the same results.

هەموو ڤیدیۆکە ⁦(2:44)⁩: random.seed() چی دەکات و بۆچی هەمان هەمان ئەنجام دەدات.

Common mistakesهەڵە باوەکان

Mistakes in word gamesهەڵەکان لە یارییە وشەییەکاندا
MistakeهەڵەWhat happensچی ڕوودەداتFixچارەسەر
letters = random.shuffle(letters)letters becomes Noneletters دەبێت بە Nonerandom.shuffle(letters)
random.shuffle(word)TypeError: a string cannot changeTypeError: ناگۆڕدرێتletters = list(word) firstسەرەتا letters = list(word)
Shuffle once, show the resultیەک جار تێکەڵکردن، پیشاندانی ئەنجامSometimes the answer itself is shownهەندێک جار خودی وەڵامەکە پیشان دەدرێتShuffle again until differentدووبارە تێکەڵ بکە تا جیاواز دەبێت
Retry loop for a word like aa دووبارە بۆ وشەیەکی وەک aaInfinite loopGuard with len(set(word)) < 2پاسەوان بە len(set(word)) < 2
random.choice() for each roundrandom.choice() بۆ هەر گەڕێکThe same word can come twiceهەمان وشە دەتوانێت دوو جار بێتrandom.sample(words, 5)
No .strip().lower()بێ .strip().lower()Python or python is judged wrongPython یان python بە هەڵە دادەنرێتinput(...).strip().lower()
Counting every guess as a tryژماردنی هەموو وەڵامێک وەک هەوڵA typo costs the player a tryهەڵەیەکی تایپکردن هەوڵێک لە یاریزان دەسووتێنێتValidate first, then tries += 1سەرەتا بپشکنە، پاشان tries += 1
main() calls main() to play againmain() بانگی main() دەکات بۆ دووبارە یاریThe call stack grows; RecursionError after ~1000 games گەورە دەبێت؛ دوای ~⁦1000⁩ یاری RecursionErrorA while True loop with break while True لەگەڵ break
Score in a global variableخاڵ لە Hard to test; any function can change itتاقیکردنەوەی قورسە؛ هەر دەتوانێت بیگۆڕێتReturn values and add them up بگەڕێنەرەوە و کۆیان بکەرەوە
random.seed() left in the gamerandom.seed() لە یارییەکەدا جێهێڵراوەEvery game is the sameهەموو یارییەک وەک یەکەSeed only in tests تەنها لە تاقیکردنەوەدا

Exercisesڕاهێنانەکان

Exerciseڕاهێنان1. Trace a round1. بەدواداچوونی گەڕێک

Without running it: the word is loop and the player types lop, pool, LOOP. Write every line that play_round() prints, and its return value.

بەبێ جێبەجێکردن: وشەکە loopـە و یاریزان lop، pool، LOOP دەنووسێت. هەموو ئەو دێڕانە بنووسە کە play_round() چاپیان دەکات و .

Hintئاماژە

Remember that .lower() runs before the comparison.

لەبیرت بێت .lower() پێش بەراوردکردن جێبەجێ دەبێت.

Show answerوەڵامەکە پیشان بدە

lop has the wrong length (no try used). pool is fair but wrong: hint l, 2 tries left. LOOP becomes loop: correct on try 2, so 2 points.

lop درێژییەکەی هەڵەیە (هیچ هەوڵێک بەکار نایەت). pool ڕەوایە بەڵام هەڵەیە: سەرەداوی l، 2 هەوڵی تر دەمێنێتەوە. LOOP دەبێت بە loop: لە هەوڵی 2دا ڕاستە، بۆیە 2 خاڵ.

step5_round.py (test line)PYTHONType in a terminalلە تێرمیناڵدا بینووسە
print("Points:", play_round("loop"))
Exerciseڕاهێنان2. A skip command2. زیادکردنی فەرمانی skip

Add a command skip: the player gives up the current word, sees the answer, gets 0 points and goes on to the next word. Update the welcome text too.

skip زیاد بکە: یاریزان دەستبەرداری وشەی ئێستا دەبێت، وەڵامەکە دەبینێت، 0 خاڵ وەردەگرێت و دەچێتە سەر وشەی داهاتوو. دەقی بەخێرهاتنیش نوێ بکەرەوە.

Hintئاماژە

Put the new test right after the quit test, before the guess is validated.

پشکنینە نوێیەکە ڕاستەوخۆ دوای پشکنینی quit دابنێ، پێش پشکنینی وەڵامەکە.

Show answerوەڵامەکە پیشان بدە
mixed_letters.py (inside play_round)PYTHONType in a terminalلە تێرمیناڵدا بینووسە
        if guess == "quit":
            return None
        if guess == "skip":
            print(f"Skipped. The word was {word}.")
            return 0

And in main(): print("Type skip to pass a word, or quit to stop."). Test run:

و لە main()ـدا: print("Type skip to pass a word, or quit to stop."). جێبەجێکردنی تاقیکردنەوە:

Sample runنموونەی جێبەجێکردن
=== Mixed Letters ===
Unmix 5 words. You have 3 tries for each word.
Type skip to pass a word, or quit to stop.
1 = programming words, 2 = Kurdish words: 1

Letters: o y a d e b r k
Your guess: skip
Skipped. The word was keyboard.

Letters: p l o o
Your guess: quit

Score: 0 out of 15
Best score: 0. Goodbye!
Exerciseڕاهێنان3. A third word list3. لیستی سێیەمی وشە

Add a list of animals (horse, camel, eagle, tiger, zebra, rabbit) as choice 3. Which lines must change?

ئاژەڵ (horse، camel، eagle، tiger، zebra، rabbit) وەک هەڵبژاردنی 3 زیاد بکە. کام دێڕانە دەبێت بگۆڕدرێن؟

Show answerوەڵامەکە پیشان بدە
mixed_letters.py (settings)PYTHONType in a terminalلە تێرمیناڵدا بینووسە
ANIMAL_WORDS = ["horse", "camel", "eagle", "tiger", "zebra", "rabbit"]
WORD_LISTS = {"1": PROGRAMMING_WORDS, "2": KURDISH_WORDS, "3": ANIMAL_WORDS}

In choose_word_list() only the two texts change: the prompt "1 = programming, 2 = Kurdish, 3 = animals: " and the message "Please type 1, 2 or 3.". The test choice in WORD_LISTS already accepts "3". The list must have at least 5 words (see exercise 4).

لە choose_word_list()ـدا تەنها دوو دەقەکە دەگۆڕێن: پرسیاری "1 = programming, 2 = Kurdish, 3 = animals: " و پەیامی "Please type 1, 2 or 3.". پشکنینی choice in WORD_LISTS خۆی "3" قبووڵ دەکات. دەبێت لانیکەم 5 وشەی هەبێت (بڕوانە ڕاهێنانی ⁦4⁩).

Sample runنموونەی جێبەجێکردن
=== Mixed Letters ===
Unmix 5 words. You have 3 tries for each word.
Type quit at any time to stop.
1 = programming, 2 = Kurdish, 3 = animals: 4
Please type 1, 2 or 3.
1 = programming, 2 = Kurdish, 3 = animals: 3

Letters: a z b e r
Your guess: quit

Score: 0 out of 15
Best score: 0. Goodbye!
Exerciseڕاهێنان4. Too many rounds4. گەڕی زۆر

Change ROUNDS = 5 to ROUNDS = 20 and choose list 1. What happens, and why? How would you fix it?

ROUNDS = 5 بگۆڕە بۆ ROUNDS = 20 و 1 هەڵبژێرە. چی ڕوودەدات و بۆچی؟ چۆن چاکی دەکەیتەوە؟

Hintئاماژە

Read the last line of the traceback.

دوا دێڕی بخوێنەرەوە.

Show answerوەڵامەکە پیشان بدە

The program stops with ValueError: Sample larger than population or is negative: random.sample() cannot pick 20 different words from a list of 10.

بە ValueError: Sample larger than population or is negative دەوەستێت: random.sample() ناتوانێت ⁦20⁩ وشەی جیاواز لە ⁦10⁩ وشەییدا هەڵبژێرێت.

Outputدەرئەنجام
=== Mixed Letters ===
Unmix 20 words. You have 3 tries for each word.
Type quit at any time to stop.
1 = programming words, 2 = Kurdish words: 1
Traceback (most recent call last):
  File "/Users/aram/python/mixed_letters.py", line 108, in <module>
    main()
  File "/Users/aram/python/mixed_letters.py", line 96, in main
    score, player_quit = play_game(words)
                         ^^^^^^^^^^^^^^^^
  File "/Users/aram/python/mixed_letters.py", line 61, in play_game
    for word in random.sample(words, ROUNDS):   # no word twice
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ".../lib/python3.12/random.py", line 430, in sample
    raise ValueError("Sample larger than population or is negative")
ValueError: Sample larger than population or is negative

The simplest fix is a rule: ROUNDS must not be larger than the shortest word list (or add more words). random.sample(words, min(ROUNDS, len(words))) stops the crash, but then the welcome line and “out of 60” are wrong, so those messages would need the real number too.

سادەترین چارەسەر یاسایەکە: ROUNDS نابێت لە کورتترین وشە گەورەتر بێت (یان وشەی زیاتر زیاد بکە). random.sample(words, min(ROUNDS, len(words))) وەستانەکە نایەڵێت، بەڵام پاشان دێڕی بەخێرهاتن و «⁦out of 60⁩» هەڵەن، بۆیە ئەو پەیامانەش پێویستیان بە ژمارە ڕاستەکە دەبێت.

Exerciseڕاهێنان5. Play again by recursion?5. دووبارە یاری بە خۆبانگکردنەوە؟

A student removes the while True loop from main() and writes if ask_yes_no("Play again? (y/n): "): main() at the end instead. The game seems to work. Give two reasons why the loop version is better.

خوێندکارێک while True لە main() لادەبات و لە جیاتی ئەوە لە کۆتاییدا دەنووسێت if ask_yes_no("Play again? (y/n): "): main(). یارییەکە وا دیارە کار دەکات. دوو هۆکار بڵێ بۆچی وەشانی باشترە.

Show answerوەڵامەکە پیشان بدە
  • Each new game is a call inside the previous call. The call stack grows with every game, and after about 1000 games Python stops with RecursionError.
  • Each call of main() has its own best = 0, so the best score is forgotten when a new game starts; and when the player finally says no, all the waiting calls finish one by one, each printing its own goodbye line.
  • هەر یارییەکی نوێ بانگکردنێکە لە ناو بانگکردنی پێشوودا. لەگەڵ هەر یارییەک گەورە دەبێت و دوای نزیکەی ⁦1000⁩ یاری بە RecursionError دەوەستێت.
  • هەر بانگکردنێکی main() best = 0ـی خۆی هەیە، بۆیە کاتێک یارییەکی نوێ دەست پێ دەکات باشترین خاڵ لەبیر دەچێت؛ و کاتێک یاریزان لە کۆتاییدا دەڵێت نەخێر، هەموو بانگکردنە چاوەڕوانەکان یەک لە دوای یەک تەواو دەبن و هەر یەکەیان دێڕی ماڵئاوایی خۆی چاپ دەکات.
Quick checkپشکنینی خێراWhich change would make scramble() loop for ever?کام گۆڕانکاری وا دەکات scramble() بۆ هەمیشە بخولێتەوە؟

Exercisesڕاهێنانەکان

One more: remember the best scoreیەکێکی تر: باشترین خاڵ لەبیر بێت

Exerciseڕاهێنان6. A best score that survives6. باشترین خاڵێک کە دەمێنێتەوە

The game says “New best score today!” because best is a variable: it is lost when the program ends. Keep the best score in a file best_score.txt instead. Write load_best() (the saved number, or 0 when there is no file yet) and save_best(best), and use them in main().

یارییەکە دەڵێت «⁦New best score today!⁩» چونکە best : کاتێک کۆتایی دێت ون دەبێت. لە جیاتی ئەوە باشترین خاڵ لە best_score.txtـدا هەڵبگرە. load_best() (ژمارە هەڵگیراوەکە، یان 0 کاتێک هێشتا نییە) و save_best(best) بنووسە و لە main()ـدا بەکاریان بهێنە.

Hintئاماژە

Copy the pattern of A counter that remembers: read inside try, start from 0 on FileNotFoundError, write with mode "w".

شێوازی ژمێرەرێک کە لەبیری ناچێت کۆپی بکە: لە ناو try بیخوێنەرەوە، لە FileNotFoundErrorـدا لە 0ـەوە دەست پێ بکە و بە دۆخی "w" بینووسە.

Show answerوەڵامەکە پیشان بدە
PYTHONType in a terminalلە تێرمیناڵدا بینووسە
BEST_FILE = "best_score.txt"


def load_best():
    """Return the saved best score, or 0 if there is none yet."""
    try:
        with open(BEST_FILE, encoding="utf-8") as f:
            return int(f.read())
    except (FileNotFoundError, ValueError):   # no file yet, or no number in it
        return 0


def save_best(best):
    """Write the best score into BEST_FILE for the next run."""
    with open(BEST_FILE, "w", encoding="utf-8") as f:
        f.write(str(best))

In main(), best = 0 becomes best = load_best(), and right after best = score add save_best(best); the message can now say “New best score!”. ValueError is caught too, so a file that holds no number starts from 0 instead of crashing (Catching file errors). Two runs, one after the other:

لە main()ـدا best = 0 دەبێت بە best = load_best() و ڕاستەوخۆ دوای best = score بنووسە save_best(best)؛ ئێستا پەیامەکە دەتوانێت بڵێت «⁦New best score!⁩». ValueErrorـیش دەگیرێت، بۆیە کە ژمارەی تێدا نییە لە 0ـەوە دەست پێ دەکات لە جیاتی ئەوەی بوەستێت (گرتنی هەڵەکانی فایل). دوو جێبەجێکردن، یەک لە دوای یەک:

Outputدەرئەنجام
=== Mixed Letters ===
Unmix 5 words. You have 3 tries for each word.
Type quit at any time to stop.
1 = programming words, 2 = Kurdish words: 1

Letters: p o l o
Your guess: loop
Correct! +3 points

Letters: d n i x e
Your guess: quit

Score: 3 out of 15
New best score!
Best score: 3. Goodbye!

=== Mixed Letters ===
Unmix 5 words. You have 3 tries for each word.
Type quit at any time to stop.
1 = programming words, 2 = Kurdish words: 1

Letters: t s i l
Your guess: slit
Not this one. Hint: it starts with l
Tries left: 2
Your guess: list
Correct! +2 points

Letters: y t h o n p
Your guess: quit

Score: 2 out of 15
Best score: 3. Goodbye!

The second run scored only 2, but it still knows the best score 3 from the first run: the file kept it.

جێبەجێکردنی دووەم تەنها 2 خاڵی هێنا، بەڵام هێشتا باشترین خاڵی 3ـی جێبەجێکردنی یەکەم دەزانێت: هەڵیگرتبوو.

Quick checkپشکنینی خێراWhy did the best score disappear between runs before this change?پێش ئەم گۆڕانکارییە، بۆچی باشترین خاڵ لە نێوان جێبەجێکردنەکاندا ون دەبوو؟

Summaryپوختە

  • Plan first: a scenario, a flowchart with standard symbols, then one function per job.
  • Scramble a word with list(word), random.shuffle(letters) (in place, returns None) and "".join(letters); shuffle again until the mix differs.
  • random.sample() gives different items; random.choice() may repeat.
  • Validate input before you use it: clean it with .strip().lower(), check it, explain the problem and ask again.
  • Pass results with return values: points, None for “quit”, a tuple for two results.
  • Repeat games with a loop, not by calling main() again; catch KeyboardInterrupt for a clean Ctrl+C.
  • Test random code with random.seed() and assert — and keep the seed out of the real game.
  • سەرەتا پلان: ، بە ، پاشان بۆ هەر کارێک .
  • وشەیەک بە list(word)، random.shuffle(letters) (لە شوێنی خۆیدا، None دەگەڕێنێتەوە) و "".join(letters) تێکەڵ بکە؛ دووبارە تێکەڵ بکە تا جیاواز دەبێت.
  • random.sample() جیاواز دەدات؛ random.choice() دەشێت دووبارە بکاتەوە.
  • پێش بەکارهێنان بپشکنە: بە .strip().lower() پاکی بکەرەوە، بیپشکنە، کێشەکە ڕوون بکەرەوە و دووبارە بپرسە.
  • ئەنجامەکان بە بگوازەرەوە: خاڵ، None بۆ «وەستان»، بۆ دوو ئەنجام.
  • یارییەکان بە دووبارە بکەرەوە، نەک بە دووبارە بانگکردنی main()؛ KeyboardInterrupt بگرە بۆ ⁦Ctrl+C⁩ـێکی ئارام.
  • کۆدی هەڵکەوتی بە random.seed() و assert تاقی بکەرەوە — و لە یارییە ڕاستەقینەکەدا دامەنێ.
Review questionsپرسیارەکانی پێداچوونەوە
Why do we turn the word into a list before shuffling?بۆچی پێش تێکەڵکردن وشەکە دەکەین بە لیست؟

Strings are immutable and shuffle() changes its argument in place; a list can be changed.

و shuffle() لە شوێنی خۆیدا دەگۆڕێت؛ دەگۆڕدرێت.

How does guess_problem() know that two words use the same letters?guess_problem() چۆن دەزانێت دوو وشە هەمان پیتەکانیان هەیە؟

It compares sorted(guess) with sorted(word): equal sorted lists mean the same letters. (How sorting works: Sorting algorithms.)

sorted(guess) لەگەڵ sorted(word) بەراورد دەکات: ڕیزکراوی یەکسان واتە هەمان پیت. (چۆنیەتیی : ئەلگۆریزمەکانی ڕیزکردن.)

What does play_round() return?play_round() چی دەگەڕێنێتەوە؟

The points (3, 2, 1 or 0), or None if the player typed quit.

خاڵەکان (⁦3⁩، 2، 1 یان ⁦0⁩)، یان None ئەگەر یاریزان quitـی نووسیبێت.

Why is if __name__ == "__main__": useful here?بۆچی if __name__ == "__main__": لێرەدا بەسوودە؟

The test file can import scramble() and guess_problem() without starting the game.

تاقیکردنەوە دەتوانێت scramble() و guess_problem() import بکات بەبێ دەستپێکردنی یارییەکە.

Lesson complete!وانەکە تەواو بوو!

Well done. Review the key terms, then go on to the next lesson.دەستخۆش. سەیرێکی زاراوە سەرەکییەکان بکەرەوە، پاشان بڕۆ بۆ وانەی داهاتوو.

Key termsزاراوە سەرەکییەکان

Next lessonوانەی داهاتوو

Python Next to JavaPython لە تەنیشت Javaـەوە

References and further readingسەرچاوەکان و خوێندنەوەی زیاتر

This lecture is a first edition. The Kurdish text and terminology are waiting for review by Kurdish IT teachers.ئەم وانەیە چاپی یەکەمە. دەقە کوردییەکە و زاراوەکانی چاوەڕێی پێداچوونەوەی مامۆستایانی کوردی بواری IT ن.