20211315鄒雪梅《Python程式設計》實驗四報告
《Python程式設計》實驗四報告
課程:《Python程式設計》
班級:2113
姓名:鄒雪梅
學號:20211315
實驗教師:王志強
實驗日期:2022年5月21日
必修/選修:公選課
一、實驗要求
Python綜合應用:爬蟲、資料處理、視覺化、機器學習、神經網路、遊戲、網路安全等。
課代表和各小組負責人收集作業(原始碼、視訊、綜合實踐報告)
注:在華為ECS伺服器(OpenOuler系統)和物理機(Windows/Linux系統)上使用VIM、PDB、IDLE、Pycharm等工具程式設計實現。
批閱:注意本次實驗不算做實驗總分,前三個實驗每個實驗10分,累計30分。本次實踐算入綜合實踐,打分為25分。
評分標準:
(1)程式能執行,功能豐富。(需求提交原始碼,並建議錄製程式執行的視訊)10分
(2)綜合實踐報告,要體現實驗分析、設計、實現過程、結果等資訊,格式規範,邏輯清晰,結構合理。10分。
(3)在實踐報告中,需要對全課進行總結,並寫課程感想體會、意見和建議等。5分
二、實驗內容
之前用pygame實現過俄羅斯方塊小遊戲,所以這次沒有用pygame,但是看到pygame可以加音效和開始動畫等,之後可能還會在假期等時間充足的時候用pygame做遊戲。本次實驗通過Python實現21點小遊戲,匯出為EXE小程式,上傳華為雲執行,程式碼上傳碼雲
三、實驗分析、設計、實現過程、結果
1.遊戲規則
首先要了解21點小遊戲的遊戲規則:
點數計算:每張牌都有點數。2 到 10 的牌的點數就是其牌面的數字,J、Q、K的點數是 10.
A有兩種演算法: 1 或者 11, 如果 A 算為 11 時總和大於 21,則 A 算為 1. 例如 (A, 8)是 19 點, (A,7,J)則為 18 點
爆牌:玩家手中牌的總點數超過 21 點
停牌:玩家不再要牌, 等待其他玩家操作
要牌:玩家根據自己手上的點數決定是否要牌, 如果要牌, 則系統再發一張牌給玩家. 如果要牌後總點數超過 21, 則算爆牌,玩家輸掉本輪遊戲;若要牌後點數為 21點, 則不能再要。如果要牌後總點數不到 21 點, 則玩家可以繼續 “要牌” “停牌”
莊家持牌總點數少於 17,則必須要牌,直到超過 16,如果莊家的總點數等於或多於 17 點,則必須停牌
如果莊家手中有 A,且 A 作 11 點時大於 16點,作 1 點時小於或等於 16 點, 則由莊家自己選擇是否要牌
注意:遊戲開始後,玩家和莊家各發兩張牌,莊家的第二張牌對外不可見。
2.原始碼
基於以上的規則,使用 Python 實現一個簡單的 21 點遊戲,該遊戲只有玩家和電腦兩個玩家,玩家通過命令列的方式輸入命令,決定是否要牌或停牌,電腦玩家要牌或停牌由程式自動控制。程式碼如下:
import random # 匯入隨機包
# 模擬要牌, 從卡牌列表中隨機選擇一張卡牌
import time
def my_random_choose():
card = random.choice(cards) # 從卡牌列表中隨機選取一張牌
flag = card[0] # flag 存放卡牌的標記
value = card[-1] # value 存放卡牌的字串型別的值
if value == 'A': # 如果卡牌為 A
return flag, value, 1 # 暫時給它的值賦為 1
elif value == '0':
return flag, '10', 10 # 卡牌為 10
elif value == 'J' or value == 'Q' or value == 'K':
return flag, value, 10 # 卡牌為 J, Q, K 的當作 10
else:
return flag, value, int(value) # 其他卡牌, 按照卡牌上的數字計算即可
# 詢問玩家是否繼續要牌, 獲取玩家選擇
def get_Input():
Input = input('是否繼續要牌(Y|N):')
while Input != 'Y' and Input != 'N': # 強制要求只能輸入 Y 或者 N, 其他輸入一律重新輸入
Input = input('是否繼續要牌(Y|N):')
return Input
# 玩家要牌
def player_hit():
# 開始遊戲,隨機發給玩家兩張卡牌
flag1, value1, num1 = my_random_choose()
flag2, value2, num2 = my_random_choose()
player_cards = [] # 玩家卡牌列表,存放玩家要的所有牌, 存放的是 flag 和 value
# 如果第一張卡牌為 A, 則賦值為 11
if num1 == 1:
num1 = 11 # 卡牌數值為 11
elif num1 != 1 and num2 == 1: # 如果第一張卡牌不為 A, 但是第二張卡牌為 A
num2 = 11 # 卡牌數值為 11
player_total = num1 + num2 # 計算當前玩家手中卡牌總點數
# 將初始發的兩張卡牌放到玩家卡牌列表中, 存放的是字串, 所以不參與計算, 只是用於輸出卡牌擁有情況
player_cards.append([flag1, value1])
player_cards.append([flag2, value2])
print('玩家手中的牌是:', [flag1, value1], [flag2, value2])
if player_total == 21: # 玩家當前點數為 21 點
# 玩家贏了
return player_total # 返回玩家點數
else: # 玩家當前點數不為 21 點
Input = get_Input() # 詢問玩家是否要繼續要牌
while Input == 'Y' or Input == 'N':
if Input == 'Y': # 玩家繼續要牌
flag, value, num = my_random_choose() # 隨機抽一張卡牌給玩家
if num == 1 and (player_total + 11 <= 21): # 如果抽到了 A, 將 A 看成 11, 看一下此時手中卡牌總點數是否大於 21
num = 11 # 如果不大於 21, 可以將當前 A 賦值為 11
player_cards.append([flag, value]) # 將抽到的卡牌放到玩家卡牌列表中
print('玩家手中的牌是:', player_cards) # 輸出當前擁有的卡牌
player_total += num # 計算玩家當前擁有的卡牌的總點數
if player_total > 21: # 如果玩家當前擁有的卡牌總點數大於 21
return player_total # 玩家爆牌, 返回 玩家卡牌總點數, 結束函式執行
elif Input == 'N': # 玩家不要牌
return player_total # 返回玩家當前卡牌總點數, 結束函式執行, 讓莊家要牌
Input = get_Input() # 玩家之前要了牌, 但是牌的總點數小於 21, 詢問玩家是否繼續要牌
# 莊家要牌
def dealer_hit(num1, dealer_cards):
DEALER_MIN_SCORE = 17 # 莊家手中的牌的總點數的最小值為 17, 如果小於 17, 莊家必須要牌
flag2, value2, num2 = my_random_choose() # 為莊家隨機選擇一張卡牌
if num1 != 11 and num2 == 1: # 莊家的第一張牌不是 A, 但是第二張卡牌是 A
num2 = 11 # 給第二張卡牌賦值為 11
dealer_cards.append([flag2, value2]) # 將莊家的第二張卡牌放到莊家卡牌列表中, 用於之後輸出擁有卡牌情況
dealer_total = num1 + num2
# 當莊家手中牌的總點數小於 17, 必須要牌,
while dealer_total < DEALER_MIN_SCORE:
flag, value, num = my_random_choose()
if num == 1 and (dealer_total + 11 <= 21):
num = 11
dealer_cards.append([flag, value])
print('莊家得到一張牌, 莊家手中的牌是: ', dealer_cards)
dealer_total += num
# 莊家手中的牌的總點數大於等於17, 必須停牌, 即返回總點數
return dealer_total
# 決定贏家
def vs(player_total, dealer_total):
if player_total > 21: # 如果玩家爆牌
# 玩家輸
print('莊家點數為 ', dealer_total, ', 玩家點數為 ', player_total, ', 莊家贏了!')
return 1, 0 # 分別返回莊家和玩家的比分
else:
if dealer_total > 21: # 莊家爆牌
print(' 莊家點數為 ', dealer_total, ', 玩家點數為 ', player_total, ', 玩家贏了!')
return 0, 1
else:
if player_total == dealer_total: # 平局
print(' 莊家點數為 ', dealer_total, ', 玩家點數為 ', player_total, ', 平局!')
return 1, 1
elif player_total > dealer_total: # 都沒有爆牌,但是玩家的卡牌總點數大於莊家卡牌總點數
# 玩家贏
print(' 莊家點數為 ', dealer_total, ', 玩家點數為 ', player_total, ', 玩家贏了!')
return 0, 1
else:
# 莊家贏
print(' 莊家點數為 ', dealer_total, ', 玩家點數為 ', player_total, ', 莊家贏了!')
return 1, 0
def start_21_game():
player_score = 0 # 玩家得分
dealer_score = 0 # 莊家得分
Input = 'Y'
round_count = 0 # 比賽的輪數
while Input == 'Y':
round_count += 1
print(f'第{round_count}輪比賽開始:')
flag1, value1, num1 = my_random_choose() # 從卡牌列表中隨機選擇一個卡牌
if num1 == 1: # 卡牌為 A
num1 = 11 # 因為只有一個卡牌,所以不會爆牌,賦值為 11
dealer_cards = [] # 莊家擁有的卡牌列表
dealer_cards.append([flag1, value1]) # 將抽到的卡牌放到莊家卡牌列表中
print('莊家手中的牌是: ', [flag1, value1], '?')
player_total = player_hit() # 呼叫玩家要牌函式, 返回值是玩家此時的卡牌總點數
dealer_total = dealer_hit(num1, dealer_cards) # 呼叫莊家要牌函式, 返回值是莊家此時的卡牌總點數
dealer_point, player_point = vs(player_total, dealer_total) # 根據玩家和莊家的卡牌總點數判斷贏家是誰, 返回值分別是莊家和贏家當局的比分
print('------------------------------')
player_score += player_point # 將玩家當局的得分加到玩家總得分上
dealer_score += dealer_point # 將莊家當局的得分加到莊家總得分上
Input = input('是否進行下一局 [Y|N]:')
while Input != 'Y' and Input != 'N':
print('請輸入 Y or N.', end='')
Input = input('請重新輸入 [Y|N]:')
return player_score, dealer_score
if __name__ == '__main__':
# 定義一個存放卡牌的列表
cards = ['♠A', '♠2', '♠3', '♠4', '♠5', '♠6', '♠7', '♠8', '♠9', '♠10', '♠J', '♠Q', '♠K',
'♣A', '♣2', '♣3', '♣4', '♣5', '♣6', '♣7', '♣8', '♣9', '♣10', '♣J', '♣Q', '♣K',
'♦A', '♦2', '♦3', '♦4', '♦5', '♦6', '♦7', '♦8', '♦9', '♦10', '♦J', '♦Q', '♦K']
# play_score 記錄玩家的得分, dealer_score 記錄莊家的得分
player_score, dealer_score = start_21_game()
print(f'玩家, 莊家總比分為:{player_score}:{dealer_score}')
if player_score > dealer_score:
print('玩家勝出')
elif player_score < dealer_score:
print('莊家勝出')
else:
print('平局')
print('遊戲結束')
print('10秒後自動關閉視窗')
time.sleep(10)
其中10s自動關閉、可重複多局遊戲、記錄遊戲得分等我自認為還是不錯的小功能(嘿嘿)
3.執行結果
(參考老師發的連結打包生成了EXE小程式)
pycharm執行
小程式執行
華為雲執行
三、程式碼上傳到碼雲
四、實驗過程中遇到的問題
問題1:華為雲執行錯誤
解決方案:詢問同學,並檢測Python位置版本,以Python形式執行(之前錯用了C語言的執行方式)
問題2:在程式編寫過程中,沒加一個功能幾乎就要錯一次
解決方案:去CSDN找大佬的部落格和經驗
五、全課總結,課程感想體會、意見和建議
1.全課總結
之前通過《看漫畫學Python》自學了一下Python但是學的並不系統也沒有深入。
學期初抱著多學習學習知識的心態,報名了python選修課。一學期下來果然沒有失望,課程進度飛快,感觸頗深。
python語言特點:
簡單:Python是一種代表簡單思想的語言。
易學:Python有極其簡單的語法。
免費、開源:Python是FLOSS(自由/開放原始碼軟體)之一。
高層語言:使用Python編寫程式時無需考慮如何管理程式使用的記憶體一類的底層細節。
可移植性:Python已被移植到很多平臺
解釋性:可以直接從原始碼執行。在計算機內部,python直譯器把原始碼轉換為位元組碼的中間形式,然後再把它翻譯成計算機使用的機器語言。
面向物件:python既支援面向過程程式設計也支援面向物件程式設計。
可擴充套件性:部分程式可以使用其他語言編寫,如c/c++。
可嵌入型:可以把Python嵌入到c/c++程式中,從而提供指令碼功能。
豐富的庫:Python標準庫確實很龐大。它可以幫助你處理各種工作,包括正則表示式、文件生成、單元測試、執行緒、資料庫、網頁瀏覽器、CGI、FTP、電子郵件、XML、XML-RPC、HTML、WAV檔案、密碼系統、GUI(圖形使用者介面)、Tk和其他與系統有關的操作
本學期學習的主要知識點:
變數賦值及其命名規則
運算子及其優先順序
基本資料型別
迴圈語句
列表、元組、字典、集合及其常用功能
字串與正則表示式
函式
面向物件程式設計
檔案操作及異常處理
Python操作資料庫
Python網路程式設計及爬蟲開發(Socket)
2.課程感想體會
(1)光聽不練假把式,多多實踐比只是聽課有用的多
(2)學會查詢相關資料,學會把運用別解決類似問題的方法解決自己的問題
(3)學習不能有怠惰心理,要持之以恆的努力
一個學期的學習感覺自己在Python或者說整個程式語言、計算機知識都收穫很多,之前通過自學不完整不繫統的知識都串聯起來了,而且通過老師幾次作業也真正會運用Python了,在一次次嘗試中也提高了自己解決問題的能力......總之感覺這門課“太值了”以後有學弟學妹問一定傾力推薦(手動狗頭)
3.意見和建議
上課同時看投影和跟著打程式碼會跟不上,投影的顯示還是不太清晰的(有時候會跟同學一起,她手機進入騰訊會議然後我們跟著騰訊會議的程式碼打,哈哈)
老師上課時候對於雲班課上Word課件的改動和一起編寫的小程式也建議分享一下,讓我們不至於因為沒跟上二“錯過就遺憾終身”
六參考資料
基本都是CSDN上大佬的部落格,因為太多和時間跨度大約有一個周,就不一一列舉了