python實(shí)現(xiàn)簡單的井字棋小游戲
Python做三子棋游戲,這個(gè)是我剛開始了解做Python小游戲的時(shí)候第一個(gè)項(xiàng)目,因?yàn)楹唵魏萌胧郑瑢?shí)現(xiàn)它的過程是我開始摸索Python的GUI界面的入門之路。這個(gè)設(shè)計(jì)也都是按照自己對(duì)于這個(gè)游戲的理解,一步一步去實(shí)現(xiàn)它。
窗口
萬能的窗口,實(shí)現(xiàn)窗口都可以進(jìn)行簡單的修改進(jìn)行使用:
from tkinter import * root = Tk() ? ? ? ? #窗口名稱 root.title("憨憨制作的三子棋") f1=Frame(root) f1.pack() w1 = Canvas(f1, width=580,height=580,background='lightcyan')#創(chuàng)建一個(gè)畫布,設(shè)置大小和背景顏色 w1.pack() root.mainloop()
畫出棋盤
#畫出棋盤 for i in range(0, 4): ? ? w1.create_line(i * 180 + 20, 20, i * 180 + 20, 560) ? ? w1.create_line(20, i * 180 + 20, 560, i * 180 + 20)
分別畫橫豎線,四條橫線四條豎線,生成九個(gè)格子。也可以畫出兩橫兩豎,更加貼近井字形狀。少畫幾條線就好,例如:
for i in range(1, 3): ? ? w1.create_line(i * 180 + 20, 20, i * 180 + 20, 560) ? ? w1.create_line(20, i * 180 + 20, 560, i * 180 + 20)
num = 0?? ????#記錄點(diǎn)擊的次數(shù),用來決定點(diǎn)擊后該畫哪種圖形 A = np.full((3, 3), 0)?? ??? ??? ?#記錄每個(gè)位置的圖形
算法
每一次點(diǎn)擊以后我們都要進(jìn)行畫圖和判斷是否達(dá)到獲勝的條件。
設(shè)置函數(shù)
def dawn(event): ? ? global w1 ? ? global num, A ? ? for i in range(0, 3): ? ? ? ? for j in range(0, 3): ? ? ? ? ? ? if 20 + j * 180 < event.y and event.y <= 20 + (j+1) * 180: ? ? ? ? ? ? ? ? break ? ? ? ? if 20 + i * 180 <= event.x and event.x <= 20 + (i+1) * 180: ? ? ? ? ? ? break ? ? if num % 2 == 0 and A[i][j] == 0: ? ? ? ? A[i][j] = 1 ? ? ? ? w1.create_line(110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2), ? ? ? ? ? ? ? ? ? ? ? ?110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2)) ? ? ? ? w1.create_line(110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2), ? ? ? ? ? ? ? ? ? ? ? ?110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2)) ? ? ? ? num += 1 ? ? if num % 2 != 0 and A[i][j] == 0: ? ? ? ? A[i][j] = 2 ? ? ? ? w1.create_oval(20 + 180 * i, 20 + 180 * j, 20 + 180 * (i + 1), 20 + 180 * (j + 1)) ? ? ? ? num += 1 ? ? if A[0][0] == A[0][1] == A[0][2] == 2 or A[1][0] == A[1][1] == A[1][2] == 2 or A[2][0] == A[2][1] == A[2][ ? ? ? ? 2] == 2 or \ ? ? ? ? ? ? A[0][0] == A[1][0] == A[2][0] == 2 or A[0][1] == A[1][1] == A[2][1] == 2 or A[0][2] == A[1][2] == \ ? ? ? ? ? ? A[2][ ? ? ? ? ? ? ? ? 2] == 2 or \ ? ? ? ? ? ? A[0][0] == A[1][1] == A[2][2] == 2 or A[2][0] == A[1][1] == A[0][2] == 2: ? ? ? ? tkinter.messagebox.showinfo('消息提示', '圓圈獲勝') ? ? elif A[0][0] == A[0][1] == A[0][2] == 1 or A[1][0] == A[1][1] == A[1][2] == 1 or A[2][0] == A[2][1] == A[2][ ? ? ? ? 2] == 1 or \ ? ? ? ? ? ? A[0][0] == A[1][0] == A[2][0] == 1 or A[0][1] == A[1][1] == A[2][1] == 1 or A[0][2] == A[1][2] == \ ? ? ? ? ? ? A[2][ ? ? ? ? ? ? ? ? 2] == 1 or \ ? ? ? ? ? ? A[0][0] == A[1][1] == A[2][2] == 1 or A[2][0] == A[1][1] == A[0][2] == 1: ? ? ? ? tkinter.messagebox.showinfo('消息提示', '叉號(hào)獲勝') w1.bind("<Button -1>", dawn)
我們拆開進(jìn)行分析:
首先是:點(diǎn)擊位置的確定,得到我們的點(diǎn)擊單元格,開始時(shí)我是用的是判斷是否在方格的內(nèi)切圓范圍內(nèi),發(fā)現(xiàn)點(diǎn)擊到方格的剩余部分會(huì)導(dǎo)致化的圖形錯(cuò)位,通過進(jìn)一步的分析發(fā)現(xiàn),可以通過分別定位點(diǎn)擊位置的橫縱坐標(biāo),確定點(diǎn)擊的方格。
for i in range(0, 3): ? ? ? ? for j in range(0, 3): ? ? ? ? ? ? if 20 + j * 180 < event.y and event.y <= 20 + (j+1) * 180: ? ? ? ? ? ? ? ? break ? ? ? ? if 20 + i * 180 <= event.x and event.x <= 20 + (i+1) * 180: ? ? ? ? ? ? break
接著,確定了位置以后我們就開始判斷當(dāng)前位置是否能畫圖形,應(yīng)該畫什么圖形,畫?是比較麻煩的需要進(jìn)行復(fù)雜的計(jì)算,畫?就比較簡單。
if num % 2 == 0 and A[i][j] == 0:?? ??? ??? ?#若為偶數(shù)就畫叉號(hào) ? ? ? ? A[i][j] = 1 ? ? ? ? w1.create_line(110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2), ? ? ? ? ? ? ? ? ? ? ? ?110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2)) ? ? ? ? w1.create_line(110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2), ? ? ? ? ? ? ? ? ? ? ? ?110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2)) ? ? ? ? num += 1 ? ? if num % 2 != 0 and A[i][j] == 0:?? ??? ?#若為奇數(shù)就畫圓圈 ? ? ? ? A[i][j] = 2 ? ? ? ? w1.create_oval(20 + 180 * i, 20 + 180 * j, 20 + 180 * (i + 1), 20 + 180 * (j + 1)) ? ? ? ? num += 1
畫完以后我們要判斷是否達(dá)到獲勝的條件,這里我沒想到簡便的方法,但是好在獲勝的情況屈指可數(shù),只有八種(橫3,豎3,兩個(gè)斜方向的)于是將八種情況列出進(jìn)行判斷是否達(dá)到獲勝條件,而且兩種圖形都需要列出。
if A[0][0] == A[0][1] == A[0][2] == 2 or A[1][0] == A[1][1] == A[1][2] == 2 or A[2][0] == A[2][1] == A[2][ ? ? ? ? 2] == 2 or \ ? ? ? ? ? ? A[0][0] == A[1][0] == A[2][0] == 2 or A[0][1] == A[1][1] == A[2][1] == 2 or A[0][2] == A[1][2] == \ ? ? ? ? ? ? A[2][ ? ? ? ? ? ? ? ? 2] == 2 or \ ? ? ? ? ? ? A[0][0] == A[1][1] == A[2][2] == 2 or A[2][0] == A[1][1] == A[0][2] == 2: ? ? ? ? tkinter.messagebox.showinfo('消息提示', '圓圈獲勝') ? ? elif A[0][0] == A[0][1] == A[0][2] == 1 or A[1][0] == A[1][1] == A[1][2] == 1 or A[2][0] == A[2][1] == A[2][ ? ? ? ? 2] == 1 or \ ? ? ? ? ? ? A[0][0] == A[1][0] == A[2][0] == 1 or A[0][1] == A[1][1] == A[2][1] == 1 or A[0][2] == A[1][2] == \ ? ? ? ? ? ? A[2][ ? ? ? ? ? ? ? ? 2] == 1 or \ ? ? ? ? ? ? A[0][0] == A[1][1] == A[2][2] == 1 or A[2][0] == A[1][1] == A[0][2] == 1: ? ? ? ? tkinter.messagebox.showinfo('消息提示', '叉號(hào)獲勝')
最后設(shè)置點(diǎn)擊時(shí)間的獲取以及退出按鈕的設(shè)置。
w1.bind("<Button -1>", dawn) def quit(): ? ? root.quit() button1 = Button(root, text="退出", font=('楷體', 20), command=quit) button1.pack()
到這里游戲的每個(gè)代碼都講解完了。
附完整代碼:
from tkinter import * import numpy as np import math import tkinter.messagebox root = Tk() ? ? ? ? #窗口名稱 root.title("憨憨制作的三子棋") f1=Frame(root) f1.pack() w1 = Canvas(f1, width=580,height=580,background='lightcyan') w1.pack() #棋盤 for i in range(0, 4): ? ? w1.create_line(i * 180 + 20, 20, i * 180 + 20, 560) ? ? w1.create_line(20, i * 180 + 20, 560, i * 180 + 20) num = 0 A = np.full((3, 3), 0) def dawn(event): ? ? global w1 ? ? global num, A ? ? for i in range(0, 3): ? ? ? ? for j in range(0, 3): ? ? ? ? ? ? if 20 + j * 180 < event.y and event.y <= 20 + (j+1) * 180: ? ? ? ? ? ? ? ? break ? ? ? ? if 20 + i * 180 <= event.x and event.x <= 20 + (i+1) * 180: ? ? ? ? ? ? break ? ? if num % 2 == 0 and A[i][j] == 0: ? ? ? ? A[i][j] = 1 ? ? ? ? w1.create_line(110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2), ? ? ? ? ? ? ? ? ? ? ? ?110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2)) ? ? ? ? w1.create_line(110 + 180 * i + 45 * math.sqrt(2), 110 + 180 * j - 45 * math.sqrt(2), ? ? ? ? ? ? ? ? ? ? ? ?110 + 180 * i - 45 * math.sqrt(2), 110 + 180 * j + 45 * math.sqrt(2)) ? ? ? ? num += 1 ? ? if num % 2 != 0 and A[i][j] == 0: ? ? ? ? A[i][j] = 2 ? ? ? ? w1.create_oval(20 + 180 * i, 20 + 180 * j, 20 + 180 * (i + 1), 20 + 180 * (j + 1)) ? ? ? ? num += 1 ? ? if A[0][0] == A[0][1] == A[0][2] == 2 or A[1][0] == A[1][1] == A[1][2] == 2 or A[2][0] == A[2][1] == A[2][ ? ? ? ? 2] == 2 or \ ? ? ? ? ? ? A[0][0] == A[1][0] == A[2][0] == 2 or A[0][1] == A[1][1] == A[2][1] == 2 or A[0][2] == A[1][2] == \ ? ? ? ? ? ? A[2][ ? ? ? ? ? ? ? ? 2] == 2 or \ ? ? ? ? ? ? A[0][0] == A[1][1] == A[2][2] == 2 or A[2][0] == A[1][1] == A[0][2] == 2: ? ? ? ? tkinter.messagebox.showinfo('消息提示', '圓圈獲勝') ? ? elif A[0][0] == A[0][1] == A[0][2] == 1 or A[1][0] == A[1][1] == A[1][2] == 1 or A[2][0] == A[2][1] == A[2][ ? ? ? ? 2] == 1 or \ ? ? ? ? ? ? A[0][0] == A[1][0] == A[2][0] == 1 or A[0][1] == A[1][1] == A[2][1] == 1 or A[0][2] == A[1][2] == \ ? ? ? ? ? ? A[2][ ? ? ? ? ? ? ? ? 2] == 1 or \ ? ? ? ? ? ? A[0][0] == A[1][1] == A[2][2] == 1 or A[2][0] == A[1][1] == A[0][2] == 1: ? ? ? ? tkinter.messagebox.showinfo('消息提示', '叉號(hào)獲勝') w1.bind("<Button -1>", dawn) def quit(): ? ? root.quit() button1 = Button(root, text="退出", font=('楷體', 20), command=quit) button1.pack() root.mainloop()
游戲?qū)崿F(xiàn)只是個(gè)人的思路和操作,可能會(huì)有很多的不足,有愿意一起研究的朋友可以聯(lián)系我,愿意虛心請(qǐng)教。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
python3中http協(xié)議提供文件服務(wù)器功能詳解
http協(xié)議是互聯(lián)網(wǎng)的通用基礎(chǔ)協(xié)議,也可以利用其來開發(fā)文件服務(wù)器,給客戶提供文件瀏覽,查看,下載,上傳等功能,這篇文章主要介紹了python3中http協(xié)議提供文件服務(wù)器功能,需要的朋友可以參考下2023-06-06利用Python開發(fā)微信支付的注意事項(xiàng)
如今支付的引入是很多互聯(lián)網(wǎng)產(chǎn)品都需要的。為了讓用戶用著更方便快捷,集成像支付寶、微信支付這樣的第三方支付也就成了常有的事。今天跟著小編就來看看微信支付開發(fā)中幾個(gè)值得注意的地方,涉及代碼之處均用 Python 編寫。2016-08-08使用Python第三方庫pygame寫個(gè)貪吃蛇小游戲
這篇文章主要介紹了使用Python第三方庫pygame寫個(gè)貪吃蛇小游戲,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-03-03Python面向?qū)ο笾o態(tài)屬性、類方法與靜態(tài)方法分析
這篇文章主要介紹了Python面向?qū)ο笾o態(tài)屬性、類方法與靜態(tài)方法,結(jié)合實(shí)例形式分析了Python面向?qū)ο蟪绦蛟O(shè)計(jì)中靜態(tài)屬性、類方法及靜態(tài)方法相關(guān)概念、使用方法及操作注意事項(xiàng),需要的朋友可以參考下2018-08-08Python實(shí)現(xiàn)Opencv cv2.Canny()邊緣檢測(cè)
這篇博客將介紹Canny邊緣檢測(cè)的概念,并利用cv2.Canny()實(shí)現(xiàn)邊緣檢測(cè),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07零基礎(chǔ)也能看懂的python內(nèi)置csv模塊教程
這篇博客就為你介紹一個(gè)知識(shí)點(diǎn),python 內(nèi)置模塊 csv 。讓大家一文就看懂csv csv(Comma-Separated Values)文件是什么?以及python 中的 csv 文件清晰解法讀取文件寫入文件 csv 文件其它說明2021-11-11