本課程設計是本專業的一門重要實踐性教學環節。在學習了專業基礎課和《Python程序設計》課程的基礎上,本課程設計旨在加深對Python程序設計的認識,對Python語言及其語言生態有一個進一步的掌握和應用,學會運用Python標准庫及外接相關庫來解決實際問題的基本能力,培養和提高學生分析問題、解決問題的能力,尤其是提高學生使用Python為開發語言來進行問題描述、交流與思考的能力,為畢業設計和以後的工程實踐打下良好的基礎。
經過小組討論分析,我們最終選擇了“五子棋”作為本次課設主題。
五子棋起源於中國上古時期的傳統黑白棋種之一。主要流行於華人和漢字文化圈的國家以及歐美一些地區,是世界上最古老的棋。古代五子棋棋盤與圍棋棋盤是通用的,直到1931年,才出現所謂五子棋專用棋盤,為十五路(15×15)棋盤。現在人們壓力日益增大,需要勞逸結合才能獲得更高的工作效率,工作之余的娛樂對於每一個人來說必不可少。五子棋這種娛樂方式容易上手,老少皆宜,而且趣味橫生,引人入勝;不僅能增強思維能力,提高智力,而且富含哲理,有助於修身養性。
本次課程設計的主要任務是以Python為開發語言完成一個100~300行左右規模的程序項目開發。
課程設計的基本要求是:在課程設計的各個階段嚴格、規范地完成相關的文檔,例如在初期按時完成設計目的、設計要求、總體設計,在後期完成詳細設計、調試與測試、設計總結等。要求能完成所選題目的主要功能,程序運行健壯、正確,代碼要有詳細注釋,可讀性好;所寫文檔結構合理、內容完整、敘述清晰。更高要求是:有創意、系統界面美觀。
由於課程設計項目具有一定的綜合性,鼓勵具有不同特長和不同能力的學生互相組隊。項目小組自己推薦一名組長,實行“組長負責制”。組長組織組員進行項目選題、任務分配、方案確定、方案設計、系統調試測試,組員分工協作。小組成員開展項目討論,互相支持,形成協作意識。
有圖形界面,能夠用鼠標進行操作。
能夠進行五子棋游戲的基本操作,即玩家輪流落子。
能夠對游戲結果進行正確的判定。
能夠實現悔棋及認輸等附加功能。
各項功能的展示與應用直觀明了。
輸出必要的提示信息讓玩家更好地進行游戲。
基於Python的標准GUI庫tkinter快速創建GUI應用程序。
運行程序提示可開始游戲。人人對戰,二人輪流落子。界面顯示提示信息當點輪到哪一方落子。先有五子“—”或“|”或“/”或“\”連成一線的玩家獲勝。若棋盤中棋子已滿,玩家均為完成五子相連則判定為平局。當黑方獲勝或白方獲勝或平局時及時作出判定,並彈出提示框,告知玩家當前對局結束。
組員:吳佳麗余葉钰劉璐瑤
任務分配:
:負責玩家操作模塊設計,包括落子、悔棋及認輸。
:負責游戲的可視化設計,包括游戲界面設計及棋盤設計。
棋盤設計部分包括運行程序開始游戲及重新開局時初始化棋盤。
:負責判定游戲結果即玩家勝負或平局判定
啟動程序運行游戲,彈出提示框,提示玩家游戲開始,黑方先進行落子。玩家可點擊棋盤無棋子處進行落子。或點擊“開局”、“悔棋”、“認輸”按鈕可重新開局或悔棋或認輸。當點擊“開局/重新開局”按鈕時,清空棋盤中的棋子,展示處與啟動程序相同的游戲界面。界面中間“黑方”與“落子”二處文字為游戲進行中的提示信息,表示當前輪到黑方進行棋子放置。輪到白方落子時會“黑方”將自動更改為“白方”,“白方”二字以白色顯示。如圖4-1所示。
如圖4-2所示,若有一方玩家存在“—”或“|”或“/”或“\”五子相連,該玩家取得該局游戲勝利。以圖中所示情況——黑方“/”五子相連為例,說明玩家取勝結果。通過黃色線條將黑方連成一線的五顆棋子相連接,此時界面中間提示信息改為“黑方獲勝”,“獲勝”二字以紅色顯示。並彈出消息提示框,提示玩家游戲結束黑方完成五子相連,取得勝利。若此時點擊悔棋按鈕,將提示玩家此時不能悔棋。如圖4-3所示;點擊認輸按鈕,將提示玩家點擊開局開始游戲,如圖4-4所示。
當玩家雙方都沒有完成五子連線,且棋盤中所有棋格都有棋子放置即無處置放棋子時,判定為平局。
為更方便展示,將棋盤改為5*5大小。如圖4-5所示,中間提示文字變更為綠色字樣“平局??!”,同時彈出消息提示框,提示玩家當前對局結束,雙方達成平局。此時游戲結束,玩家不可再悔棋或認輸,若玩家點擊悔棋或認輸按鈕,效果與有一方玩家獲勝時相同。即游戲界面不做改變,彈出消息提示框,該消息提示框與圖4-3、圖4-4中消息提示框相同,不再重復展示。
在一局游戲過程中,若玩家首次點擊認輸按鈕。棋盤不做改變,游戲界面中間文字“落子”變為“認輸”如圖4-6所示。此時游戲結束,玩家不可再悔棋或認輸,若玩家點擊悔棋或認輸按鈕,效果與有一方玩家獲勝時相同。即游戲界面不做改變,彈出消息提示框,該消息提示框與圖4-3、圖4-4中消息提示框相同,不再重復展示。
游戲過程中,若一個回合內該玩家首次進行悔棋,取回該玩家剛放置到棋盤上的棋子,並將中間的提示信息“某方落子”改回到該玩家。以黑方悔棋為例,悔棋前及悔棋後游戲部分界面分別如圖4-7、圖4-8所示。若該玩家在一個回合內已經進行過悔棋操作,再次點擊悔棋按鈕,則不改變游戲界面及棋盤,但回彈出提示框此時不能悔棋,該消息提示框及提示信息與獲勝時點擊悔棋按鈕,即圖4-4中的提示框相同。
窗體界面直觀明了,游戲過程中有適當的提示信息有助於玩家更好的進行游戲。同時窗體的顏色搭配即窗體大小設置合適。玩家不會因游戲界面顏色沖擊或棋盤、文字信息等過大過小產生疲勞。程序能對游戲結果進行正確的判定,悔棋及認輸這兩個附加功能也能夠實現。課程設計最初定下的功能和要求均能實現。在此基礎上,玩家完成五子相連時用黃色線條標記,讓玩家能有更好的體驗。還加上了一個回合內只允許玩家各悔棋一次,增加挑戰,讓游戲更加有趣。
小組超額完成了最初想要實現的功能和要求,所以我們給自己評價為優秀!
當然這個小程序也很多不足之處。例如沒有標記出最後放置的棋子,玩家悔棋後也沒有標記出悔棋前的棋子等等。我們往後也應努力學習,做的更好。
所負責部分大致可分為三大模塊。首先,判斷游戲勝負的四種情況,即橫、豎、斜方向五子一線;其次,判斷棋盤是否可以繼續下棋,即是否平局;最後,判斷玩家輸贏,並彈出提示框。
from tkinter import*
from tkinter import messagebox
Tkinter庫:
Tkinter是Python 的標准 GUI 庫。Python 使用 Tkinter 可以快速的創建 GUI 應用程序。由於 Tkinter 是內置到 python 的安裝包中、只要安裝好 Python 之後就能 import Tkinter 庫、而且 IDLE 也是用 Tkinter 編寫而成、簡單的圖形界面可以由Tkinter 庫完成。
Messagebox 函數分析:
函數定義:<整型> MessageBox(<字符串> Text, <字符串> Title, <整型> nType);
函數功能: 彈出一個消息框。
參數:
Text <字符串>,消息框的正文;
Title <字符串>,消息框的標題;
nType <整型>,消息框的類型。
返回值:<整型>,用戶在消息框上點擊關閉時的選擇的按鈕。
說明:
nType對應的對話框如下表所示:
0: 確定
1: 確定,取消
2: 終止,重試,忽略
3: 是,否,取消
4: 是,否
5: 重試,取消
6: 取消,再試一次,繼續
返回值對應的值如下:
1: 確定
2: 取消
3: 終止
4: 重試
5: 忽略
6: 是
7: 否
:再試一次
自定義panduan()函數並利用for語句循環,判斷棋子是否為橫、豎、斜五子連線,列表QP[a][b]中必須滿足 0 <= a,b <= 17,i、j必須嚴格控制。若有五子連線情況發生,在棋子上增加一條黃色標記線貫穿五子,更易看出。
代碼如下:
def panduan():
iswin = 0 #標記是否有一方完成五子相連,0代表否
for i in range (num-4):
for j in range (num): #判斷是否出現有一方"—"五子相連
If QP[i][j]==QP[i+1][j]==QP[i+2][j]==QP[i+3][j]==QP[i+4][j] != -1:
iswin=1 canvas.create_line(mesh*(i+1)-Qr/2,mesh*(j+1),mesh*(i+5)+Qr/2,mesh*(j+1),fill="yellow")
win()
for i in range (num):
for j in range (num-4): #判斷是否出現有一方"|"五子相連
if QP[i][j]==QP[i][j+1]==QP[i][j+2]==QP[i][j+3]==QP[i][j+4] != -1:
iswin=1 canvas.create_line(mesh*(i+1),mesh*(j+1)-Qr/2,mesh*(i+1),mesh*(j+5)+Qr/2,fill="yellow")
win()
for i in range (num-4):
for j in range (num-4): #判斷是否出現有一方"\"五子相連 if QP[i][j]==QP[i+1][j+1]==QP[i+2][j+2]==QP[i+3][j+3]==QP[i+4][j+4] != -1:
iswin = 1
canvas.create_line(mesh*(i+1)-Qr/2,mesh*(j+1)-Qr/2,mesh*(i+5)+Qr/2,mesh*(j+5)+Qr/2,fill="yellow")
win()
for i in range (num-4):
for j in range (4,num): #判斷是否出現有一方"/"五子相連
if QP[i][j]==QP[i+1][j-1]==QP[i+2][j-2]==QP[i+3][j-3]==QP[i+4][j-4] != -1:
iswin=1 canvas.create_line(mesh*(i+1)-Qr/2,mesh*(j+1)+Qr/2,mesh*(i+5)+Qr/2,mesh*(j-3)-Qr/2,fill="yellow")
win()
函數及語句分析:
for循環:
作用:for循環語句是python中的一個循環控制語句,任何有序的序列對象內的元素都可以遍歷,比如字符串、列表、元組等可迭代對像。
一般格式:第一行是要先定義一個賦值目標(迭代變量),和要遍歷(迭代)的對像;首行後面是要執行的語句塊。
for 目標 in 對像:
print賦值目標
循環過程: i相當於目標,range(num)是遍歷對像。當運行for循環語句時,每一次迭代時,i都會從遍歷對像range(num)中接收一個新值輸出。結束循環後,目標i會保留最後一個值
Canvas組件:
Python Tkinter 畫布(Canvas)組件和 html5 中的畫布一樣,都是用來繪圖的。可以將圖形、文本、小部件或框架放置在畫布上。canvas.create_line()主要實現的是畫一條直線,後面()
中給的參數就是線段兩點的坐標,兩點確定一條直線。
Canvas 組件支持以下標准選項:
arc 創建一個扇形
coord = 10, 50, 240, 210
arc = canvas.create_arc(coord, start=0, extent=150, fill="blue")
image 創建圖像
filename = PhotoImage(file = "sunshine.gif")
image = canvas.create_image(50, 50, anchor=NE, image=filename)
line 創建線條
line = canvas.create_line(x0, y0, x1, y1, ..., xn, yn, options)
oval 創建一個圓
oval = canvas.create_oval(x0, y0, x1, y1, options)
polygon 創建一個至少有三個頂點的多邊形
oval = canvas.create_polygon(x0, y0, x1, y1,…xn, yn, options)
分析:定義一個列表boring記錄每個棋格的狀態,包括棋格是否有棋子,若有棋子是為黑棋還是白棋。For循環語句遍歷棋盤(列表QP[a][b]中必須滿足 0 <= a,b <= 17,i、j必須嚴格控制),當棋盤中不存在無棋子的棋格且雙方均未完成五子連線,判定為平局並彈出提示框。
代碼如下:
boring=[] #遍歷棋盤,記錄每個棋格狀態
for i in range(num):
for j in range(num):
boring.append(QP[i][j])
if -1 not in boring and iswin != 1:
print(messagebox.askokcancel('游戲結束','旗鼓相當!平局!'))
append()函數
描述:append() 方法用於在列表末尾添加新的對象。
用法: list.append(obj) obj為添加到列表末尾的對象
返回值:該方法無返回值,但是會修改原來的列表。
本例應用:
boring.append(QP[i][j])
作用是將最新遍歷的棋格狀態添加到boring列表最後。
輸出分析
輸出提示框,顯示游戲結束,旗鼓相當!平局!
print(messagebox.askokcancel('游戲結束','旗鼓相當!平局!')
函數分析:
messagebox.askokcancel()是tkinter庫中的一個組件,用來設置一個消息框。
askokcancel()設置對話框的主要文本內容,可以用’\n’來實現換行
返回值為Boolean類型。
分析:判斷黑子還是白子獲勝,彈出提示框,顯示“游戲結束,黑方五子相連!獲勝!”或“游戲結束,白方五子相連!獲勝!”。
變量設置:global設置全局變量stop,hq。其中tag為之前定義的,tag標記執棋方,0代表黑方,1代表白方 ;stop標記游戲狀態,0代表游戲進行中,1代表游戲結束;hq標記是否可悔棋,0代表不可以,1代表可以。
代碼如下:
def win():
global stop,hq
a.config(text=key[(tag+1)%2],fg=color[(tag+1)%2])
b.config(text = "獲勝",fg='red')
stop,hq = 1,0 #決出勝負後游戲結束,不可悔棋
if tag == 0:
r=messagebox.askokcancel('游戲結束','白方五子相連!獲勝!')
else:
r=messagebox.askokcancel('游戲結束','黑方五子相連!獲勝!')
print(r)
前要:
a = Label(tk,text=key[tag],fg=color[tag],bg = "pink",font = ("楷體", "18", "bold"))
b = Label(tk,text= "落子" ,fg=color[tag],bg = "pink",font = ("楷體", "18", "bold"))
函數分析:
a.config(text=key[(tag+1)%2],fg=color[(tag+1)%2])
b.config(text = "獲勝",fg='red')
通過tag判斷棋子的顏色,彈出的消息框中獲勝的字體為紅色。
把print()替換為logging,logging不會拋出錯誤,而且可以輸出到文件。
它允許你指定記錄信息的級別,有debug,info,warning,error等幾個級別,當我們指定level=INFO時,logging.debug就不起作用了。同理,level=WARNING後,debug和info就不起作用了。這樣一來,就可以放心地輸出不同級別的信息,也不用刪除,最後統一控制輸出哪個級別的信息。logging的另一個好處是通過簡單的配置,一條語句可以同時輸出到不同的地方。
使用pdb進行調試,pdb是python自帶的一個包,為python程序提供了一種交互的源代碼調試功能,主要特性包括設置斷點、單步調試、進入函數調試、查看當前代碼、查看棧片段、動態改變變量的值等。
pdb常用命令如下:
圖6-1 pdb常用命令表
步驟如下:
[1]讓程序以單步方式運行,可以隨時查看運行狀態。
[2]以參數-mpdb啟動後,pdb定位到下一步要執行的代碼->s=‘0’。輸入命令l來查看代碼
[3]輸入命令n可以單步執行代碼
[4]任何時候都可以輸入命令p變量名來查看變量
[5]輸入命令q結束調試,退出程序
黑子右斜五子連線,黑方獲勝
黑方五子豎連線,黑方獲勝
黑子左斜五子連線,黑方獲勝
白子五子橫連線,白方獲勝