原文链接:
彩色圆圈“连连看”
有个网友留言要把原文中的方块改成圆圈,再要加入消去的分数。大致效果如下:
以下就把原文的代码作几步简单的修改:
Box类的修改
把矩形及方框用圆圈和圆弧来代替:
self.rect = shapes.Circle(x+w//2, y+h//2, min(w,h)//2, color=color, batch=batch)
self.box = shapes.Arc(x+w//2, y+h//2, min(w,h)//2, color=Color('WHITE').rgba, batch=batch)
Game类的修改
Game类中增加分数属性:
update方法中增加分数和显示
点击事件的修改
在on_mouse_press事件中增加分数的显示:
部分代码的替代
在源码全文中搜索并替代: .rect 替换为 .cir ; .box 替换为 .arc
class Box类名也可以修改一下,不作修改也不影响代码的运行。
大致就以上几步就完成了修改:
完整代码
from pyglet import *
from colorlib import *
from pointlib import Point
from pyglet.window import key
W, H = 800, 600
window = window.Window(W, H)
gl.glClearColor(*Color('lightblue3').decimal)
batch, batch2, group = graphics.Batch(), graphics.Batch(), graphics.Group()
row, col, space = 8, 10, 5
w, h = W//(col+2), H//(row+2)
x0, y0 = (W-(w+space)*col)//2, (H-(h+space)*row)//2
sound1, sound2 = media.load('box.mp3'), media.load('box2.mp3')
def randColor():
COLOR = []
while len(COLOR)<row*col//4:
if not ((c:=randcolorTuple()) in COLOR or Color(c).name[-1] in '0123456789'):
COLOR.append(c)
return sample(COLOR*4, row*col)
class Box:
def __init__(self, x, y, w, h, color, batch=batch):
self.x, self.y, self.w, self.h = x, y, w, h
self.cir = shapes.Circle(x+w//2, y+h//2, min(w,h)//2, color=color, batch=batch)
self.arc = shapes.Arc(x+w//2, y+h//2, min(w,h)//2, color=Color('WHITE').rgba, batch=batch)
def hide(self):
self.arc.batch = self.cir.batch = None
def show(self):
self.arc.batch = self.cir.batch = batch
def on_mouse_over(self, x, y):
return self.x<=x<=self.x+self.w and self.y<=y<=self.y+self.h
class Matrix:
def __init__(self, r=row, c=col):
self.array = [[1]*c for _ in range(r)]
self.point = []
self.lines = [shapes.Line(*[-3]*4, width=5, color=Color('light gold').rgba,
batch=batch2, group=group) for _ in range(5)]
for line in self.lines: line.visible = False
def __repr__(self):
return '\n'.join(map(str,self.array))+'\n'
def true(self, point):
try: return self.array[point.x+1][point.y+1]
except: return 0
def alltrue(self, points):
if isinstance(points,(tuple,list)) and all(isinstance(p, Point) for p in points):
try: return all(self.array[p.x+1][p.y+1] for p in points)
except: return 0
def adjacent(self, point1, point2):
return point1*point2
def inline(self, point1, point2):
return point1^point2 and self.alltrue(point1**point2)
def diagonal(self, point1, point2):
if point1&point2:
for point in point1%point2:
state1 = self.adjacent(point, point1) or self.inline(point, point1)
state2 = self.adjacent(point, point2) or self.inline(point, point2)
if self.true(point) and state1 and state2:
self.point.append(point)
return True
def connect1(self, p1, p2):
return self.adjacent(p1, p2) or self.inline(p1, p2) or self.diagonal(p1, p2)
def connect2(self, p1, p2):
for i in range(1, max(row, col)):
for p in zip(i+p1, i+p2):
for i in range(2):
if self.true(p[i]) and (self.adjacent(p[i],(p1,p2)[i]) or
self.inline(p[i],(p1,p2)[i]))and self.diagonal(p[i], (p2,p1)[i]):
self.point.append(p[i])
return True
def connect(self, p1, p2):
if (ret := self.connect1(p1, p2) or self.connect2(p1, p2)):
self.showlines(p1, p2)
return ret
def getxy(self, row, col):
return x0+col*(w+space)+w//2, y0+row*(h+space)+h//2
def drawline(self, *args):
for i,p in enumerate(args[:-1]):
self.lines[i].x, self.lines[i].y = self.getxy(*p)
self.lines[i].x2, self.lines[i].y2 = self.getxy(*args[i+1])
self.lines[i].visible = True
def showlines(self, point1, point2):
if len(self.point)==3: self.point.pop(0)
if len(self.point)==2 and not self.point[0]^point1: self.point.reverse()
points = point1, *self.point, point2
self.drawline(*points)
self.point.clear()
def hidelines(self):
for line in self.lines: line.visible = False
def linevisible(self):
return self.lines[0].visible
def initMatrix(row, col):
global matrix, Array, Boxes
matrix = Matrix(row+2, col+2)
Array, Boxes = matrix.array, Matrix().array
for i in range(row):
for j in range(col):
Array[i+1][j+1] = 0
COLOR = randColor()
for r,arr in enumerate(Boxes):
for c,_ in enumerate(arr):
Boxes[r][c] = Box(x0+c*(w+space), y0+r*(h+space), w, h, COLOR[c+r*len(arr)])
class Game:
def __init__(self):
initMatrix(row, col)
self.score = 0
self.rc, self.rc2 = Point(), Point()
self.array, self.arces = Array, Boxes
self.last1, self.last2, self.lastz = None, None, None
self.label1 = text.Label('Congratulations!', color=Color().randcolor().rgba, font_size=50,
x=W//2, y=H//2+80, anchor_x='center', anchor_y='center', bold=True, batch=batch)
self.label2 = text.Label('Any key to restart...', color=Color().randcolor().rgba, font_size=36,
x=W//2, y=H//2-50, anchor_x='center', anchor_y='center', bold=True, batch=batch)
def on_mouse_click(self, x, y):
if matrix.linevisible(): return
if self.success(): main(event)
r, c = (y-y0)//(h+space), (x-x0)//(w+space)
if r in range(row) and c in range(col) and self.arces[r][c].on_mouse_over(x, y) and not self.array[r+1][c+1]:
if self.last1 is None and self.last2 is None:
self.rc, self.last1 = Point(r, c), self.arces[r][c]
self.last1.arc.color = Color('RED').rgba
elif self.last1 is not None and self.last2 is None:
self.rc2, self.last2 = Point(r, c), self.arces[r][c]
self.last2.arc.color = Color('RED').rgba
if self.rc == self.rc2:
self.last1.arc.color = Color('WHITE').rgba
self.last1, self.last2 = None, None
else:
if self.last1.cir.color==self.last2.cir.color:
matrix.connect(self.rc, self.rc2)
clock.schedule_interval(self.update, 0.5)
return (r, c), Color(self.arces[r][c].cir.color).name
def update(self, event):
clock.unschedule(self.update)
if self.last1.cir.color==self.last2.cir.color and matrix.connect(self.rc, self.rc2):
self.hide()
sound1.play()
self.score += 10
window.set_caption(window.caption.split('分数:')[0] + f'分数:{self.score}')
else:
sound2.play()
self.last1.arc.color = self.last2.arc.color = Color('WHITE').rgba
self.lastz = self.last1, self.last2
self.last1, self.last2 = None, None
matrix.hidelines()
if game.success():
window.set_caption('彩色方块连连看——任务完成!')
game.label1.batch = game.label2.batch = batch2
clock.schedule_interval(main, 5) # 5秒后自动开始
def hide(self):
self.last1.hide(); self.last2.hide()
self.array[self.rc.x+1][self.rc.y+1] = self.array[self.rc2.x+1][self.rc2.y+1] = 1
def unhide(self):
self.lastz[0].show(); self.lastz[1].show()
self.array[self.rc.x+1][self.rc.y+1] = self.array[self.rc2.x+1][self.rc2.y+1] = 0
def success(self):
return sum(sum(self.array,[]))==(row+2)*(col+2)
def main(event):
global game
game = Game()
game.label1.batch = game.label2.batch = None
window.set_caption('彩色方块连连看')
clock.unschedule(main)
@window.event
def on_draw():
window.clear()
batch.draw()
batch2.draw()
@window.event
def on_mouse_press(x, y, dx, dy):
global score
if (ret := game.on_mouse_click(x, y)):
window.set_caption(f'彩色方块连连看——坐标:{ret[0]} 颜色:{ret[1]} 分数:{game.score}')
@window.event
def on_key_press(symbol, modifiers):
if game.success(): main(event)
if symbol == key.S and modifiers & key.MOD_CTRL:
main(event)
elif symbol == key.Z and modifiers & key.MOD_CTRL:
game.unhide()
elif symbol == key.R and modifiers & key.MOD_CTRL:
for i in range(row):
for j in range(col):
Array[i+1][j+1], Boxes[i][j].arc.batch, Boxes[i][j].cir.batch = 0, batch, batch
elif symbol == key.F and modifiers & key.MOD_CTRL:
if sum(sum(game.array,[]))%2: return
boxsample = []
for i,arr in enumerate(Array[1:-1]):
for j,n in enumerate(arr[1:-1]):
if n==0: boxsample.append(Boxes[i][j].cir.color)
boxsample = sample(boxsample,len(boxsample))
for i,arr in enumerate(Array[1:-1]):
for j,n in enumerate(arr[1:-1]):
if n==0: Boxes[i][j].cir.color = boxsample.pop()
main(event)
app.run()
目录
完