当前位置:   article > 正文

Python 一步一步教你用pyglet制作“彩色方块连连看”游戏(续)

Python 一步一步教你用pyglet制作“彩色方块连连看”游戏(续)

“彩色方块连连看”游戏(续)

上期讲到相同的色块连接,链接见: 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('彩色色块连连看——任务完成!') 

代码:

  1. from pyglet import *
  2. from colorlib import *
  3. W, H = 800, 600
  4. window = window.Window(W, H, caption='彩色色块连连看')
  5. gl.glClearColor(*Color('lightblue3').decimal)
  6. batch, group = graphics.Batch(),graphics.Group()
  7. row, col, space = 6, 8, 5
  8. w, h = W//(col+2), H//(row+2)
  9. x0, y0 = (W-(w+space)*col)//2, (H-(h+space)*row)//2
  10. COLOR = []
  11. while len(COLOR)<row*col//4:
  12. if (c:=randcolorTuple()) not in COLOR:
  13. COLOR.append(c)
  14. COLOR = sample(COLOR*4, row*col)
  15. Array, Boxes = [[[1]*col for _ in range(row)] for _ in range(2)]
  16. class Box:
  17. def __init__(self, x, y, w, h, color, batch=batch):
  18. self.x, self.y, self.w, self.h = x, y, w, h
  19. self.rect = shapes.Rectangle(x, y, w, h, color=color, batch=batch)
  20. self.box = shapes.Box(x, y, w, h, color=Color('WHITE').rgba, thickness=3, batch=batch)
  21. self.box.group = group
  22. def hide(self):
  23. self.box.batch = self.rect.batch = None
  24. def on_mouse_over(self, x, y):
  25. return self.x<=x<=self.x+self.w and self.y<=y<=self.y+self.h
  26. for r,arr in enumerate(Boxes):
  27. for c,_ in enumerate(arr):
  28. Boxes[r][c] = Box(x0+c*(w+space), y0+r*(h+space), w, h, COLOR[c+r*len(arr)])
  29. class RC:
  30. def __init__(self, r=0, c=0):
  31. self.r, self.c = r, c
  32. def __repr__(self):
  33. return f'Rc({self.r}, {self.c})'
  34. def __and__(self, other):
  35. return self.r == other.r and self.c == other.c
  36. def __or__(self, other):
  37. return self.r == other.r or self.c == other.c
  38. def __eq__(self, other):
  39. return self & other
  40. def __lt__(self, other):
  41. return self.r == other.r and self.c != other.c
  42. def __gt__(self, other):
  43. return self.r != other.r and self.c == other.c
  44. def __le__(self, other):
  45. return self.r == other.r and self.c - other.c
  46. def __ge__(self, other):
  47. return self.c == other.c and self.r - other.r
  48. def __xor__(self, other):
  49. return self < other or self > other
  50. def __mod__(self, other):
  51. return [RC(self.r, other.c), RC(other.r, self.c)]
  52. def __truediv__(self, other):
  53. return 1 if self<other and (self<=other)<0 or self>other and (self>=other)<0 else -1
  54. def __add__(self, other):
  55. return abs(self<=other)==1 or abs(self>=other)==1
  56. def __sub__(self, other):
  57. if self<other: return [RC(self.r,_) for _ in range(self.c+(self/other),other.c,self/other)]
  58. if self>other: return [RC(_,self.c) for _ in range(self.r+(self/other),other.r,self/other)]
  59. return []
  60. def __mul__(self, other):
  61. if self<other: return not any(Array[self.r+1][_+1] for _ in range(self.c+(self/other),other.c,self/other))
  62. if self>other: return not any(Array[_+1][self.c+1] for _ in range(self.r+(self/other),other.r,self/other))
  63. return False
  64. class Game:
  65. def __init__(self):
  66. self.array = Array
  67. self.boxes = Boxes
  68. self.rc, self.rc2 = RC(), RC()
  69. self.last, self.last2 = None, None
  70. self.line = shapes.Line(0, 0, 0, 0, width=5, color=Color('light gold').rgba, batch=batch, group=group)
  71. self.line.visible = False
  72. def on_mouse_click(self, x, y):
  73. if self.line.visible or self.success(): return
  74. r, c = (y-y0)//(h+space), (x-x0)//(w+space)
  75. 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]:
  76. if self.last is None and self.last2 is None:
  77. self.rc, self.last = RC(r, c), self.boxes[r][c]
  78. self.last.box.color = Color('RED').rgba
  79. elif self.last is not None and self.last2 is None:
  80. self.rc2, self.last2 = RC(r, c), self.boxes[r][c]
  81. self.last2.box.color = Color('RED').rgba
  82. if self.rc == self.rc2:
  83. self.last.box.color = Color('WHITE').rgba
  84. self.last, self.last2 = None, None
  85. else:
  86. self.line.x, self.line.y = self.getxy(r, c)
  87. self.line.x2, self.line.y2 = self.getxy(self.rc.r, self.rc.c)
  88. self.line.visible = True
  89. clock.schedule_interval(self.update, 0.3)
  90. return (r, c), Color(self.boxes[r][c].rect.color).name
  91. def getxy(self, row, col):
  92. return x0+col*(w+space)+w//2, y0+row*(h+space)+h//2
  93. def update(self, event):
  94. self.line.visible = False
  95. clock.unschedule(self.update)
  96. if self.last.rect.color==self.last2.rect.color and self.rc*self.rc2:
  97. self.last.hide(); self.last2.hide()
  98. self.array[self.rc.r][self.rc.c] = self.array[self.rc2.r][self.rc2.c] = 0
  99. else:
  100. self.last.box.color = self.last2.box.color = Color('WHITE').rgba
  101. self.last, self.last2 = None, None
  102. if game.success():
  103. window.set_caption('彩色色块连连看——任务完成!')
  104. def success(self):
  105. return sum(sum(self.array,[]))==0
  106. @window.event
  107. def on_draw():
  108. window.clear()
  109. batch.draw()
  110. @window.event
  111. def on_mouse_press(x, y, dx, dy):
  112. ret = game.on_mouse_click(x, y)
  113. if ret and not game.success():
  114. window.set_caption(f'彩色色块连连看——坐标:{ret[0]} 颜色:{ret[1]}')
  115. game = Game()
  116. app.run()

