設計思路
使用Python中的turtle庫實現棋盤棋子的控制。
程序功能:游戲雙方輪流使用鼠標進行落子,並自動判定勝負
畫布的初始化
1.棋盤尺寸
查閱資料可知,標准五子棋棋盤大小為15格*15格
考慮電腦屏幕大小,取棋盤大小為420*420
2.區分棋盤與非棋盤區域
用灰色填充棋盤區域
color('grey')
begin_fill()
penup()
goto(-210,-210)
pendown()
goto(-210,210)
goto(210,210)
goto(210,-210)
goto(-210,-210)
end_fill()
3.畫線
color('black')
for i in range(-210,211,30):
penup()
goto(i,-550)
pendown()
goto(i,550)
for i in range(-210,211,30):
penup()
goto(-550,i)
pendown()
goto(550,i)
吸附功能
此處使用了奇怪的實現方式,不建議學習。代碼如下:
for i in range(1,16):
for j in range(1,16):
for x in range(-240+30*i-15,-240+30*i+15):
for y in range(240-30*j-15,240-30*j+15):
P[(x,y)]=(i,j)
P是從屏幕上點的坐標到棋盤上的行、列數的映射
雙方輪流落子功能
用一個 bool變量表示 [當前是白方回合]
def play(x,y):
global t
t=not t
每次調用play函數都交換落子權
if t:
color('white')
draw(p[0],p[1])
m[p]=-1
else:
color('black')
draw(p[0],p[1])
m[p]=1
不合法落子的處理
情況一 在棋盤外落子
if (x,y) not in P:
t=not t
return
情況二 在已落子處落子
p=P[(x,y)]
if m[p]!=0:
t=not t
return
其中m的含義在交換落子權處可以看出。
m[p]=1表示p點有黑棋,m[p]=-1表示有白棋,m[p]=0表示沒有棋子
判斷勝負
def game_end(x,y):
global Gmov
for i in tw:
tot[i]=0
xn=x+i[0]
yn=y+i[1]
while (xn in range(1,16)) and (yn in range(1,16)) and m[(xn,yn)]==m[(x,y)]:
tot[i]=tot[i]+1
xn=xn+i[0]
yn=yn+i[1]
for i in range(4):
if tot[tw[i]]+tot[tw[7-i]]+1 >= 5:
begin_fill()
penup()
goto(-210,-210)
pendown()
goto(-210,210)
goto(210,210)
goto(210,-210)
goto(-210,-210)
end_fill()
print("game over")
Gmov=True
return
如上,在每次落子后向周圍8個方向搜索連續的相同顏色的棋子的個數。
總代碼
from turtle import *
ht()
speed(0)
rt(90)
Gmov=False
# 15*15
def drawnet():
# too slow?
# use:
# tracer(False)
color('grey')
begin_fill()
penup()
goto(-210,-210)
pendown()
goto(-210,210)
goto(210,210)
goto(210,-210)
goto(-210,-210)
end_fill()
color('black')
for i in range(-210,211,30):
penup()
goto(i,-550)
pendown()
goto(i,550)
for i in range(-210,211,30):
penup()
goto(-550,i)
pendown()
goto(550,i)
t=True
m={}
P={}
for i in range(1,16):
for j in range(1,16):
for x in range(-240+30*i-15,-240+30*i+15):
for y in range(240-30*j-15,240-30*j+15):
P[(x,y)]=(i,j)
m[(i,j)]=0
tw=[(-1,-1),(-1,0),(-1,1),(0,-1),(0,1),(1,-1),(1,0),(1,1)]
tot={}
def game_end(x,y):
global Gmov
for i in tw:
tot[i]=0
xn=x+i[0]
yn=y+i[1]
while (xn in range(1,16)) and (yn in range(1,16)) and m[(xn,yn)]==m[(x,y)]:
tot[i]=tot[i]+1
xn=xn+i[0]
yn=yn+i[1]
for i in range(4):
if tot[tw[i]]+tot[tw[7-i]]+1 >= 5:
begin_fill()
penup()
goto(-210,-210)
pendown()
goto(-210,210)
goto(210,210)
goto(210,-210)
goto(-210,-210)
end_fill()
print("game over")
Gmov=True
return
def draw(i,j):
x=-240+30*i
y=240-30*j
penup()
goto(x-5,y)
pendown()
begin_fill()
circle(5)
end_fill()
def play(x,y):
if(Gmov):
return
global t
t=not t
if (x,y) not in P:
t=not t
return
p=P[(x,y)]
if m[p]!=0:
t=not t
return
if t:
color('white')
draw(p[0],p[1])
m[p]=-1
else:
color('black')
draw(p[0],p[1])
m[p]=1
game_end(p[0],p[1])
def undo(x,y):
print("Sorry,not supported yet.")
setup(550,550)
drawnet()
onscreenclick(play,1,None)
onscreenclick(undo,3,None)
done()