Wordle là một trò chơi phổ biến trong đó bạn đoán một từ có năm chữ cái sau sáu lần thử. Sau mỗi lần đoán, màu của các ô sẽ thay đổi để hiển thị mức độ gần đúng của bạn với từ.
Nó tương tự như trò chơi Hangman mà tôi đã chỉ cho bạn cách xây dựng bằng Python.
Trong hướng dẫn này, chúng ta sẽ xây dựng phiên bản đầu cuối của trò chơi phổ biến Wordle bằng cách sử dụng Python và Rich, một thư viện dành cho định dạng văn bản có định dạng.
Nếu bạn chưa quen với Rich, hãy xem hướng dẫn này để bắt đầu. Đảm bảo rằng bạn đã cài đặt Rich trước khi bắt đầu theo dõi tại đây.
Bản trình diễn dự án
Hãy xem trò chơi cuối cùng của chúng ta sẽ như thế nào:
Hãy viết mã trò chơi Wordle của chúng tôi
Giống như trò chơi Wordle thực, một từ gồm năm chữ cái ngẫu nhiên được chọn hàng ngày. Để làm điều này, chúng tôi sẽ chọn một từ ngẫu nhiên từ danh sách các từ có năm chữ cái.
Vì vậy, trước tiên, hãy xác định danh sách các từ được gọi là word_list
trong một tách biệt words.py
tập tin:
word_list = ['ABOUT', 'ABOVE', 'ABUSE', 'ACTOR', 'ACUTE', 'ADMIT', 'ADOPT', 'ADULT', 'AFTER', 'AGAIN', 'AGENT', 'AGREE', 'AHEAD', 'ALARM', 'ALBUM', 'ALERT', 'ALIKE', 'ALIVE', 'ALLOW', 'ALONE', 'ALONG', 'ALTER', 'AMONG', 'ANGER', 'ANGLE', 'ANGRY', 'APART', 'APPLE', 'APPLY', 'ARENA', 'ARGUE', 'ARISE', 'ARRAY', 'ASIDE', 'ASSET', 'AUDIO', 'AUDIT', 'AVOID', 'AWARD', 'AWARE', 'BADLY', 'BAKER', 'BASES', 'BASIC', 'BASIS', 'BEACH', 'BEGAN', 'BEGIN', 'BEGUN', 'BEING', 'BELOW', 'BENCH', 'BILLY', 'BIRTH', 'BLACK', 'BLAME', 'BLIND', 'BLOCK', 'BLOOD', 'BOARD', 'BOOST', 'BOOTH', 'BOUND', 'BRAIN', 'BRAND', 'BREAD', 'BREAK', 'BREED', 'BRIEF', 'BRING', 'BROAD', 'BROKE', 'BROWN', 'BUILD', 'BUILT', 'BUYER', 'CABLE', 'CALIF', 'CARRY', 'CATCH', 'CAUSE', 'CHAIN', 'CHAIR', 'CHART', 'CHASE', 'CHEAP', 'CHECK', 'CHEST', 'CHIEF', 'CHILD', 'CHINA', 'CHOSE', 'CIVIL', 'CLAIM', 'CLASS', 'CLEAN', 'CLEAR', 'CLICK', 'CLOCK', 'CLOSE', 'COACH', 'COAST', 'COULD', 'COUNT', 'COURT', 'COVER', 'CRAFT', 'CRASH', 'CREAM', 'CRIME', 'CROSS', 'CROWD', 'CROWN', 'CURVE', 'CYCLE', 'DAILY', 'DANCE', 'DATED', 'DEALT', 'DEATH', 'DEBUT', 'DELAY', 'DEPTH', 'DOING', 'DOUBT', 'DOZEN', 'DRAFT', 'DRAMA', 'DRAWN', 'DREAM', 'DRESS', 'DRILL', 'DRINK', 'DRIVE', 'DROVE', 'DYING', 'EAGER', 'EARLY', 'EARTH', 'EIGHT', 'ELITE', 'EMPTY', 'ENEMY', 'ENJOY', 'ENTER', 'ENTRY', 'EQUAL', 'ERROR', 'EVENT', 'EVERY', 'EXACT', 'EXIST', 'EXTRA', 'FAITH', 'FALSE', 'FAULT', 'FIBER', 'FIELD', 'FIFTH', 'FIFTY', 'FIGHT', 'FINAL', 'FIRST', 'FIXED', 'FLASH', 'FLEET', 'FLOOR', 'FLUID', 'FOCUS', 'FORCE', 'FORTH', 'FORTY', 'FORUM', 'FOUND', 'FRAME', 'FRANK', 'FRAUD', 'FRESH', 'FRONT', 'FRUIT', 'FULLY', 'FUNNY', 'GIANT', 'GIVEN', 'GLASS', 'GLOBE', 'GOING', 'GRACE', 'GRADE', 'GRAND', 'GRANT', 'GRASS', 'GREAT', 'GREEN', 'GROSS', 'GROUP', 'GROWN', 'GUARD', 'GUESS', 'GUEST', 'GUIDE', 'HAPPY', 'HARRY', 'HEART', 'HEAVY', 'HENCE', 'HENRY', 'HORSE', 'HOTEL', 'HOUSE', 'HUMAN', 'IDEAL', 'IMAGE', 'INDEX', 'INNER', 'INPUT', 'ISSUE', 'JAPAN', 'JIMMY', 'JOINT', 'JONES', 'JUDGE', 'KNOWN', 'LABEL', 'LARGE', 'LASER', 'LATER', 'LAUGH', 'LAYER', 'LEARN', 'LEASE', 'LEAST', 'LEAVE', 'LEGAL', 'LEVEL', 'LEWIS', 'LIGHT', 'LIMIT', 'LINKS', 'LIVES', 'LOCAL', 'LOGIC', 'LOOSE', 'LOWER', 'LUCKY', 'LUNCH', 'LYING', 'MAGIC', 'MAJOR', 'MAKER', 'MARCH', 'MARIA', 'MATCH', 'MAYBE', 'MAYOR', 'MEANT', 'MEDIA', 'METAL', 'MIGHT', 'MINOR', 'MINUS', 'MIXED', 'MODEL', 'MONEY', 'MONTH', 'MORAL', 'MOTOR', 'MOUNT', 'MOUSE', 'MOUTH', 'MOVIE', 'MUSIC', 'NEEDS', 'NEVER', 'NEWLY', 'NIGHT', 'NOISE', 'NORTH', 'NOTED', 'NOVEL', 'NURSE', 'OCCUR', 'OCEAN', 'OFFER', 'OFTEN', 'ORDER', 'OTHER', 'OUGHT', 'PAINT', 'PANEL', 'PAPER', 'PARTY', 'PEACE', 'PETER', 'PHASE', 'PHONE', 'PHOTO', 'PIECE', 'PILOT', 'PITCH', 'PLACE', 'PLAIN', 'PLANE', 'PLANT', 'PLATE', 'POINT', 'POUND', 'POWER', 'PRESS', 'PRICE', 'PRIDE', 'PRIME', 'PRINT', 'PRIOR', 'PRIZE', 'PROOF', 'PROUD', 'PROVE', 'QUEEN', 'QUICK', 'QUIET', 'QUITE', 'RADIO', 'RAISE', 'RANGE', 'RAPID', 'RATIO', 'REACH', 'READY', 'REFER', 'RIGHT', 'RIVAL', 'RIVER', 'ROBIN', 'ROGER', 'ROMAN', 'ROUGH', 'ROUND', 'ROUTE', 'ROYAL', 'RURAL', 'SCALE', 'SCENE', 'SCOPE', 'SCORE', 'SENSE', 'SERVE', 'SEVEN', 'SHALL', 'SHAPE', 'SHARE', 'SHARP', 'SHEET', 'SHELF', 'SHELL', 'SHIFT', 'SHIRT', 'SHOCK', 'SHOOT', 'SHORT', 'SHOWN', 'SIGHT', 'SINCE', 'SIXTH', 'SIXTY', 'SIZED', 'SKILL', 'SLEEP', 'SLIDE', 'SMALL', 'SMART', 'SMILE', 'SMITH', 'SMOKE', 'SOLID', 'SOLVE', 'SORRY', 'SOUND', 'SOUTH', 'SPACE', 'SPARE', 'SPEAK', 'SPEED', 'SPEND', 'SPENT', 'SPLIT', 'SPOKE', 'SPORT', 'STAFF', 'STAGE', 'STAKE', 'STAND', 'START', 'STATE', 'STEAM', 'STEEL', 'STICK', 'STILL', 'STOCK', 'STONE', 'STOOD', 'STORE', 'STORM', 'STORY', 'STRIP', 'STUCK', 'STUDY', 'STUFF', 'STYLE', 'SUGAR', 'SUITE', 'SUPER', 'SWEET', 'TABLE', 'TAKEN', 'TASTE', 'TAXES', 'TEACH', 'TEETH', 'TERRY', 'TEXAS', 'THANK', 'THEFT', 'THEIR', 'THEME', 'THERE', 'THESE', 'THICK', 'THING', 'THINK', 'THIRD', 'THOSE', 'THREE', 'THREW', 'THROW', 'TIGHT', 'TIMES', 'TIRED', 'TITLE', 'TODAY', 'TOPIC', 'TOTAL', 'TOUCH', 'TOUGH', 'TOWER', 'TRACK', 'TRADE', 'TRAIN', 'TREAT', 'TREND', 'TRIAL', 'TRIED', 'TRIES', 'TRUCK', 'TRULY', 'TRUST', 'TRUTH', 'TWICE', 'UNDER', 'UNDUE', 'UNION', 'UNITY', 'UNTIL', 'UPPER', 'UPSET', 'URBAN', 'USAGE', 'USUAL', 'VALID', 'VALUE', 'VIDEO', 'VIRUS', 'VISIT', 'VITAL', 'VOICE', 'WASTE', 'WATCH', 'WATER', 'WHEEL', 'WHERE', 'WHICH', 'WHILE', 'WHITE', 'WHOLE', 'WHOSE', 'WOMAN', 'WOMEN', 'WORLD', 'WORRY', 'WORSE', 'WORST', 'WORTH', 'WOULD', 'WOUND', 'WRITE', 'WRONG', 'WROTE', 'YIELD', 'YOUNG', 'YOUTH']
Các chức năng tiện ích
Chúng ta sẽ định nghĩa một vài chức năng tiện ích để giúp chúng ta in văn bản màu trên bảng điều khiển. Chúng tôi sẽ sử dụng các cài đặt tương tự như mặc định của Wordle:
- Màu xanh lá cây = đúng chữ cái ở đúng vị trí
- Màu vàng = đúng chữ cái, nhưng ở vị trí không chính xác
- Màu xám = chữ cái sai
Đối với điều này, chúng tôi sẽ sử dụng Rich. Khá dễ dàng để in văn bản màu bằng mã này:
from rich.console import Console
from random import choice
from words import word_list
WELCOME_MESSAGE = f'\n[white on blue] WELCOME TO WORDLE [/]\n'
PLAYER_INSTRUCTIONS = "You may start guessing\n"
ALLOWED_GUESSES = 6
def correct_place(letter):
return f'[black on green]{letter}[/]'
def correct_letter(letter):
return f'[black on yellow]{letter}[/]'
def incorrect_letter(letter):
return f'[black on white]{letter}[/]'
if __name__ == '__main__':
console = Console()
chosen_word = choice(word_list)
console.print(WELCOME_MESSAGE)
console.print(PLAYER_INSTRUCTIONS)
Trong đoạn mã trên, chúng tôi đã xác định ba chức năng để in văn bản màu bằng Rich. Chúng tôi cũng đã thêm thông báo chào mừng và hướng dẫn người chơi, sẽ được sử dụng trong chức năng chính.
Các dự đoán được phép được đặt thành 6. Trong chức năng chính, trước tiên chúng ta tạo một phiên bản của Console
lớp từ rich.console
. Sau đó chúng tôi chọn một từ ngẫu nhiên từ word_list
định nghĩa trong words.py
.
Ở dòng cuối cùng, chúng tôi chỉ in thông báo Chào mừng và Hướng dẫn Người chơi bằng cách sử dụng console.print
.
Vòng lặp trò chơi
Chúng tôi sẽ chạy một vòng lặp while cho đến khi tất cả các dự đoán đã được sử dụng. Hãy xem mã và sau đó giải thích nó.
GUESS_STATEMENT = "\nEnter your guess"
SQUARES = {
'correct_place': '🟩',
'correct_letter': '🟨',
'incorrect_letter': '⬛'
}
def check_guess(guess, answer):
guessed = []
wordle_pattern = []
for i, letter in enumerate(guess):
if answer[i] == guess[i]:
guessed += correct_place(letter)
wordle_pattern.append(SQUARES['correct_place'])
elif letter in answer:
guessed += correct_letter(letter)
wordle_pattern.append(SQUARES['correct_letter'])
else:
guessed += incorrect_letter(letter)
wordle_pattern.append(SQUARES['incorrect_letter'])
return ''.join(guessed), ''.join(wordle_pattern)
def game(console, chosen_word):
end_of_game = False
already_guessed = []
full_wordle_pattern = []
all_words_guessed = []
while not end_of_game:
guess = Prompt.ask(GUESS_STATEMENT).upper()
while len(guess) != 5 or guess in already_guessed:
if guess in already_guessed:
console.print("[red]You've already guessed this word!!\n[/]")
else:
console.print('[red]Please enter a 5-letter word!!\n[/]')
guess = Prompt.ask(GUESS_STATEMENT).upper()
already_guessed.append(guess)
guessed, pattern = check_guess(guess, chosen_word)
all_words_guessed.append(guessed)
full_wordle_pattern.append(pattern)
console.print(*all_words_guessed, sep="\n")
if guess == chosen_word or len(already_guessed) == ALLOWED_GUESSES:
end_of_game = True
if len(already_guessed) == ALLOWED_GUESSES and guess != chosen_word:
console.print(f"\n[red]WORDLE X/{ALLOWED_GUESSES}[/]")
console.print(f'\n[green]Correct Word: {chosen_word}[/]')
else:
console.print(f"\n[green]WORDLE {len(already_guessed)}/{ALLOWED_GUESSES}[/]\n")
console.print(*full_wordle_pattern, sep="\n")
Các game()
hàm chấp nhận hai đối số – console
và chosen_word
(Câu trả lời chính xác). Chúng tôi có một biến boolean end_of_game
về cơ bản điều khiển vòng lặp while. Vòng lặp while sẽ chạy cho đến khi end_of_game
trở thành Đúng.
already_guessed
là một danh sách sẽ chứa các từ mà người dùng đã đoán. Các full_wordle_pattern
danh sách sẽ chứa mẫu Wordle (được làm bằng các ô vuông màu). Các all_words_guessed
danh sách sẽ chứa các từ với màu sắc của chúng.
Sau đó, chúng tôi chạy một vòng lặp while cho đến khi end_of_game
và nhắc người dùng đoán từ. Chúng tôi cũng liên tục kiểm tra xem từ mà người dùng đoán có chứa năm chữ cái hay không cũng như liệu người dùng đã đoán từ đó chưa.
Trong cả hai trường hợp, chúng tôi in lỗi và nhắc người dùng đoán lại.
Nếu người dùng đã đoán một từ, chúng tôi đặt từ đó vào already_guessed
danh sách. Sau đó, chúng tôi sử dụng một chức năng gọi là check_guess()
để kiểm tra xem người dùng đã đoán đúng từ hay chưa.
check_guess()
chức năng
Hàm này chấp nhận hai đối số – từ do người dùng đoán và câu trả lời đúng. Nó so sánh chúng theo từng chữ cái và sau đó sử dụng các hàm trợ giúp mà chúng tôi đã xác định trước đó để tạo chuỗi định dạng phong phú cho từng chữ cái. Sau đó, nó nối tất cả chúng lại với nhau thành một chuỗi duy nhất.
Hàm này trả về hai chuỗi – Từ được đoán định dạng phong phú và các ô vuông được tô màu cho từ được đoán đó.
Các chuỗi trả về được lưu trữ trong hai biến, guessed
và pattern
sau đó được thêm vào danh sách tương ứng của chúng, all_words_guessed
và full_wordle_pattern
.
Trong mỗi vòng lặp, chúng tôi sẽ in các phần tử trong all_words_guessed
danh sách được phân tách bằng ký tự xuống dòng (\n
). Nếu người dùng đã đoán đúng từ hoặc đã hết số lần đoán cho phép, chúng tôi sẽ đặt end_of_game
đến True
và vòng lặp sẽ kết thúc.
Xa hơn bên ngoài vòng lặp, chúng tôi sẽ kiểm tra xem các lượt đoán được phép đã hết chưa và người dùng không thể đoán chính xác từ đó. Nếu đây là trường hợp, chúng tôi sẽ in đúng từ và WORDLE X/6. Nhưng trong trường hợp khác, chúng tôi sẽ in WORDLE n
/6 trong đó n là số lượt đoán mà người dùng đã thực hiện để đoán đúng từ.
Cuối cùng, chúng tôi sẽ in danh sách mẫu Wordle được phân tách bằng ký tự xuống dòng (\n
).
Trong chức năng chính, chúng tôi sẽ gọi game()
chức năng với console
và chosen_word
như các đối số.
Mã dự án đầy đủ
Đây là mã đầy đủ cho bản sao Wordle:
from rich.prompt import Prompt
from rich.console import Console
from random import choice
from words import word_list
SQUARES = {
'correct_place': '🟩',
'correct_letter': '🟨',
'incorrect_letter': '⬛'
}
WELCOME_MESSAGE = f'\n[white on blue] WELCOME TO WORDLE [/]\n'
PLAYER_INSTRUCTIONS = "You may start guessing\n"
GUESS_STATEMENT = "\nEnter your guess"
ALLOWED_GUESSES = 6
def correct_place(letter):
return f'[black on green]{letter}[/]'
def correct_letter(letter):
return f'[black on yellow]{letter}[/]'
def incorrect_letter(letter):
return f'[black on white]{letter}[/]'
def check_guess(guess, answer):
guessed = []
wordle_pattern = []
for i, letter in enumerate(guess):
if answer[i] == guess[i]:
guessed += correct_place(letter)
wordle_pattern.append(SQUARES['correct_place'])
elif letter in answer:
guessed += correct_letter(letter)
wordle_pattern.append(SQUARES['correct_letter'])
else:
guessed += incorrect_letter(letter)
wordle_pattern.append(SQUARES['incorrect_letter'])
return ''.join(guessed), ''.join(wordle_pattern)
def game(console, chosen_word):
end_of_game = False
already_guessed = []
full_wordle_pattern = []
all_words_guessed = []
while not end_of_game:
guess = Prompt.ask(GUESS_STATEMENT).upper()
while len(guess) != 5 or guess in already_guessed:
if guess in already_guessed:
console.print("[red]You've already guessed this word!!\n[/]")
else:
console.print('[red]Please enter a 5-letter word!!\n[/]')
guess = Prompt.ask(GUESS_STATEMENT).upper()
already_guessed.append(guess)
guessed, pattern = check_guess(guess, chosen_word)
all_words_guessed.append(guessed)
full_wordle_pattern.append(pattern)
console.print(*all_words_guessed, sep="\n")
if guess == chosen_word or len(already_guessed) == ALLOWED_GUESSES:
end_of_game = True
if len(already_guessed) == ALLOWED_GUESSES and guess != chosen_word:
console.print(f"\n[red]WORDLE X/{ALLOWED_GUESSES}[/]")
console.print(f'\n[green]Correct Word: {chosen_word}[/]')
else:
console.print(f"\n[green]WORDLE {len(already_guessed)}/{ALLOWED_GUESSES}[/]\n")
console.print(*full_wordle_pattern, sep="\n")
if __name__ == '__main__':
console = Console()
chosen_word = choice(word_list)
console.print(WELCOME_MESSAGE)
console.print(PLAYER_INSTRUCTIONS)
game(console, chosen_word)
kết thúc
Trong bài viết này, chúng tôi đã tạo phiên bản đầu cuối của Wordle rất riêng. Nhưng vẫn còn rất nhiều điều bạn có thể xây dựng từ đây. Tương tự như Wordle thực, bạn có thể tạo phiên bản web của dự án này.
Hãy cho tôi biết nếu bạn có bất kỳ câu hỏi! Chia sẻ với bạn bè của bạn.
Kho lưu trữ mã: https://github.com/ashutoshkrris/Terminal-Wordle
Bạn có thể đọc bài viết này và các bài viết khác của tôi trên blog của tôi tại đây.