第九步

实现同行或同列的连线,self.rc+self.rc2就能实现同行或同列的点连线。

if self.last.rect.color==self.last2.rect.color and ((self.rc*self.rc2) or (self.rc+self.rc2)):

代码

  1. from pyglet import *
  2. from colorlib import *
  3. W, H = 800, 600
  4. window = window.Window(W, H, caption='彩色方块连连看')
  5. gl.glClearColor(*Color('lightblue3').decimal)
  6. batch, group = graphics.Batch(),graphics.Group()
  7. row, col, space = 8, 10, 5
  8. w, h = W//(col+2), H//(row+2)
  9. x0, y0 = (W-(w+space)*col)//2, (H-(h+space)*row)//2
  10. COLOR = []
  11. while len(COLOR)<row*col//8:
  12. if (c:=randcolorTuple()) not in COLOR:
  13. COLOR.append(c)
  14. COLOR = sample(COLOR*8, row*col)
  15. class Box:
  16. def __init__(self, x, y, w, h, color, batch=batch):
  17. self.x, self.y, self.w, self.h = x, y, w, h
  18. self.rect = shapes.Rectangle(x, y, w, h, color=color, batch=batch)
  19. self.box = shapes.Box(x, y, w, h, color=Color('WHITE').rgba, thickness=3, batch=batch)
  20. self.box.group = group
  21. def hide(self):
  22. self.box.batch = self.rect.batch = None
  23. def on_mouse_over(self, x, y):
  24. return self.x<=x<=self.x+self.w and self.y<=y<=self.y+self.h
  25. class Matrix:
  26. def __init__(self, row=row, col=col):
  27. self.array = [[0]*col for _ in range(row)]
  28. def __repr__(self):
  29. return '\n'.join(map(str,self.array))+'\n'
  30. matrix = Matrix(row+2, col+2)
  31. Array, Boxes = matrix.array, Matrix().array
  32. for i in range(row):
  33. for j in range(col):
  34. Array[i+1][j+1] = 1
  35. for r,arr in enumerate(Boxes):
  36. for c,_ in enumerate(arr):
  37. Boxes[r][c] = Box(x0+c*(w+space), y0+r*(h+space), w, h, COLOR[c+r*len(arr)])
  38. class RC:
  39. def __init__(self, r=0, c=0):
  40. self.r, self.c = r, c
  41. def __repr__(self):
  42. return f'Rc({self.r}, {self.c})'
  43. def __and__(self, other):
  44. return self.r == other.r and self.c == other.c
  45. def __or__(self, other):
  46. return self.r == other.r or self.c == other.c
  47. def __eq__(self, other):
  48. return self & other
  49. def __lt__(self, other):
  50. return self.r == other.r and self.c != other.c
  51. def __gt__(self, other):
  52. return self.r != other.r and self.c == other.c
  53. def __le__(self, other):
  54. return self.r == other.r and self.c - other.c
  55. def __ge__(self, other):
  56. return self.c == other.c and self.r - other.r
  57. def __xor__(self, other):
  58. return self < other or self > other
  59. def __mod__(self, other):
  60. return [RC(self.r, other.c), RC(other.r, self.c)]
  61. def __truediv__(self, other):
  62. return 1 if self<other and (self<=other)<0 or self>other and (self>=other)<0 else -1
  63. def __add__(self, other):
  64. return abs(self<=other)==1 or abs(self>=other)==1
  65. def __sub__(self, other):
  66. if self<other: return [RC(self.r,_) for _ in range(self.c+(self/other),other.c,self/other)]
  67. if self>other: return [RC(_,self.c) for _ in range(self.r+(self/other),other.r,self/other)]
  68. return []
  69. def __mul__(self, other):
  70. if self<other: return not any(Array[self.r+1][_+1] for _ in range(self.c+(self/other),other.c,self/other))
  71. if self>other: return not any(Array[_+1][self.c+1] for _ in range(self.r+(self/other),other.r,self/other))
  72. return False
  73. class Game:
  74. def __init__(self):
  75. self.array = Array
  76. self.boxes = Boxes
  77. self.rc, self.rc2 = RC(), RC()
  78. self.last, self.last2 = None, None
  79. self.line = shapes.Line(0, 0, 0, 0, width=5, color=Color('light gold').rgba, batch=batch, group=group)
  80. self.line.visible = False
  81. def on_mouse_click(self, x, y):
  82. if self.line.visible or self.success(): return
  83. r, c = (y-y0)//(h+space), (x-x0)//(w+space)
  84. if r in range(row) and c in range(col) and self.boxes[r][c].on_mouse_over(x, y) and self.array[r+1][c+1]:
  85. if self.last is None and self.last2 is None:
  86. self.rc, self.last = RC(r, c), self.boxes[r][c]
  87. self.last.box.color = Color('RED').rgba
  88. elif self.last is not None and self.last2 is None:
  89. self.rc2, self.last2 = RC(r, c), self.boxes[r][c]
  90. self.last2.box.color = Color('RED').rgba
  91. if self.rc == self.rc2:
  92. self.last.box.color = Color('WHITE').rgba
  93. self.last, self.last2 = None, None
  94. else:
  95. self.line.x, self.line.y = self.getxy(r, c)
  96. self.line.x2, self.line.y2 = self.getxy(self.rc.r, self.rc.c)
  97. self.line.visible = True
  98. clock.schedule_interval(self.update, 0.3)
  99. return RC(r, c), Color(self.boxes[r][c].rect.color).name
  100. def getxy(self, row, col):
  101. return x0+col*(w+space)+w//2, y0+row*(h+space)+h//2
  102. def update(self, event):
  103. self.line.visible = False
  104. clock.unschedule(self.update)
  105. if self.last.rect.color==self.last2.rect.color and ((self.rc*self.rc2) or (self.rc+self.rc2)):
  106. self.last.hide(); self.last2.hide()
  107. self.array[self.rc.r+1][self.rc.c+1] = self.array[self.rc2.r+1][self.rc2.c+1] = 0
  108. print(matrix)
  109. else:
  110. self.last.box.color = self.last2.box.color = Color('WHITE').rgba
  111. self.last, self.last2 = None, None
  112. if game.success():
  113. window.set_caption('彩色色块连连看——任务完成!')
  114. def success(self):
  115. return sum(sum(self.array,[]))==0
  116. @window.event
  117. def on_draw():
  118. window.clear()
  119. batch.draw()
  120. @window.event
  121. def on_mouse_press(x, y, dx, dy):
  122. ret = game.on_mouse_click(x, y)
  123. if ret and not game.success():
  124. window.set_caption(f'彩色色块连连看——坐标:{ret[0]} 颜色:{ret[1]}')
  125. game = Game()
  126. app.run()

