“彩色方块连连看”游戏(续)
上期讲到相同的色块连接,链接见:Python 一步一步教你用pyglet制作“彩色方块连连看”游戏-CSDN博客
第八步
续上期,接下来要实现相邻方块的连线:
首先来进一步扩展 行列的类:
class RC:
def __init__(self, r=0, c=0):
self.r, self.c = r, c
def __repr__(self):
return f'Rc({self.r}, {self.c})'
def __and__(self, other):
return self.r == other.r and self.c == other.c
def __or__(self, other):
return self.r == other.r or self.c == other.c
def __eq__(self, other):
return self & other
def __lt__(self, other):
return self.r == other.r and self.c != other.c
def __gt__(self, other):
return self.r != other.r and self.c == other.c
def __le__(self, other):
return self.r == other.r and self.c - other.c
def __ge__(self, other):
return self.c == other.c and self.r - other.r
def __xor__(self, other):
return self < other or self > other
def __mod__(self, other):
return [RC(self.r, other.c), RC(other.r, self.c)]
def __truediv__(self, other):
return 1 if self<other and (self<=other)<0 or self>other and (self>=other)<0 else -1
def __add__(self, other):
return abs(self<=other)==1 or abs(self>=other)==1
def __sub__(self, other):
if self<other: return [RC(self.r,_) for _ in range(self.c+(self/other),other.c,self/other)]
if self>other: return [RC(_,self.c) for _ in range(self.r+(self/other),other.r,self/other)]
return []
def __mul__(self, other):
if self<other: return not any(Array[self.r+1][_+1] for _ in range(self.c+(self/other),other.c,self/other))
if self>other: return not any(Array[_+1][self.c+1] for _ in range(self.r+(self/other),other.r,self/other))
return False
由上面的类可知,self.rc*self.rc2就表示两点相邻,加时update方法中的if语句,就能实现相邻色块的连线并消去:
def update(self, event):
self.line.visible = False
clock.unschedule(self.update)
if self.last.rect.color==self.last2.rect.color and self.rc*self.rc2:
self.last.hide(); self.last2.hide()
self.array[self.rc.r][self.rc.c] = self.array[self.rc2.r][self.rc2.c] = 0
else:
self.last.box.color = self.last2.box.color = Color('WHITE').rgba
self.last, self.last2 = None, None
if game.success():
window.set_caption('彩色色块连连看——任务完成!')
代码:
from pyglet import * from colorlib import * W, H = 800, 600 window = window.Window(W, H, caption='彩色色块连连看') gl.glClearColor(*Color('lightblue3').decimal) batch, group = graphics.Batch(),graphics.Group() row, col, space = 6, 8, 5 w, h = W//(col+2), H//(row+2) x0, y0 = (W-(w+space)*col)//2, (H-(h+space)*row)//2 COLOR = [] while len(COLOR)<row*col//4: if (c:=randcolorTuple()) not in COLOR: COLOR.append(c) COLOR = sample(COLOR*4, row*col) Array, Boxes = [[[1]*col for _ in range(row)] for _ in range(2)] 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.rect = shapes.Rectangle(x, y, w, h, color=color, batch=batch) self.box = shapes.Box(x, y, w, h, color=Color('WHITE').rgba, thickness=3, batch=batch) self.box.group = group def hide(self): self.box.batch = self.rect.batch = None def on_mouse_over(self, x, y): return self.x<=x<=self.x+self.w and self.y<=y<=self.y+self.h 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 RC: def __init__(self, r=0, c=0): self.r, self.c = r, c def __repr__(self): return f'Rc({self.r}, {self.c})' def __and__(self, other): return self.r == other.r and self.c == other.c def __or__(self, other): return self.r == other.r or self.c == other.c def __eq__(self, other): return self & other def __lt__(self, other): return self.r == other.r and self.c != other.c def __gt__(self, other): return self.r != other.r and self.c == other.c def __le__(self, other): return self.r == other.r and self.c - other.c def __ge__(self, other): return self.c == other.c and self.r - other.r def __xor__(self, other): return self < other or self > other def __mod__(self, other): return [RC(self.r, other.c), RC(other.r, self.c)] def __truediv__(self, other): return 1 if self<other and (self<=other)<0 or self>other and (self>=other)<0 else -1 def __add__(self, other): return abs(self<=other)==1 or abs(self>=other)==1 def __sub__(self, other): if self<other: return [RC(self.r,_) for _ in range(self.c+(self/other),other.c,self/other)] if self>other: return [RC(_,self.c) for _ in range(self.r+(self/other),other.r,self/other)] return [] def __mul__(self, other): if self<other: return not any(Array[self.r+1][_+1] for _ in range(self.c+(self/other),other.c,self/other)) if self>other: return not any(Array[_+1][self.c+1] for _ in range(self.r+(self/other),other.r,self/other)) return False class Game: def __init__(self): self.array = Array self.boxes = Boxes self.rc, self.rc2 = RC(), RC() self.last, self.last2 = None, None self.line = shapes.Line(0, 0, 0, 0, width=5, color=Color('light gold').rgba, batch=batch, group=group) self.line.visible = False def on_mouse_click(self, x, y): if self.line.visible or self.success(): return r, c = (y-y0)//(h+space), (x-x0)//(w+space) if r in range(row) and c in range(col) and self.boxes[r][c].on_mouse_over(x, y) and self.array[r][c]: if self.last is None and self.last2 is None: self.rc, self.last = RC(r, c), self.boxes[r][c] self.last.box.color = Color('RED').rgba elif self.last is not None and self.last2 is None: self.rc2, self.last2 = RC(r, c), self.boxes[r][c] self.last2.box.color = Color('RED').rgba if self.rc == self.rc2: self.last.box.color = Color('WHITE').rgba self.last, self.last2 = None, None else: self.line.x, self.line.y = self.getxy(r, c) self.line.x2, self.line.y2 = self.getxy(self.rc.r, self.rc.c) self.line.visible = True clock.schedule_interval(self.update, 0.3) return (r, c), Color(self.boxes[r][c].rect.color).name def getxy(self, row, col): return x0+col*(w+space)+w//2, y0+row*(h+space)+h//2 def update(self, event): self.line.visible = False clock.unschedule(self.update) if self