python开发的连连看小游戏

这篇具有很好参考价值的文章主要介绍了python开发的连连看小游戏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

说明:

1.在网上找了一个基础版本改进而来,大概增加了200行代码,相对原版要复杂一些;

2.界面采用tkinter开发,比较简单;

3.新增了连接线功能;

4.新增了积分功能;

5.新增了陷入死局时,重新打散功能;

6.新增了关卡功能,目前设置了5关;

7.新增了计算当前地图有多少可连通图标功能。

陷入死局时,效果如下:

python开发的连连看小游戏

打散后,重新排列,然后聚在一起:

python开发的连连看小游戏

 进入下一关界面:

python开发的连连看小游戏

 进入第二关效果如下:

python开发的连连看小游戏

 后面的关卡与上面类似。

源代码只有一个文件,用到的库比较少、比较小,安装起来很容易。代码如下:

from tkinter import BOTH,FIRST,LAST,GROOVE,FLAT
import os, random
import tkinter as tk
import tkinter.messagebox
import numpy as np
from PIL import Image, ImageTk
import time
from playsound import playsound

class MainWindow():
    __gameTitle = "连连看游戏"
    __windowWidth = 600
    __windowHeigth = 500
    __gameSize = 10 # 游戏尺寸
    __iconKind = __gameSize * __gameSize / 4 # 小图片种类数量
    __iconWidth = 40
    __iconHeight = 40
    __map = [] # 游戏地图
    __delta = 25
    __isFirst = True
    __isGameStart = False
    __formerPoint = None
    EMPTY = -1
    NONE_LINK = 0
    STRAIGHT_LINK = 1
    ONE_CORNER_LINK = 2
    TWO_CORNER_LINK = 3
    __images = []#蒙板阴影图像
    __level = 1#游戏关卡
    __point_position = {}
    __score = 0

    def __init__(self):
        self.__root = tk.Tk()
        self.__root.title(self.__gameTitle)
        self.centerWindow(self.__windowWidth, self.__windowHeigth)
        self.__root.minsize(460, 460)

        self.__addComponets()
        self.new_game()
        
        self.__root.mainloop()
        
       
    #菜单栏中添加一个叫“游戏”的菜单项
    def __addComponets(self):
        #菜单栏
        self.menubar = tk.Menu(self.__root, bg="lightgrey", fg="black")
        
        #子菜单
        self.file_menu = tk.Menu(self.menubar, tearoff=0, bg="lightgrey", fg="black")
        self.file_menu.add_command(label="新游戏", command=self.new_game, accelerator="Ctrl+N")
        
        self.menubar.add_cascade(label="游戏", menu=self.file_menu)
        self.__root.configure(menu=self.menubar)
        self.__root.bind('<Control-n>',self.new_game)#实现快捷键功能ctrl+N
        #
        self.canvas = tk.Canvas(self.__root, bg = '#D3D3D3', width = 450, height = 450,cursor="hand2")
        self.canvas.grid(row=0,column=0,sticky='N',pady = 5,rowspan=2,padx=(50,0))
        self.canvas.bind('<Button-1>', self.clickCanvas)
        #分数面板
        self.label_score = tkinter.Label(self.__root,width=10,height=2,font=('黑体',13,'bold'),fg="#802A2A",bg="#F5DEB3")
        self.label_score.grid(row=0,column=1)
        #显示当前可连接数
        self.label_linknums = tkinter.Label(self.__root,width=10,height=2,font=('黑体',13,'bold'),fg="#228B22")
        self.label_linknums.grid(row=1,column=1)
    
    '''
    判断两个接点之间是否能连通
    '''
    def __isLink(self,fromPoint,point):
        return self.isStraightLink(fromPoint,point) or self.isOneCornerLink(fromPoint,point) or self.isTwoCornerLink(fromPoint,point)
    
    '''
    获取提示,逻辑有点复杂,主要解决以下问题:
    1.获取当前地图上所有的图标;
    2.然后遍历,计算有多少对可连通的图标;
    3.如果有三个或者四个相同的图标可以相互连通,要进行判断,以勉出现重复计算。
    '''
    def getPromptPoint(self):
        _link_point = []
        
        _icons_arr = self.__map.flatten()#先转化为一维数组,便于操作
        for i in set(_icons_arr):
            if i == self.EMPTY: continue #忽略为空的坐标
            _arr = np.where(_icons_arr==i)[0]#元组的第一个元素,是由i元素的索引组成的数组
            if _arr.size == 4:#剩下4个相同图标
                _point1 = Point(int(_arr[0]%10),int(_arr[0]/10))# 计算x,y坐标
                _point2 = Point(int(_arr[1]%10),int(_arr[1]/10))
                _point3 = Point(int(_arr[2]%10),int(_arr[2]/10))
                _point4 = Point(int(_arr[3]%10),int(_arr[3]/10))
                #4个接点6条线,但最多只能计算2条线,再多就会出现重复计数
                if self.__isLink(_point1,_point2):
                    _link_point.append((_point1,_point2))
                    if self.__isLink(_point3,_point4):
                        _link_point.append((_point3,_point4))
                elif self.__isLink(_point1,_point3):
                    _link_point.append((_point1,_point3))
                    if self.__isLink(_point2,_point4):
                        _link_point.append((_point2,_point4))
                elif self.__isLink(_point1,_point4):
                    _link_point.append((_point1,_point4))
                    if self.__isLink(_point2,_point3):
                        _link_point.append((_point2,_point3))
                elif self.__isLink(_point2,_point3):
                    _link_point.append((_point2,_point3))
                elif self.__isLink(_point2,_point4):
                    _link_point.append((_point2,_point4))
                elif self.__isLink(_point3,_point4):
                    _link_point.append((_point3,_point4))    
                    
            elif _arr.size == 2:#剩下2个相同图标
                _point1 = Point(int(_arr[0]%10),int(_arr[0]/10))# 计算x,y坐标
                _point2 = Point(int(_arr[1]%10),int(_arr[1]/10))
                if self.__isLink(_point1,_point2):
                    _link_point.append((_point1,_point2))
                    
        self.label_linknums['text'] = f"{len(_link_point)}连"

        print("_link_point",_link_point)
        return _link_point
    
    
    def centerWindow(self, width, height):#700 500
        screenwidth = self.__root.winfo_screenwidth()#窗口距离屏幕左边的宽
        screenheight = self.__root.winfo_screenheight()#窗口距离屏幕顶部的高
        size = '%dx%d+%d+%d' % (width, height, (screenwidth - width)/2, (screenheight - height)/2)
        self.__root.geometry(size)


    def add_score(self):
        self.__score += 2 #消除一对图标,分数加2
        self.set_label_text()
        
    def set_label_text(self):
        self.label_score['text'] = f"{self.__score}分"
        
    '''
    这个方法需要注意的积分问题:
    1.开始新游戏时,将积分清零;
    2.开始下一关时,将前一关的积分累积起来。
    '''
    def new_game(self, event=None,level=1,score = 0):
        self.__score = score
        self.set_label_text()
        self.__level = level
        self.extractSmallIconList()
        self.iniMap()
        self.drawMap()
        self.getPromptPoint()
        
        self.__isGameStart = True
    
    def clickCanvas(self, event):
        if not self.__isGameStart:
            return
        
        # 确认有效点击坐标
        point = self.getInnerPoint(Point(event.x, event.y))
        if not point.isUserful() or self.isEmptyInMap(point):
            return
        
        #__isFirst在三种情况下为True,1.游戏开始的时候;2.同一个图标点击了两次;3.成功消除一组图标。
        if self.__isFirst:
            self.drawSelectedArea(point)
            self.__isFirst= False
            self.__formerPoint = point
        else:
            if self.__formerPoint.isEqual(point):#两次点击的是同一个图标
                self.__isFirst = True
                self.canvas.delete("rectRedOne")
                self.canvas.delete('image_mask')
            else:
                linkType = self.getLinkType(self.__formerPoint, point)
                if linkType['type'] != self.NONE_LINK:
                    #画连接线
                    self.draw_link_line(self.__formerPoint,point,linkType)
                    playsound("music2.mp3")
                    time.sleep(.5)# 显示画线的延迟
                    
                    self.ClearLinkedBlocks(self.__formerPoint, point)
                    self.canvas.delete("rectRedOne")
                    self.canvas.delete("linkline")
                    self.canvas.delete('image_mask')
                    #增加分数
                    self.add_score()
                            
                    _link_point = self.getPromptPoint()
                    self.__isFirst = True
                    if len(_link_point) == 0:
                        if self.isGameEnd():
                            if tk.messagebox.askokcancel('确认操作', '是否进入下一关?'):
                                self.__level = self.__level+1
                                self.new_game(level = self.__level,score = self.__score)
                            else:
                                self.__isGameStart = False
                        else: #没有可连通图标,且当前地图上还有图标存在,游戏未结束时,打散当前地图
                            tk.messagebox.showinfo("提示", "已没有可连通图标,需重新打散!")
                            self.shuffleMap()
                            self.drawMap()
                            self.getPromptPoint()
                else:
                    self.__formerPoint = point
                    self.canvas.delete("rectRedOne")
                    self.drawSelectedArea(point)

    # 判断游戏是否结束
    def isGameEnd(self):
        for y in range(0, self.__gameSize):
            for x in range(0, self.__gameSize):
                if self.__map[y][x] != self.EMPTY:
                    return False
        return True
    
    '''
    消除图像前,把两个图像之间的连接线画出来。
    '''
    def draw_link_line(self,formerPoint,point,linkType):
        if linkType['type'] == self.STRAIGHT_LINK:
            p1 = self.getOuterCenterPoint(formerPoint)
            p2 = self.getOuterCenterPoint(point)
            
            #arrow表示线的箭头样式,默认不带箭头,参数值 FIRST表示添加箭头带线段开始位置,LAST表示到末尾占位置,BOTH表示两端均添加
            self.canvas.create_line((p1.x, p1.y),(p2.x, p2.y),fill = 'red',tags = 'linkline',width=3, arrow=LAST)
        if linkType['type'] == self.ONE_CORNER_LINK:           
            corner1 = self.getOuterCenterPoint(linkType["p1"])
            
            p1 = self.getOuterFitCenterPoint(formerPoint,corner1)
            p2 = self.getOuterFitCenterPoint(point,corner1)
            
            self.canvas.create_line((p1.x, p1.y),(corner1.x, corner1.y),fill = 'red',tags = 'linkline',width=3)
            self.canvas.create_line((p2.x, p2.y),(corner1.x, corner1.y),fill = 'red',tags = 'linkline',width=3, arrow=FIRST)
        elif linkType['type'] == self.TWO_CORNER_LINK:
            corner1 = self.getOuterCenterPoint(linkType["p1"])
            corner2 = self.getOuterCenterPoint(linkType["p2"])
            
            p1 = self.getOuterFitCenterPoint(formerPoint,corner1)
            p2 = self.getOuterFitCenterPoint(point,corner2)
                    
            self.canvas.create_line((p1.x, p1.y),(corner1.x, corner1.y),fill = 'red',tags = 'linkline',width=3)
            self.canvas.create_line((p2.x, p2.y),(corner2.x, corner2.y),fill = 'red',tags = 'linkline',width=3, arrow=FIRST)
            self.canvas.create_line((corner1.x, corner1.y),(corner2.x, corner2.y),fill = 'red',tags = 'linkline',width=3)
        self.canvas.update()

    '''
    提取小头像数组
    '''
    def extractSmallIconList(self):
        self.__icons = []
        imageSouce = Image.open(f"图片/new{self.__level}.png")
        for index in range(0, int(self.__iconKind)):#0-24
            region = imageSouce.crop((self.__iconWidth * index, 0, 
                    self.__iconWidth * index + self.__iconWidth - 1, self.__iconHeight - 1))
            self.__icons.append(ImageTk.PhotoImage(region))

    '''
    初始化地图 存值为0-24
    '''
    def iniMap(self):
        self.__map = [] # 重置地图
        _tmpRecords = []
        
        # 0-24,一共25个图标,每个图标出现4次,总共出现100次
        _total = self.__gameSize * self.__gameSize
        _tmpRecords = np.linspace(0, self.__iconKind, _total, endpoint = False,dtype=int) 
        np.random.shuffle(_tmpRecords)#重新打散洗牌
        self.__map = _tmpRecords.reshape((10,10))#将一维数组100,转化为二维10*10

    '''
    初始化地图 存值为0-24,当前地图中,如果没有可连通路线、进入死局时,将现有的图标进行打散重新洗牌。
    '''
    def shuffleMap(self):
        _icons_arr = self.__map.flatten()#先转化为一维数组,便于操作
        self.__map = []#重置地图
        for i in set(_icons_arr):
            if i == self.EMPTY: continue
            _tuple = np.where(_icons_arr==i)[0]#元组的第一个元素,是由i元素的索引组成的数组
            self.__map.extend([i]* _tuple.size)#第i个图标出现的次数

        np.random.shuffle(self.__map)#洗牌
        _len = len(self.__map)
        _total = self.__gameSize * self.__gameSize
        self.__map[_len:_total] = [self.EMPTY]*(_total-_len)#剩余元素置为空(-1),填满至整个地图0-99
        self.__map = np.array(self.__map).reshape((self.__gameSize,self.__gameSize))#转化为二维数组10*10


    '''
    根据地图绘制图像
    1.在使用create_image()函数时,需要先通过Pillow库(或其他图片处理库)读取图片文件并生成图片对象,然后再将这个图片对象传递给create_image()函数,在指定的坐标位置将图片添加到画布上。
    2.canvas.create_image(x, y, image=图像对象, anchor=定位点),x和y表示图像锚点在画布上的位置,即图像在画布上的左上角坐标。image参数是一个tkinter中的PhotoImage()对象,它可以指定要加载的图像文件。anchor参数是一个字符串,用于指定图像锚点的位置,可以是"nw"(左上角)、"n"(上)、"ne"(右上角)、"w"(左)、"center"(中心)、"e"(右)、"sw"(左下角)或"s"(下)。如果不指定anchor参数,则默认为“center”。
    '''
    def drawMap(self):
        self.canvas.delete("all")#字符串"all""是代表画布上所有项目的特殊标记
        for y in range(0, self.__gameSize):
            for x in range(0, self.__gameSize):
                point = self.getOuterLeftTopPoint(Point(x, y))
                if self.__map[y][x] != self.EMPTY:#打散重绘时,不再置空的图标
                    self.canvas.create_image((point.x, point.y),image=self.__icons[self.__map[y][x]], anchor='nw', tags = 'im%d%d' % (x, y))

                
    '''
    根据两点不同的位置,获取对应边的中心连接点。例如目标图标在左边,就取靠左的一边的中点。如果连接目标在右边,就取靠右一边的中点坐标。
    '''
    def getOuterFitCenterPoint(self, formerPoint, corner):
        _formerPoint = self.getOuterCenterPoint(formerPoint)
        if _formerPoint.y>corner.y:
            fitCenterPoint = Point(self.getX(formerPoint.x) + int(self.__iconWidth / 2),self.getY(formerPoint.y))#顶边
        elif _formerPoint.y<corner.y:
            fitCenterPoint = Point(self.getX(formerPoint.x) + int(self.__iconWidth / 2),self.getY(formerPoint.y) + int(self.__iconHeight))#底边
        elif _formerPoint.y == corner.y:
            if _formerPoint.x > corner.x:
                fitCenterPoint = Point(self.getX(formerPoint.x),self.getY(formerPoint.y)+int(self.__iconHeight / 2))#左边
            elif _formerPoint.x < corner.x:
                fitCenterPoint = Point(self.getX(formerPoint.x) + int(self.__iconWidth),self.getY(formerPoint.y)+int(self.__iconHeight / 2))#右边
                    
        return fitCenterPoint
       
    '''
    获取内部坐标对应矩形左上角顶点坐标
    '''
    def getOuterLeftTopPoint(self, point):
        return Point(self.getX(point.x), self.getY(point.y))

    '''
    获取内部坐标对应矩形中心坐标
    '''
    def getOuterCenterPoint(self, point):
        return Point(self.getX(point.x) + int(self.__iconWidth / 2), 
                self.getY(point.y) + int(self.__iconHeight / 2))
    
    def getX(self, x):# x * 40 + 25
        return x * self.__iconWidth + self.__delta

    def getY(self, y):
        return y * self.__iconHeight + self.__delta

    '''
    获取内部坐标
    '''
    def getInnerPoint(self, point):
        x = -1
        y = -1

        for i in range(0, self.__gameSize):
            x1 = self.getX(i)
            x2 = self.getX(i + 1)
            if point.x >= x1 and point.x < x2:
                x = i

        for j in range(0, self.__gameSize):
            j1 = self.getY(j)
            j2 = self.getY(j + 1)
            if point.y >= j1 and point.y < j2:
                y = j

        return Point(x, y)

    '''
    创建一块蒙板,覆盖到选中的图形上
    '''
    def create_mask(self,x1, y1, x2, y2, **kwargs):
        #(0,0,0)代表黑色的RGB,127代表alpha透明度,(x2-x1, y2-y1)指长宽
        image = Image.new('RGBA', (x2-x1, y2-y1), (0,0,0,127))
        self.__images = [ImageTk.PhotoImage(image)]#这里一定要用一个实例变量存储,局部变量没有效果,原因不清楚
        self.canvas.create_image(x1, y1, image=self.__images[0], anchor='nw',tags = "image_mask")
    
    '''
    选择的区域变红,point为内部坐标
    '''
    def drawSelectedArea(self, point):
        pointLT = self.getOuterLeftTopPoint(point)
        pointRB = self.getOuterLeftTopPoint(Point(point.x + 1, point.y + 1))
        
        self.canvas.create_rectangle(pointLT.x, pointLT.y, pointRB.x - 1, pointRB.y - 1, outline = 'red', tags = "rectRedOne", width=2)
        #蒙板
        self.create_mask(pointLT.x, pointLT.y, pointRB.x - 1, pointRB.y - 1, fill='skyblue', alpha=.5,width=0)
        
    '''
    消除连通的两个块
    '''
    def ClearLinkedBlocks(self, p1, p2):
        self.__map[p1.y][p1.x] = self.EMPTY
        self.__map[p2.y][p2.x] = self.EMPTY
        self.canvas.delete('im%d%d' % (p1.x, p1.y))
        self.canvas.delete('im%d%d' % (p2.x, p2.y))

    '''
    地图上该点是否为空
    '''
    def isEmptyInMap(self, point):
        if self.__map[point.y][point.x] == self.EMPTY:
            return True
        else:
            return False

    '''
    获取两个点连通类型
    '''
    def getLinkType(self, p1, p2):
        # 首先判断两个方块中图片是否相同
        if self.__map[p1.y][p1.x] != self.__map[p2.y][p2.x]:
            return { 'type': self.NONE_LINK }

        if self.isStraightLink(p1, p2):
            return {
                'type': self.STRAIGHT_LINK
            }
        res = self.isOneCornerLink(p1, p2)
        if res:
            return {
                'type': self.ONE_CORNER_LINK,
                'p1': res
            }
        res = self.isTwoCornerLink(p1, p2)
        if res:
            return {
                'type': self.TWO_CORNER_LINK,
                'p1': res['p1'],
                'p2': res['p2']
            }
        return {
            'type': self.NONE_LINK
        }


    '''
    直连
    '''
    def isStraightLink(self, p1, p2):
        start = -1
        end = -1
        # 水平
        if p1.y == p2.y:
            # 大小判断
            if p2.x < p1.x:
                start = p2.x
                end = p1.x
            else:
                start = p1.x
                end = p2.x
            for x in range(start + 1, end):
                if self.__map[p1.y][x] != self.EMPTY:
                    return False
            return True
        elif p1.x == p2.x:
            if p1.y > p2.y:
                start = p2.y
                end = p1.y
            else:
                start = p1.y
                end = p2.y
            for y in range(start + 1, end):
                if self.__map[y][p1.x] != self.EMPTY:
                    return False
            return True
        return False

    def isOneCornerLink(self, p1, p2):
        pointCorner = Point(p1.x, p2.y)
        if self.isStraightLink(p1, pointCorner) and self.isStraightLink(pointCorner, p2) and self.isEmptyInMap(pointCorner):
            return pointCorner

        pointCorner = Point(p2.x, p1.y)
        if self.isStraightLink(p1, pointCorner) and self.isStraightLink(pointCorner, p2) and self.isEmptyInMap(pointCorner):
            return pointCorner

    def isTwoCornerLink(self, p1, p2):
        for y in range(-1, self.__gameSize + 1):
            pointCorner1 = Point(p1.x, y)
            pointCorner2 = Point(p2.x, y)
            if y == p1.y or y == p2.y:
                continue
            if y == -1 or y == self.__gameSize:
                if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner2, p2):
                    return {'p1': pointCorner1, 'p2': pointCorner2}
            else:
                if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner1, pointCorner2) and self.isStraightLink(pointCorner2, p2) and self.isEmptyInMap(pointCorner1) and self.isEmptyInMap(pointCorner2):
                    return {'p1': pointCorner1, 'p2': pointCorner2}

        # 横向判断
        for x in range(-1, self.__gameSize + 1):
            pointCorner1 = Point(x, p1.y)
            pointCorner2 = Point(x, p2.y)
            if x == p1.x or x == p2.x:
                continue
            if x == -1 or x == self.__gameSize:
                if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner2, p2):
                    return {'p1': pointCorner1, 'p2': pointCorner2}
            else:
                if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner1, pointCorner2) and self.isStraightLink(pointCorner2, p2) and self.isEmptyInMap(pointCorner1) and self.isEmptyInMap(pointCorner2):
                    return {'p1': pointCorner1, 'p2': pointCorner2}


