#绘制五子棋
from tkinter import *
from tkinter import messagebox
root = Tk()#创建窗体
root.title('绘制五子棋')
cell_size = 30 #每一个方格的边长
C = 20 #列数
R = 20 #行数
height = R * cell_size#画布高度
width = C * cell_size#画布宽度
cv = Canvas(root, height=height, width=width)
cv.pack() #把所有的控件对象放置在指定位置,才能展示在界面窗体
global color_now
color_now = True
color_s = ("#FFFFFF","#000000")#白色
#画小格子
def xgz(cv, c, r, color="#CCCCCC"):
"""
canvas: 画板,用于绘制一个方块的Canvas对象
c: 方块所在列
r: 方块所在行
color: 方块颜色,默认为,轻灰色
"""
x0= c*cell_size
y0= r*cell_size
x1= x0+cell_size
y1= y0+cell_size
cv.create_rectangle(x0, y0, x1, y1, fill=color, outline="white", width=2)
#绘制棋子
def qizi(cv, c, r, color="#000000"):
"""
canvas: 画板,用于绘制一个方块的Canvas对象
c: 棋子横坐标
r: 棋子纵坐标
color: 方块颜色,默认为#CCCCCC,轻灰色
"""
x0= int(c-cell_size/2)
y0= int(r-cell_size/2)
x1= int(x0+cell_size)
y1= int(y0+cell_size)
cv.create_oval(x0, y0, x1, y1, fill=color)#圆是绘制矩形后内部切取的
def drawQP(x,y):
#画棋盘
for ci in range(1,x):
for ri in range(1,y):
xgz(cv,ci,ri)
#通过获取鼠标点击的位置,矫正坐标点
def getqizi(qzx):
if qzx < cell_size:#超棋盘范围
return cell_size
if qzx > (R-1)*cell_size:#超棋盘范围
return (R-1)*cell_size
xa = int(qzx/cell_size)
xb = qzx%cell_size
if xb >= cell_size/2:#四舍五入取临近坐标点
return int(xa*cell_size + cell_size)
else:
return int(xa*cell_size)
#存放棋子列表的二维列表---用于重复判断,五子连线判断
global block_list
block_list = [] #建立一个变量,计入已经固定的方块,使其不会重叠,先生成初始的
def get_block_list(x,y):
for i in range(x): #由空字符串,由R行C列组成的一个二维列表
i_row = ['' for j in range(y)]
block_list.append(i_row)
#判断下的点是否已存在棋子
def checkCF(xi,yi):
isQz = False
if (block_list[xi][yi]):
isQz = True
return isQz
directions = [0,1,2,3]#横向,竖向,斜
def direction(xi,yi,direction):
"""
xi: 棋子横坐标
yi: 棋子纵坐标
direction: #横向,竖向,斜1,斜2--每个方向遍历检查是否五子相连
"""
isFive = FALSE
list_temp = []
colora = block_list[xi][yi]
for i in range(-4,5):
if direction == directions[0]:
ax = xi+i
ay = yi
if direction == directions[1]:
ax = xi
ay = yi+i
if direction == directions[2]:
ax = xi+i
ay = yi+i
if direction == directions[3]:
ax = xi+i
ay = yi-i
if ax<0 or ax> C-2 or ay<0 or ay> R-2:#超边界略过
continue
if block_list[ax][ay] != colora:#有不一样的清空并略过,确保相连5个
list_temp = []
continue
list_temp.append(block_list[ax][ay])#一样的加入列表
if len(list_temp)==5:#判断列表是否满5个
isFive = True
return isFive
#判断是否成功(5子连成一条线)
def isFive(xi,yi):
isFive = FALSE
for i in directions:
isFive = direction(xi,yi,i)
if isFive:
return isFive
return isFive
#连线后清除所有,重新恢复初始化
#计算用户下棋点,鼠标点击事件触发
def fqizi(event):
global color_now
global block_list
qilist = []
qzx = event.x
qzy = event.y
qzx = getqizi(qzx)
qzy = getqizi(qzy)#棋子坐标位置处理
qzxi = int(qzx/30) - 1#棋子数组位置处理
qzyi = int(qzy/30) - 1
if(checkCF(qzxi,qzyi)):#判断下的点是否已存在棋子
messagebox.showinfo("不能下在此处")
return
if color_now:
qizi(cv,qzx,qzy,color=color_s[0])#绘制棋子
block_list[qzxi][qzyi] = color_s[0]#棋子存于二维列表
color_now = False
else:
qizi(cv,qzx,qzy,color=color_s[1])
block_list[qzxi][qzyi] = color_s[1]
color_now = True
if(isFive(qzxi,qzyi)):#判断棋子是否五子连线
if (block_list[qzxi][qzyi] == color_s[0]):
messagebox.showinfo("Game Over!","白子五子连线")
else:
messagebox.showinfo("Game Over!","黑色五子连线")
cv.delete(ALL)#清除画布上所有图形
block_list = []#清空存储的二维数组
get_block_list(R-1,C-1)#重新创建空字符串二位数组
drawQP(C-1,R-1)#重新绘制棋盘
#画棋盘
drawQP(C-1,R-1)
#建立二位数组
get_block_list(R-1,C-1)
#绑定鼠标左键按下事件
cv.bind("", fqizi)
root.mainloop()
五子棋练完,可以试着独立写写俄罗斯方块