第十步

改写RC行列类完善更多的功能,见另一篇博文:

Python 妙用运算符重载——玩出“点”花样来-CSDN博客

RC行列改写成整数坐标点的类,完整的 pointlib.py代码如下:

class Point:
    def __init__(self, x=0, y=0):
        self.x, self.y = x, y
    def __repr__(self):
        return f'Point({self.x}, {self.y})'
    def __str__(self):
        return f'({self.x}, {self.y})'
    def __getitem__(self, index):
        if index in range(-2,2):
            return self.y if index in (1,-1) else self.x
        raise IndexError("Index out of range")
    def __setitem__(self, index, value):
        if index in (0, -2):
            self.x = value
        elif index in (1, -1):
            self.y = value
        else:
            raise IndexError("Index out of range.")
    @property
    def value(self):
        return self.x, self.y
    def __len__(self):
        return 2
    def __abs__(self):
        return Point(*map(abs,(self.x, self.y)))
    def __bool__(self):
        return self.x>=0 and self.y>=0
    def __neg__(self):
        return Point(-self.x, -self.y)
    def __pos__(self):
        return self(0, 1), self(0, -1), self(-1), self(1)
    def __call__(self, dx=0, dy=0):
        return Point(self.x + dx, self.y + dy)
    def __eq__(self, other):
        return self.x == other.x and self.y == other.y
    def __ne__(self, other):
        return self.x != other.x or self.y != other.y
    def __gt__(self, other):
        return self.x == other.x and self.y - other.y
    def __lt__(self, other):
        return self.y == other.y and self.x - other.x
    def __ge__(self, other):
        return self.x == other.x and abs(self.y - other.y)==1
    def __le__(self, other):
        return self.y == other.y and abs(self.x - other.x)==1
    def __and__(self, other):
        return self.x != other.x and self.y != other.y
    def __radd__(self, n):
        return self(0, n), self(0, -n), self(-n), self(n)
    def __or__(self, other):
        return self.x == other.x or self.y == other.y
    def __xor__(self, other):
        return self.x == other.x and self.y != other.y or self.x != other.x and self.y == other.y
    def __invert__(self):
        return Point(self.y, self.x)
    def __lshift__(self, other):
        return Point(self.x + other, self.y)
    def __rshift__(self, other):
        return Point(self.x, self.y + other)
    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)
    def __sub__(self, other):
        return ((self.x - other.x)**2 + (self.y - other.y)**2)**0.5
    def __mul__(self, other):
        return self >= other or self <= other
    def __truediv__(self, other):
        return (self^other) and (1 if (self<other)<0 or (self>other)<0 else -1)
    def __pow__(self, other):
        if self^other:
            if self<other: return [Point(_, self.y) for _ in range(self.x+(self/other),other.x,self/other)]
            if self>other: return [Point(self.x, _) for _ in range(self.y+(self/other),other.y,self/other)]
    def __mod__(self, other):
        return [Point(self.x, other.y), Point(other.x, self.y)]
    def __floordiv__(self, other):
        if self&other:
            mod1, mod2 = self % other
            return self**mod1 + [mod1] + mod1**other, self**mod2 + [mod2] + mod2**other
    def __rpow__(self, other):
        assert(isinstance(other, (tuple, list)) and len(other)==3)
        x, y, n = other
        return [Point(i, n) for i in range(min(x, self.x), max(x, self.x)+1)]
    def __rfloordiv__(self, other: tuple):
        assert(isinstance(other, (tuple, list)) and len(other)==3)
        x, y, n = other
        return [Point(n, i) for i in range(min(y, self.y), max(y, self.y)+1)]