class Point():
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def isUserful(self):
        if self.x >= 0 and self.y >= 0:
            return True
        else:
            return False
                    
    '''
    判断两个点是否相同
    '''
    def isEqual(self, point):
        if self.x == point.x and self.y == point.y:
            return True
        else:
            return False

    '''
    克隆一份对象
    '''
    def clone(self):
        return Point(self.x, self.y)

    '''
    改为另一个对象
    '''
    def changeTo(self, point):
        self.x = point.x
        self.y = point.y
      
    '''
    显示坐标
    '''
    def __repr__(self):
        return f"x={self.x},y={self.y}"
   
MainWindow()

再提一点,就是游戏地图的制作,原理就是找25张图片,把它们压缩成40*40像素的图标,然后横排合成一张图。在网上找了很久,也没发现靠谱的软件,其实用python程序就能实现这个功能。

代码来源:

使用Python批量拼接图片_python多图合并成一张图_谢欣桁的博客-CSDN博客

稍微改了下:

import os
import math
from PIL import Image
 
 
def merge_images(image_folder, output_file, n, m):
    # 获取所有图像文件的列表
    image_files = [os.path.join(image_folder, f) for f in os.listdir(image_folder) if f.endswith('.png')]
 
    # 计算每个小图像的大小和大图像的大小
    image_count = len(image_files)
    if image_count == 0:
        print('No image files found in the directory:', image_folder)
        return
 
    # 计算小图像的大小以及大图像的大小
    img = Image.open(image_files[0])
