3.6 猜数字游戏
這個練習是個小游戲,很經典,通常非常適合計算機語言學習中的控制語句入門。
游戲規則為:首先系統自動產生一個1到100之間的隨機整數,允許用戶通過輸入多次猜測,并每次都進行大小提醒,直至猜中為止。
編程其實就是要告訴計算機該怎么處理這個邏輯,因此首先需要自己對這個游戲的流程處理做出一個清晰的描述,我們不妨以偽代碼的方式來給出一個步驟:
設置一個隨機數
輸入猜數
如果猜數大了,輸出大了
如果猜數小了,輸出小了
如果猜數相等,輸出成功,并退出
...
顯然如果用戶沒有猜中,還需要繼續輸入猜數,因此可能的步驟為:
設置一個隨機數
輸入猜數
如果猜數大了,輸出大了
如果猜數小了,輸出小了
如果猜數相等,輸出成功,并退出
輸入猜數
如果猜數大了,輸出大了
如果猜數小了,輸出小了
如果猜數相等,輸出成功,并退出
輸入猜數
如果猜數大了,輸出大了
如果猜數小了,輸出小了
如果猜數相等,輸出成功,并退出
...
顯然這是個循環問題,循環的內容就是輸入猜數到三種不同的判斷,但是循環的次數并不能確定,它只能依賴用戶是否猜中,只有沒猜中才需要繼續循環,因此完整的步驟應該為:
設置一個隨機數
循環(不固定次數的循環)
? ? 輸入猜數
?? ?如果猜數大了,輸出大了
?? ?如果猜數小了,輸出小了
?? ?如果猜數相等,輸出成功,并退出
有前面學習的經驗,就會看出來這個循環應該是while,里面的如果就是if。這些并不十分難做。不過,如何得到一個隨機數呢?
但凡遇到此類問題,可以想象,Python一定提供了相應的方法,而無需我們自己來做(其實真正實現一個隨機數并不容易)。利用互聯網搜索也可以很快了解到,比如利用random模塊:
import random print(random.randint(1, 6))每次運行,都會輸出一個1到6(含1和6)的隨機整數。random字面就是隨機的意思,randint函數字面就是隨機整數的意思。
按照剛才的偽代碼,對應著,代碼可以寫為:
可以復制的代碼為:
import random randNum = random.randint(1, 100) while True: num = int(input()) if num < randNum: print('小了')elif num > randNum: print('大了')else:print('猜中') break這個循環采取了一個較為簡單的實現方法,就是始終為真,只要猜中就退出,從而可以結束循環。?
大家試一試,如何能更快的猜中呢?隨便猜?從1到100挨個猜?折半猜(比如首先猜50,如果提示大了,就輸入25,如果又提示小了,就再輸入37,等等)。大家可以自己來判斷下哪一種方法更為合理。
語句的次序很重要,有人寫成這個樣子,將輸入猜數和判斷猜數交換了位置:
import random randNum = random.randint(1, 100) while True: if num < randNum: print('小了')elif num > randNum: print('大了')else:print('猜中') breaknum = int(input())運行界面為:
顯然,由于在第四行進行num和randNum大小判斷時,由于還沒有num的數值,因此出現了num沒有定義的常見錯誤。當然,不是說,這個輸入猜數和判斷猜數就一定不能交換位置,也可以通過下面的方法來解決:
import random randNum = random.randint(1, 100) num = int(input()) while True:if num < randNum:print('小了')elif num > randNum:print('大了')else:print('猜中')breaknum = int(input())這里在第三行、循環語句的前面增加了一個輸入猜數的語句,雖然重復寫了兩次輸入猜數的語句,但是也可以實現相同的目的。
不過,既然循環就已經知道了輸入的猜數,那么為什么還使用True來控制循環條件呢?這里其實展示了一種新的思路,即將用戶輸入不等于隨機數作為循環條件:
import randomrandNum = random.randint(1, 100) num = int(input()) while num != randNum:if num < randNum:print('小了')else:print('大了')num = int(input()) print('猜中')注意一點,由于在循環里面,是不可能實現兩個數值相等的,因此就無需在循環內判斷是否相同并輸出“猜中”,相反,結束循環即表示猜中了,因此在循環后可以表達“猜中”的輸出。
當然,為了防止以后不小心在循環結束后和輸出“猜中”前增加其他代碼,還可以使用else來強制循環一結束即可運行輸出“猜中”的代碼:
import randomrandNum = random.randint(1, 100) num = int(input()) while num != randNum:if num < randNum:print('小了')else:print('大了')num = int(input()) else:print('猜中')我們還是回到最先的版本上來:
import random randNum = random.randint(1, 100) while True: num = int(input()) if num < randNum: print('小了')elif num > randNum: print('大了')else:print('猜中') break接下來,我們準備將問題稍微復雜一些,其實我們在輸入猜數的時候,很容易因為輸入不合規導致代碼運行失敗,比如輸入小數、字符(如abcd)或者什么都不輸入直接回車,大家都會發現代碼運行出錯了:
或者輸入-1,似乎代碼也能運行,但是不應該允許用戶輸入小于1或者大于100的數:
因此,良好的代碼應該能判斷下輸入的內容是否合規。我們一個一個來,先處理-1和101的問題:
import randomrandNum = random.randint(1, 100) while True:num = int(input())if num >= 1 and num <= 100:if num < randNum:print('小了')elif num > randNum:print('大了')else:print('猜中')breakelse:print('請輸入1到100的整數!')這個處理比較簡答,就是在現有的大小判斷外,再增加一個猜數數值的范圍判斷,只有在范圍之內的再去考慮大小判斷。
關于如何判斷是否輸入的數字,不妨搜索下:
很多初學者對于這種邊搜索邊學習的方法感到困惑,覺得應該全部學習好后,才能編程。其實,對于編程,在學習完基本知識后,通過邊上機邊搜索的方法,學習非常快,也是很多人的方法。
這里很快就能知道一種常見的函數isdigit,在剛才代碼判斷數值范圍的外面再增加一個是否為數字的判斷:
import randomrandNum = random.randint(1, 100) while True:num = input()if num.isdigit():num = int(num)if num >= 1 and num <= 100:if num < randNum:print('小了')elif num > randNum:print('大了')else:print('猜中')breakelse:print('請輸入1到100的整數!')else:print('請輸入正確的整數!')但是,對于這種輸入數值的判斷,isdigit函數還是有點簡單,比如你會發現當你輸入-1時,它居然出現和輸入非數字一樣的提示(正確的提示應該是“請輸入1到100的整數!”):?
原因只能說明-1在遇到isdigit函數判斷時就被認為不是數字,因為負號它認為不是數字!這不是我們的問題,而是isdigit函數過于簡單造成的。當然我們可以去查找或者自己設計一些更為強大的判斷數字函數來替換isdigit,這些留給大家來完成。
不過,更為強大的方法考慮使用異常處理:
import randomrandNum = random.randint(1, 100) while True:num = input()try:num = int(num)if num >= 1 and num <= 100:if num < randNum:print('小了')elif num > randNum:print('大了')else:print('猜中')breakelse:print('請輸入1到100的整數!')except ValueError:print('請輸入正確的整數!')這個不做要求,對于部分有興趣的同學可以關注下。這個代碼后期在學習完異常處理后,你會發現它非常簡單高效!
配套學習資源、慕課視頻:
Python大數據分析-李樹青https://www.njcie.com/python/
總結
- 上一篇: kalilinux安装中文输入法 安装f
- 下一篇: 国标中不能用作公差基准字母