第十一步

实现一个折角的连线,如下图a点到b点,只要判断a->c->b或者a->d->b是通路即可:

对角连线的核心函数:

    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

第十二步

实现两个折角的连线,如下图的P点,如它和指点坐标不是相邻也不是同行或同列并且一个折角也不能相连,那么它向上下左右逐点延伸,只要有一个点能与指点坐标一个折角相连就完成了两个折角的相连。

最终实现

用前两步的思路,进一步完善和改写各个类,以完成所有的各种连线情况: 

一、相邻

    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

四、以上3种情况

    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

完整代码

再加上键盘事件等功能:

ctrl+Z 恢复一步

ctrl+F 保留剩余方块的随机刷新

ctrl+R 保留所有方块的重新开始 

ctrl+S 全部刷新的重新开始

完整代码: 

  1. from pyglet import *
  2. from colorlib import *
  3. from pointlib import Point
  4. from pyglet.window import key
  5. W, H = 800, 600
  6. window = window.Window(W, H)
  7. gl.glClearColor(*Color('lightblue3').decimal)
  8. batch, batch2, group = graphics.Batch(), graphics.Batch(), graphics.Group()
  9. row, col, space = 8, 10, 5
  10. w, h = W//(col+2), H//(row+2)
  11. x0, y0 = (W-(w+space)*col)//2, (H-(h+space)*row)//2
  12. sound1, sound2 = media.load('box.mp3'), media.load('box2.mp3')
  13. def randColor():
  14. COLOR = []
  15. while len(COLOR)<row*col//4:
  16. if not ((c:=randcolorTuple()) in COLOR or Color(c).name[-1] in '0123456789'):
  17. COLOR.append(c)
  18. return sample(COLOR*4, row*col)
  19. class Box:
  20. def __init__(self, x, y, w, h, color, batch=batch):
  21. self.x, self.y, self.w, self.h = x, y, w, h
  22. self.rect = shapes.Rectangle(x, y, w, h, color=color, batch=batch)
  23. self.box = shapes.Box(x, y, w, h, color=Color('WHITE').rgba, thickness=3, batch=batch)
  24. def hide(self):
  25. self.box.batch = self.rect.batch = None
  26. def show(self):
  27. self.box.batch = self.rect.batch = batch
  28. def on_mouse_over(self, x, y):
  29. return self.x<=x<=self.x+self.w and self.y<=y<=self.y+self.h
  30. class Matrix:
  31. def __init__(self, r=row, c=col):
  32. self.array = [[1]*c for _ in range(r)]
  33. self.point = []
  34. self.lines = [shapes.Line(*[-3]*4, width=5, color=Color('light gold').rgba,
  35. batch=batch2, group=group) for _ in range(5)]
  36. for line in self.lines: line.visible = False
  37. def __repr__(self):
  38. return '\n'.join(map(str,self.array))+'\n'
  39. def true(self, point):
  40. try: return self.array[point.x+1][point.y+1]
  41. except: return 0
  42. def alltrue(self, points):
  43. if isinstance(points,(tuple,list)) and all(isinstance(p, Point) for p in points):
  44. try: return all(self.array[p.x+1][p.y+1] for p in points)
  45. except: return 0
  46. def adjacent(self, point1, point2):
  47. return point1*point2
  48. def inline(self, point1, point2):
  49. return point1^point2 and self.alltrue(point1**point2)
  50. def diagonal(self, point1, point2):
  51. if point1&point2:
  52. for point in point1%point2:
  53. state1 = self.adjacent(point, point1) or self.inline(point, point1)
  54. state2 = self.adjacent(point, point2) or self.inline(point, point2)
  55. if self.true(point) and state1 and state2:
  56. self.point.append(point)
  57. return True
  58. def connect1(self, p1, p2):
  59. return self.adjacent(p1, p2) or self.inline(p1, p2) or self.diagonal(p1, p2)
  60. def connect2(self, p1, p2):
  61. for i in range(1, max(row, col)):
  62. for p in zip(i+p1, i+p2):
  63. for i in range(2):
  64. if self.true(p[i]) and (self.adjacent(p[i],(p1,p2)[i]) or
  65. self.inline(p[i],(p1,p2)[i]))and self.diagonal(p[i], (p2,p1)[i]):
  66. self.point.append(p[i])
  67. return True
  68. def connect(self, p1, p2):
  69. if (ret := self.connect1(p1, p2) or self.connect2(p1, p2)):
  70. self.showlines(p1, p2)
  71. return ret
  72. def getxy(self, row, col):
  73. return x0+col*(w+space)+w//2, y0+row*(h+space)+h//2
  74. def drawline(self, *args):
  75. for i,p in enumerate(args[:-1]):
  76. self.lines[i].x, self.lines[i].y = self.getxy(*p)
  77. self.lines[i].x2, self.lines[i].y2 = self.getxy(*args[i+1])
  78. self.lines[i].visible = True
  79. def showlines(self, point1, point2):
  80. if len(self.point)==3: self.point.pop(0)
  81. if len(self.point)==2 and not self.point[0]^point1: self.point.reverse()
  82. points = point1, *self.point, point2
  83. self.drawline(*points)
  84. self.point.clear()
  85. def hidelines(self):
  86. for line in self.lines: line.visible = False
  87. def linevisible(self):
  88. return self.lines[0].visible
  89. def initMatrix(row, col):
  90. global matrix, Array, Boxes
  91. matrix = Matrix(row+2, col+2)
  92. Array, Boxes = matrix.array, Matrix().array
  93. for i in range(row):
  94. for j in range(col):
  95. Array[i+1][j+1] = 0
  96. COLOR = randColor()
  97. for r,arr in enumerate(Boxes):
  98. for c,_ in enumerate(arr):
  99. Boxes[r][c] = Box(x0+c*(w+space), y0+r*(h+space), w, h, COLOR[c+r*len(arr)])
  100. class Game:
  101. def __init__(self):
  102. initMatrix(row, col)
  103. self.rc, self.rc2 = Point(), Point()
  104. self.array, self.boxes = Array, Boxes
  105. self.last1, self.last2, self.lastz = None, None, None
  106. self.label1 = text.Label('Congratulations!', color=Color().randcolor().rgba, font_size=50,
  107. x=W//2, y=H//2+80, anchor_x='center', anchor_y='center', bold=True, batch=batch)
  108. self.label2 = text.Label('Any key to restart...', color=Color().randcolor().rgba, font_size=36,
  109. x=W//2, y=H//2-50, anchor_x='center', anchor_y='center', bold=True, batch=batch)
  110. def on_mouse_click(self, x, y):
  111. if matrix.linevisible(): return
  112. if self.success(): main(event)
  113. r, c = (y-y0)//(h+space), (x-x0)//(w+space)
  114. if r in range(row) and c in range(col) and self.boxes[r][c].on_mouse_over(x, y) and not self.array[r+1][c+1]:
  115. if self.last1 is None and self.last2 is None:
  116. self.rc, self.last1 = Point(r, c), self.boxes[r][c]
  117. self.last1.box.color = Color('RED').rgba
  118. elif self.last1 is not None and self.last2 is None:
  119. self.rc2, self.last2 = Point(r, c), self.boxes[r][c]
  120. self.last2.box.color = Color('RED').rgba
  121. if self.rc == self.rc2:
  122. self.last1.box.color = Color('WHITE').rgba
  123. self.last1, self.last2 = None, None
  124. else:
  125. if self.last1.rect.color==self.last2.rect.color:
  126. matrix.connect(self.rc, self.rc2)
  127. clock.schedule_interval(self.update, 0.5)
  128. return (r, c), Color(self.boxes[r][c].rect.color).name
  129. def update(self, event):
  130. clock.unschedule(self.update)
  131. if self.last1.rect.color==self.last2.rect.color and matrix.connect(self.rc, self.rc2):
  132. self.hide()
  133. sound1.play()
  134. else:
  135. sound2.play()
  136. self.last1.box.color = self.last2.box.color = Color('WHITE').rgba
  137. self.lastz = self.last1, self.last2
  138. self.last1, self.last2 = None, None
  139. matrix.hidelines()
  140. if game.success():
  141. window.set_caption('彩色方块连连看——任务完成!')
  142. game.label1.batch = game.label2.batch = batch2
  143. clock.schedule_interval(main, 5) # 5秒后自动开始
  144. def hide(self):
  145. self.last1.hide(); self.last2.hide()
  146. self.array[self.rc.x+1][self.rc.y+1] = self.array[self.rc2.x+1][self.rc2.y+1] = 1
  147. def unhide(self):
  148. self.lastz[0].show(); self.lastz[1].show()
  149. self.array[self.rc.x+1][self.rc.y+1] = self.array[self.rc2.x+1][self.rc2.y+1] = 0
  150. def success(self):
  151. return sum(sum(self.array,[]))==(row+2)*(col+2)
  152. def main(event):
  153. global game
  154. game = Game()
  155. game.label1.batch = game.label2.batch = None
  156. window.set_caption('彩色方块连连看')
  157. clock.unschedule(main)
  158. @window.event
  159. def on_draw():
  160. window.clear()
  161. batch.draw()
  162. batch2.draw()
  163. @window.event
  164. def on_mouse_press(x, y, dx, dy):
  165. if (ret := game.on_mouse_click(x, y)):
  166. window.set_caption(f'彩色方块连连看——坐标:{ret[0]} 颜色:{ret[1]}')
  167. @window.event
  168. def on_key_press(symbol, modifiers):
  169. if game.success(): main(event)
  170. if symbol == key.S and modifiers & key.MOD_CTRL:
  171. main(event)
  172. elif symbol == key.Z and modifiers & key.MOD_CTRL:
  173. game.unhide()
  174. elif symbol == key.R and modifiers & key.MOD_CTRL:
  175. for i in range(row):
  176. for j in range(col):
  177. Array[i+1][j+1], Boxes[i][j].box.batch, Boxes[i][j].rect.batch = 0, batch, batch
  178. elif symbol == key.F and modifiers & key.MOD_CTRL:
  179. if sum(sum(game.array,[]))%2: return
  180. boxsample = []
  181. for i,arr in enumerate(Array[1:-1]):
  182. for j,n in enumerate(arr[1:-1]):
  183. if n==0: boxsample.append(Boxes[i][j].rect.color)
  184. boxsample = sample(boxsample,len(boxsample))
  185. for i,arr in enumerate(Array[1:-1]):
  186. for j,n in enumerate(arr[1:-1]):
  187. if n==0: Boxes[i][j].rect.color = boxsample.pop()
  188. main(event)
  189. app.run()

运行效果

目录

“彩色方块连连看”游戏(续)

第八步

第九步

第十步

第十一步

第十二步

最终实现

完整代码

运行效果


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/398890
推荐阅读
相关标签
  

闽ICP备14008679号