#     img_size0 = img.size[0]
#     img_size1 = img.size[1]
    img_size0 = 40
    img_size1 = 40
    new_img_size0 = img_size0 * n
    new_img_size1 = img_size1 * m
 
    # 创建一个新的大图像
    new_img = Image.new('RGB', (new_img_size0, new_img_size1), 'white')
 
    # 将所有小图像粘贴到新图像的正确位置
    for i, f in enumerate(image_files):
        row = int(i / n)
        col = i % n
        img = Image.open(f)
        img = img.resize((img_size0, img_size1))
        new_img.paste(img, (col * img_size0, row * img_size1))
 
    # 保存大图像
    new_img.save(output_file)
 
 
# 用法示例
image_folder = 'C:/Users/Administrator/Desktop/图标/卡通' #目录下放25张png图片
output_file = 'C:/Users/Administrator/Desktop/图标/卡通/new5.png'#运行程序合成一张图
n = 25  # 每行显示的图像数
m = 1  # 每列显示的图像数
merge_images(image_folder, output_file, n, m)

2023.6.16日更新:通过chatGPT对部分代码进行了改进,代码精简了一些。

精简版代码如下:

# -*- coding: utf-8 -*-

from tkinter import BOTH,FIRST,LAST,GROOVE,FLAT
import os, random
import tkinter as tk
import tkinter.messagebox
import numpy as np
from PIL import Image, ImageTk
import time
from playsound import playsound
 
