# Python實作課程
## 第二堂課 : Hangman劊子手
## 2022 / 4 / 08
### Tony
---
## 遊戲介紹
----
Hangman,是一個雙人猜單字遊戲。A想一個字,
B嘗試猜A所想的字中的每一個字母。 要猜的字以<font color='FFF300'>一列橫線</font>表示。如果B猜中其中一個字母,A便須於該字母出現的<font color='FFF300'>所有位置上</font>寫上該字母。
如果猜的字母沒有於該字中出現,A便會畫吊頸公仔的其中一筆。
![](https://i.imgur.com/U5SoyMS.png =30%x)
----
用電腦做的話....
* 我們沒辦法畫圖(或是說畫圖偏難)
所以把畫圖改成生命值
* 每次猜之前
都先秀出目前題目狀況和用過的字母
---
## 開始寫Code
----
模板:[點我](https://github.com/Tony041010/2022_CRC_Python_Project_Class_Template/blob/main/Hangman.py)
----
一、選擇單字
從一長串單字中抽出一個可行的單字
可行:中間沒有特殊符號(Ex. '-'),沒有空格
```python=
import random
def get_valid_word(words): # words是裝一堆單字的陣列
word = random.choice(words) #從word當中挑一個字出來
while '-' in word and ' ' in word:
word = random.choice(words)
#回傳大寫的單字,本程式全部都用大寫字母操作
return word.upper()
```
----
二、設定基本遊戲環境
我們總共需要四種不同的資料:
1. word:要猜的字
2. word_letters:word裡面所有<font color='red'>種類</font>的字母
3. alphabet:全部26個字母
4. used_letters:猜過的字母
----
先備工具:set()、string.ascii_uppercase
* set() : 把一個字串變成集合(set),他不會有重複的字元
* string.ascii_uppercase:26個英文字母組成的字串
like this : 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
```python=
word = get_valid_word(words)
word_letters = set(word) #letters in the word
alphabet = set(string.ascii_uppercase)
used_letters = set() #what the user has guessed
```
----
設定基礎遊戲框架
流程:
1. 輸入要猜的字母
2. 如果沒猜過,記錄下來
3. 如果有猜對,寫進答案區
4. 反之如果猜過,提醒玩家
5. 如果輸入錯誤,提醒玩家
重複直到遊戲結束
----
```python=
user_letter = input('Type sth : ') # 1.
if user_letter in alphabet - used_letters: # 2.
used_letters.add(user_letter)
if user_letter in word_letters: # 3.
word_letters.remove(user_letter)
elif user_letter in used_letters: # 4.
print('猜過了')
else: # 5.
print('輸入錯誤,再輸入一遍')
```
----
每次輸入之前要讓玩家知道現在答案的長相 & 猜過哪些字母
``'-'.join(['A', 'B', 'C'])``:把該list/set的內容用左邊的東西隔開顯示 → A-B-C
```python=
print('You have used the letters :', ' '.join(used_letters))
# 偵測現在單字裡的字母被猜了幾種,猜過就顯示,沒猜過就用 - 代替
word_list = [letter if letter in used_letters else '-' for letter in word]
print('Current word: ', ' '.join(word_list))
```
----
遊戲終止條件有兩個:
1. 答案被猜出來
2. 生命用完
我們先解決第一項,用迴圈即可
```python=
while len(word_letters) > 0 : #還沒猜完
... #剛剛寫的東西們
```
----
三、引入生命機制
傳統Hangman中,每猜錯一次就會畫一筆
這邊我們不畫圖,改用生命值取代,每猜錯一次扣一點,從6點開始扣
```python=
lives = 6 # 跟剛剛的資料寫在一起
#修改以下code
# 1.
while len(word_letters) > 0 and lives > 0:
# 2.
print('You have', lives, 'lives and you have used these letters:', ' '.join(used_letters))
# 3.
if user_letter in alphabet - used_letters:
used_letters.add(user_letter)
if user_letter in word_letters:
word_letters.remove(user_letter)
else: #猜錯扣點
lives = lives - 1
print('猜錯了!')
```
----
跳出迴圈代表猜完OR沒命了
這時候要判斷情況
```python=
if lives == 0: # 沒命,涼去
print('GG. Try again.')
else: #還有命,代表猜完了,歐耶!
print(f'Congratulations! You have guess the word {word}!')
```
---
完整code
沒寫完先不要看
----
```python=
'''
Process:
1. Set get_valid_word
2. Set up used_letters, alphabet, word, word_letters
3. Test type sth and can it show the used_letters
4. put everything in the while loop
5. Show word list
6. Put 'lives' into the game
'''
import random
import string
# You can add any words you like
# Or from this place : 'https://www.randomlists.com/data/words.json'
words = ["alike","basic","abandon","embarrassed","alert","circumstance","aim","object","fundamental","Physics","unusual","aboard","original","attractive","research","expression","abrupt","absent","absorbed","absorbing","abstracted","absurd","abundant","massive","accept","acceptable","accessible","accidental","account","accuracy"]
def get_valid_word(words):
word = random.choice(words) #random;y chooses sth from that list
while '-' in word or ' ' in word:
word = random.choice(word)
return word.upper()
def hangman():
word = get_valid_word(words)
word_letters = set(word) #letters in the word
alphabet = set(string.ascii_uppercase) # {'B', 'J', 'H', 'P', 'F', 'U', 'S', 'C', 'X', 'Q', 'G', 'I', 'N', 'V', 'T', 'A', 'K', 'R', 'Z', 'M', 'L', 'D', 'E', 'W', 'Y', 'O'}
used_letters = set() #what the user has guessed
lives = 6
# getting user input
while len(word_letters) > 0 and lives > 0:
#letters used
print('You have ', lives, 'lives left and you have used these letters: ', ' '.join(used_letters))
# What current word is (ex. W - R D)
word_list = [letter if letter in used_letters else '-' for letter in word]
print('Current word: ', ' '.join(word_list))
user_letter = input('Type something : ').upper()
#Detect if the user_letter is used or not
if user_letter in alphabet - used_letters:
used_letters.add(user_letter)
# If the letter is one of the letters we need, remove it from the word_letters(means it's being picked)
if user_letter in word_letters:
word_letters.remove(user_letter)
else:
lives = lives - 1 # take away a life if wrong
print('Letter is not in words.')
# 2. If it's already guessed, report.
elif user_letter in used_letters:
print('You have already used that character. Please try again.')
# 3. If it's not the thing in our game, report.
else:
print('Invalid character. Please try again.')
# gets here when len(word_letters) == 0 OR when lives == 0
if lives == 0:
print(f'Sorry, you died. The word is {word}.')
else:
print(f'Congratulation! You have guess the word {word}!')
if __name__ == '__main__':
hangman()
```
{"metaMigratedAt":"2023-06-16T22:40:44.923Z","metaMigratedFrom":"YAML","title":"Python實作二:Hangman劊子手","breaks":true,"slideOptions":"{\"transition\":\"slide\",\"theme\":null}","contributors":"[{\"id\":\"4f731eff-9d88-41f4-af56-2e3e02f20cfc\",\"add\":5819,\"del\":83}]"}