class MainWindow():
    __gameTitle = "连连看游戏"
    __windowWidth = 600
    __windowHeigth = 500
    __gameSize = 10 # 游戏尺寸
    __iconKind = __gameSize * __gameSize / 4 # 小图片种类数量
    __iconWidth = 40
    __iconHeight = 40
    __map = [] # 游戏地图
    __delta = 25
    __isFirst = True
    __isGameStart = False
    __formerPoint = None
    EMPTY = -1
    NONE_LINK = 0
    STRAIGHT_LINK = 1
    ONE_CORNER_LINK = 2
    TWO_CORNER_LINK = 3
    __images = []#蒙板阴影图像
    __level = 1#游戏关卡
    __point_position = {}
    __score = 0
 
    def __init__(self):
        self.__root = tk.Tk()
        self.__root.title(self.__gameTitle)
        self.centerWindow(self.__windowWidth, self.__windowHeigth)
        self.__root.minsize(460, 460)
 
        self.__addComponets()
        self.new_game()
        
        self.__root.mainloop()
        
       
    #菜单栏中添加一个叫“游戏”的菜单项
    def __addComponets(self):
        #菜单栏
        self.menubar = tk.Menu(self.__root, bg="lightgrey", fg="black")
        
        #子菜单
        self.file_menu = tk.Menu(self.menubar, tearoff=0, bg="lightgrey", fg="black")
        self.file_menu.add_command(label="新游戏", command=self.new_game, accelerator="Ctrl+N")
        
        self.menubar.add_cascade(label="游戏", menu=self.file_menu)
        self.__root.configure(menu=self.menubar)
        self.__root.bind('<Control-n>',self.new_game)#实现快捷键功能ctrl+N
        #
        self.canvas = tk.Canvas(self.__root, bg = '#D3D3D3', width = 450, height = 450,cursor="hand2")
        self.canvas.grid(row=0,column=0,sticky='N',pady = 5,rowspan=2,padx=(50,0))
        self.canvas.bind('<Button-1>', self.clickCanvas)
        #分数面板
        self.label_score = tkinter.Label(self.__root,width=10,height=2,font=('黑体',13,'bold'),fg="#802A2A",bg="#F5DEB3")
        self.label_score.grid(row=0,column=1)
        #显示当前可连接数
        self.label_linknums = tkinter.Label(self.__root,width=10,height=2,font=('黑体',13,'bold'),fg="#228B22")
        self.label_linknums.grid(row=1,column=1)
    
    '''
    判断两个接点之间是否能连通
    '''
    def __isLink(self,fromPoint,point):
        return self.isStraightLink(fromPoint,point) or self.isOneCornerLink(fromPoint,point) or self.isTwoCornerLink(fromPoint,point)
    
    '''
    获取提示,逻辑有点复杂,主要解决以下问题:
    1.获取当前地图上所有的图标;
    2.然后遍历,计算有多少对可连通的图标;
    3.如果有三个或者四个相同的图标可以相互连通,要进行判断,以勉出现重复计算。
    '''
    def getPromptPoint(self):
        _link_point = []
        
        _icons_arr = self.__map.flatten()#先转化为一维数组,便于操作
        for i in set(_icons_arr):
            if i == self.EMPTY: continue #忽略为空的坐标
            _arr = np.where(_icons_arr==i)[0]#元组的第一个元素,是由i元素的索引组成的数组
            if _arr.size == 4:#剩下4个相同图标
                _point1 = Point(int(_arr[0]%10),int(_arr[0]/10))# 计算x,y坐标
                _point2 = Point(int(_arr[1]%10),int(_arr[1]/10))
                _point3 = Point(int(_arr[2]%10),int(_arr[2]/10))
                _point4 = Point(int(_arr[3]%10),int(_arr[3]/10))
                #4个接点6条线,但最多只能计算2条线,再多就会出现重复计数
                if self.__isLink(_point1,_point2):
                    _link_point.append((_point1,_point2))
                    if self.__isLink(_point3,_point4):
                        _link_point.append((_point3,_point4))
                elif self.__isLink(_point1,_point3):
                    _link_point.append((_point1,_point3))
                    if self.__isLink(_point2,_point4):
                        _link_point.append((_point2,_point4))
                elif self.__isLink(_point1,_point4):
                    _link_point.append((_point1,_point4))
                    if self.__isLink(_point2,_point3):
                        _link_point.append((_point2,_point3))
                elif self.__isLink(_point2,_point3):
                    _link_point.append((_point2,_point3))
                elif self.__isLink(_point2,_point4):
                    _link_point.append((_point2,_point4))
                elif self.__isLink(_point3,_point4):
                    _link_point.append((_point3,_point4))    
                    
            elif _arr.size == 2:#剩下2个相同图标
                _point1 = Point(int(_arr[0]%10),int(_arr[0]/10))# 计算x,y坐标
                _point2 = Point(int(_arr[1]%10),int(_arr[1]/10))
                if self.__isLink(_point1,_point2):
                    _link_point.append((_point1,_point2))
                    
        self.label_linknums['text'] = f"{len(_link_point)}连"
 
        print("_link_point",_link_point)
        return _link_point
    
    
    def centerWindow(self, width, height):#700 500
        screenwidth = self.__root.winfo_screenwidth()#窗口距离屏幕左边的宽
        screenheight = self.__root.winfo_screenheight()#窗口距离屏幕顶部的高
        size = '%dx%d+%d+%d' % (width, height, (screenwidth - width)/2, (screenheight - height)/2)
        self.__root.geometry(size)
 
 
    def add_score(self):
        self.__score += 2 #消除一对图标,分数加2
        self.set_label_text()
        
    def set_label_text(self):
        self.label_score['text'] = f"{self.__score}分"
        
    '''
    这个方法需要注意的积分问题:
    1.开始新游戏时,将积分清零;
    2.开始下一关时,将前一关的积分累积起来。
    '''
    def new_game(self, event=None,level=1,score = 0):
        self.__score = score
        self.set_label_text()
        self.__level = level
        self.extractSmallIconList()
        self.iniMap()
        self.drawMap()
        self.getPromptPoint()
        
        self.__isGameStart = True
    
    def clickCanvas(self, event):
        if not self.__isGameStart:
            return
        
        # 确认有效点击坐标
        point = self.getInnerPoint(Point(event.x, event.y))
        if not point.isUserful() or self.isEmptyInMap(point):
            return
        
        #__isFirst在三种情况下为True,1.游戏开始的时候;2.同一个图标点击了两次;3.成功消除一组图标。
        if self.__isFirst:
            self.drawSelectedArea(point)
            self.__isFirst= False
            self.__formerPoint = point
        else:
            if self.__formerPoint.isEqual(point):#两次点击的是同一个图标
                self.__isFirst = True
                self.canvas.delete("rectRedOne")
                self.canvas.delete('image_mask')
            else:
                linkType = self.getLinkType(self.__formerPoint, point)
                if linkType['type'] != self.NONE_LINK:
                    #画连接线
                    self.draw_link_line(self.__formerPoint,point,linkType)
                    playsound("music2.mp3")
                    time.sleep(.5)# 显示画线的延迟
                    
                    self.ClearLinkedBlocks(self.__formerPoint, point)
                    self.canvas.delete("rectRedOne")
                    self.canvas.delete("linkline")
                    self.canvas.delete('image_mask')
                    #增加分数
                    self.add_score()
                            
                    _link_point = self.getPromptPoint()
                    self.__isFirst = True
                    if len(_link_point) == 0:
                        if self.isGameEnd():
                            if tk.messagebox.askokcancel('确认操作', '是否进入下一关?'):
                                self.__level = self.__level+1
                                self.new_game(level = self.__level,score = self.__score)
                            else:
                                self.__isGameStart = False
                        else: #没有可连通图标,且当前地图上还有图标存在,游戏未结束时,打散当前地图
                            tk.messagebox.showinfo("提示", "已没有可连通图标,需重新打散!")
                            self.shuffleMap()
                            self.drawMap()
                            self.getPromptPoint()
                else:
                    self.__formerPoint = point
                    self.canvas.delete("rectRedOne")
                    self.drawSelectedArea(point)
    
    # 判断游戏是否结束
    def isGameEnd(self):
        return np.all(self.__map == self.EMPTY)
    
    '''
    消除图像前,把两个图像之间的连接线画出来。
    '''
    def draw_link_line(self,formerPoint,point,linkType):
        if linkType['type'] == self.STRAIGHT_LINK:
            p1 = self.getOuterCenterPoint(formerPoint)
            p2 = self.getOuterCenterPoint(point)
            
            #arrow表示线的箭头样式,默认不带箭头,参数值 FIRST表示添加箭头带线段开始位置,LAST表示到末尾占位置,BOTH表示两端均添加
            self.canvas.create_line((p1.x, p1.y),(p2.x, p2.y),fill = 'red',tags = 'linkline',width=3, arrow=LAST)
        if linkType['type'] == self.ONE_CORNER_LINK:           
            corner1 = self.getOuterCenterPoint(linkType["p1"])
            
            p1 = self.getOuterFitCenterPoint(formerPoint,corner1)
            p2 = self.getOuterFitCenterPoint(point,corner1)
            
            self.canvas.create_line((p1.x, p1.y),(corner1.x, corner1.y),fill = 'red',tags = 'linkline',width=3)
            self.canvas.create_line((p2.x, p2.y),(corner1.x, corner1.y),fill = 'red',tags = 'linkline',width=3, arrow=FIRST)
        elif linkType['type'] == self.TWO_CORNER_LINK:
            corner1 = self.getOuterCenterPoint(linkType["p1"])
            corner2 = self.getOuterCenterPoint(linkType["p2"])
            
            p1 = self.getOuterFitCenterPoint(formerPoint,corner1)
            p2 = self.getOuterFitCenterPoint(point,corner2)
                    
            self.canvas.create_line((p1.x, p1.y),(corner1.x, corner1.y),fill = 'red',tags = 'linkline',width=3)
            self.canvas.create_line((p2.x, p2.y),(corner2.x, corner2.y),fill = 'red',tags = 'linkline',width=3, arrow=FIRST)
            self.canvas.create_line((corner1.x, corner1.y),(corner2.x, corner2.y),fill = 'red',tags = 'linkline',width=3)
        self.canvas.update()
 
    '''
    提取小头像数组
    '''
    def extractSmallIconList(self):
        self.__icons = []
        imageSouce = Image.open(f"图片/new{self.__level}.png")
        for index in range(0, int(self.__iconKind)):#0-24
            region = imageSouce.crop((self.__iconWidth * index, 0, 
                    self.__iconWidth * index + self.__iconWidth - 1, self.__iconHeight - 1))
            self.__icons.append(ImageTk.PhotoImage(region))
 
    '''
    初始化地图 存值为0-24
    '''
    def iniMap(self):
        self.__map = [] # 重置地图
        _tmpRecords = []
        
        # 0-24,一共25个图标,每个图标出现4次,总共出现100次
        _total = self.__gameSize * self.__gameSize
        _tmpRecords = np.linspace(0, self.__iconKind, _total, endpoint = False,dtype=int) #用25个图标构建100个位置
        np.random.shuffle(_tmpRecords)#重新打散洗牌
        self.__map = _tmpRecords.reshape((10,10))#将一维数组100,转化为二维10*10
 
    '''
    初始化地图 存值为0-24,当前地图中,如果没有可连通路线、进入死局时,将现有的图标进行打散重新洗牌。
    ''' 
    def shuffleMap(self):
        _icons_arr = self.__map.flatten()#先转化为一维数组,便于操作
        self.__map = np.array([i for i in _icons_arr if i != self.EMPTY])
        np.random.shuffle(self.__map)#洗牌
        self.__map = np.pad(self.__map, (0, self.__gameSize**2 - len(self.__map)), 'constant', constant_values=self.EMPTY)#补齐剩下地图的值-1
        self.__map = self.__map.reshape((self.__gameSize, self.__gameSize))
 
    '''
    根据地图绘制图像
    1.在使用create_image()函数时,需要先通过Pillow库(或其他图片处理库)读取图片文件并生成图片对象,然后再将这个图片对象传递给create_image()函数,在指定的坐标位置将图片添加到画布上。
    2.canvas.create_image(x, y, image=图像对象, anchor=定位点),x和y表示图像锚点在画布上的位置,即图像在画布上的左上角坐标。image参数是一个tkinter中的PhotoImage()对象,它可以指定要加载的图像文件。anchor参数是一个字符串,用于指定图像锚点的位置,可以是"nw"(左上角)、"n"(上)、"ne"(右上角)、"w"(左)、"center"(中心)、"e"(右)、"sw"(左下角)或"s"(下)。如果不指定anchor参数,则默认为“center”。
    '''
    def drawMap(self):
        self.canvas.delete("all")
        y, x = np.where(self.__map != self.EMPTY)
        for i in range(len(x)):
            point = self.getOuterLeftTopPoint(Point(x[i], y[i]))
            self.canvas.create_image((point.x, point.y), image=self.__icons[self.__map[y[i]][x[i]]], anchor='nw', tags='im%d%d' % (x[i], y[i]))

    '''
    根据两点不同的位置,获取对应边的中心连接点。例如目标图标在左边,就取靠左的一边的中点。如果连接目标在右边,就取靠右一边的中点坐标。
    '''   
    def getOuterFitCenterPoint(self,former_point, corner):
        _former_point = self.getOuterCenterPoint(former_point)
        mapping = {
        _former_point.y > corner.y: (self.getX(former_point.x) + int(self.__iconWidth / 2), self.getY(former_point.y)),
        _former_point.y < corner.y: (self.getX(former_point.x) + int(self.__iconWidth / 2), self.getY(former_point.y) + int(self.__iconHeight)),
        _former_point.y == corner.y and _former_point.x > corner.x: (self.getX(former_point.x), self.getY(former_point.y) + int(self.__iconHeight / 2)),
        _former_point.y == corner.y and _former_point.x < corner.x: (self.getX(former_point.x) + int(self.__iconWidth),self.getY(former_point.y) + int(self.__iconHeight / 2))
        }
        x, y = mapping[True]
        return Point(x, y)

    '''
    获取内部坐标对应矩形左上角顶点坐标
    '''
    def getOuterLeftTopPoint(self, point):
        return Point(self.getX(point.x), self.getY(point.y))
 
    '''
    获取内部坐标对应矩形中心坐标
    '''
    def getOuterCenterPoint(self, point):
        return Point(self.getX(point.x) + int(self.__iconWidth / 2), 
                self.getY(point.y) + int(self.__iconHeight / 2))
    
    def getX(self, x):# x * 40 + 25
        return x * self.__iconWidth + self.__delta
 
    def getY(self, y):
        return y * self.__iconHeight + self.__delta
 
    '''
    获取内部坐标,将点击的像素坐标转换为point坐标,即icon位置坐标
    '''
    def getInnerPoint(self, point):
        x = -1
        y = -1

        for i in range(0, self.__gameSize):
            x1 = self.getX(i)
            x2 = self.getX(i + 1)
            if point.x >= x1 and point.x < x2:
                x = i

        for j in range(0, self.__gameSize):
            j1 = self.getY(j)
            j2 = self.getY(j + 1)
            if point.y >= j1 and point.y < j2:
                y = j
        
        return Point(x, y)
    '''
    创建一块蒙板,覆盖到选中的图形上
    '''
    def create_mask(self,x1, y1, x2, y2, **kwargs):
        #(0,0,0)代表黑色的RGB,127代表alpha透明度,(x2-x1, y2-y1)指长宽
        image = Image.new('RGBA', (x2-x1, y2-y1), (0,0,0,127))
        self.__images = [ImageTk.PhotoImage(image)]#这里一定要用一个实例变量存储,局部变量没有效果,原因不清楚
        self.canvas.create_image(x1, y1, image=self.__images[0], anchor='nw',tags = "image_mask")
    
    '''
    选择的区域变红,point为内部坐标
    '''
    def drawSelectedArea(self, point):
        pointLT = self.getOuterLeftTopPoint(point)
        pointRB = self.getOuterLeftTopPoint(Point(point.x + 1, point.y + 1))
        
        self.canvas.create_rectangle(pointLT.x, pointLT.y, pointRB.x - 1, pointRB.y - 1, outline = 'red', tags = "rectRedOne", width=2)
        #蒙板
        self.create_mask(pointLT.x, pointLT.y, pointRB.x - 1, pointRB.y - 1, fill='skyblue', alpha=.5,width=0)
        
    '''
    消除连通的两个块
    '''
    def ClearLinkedBlocks(self, p1, p2):
        self.__map[p1.y][p1.x] = self.EMPTY
        self.__map[p2.y][p2.x] = self.EMPTY
        self.canvas.delete('im%d%d' % (p1.x, p1.y))
        self.canvas.delete('im%d%d' % (p2.x, p2.y))
 
    '''
    地图上该点是否为空
    '''
    def isEmptyInMap(self, point):
        return self.__map[point.y][point.x] == self.EMPTY
 
    '''
    获取两个点连通类型
    '''
    def getLinkType(self, p1, p2):
        # 首先判断两个方块中图片是否相同
        if self.__map[p1.y][p1.x] != self.__map[p2.y][p2.x]:
            return { 'type': self.NONE_LINK }
 
        if self.isStraightLink(p1, p2):
            return {'type': self.STRAIGHT_LINK}
        
        res = self.isOneCornerLink(p1, p2)
        if res:
            return {'type': self.ONE_CORNER_LINK,'p1': res}
        
        res = self.isTwoCornerLink(p1, p2)
        if res:
            return {'type': self.TWO_CORNER_LINK,'p1': res['p1'],'p2': res['p2']}
        
        return {'type': self.NONE_LINK}

    '''
    直连
    '''
    def isStraightLink(self, p1, p2):
        if p1.y == p2.y:
            start, end = sorted([p1.x, p2.x])
            for x in range(start + 1, end):
                if self.__map[p1.y][x] != self.EMPTY:
                    return False
        elif p1.x == p2.x:
            start, end = sorted([p1.y, p2.y])
            for y in range(start + 1, end):
                if self.__map[y][p1.x] != self.EMPTY:
                    return False
        else:
            return False
        return True

    def isOneCornerLink(self, p1, p2):
        pointCorner = Point(p1.x, p2.y)
        if self.isStraightLink(p1, pointCorner) and self.isStraightLink(pointCorner, p2) and self.isEmptyInMap(pointCorner):
            return pointCorner
 
        pointCorner = Point(p2.x, p1.y)
        if self.isStraightLink(p1, pointCorner) and self.isStraightLink(pointCorner, p2) and self.isEmptyInMap(pointCorner):
            return pointCorner
 
    '''
    这可能是此文件最复杂的一个函数,for循环中的第一个数组是纵向比较(x不变),第二个是横向比较(y不变),合在一起可以减少代码量
    '''
    def isTwoCornerLink(self, p1, p2):
        for x1,y1,x2,y2 in [(p1.x, y, p2.x, y) for y in range(-1, self.__gameSize + 1)] + [(x, p1.y, x, p2.y) for x in range(-1, self.__gameSize + 1)]:
            pointCorner1 = Point(x1, y1) 
            pointCorner2 = Point(x2, y2)
                
            if pointCorner1==p1 or pointCorner2==p2:continue #排除p1与p2两个点
                
            if y1 == -1 or y1 == self.__gameSize or x2 == -1 or x2 == self.__gameSize: #处理最外四条边上的双拐点
                if self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner2, p2):
                    return {'p1': pointCorner1, 'p2': pointCorner2}
            elif self.isStraightLink(p1, pointCorner1) and self.isStraightLink(pointCorner1, pointCorner2) and self.isStraightLink(pointCorner2, p2) and self.isEmptyInMap(pointCorner1) and self.isEmptyInMap(pointCorner2):
                    return {'p1': pointCorner1, 'p2': pointCorner2}
        
class Point():
    def __init__(self, x, y):
        self.x = x
        self.y = y
 
    def isUserful(self):
        return self.x >= 0 and self.y >= 0
                    
    '''
    判断两个点是否相同
    '''
    def isEqual(self, point):
        return self.x == point.x and self.y == point.y
    '''
    克隆一份对象
    '''
    def clone(self):
        return Point(self.x, self.y)
 
    '''
    改为另一个对象
    '''
    def changeTo(self, point):
        self.x = point.x
        self.y = point.y
      
    '''
    显示坐标
    '''
    def __repr__(self):
        return f"x={self.x},y={self.y}"
   
MainWindow()
 

改进版尽管功能更加强大,但有点复杂,如果初学,可以先看基础版。

增强版代码包(含图片、音效文件):

https://download.csdn.net/download/qiuqiuit/87895753

基础版代码包(包含图片): 

https://download.csdn.net/download/qiuqiuit/87895720文章来源地址https://www.toymoban.com/news/detail-480863.html

到了这里,关于python开发的连连看小游戏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 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

    2024年04月08日
    浏览(47)
  • 基于Java的连连看游戏设计与实现

    目录 一、连连看开发背景 二、Java游戏开发 1.现状 2.Java日益趋向成熟 3.Java在网络方面的良好表现 4.游戏速度 三、连连看开发环境 四、技术介绍 Java swing 五、连连看所用画图方法 1.简介 2.描述 3.方法 注意: 六、连连看游戏设计 1.功能模块 2.玩家面向游戏体验 七、连连看游戏

    2024年02月04日
    浏览(33)
  • Android实训1_动物连连看游戏界面制作_线性布局

    实训1  动物连连看游戏界面制作 【实训名称】 动物连连看游戏界面制作 【实训效果】 【实训目的】 掌握Android中线性布局的使用 【实训素材】 drawable-hdpi文件夹: 【实训素材CSDN资源链接】 https://download.csdn.net/download/xiaohui_student/88351533?spm=1001.2014.3001.5503 【准备工作】 创建

    2024年02月08日
    浏览(30)
  • 【开发Log】C++QT连连看

    开发的初衷是闲来无事开了把宠物连连看,然后发现打了几遍第一关都过不去,于是想自己写个,这样就可以任意使用提示次数了(bushi。其实今天正好是老妈生日,问了下老妈她竟然还玩连连看,还ak了orz。于是乎,想写个上强度版给老妈作生日礼物2333 昨天出去玩了,今天

    2023年04月27日
    浏览(30)
  • Android 连连看基本布局示例

    这是一个基本的 Android 连连看应用程序布局代码示例,其中使用了LinearLayout组件和Button组件。通过在水平和垂直方向上添加按钮,可以创建可玩的连连看游戏。将图形资源文件与此布局结合使用,即可创建完整的应用程序。

    2023年05月25日
    浏览(27)
  • 六一儿童节-王者连连看

    庆祝六一 用java实现的连连看练手小游戏    王者连连看 游戏的目标是通过消除相同的图案来得分并进入更高级别的挑战。   游戏分为四个难度   可以自由选择也可以依次闯关。   每次时间倒计时100秒 ,你需要在有效时间内连完所有的即为过关。   ps:图片用的王

    2024年02月09日
    浏览(28)
  • Python星际生存小游戏开发

    项目名称:python星际生存游戏 编程语言:python 用到关键知识:pygame模块,面向对象思想,python基础等等 实现功能: 1:飞机的运动,发射子弹,飞机的生命值动态显示 2:太空中障碍物的无规则移动。障碍物的大小形态不一 3:背景音乐:发射子弹声音,飞机爆炸声音,中弹

    2024年02月06日
    浏览(33)
  • python小游戏开发(飞机大战)

    目录 一:背景       1. pygame 模块初识 二.项目设计内容 开发一款飞机大战游戏,要求: (1)实现飞机的移动、子弹发射,对本次游戏有一个初步的编写及认识。 (2)飞机的持续按键移动和飞机自爆优化。 (3)进行基类的抽取,使代码更具有层次性和简化重复代码。 (

    2024年02月16日
    浏览(35)
  • 用python开发一个炸金花小游戏

    众所周知扑克牌可谓是居家旅行、桌面交友的必备道具, 今天我们用  Python  来实现一个类似 炸金花 的扑克牌小游戏,先来看一下基本的游戏规则。 炸(诈)金花又叫三张牌,是在全国广泛流传的一种民间多人纸牌游戏。游戏使用一副除去大小王的扑克牌,共 4 个花色

    2024年02月09日
    浏览(34)
  • Python开发小游戏:写一个飞机大战只需要500行代码!

    ‘’’ :param background_image_path: 背景图片的路径地址 :param size: 游戏窗口的大小 :param title: 游戏窗口的标题 :param font_name: 指定字体 :param font_size: 指定字体大小 :param speed: 背景图滚动整个窗口一次所用时间,单位为ms ‘’’ self.size = size self.screen = pygame.display.set_mode(size) self.tit

    2024年04月11日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包