python tkinter实现连连看游戏


Posted in Python onNovember 16, 2020

需要自己添加图片素材呦

python tkinter实现连连看游戏

运行效果:

python tkinter实现连连看游戏

完整代码

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @Date  : 2017-10-02 15:19:24
# @Author : Salamander	(1906747819@qq.com)
# @Link  : http://51lucy.com

import os, random
import tkinter as tk
import tkinter.messagebox
from PIL import Image, ImageTk

class MainWindow():
	__gameTitle = "连连看游戏"
	__windowWidth = 700
	__windowHeigth = 500
	__icons = []
	__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

	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.extractSmallIconList()

		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.file_new, accelerator="Ctrl+N")

		self.menubar.add_cascade(label="游戏", menu=self.file_menu)
		self.root.configure(menu=self.menubar)

		self.canvas = tk.Canvas(self.root, bg = 'white', width = 450, height = 450)
		self.canvas.pack(side=tk.TOP, pady = 5)
		self.canvas.bind('<Button-1>', self.clickCanvas)
    

	def centerWindow(self, width, height):
	  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 file_new(self, event=None):
		self.iniMap()
		self.drawMap()
		self.__isGameStart = True

	def clickCanvas(self, event):
		if self.__isGameStart:
			point = self.getInnerPoint(Point(event.x, event.y))
			# 有效点击坐标
			if point.isUserful() and not self.isEmptyInMap(point):
				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")
					else:
						linkType = self.getLinkType(self.__formerPoint, point)
						if linkType['type'] != self.NONE_LINK:
							# TODO Animation
							self.ClearLinkedBlocks(self.__formerPoint, point)
							self.canvas.delete("rectRedOne")
							self.__isFirst = True
							if self.isGameEnd():
								tk.messagebox.showinfo("You Win!", "Tip")
								self.__isGameStart = False
						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 extractSmallIconList(self):
		imageSouce = Image.open(r'images\NARUTO.png')
		for index in range(0, int(self.__iconKind)):
			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 = []
		records = []
		for i in range(0, int(self.__iconKind)):
			for j in range(0, 4):
				tmpRecords.append(i)

		total = self.__gameSize * self.__gameSize
		for x in range(0, total):
			index = random.randint(0, total - x - 1)
			records.append(tmpRecords[index])
			del tmpRecords[index]

		# 一维数组转为二维,y为高维度
		for y in range(0, self.__gameSize):
			for x in range(0, self.__gameSize):
				if x == 0:
					self.__map.append([])
				self.__map[y].append(records[x + y * self.__gameSize])

	'''
	根据地图绘制图像
	'''
	def drawMap(self):
		self.canvas.delete("all")
		for y in range(0, self.__gameSize):
			for x in range(0, self.__gameSize):
				point = self.getOuterLeftTopPoint(Point(x, y))
				im = self.canvas.create_image((point.x, point.y), 
					image=self.__icons[self.__map[y][x]], anchor='nw', tags = 'im%d%d' % (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):
		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)

	'''
	选择的区域变红,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")


	'''
	消除连通的两个块
	'''
	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

MainWindow()

以上就是python tkinter实现连连看游戏的详细内容,更多关于python tkinter连连看的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
Python 字典dict使用介绍
Nov 30 Python
发布你的Python模块详解
Sep 15 Python
python使用SMTP发送qq或sina邮件
Oct 21 Python
python DataFrame获取行数、列数、索引及第几行第几列的值方法
Apr 08 Python
无法使用pip命令安装python第三方库的原因及解决方法
Jun 12 Python
python错误调试及单元文档测试过程解析
Dec 19 Python
python打印n位数“水仙花数”(实例代码)
Dec 25 Python
Python如何实现的二分查找算法
May 27 Python
在Tensorflow中实现leakyRelu操作详解(高效)
Jun 30 Python
python安装mysql的依赖包mysql-python操作
Jan 01 Python
Python MNIST手写体识别详解与试练
Nov 07 Python
Python写情书? 10行代码展示如何把情书写在她的照片里
Apr 21 Python
详解python os.path.exists判断文件或文件夹是否存在
Nov 16 #Python
Python 删除List元素的三种方法remove、pop、del
Nov 16 #Python
python 从list中随机取值的方法
Nov 16 #Python
python实现在列表中查找某个元素的下标示例
Nov 16 #Python
python如何获得list或numpy数组中最大元素对应的索引
Nov 16 #Python
Python实现列表索引批量删除的5种方法
Nov 16 #Python
Python 列表反转显示的四种方法
Nov 16 #Python
You might like
URL Rewrite的设置方法
2007/01/02 PHP
PHP实现二维数组中的查找算法小结
2018/06/09 PHP
浅析用prototype定义自己的方法
2013/11/14 Javascript
IE下双击checkbox反应延迟问题的解决方法
2014/03/27 Javascript
javascript的push使用指南
2014/12/05 Javascript
jQuery聚合函数实例
2015/05/21 Javascript
基于jQuery实现Ajax验证用户名是否存在实例
2016/03/30 Javascript
简单了解JavaScript操作XPath的一些基本方法
2016/06/03 Javascript
快速解决js动态改变dom元素属性后页面及时渲染的问题
2016/07/06 Javascript
NodeJS收发GET和POST请求的示例代码
2017/08/25 NodeJs
jQuery实现table中两列CheckBox只能选中一个的示例
2017/09/22 jQuery
javascript设计模式 ? 工厂模式原理与应用实例分析
2020/04/09 Javascript
JavaScript 几种循环方式以及模块化的总结
2020/09/03 Javascript
Python实现栈的方法
2015/05/26 Python
python 添加用户设置密码并发邮件给root用户
2016/07/25 Python
Python读取图片属性信息的实现方法
2016/09/11 Python
Python3 加密(hashlib和hmac)模块的实现
2017/11/23 Python
Python实现的文本对比报告生成工具示例
2018/05/22 Python
Python图像处理之图片文字识别功能(OCR)
2019/07/30 Python
python Popen 获取输出,等待运行完成示例
2019/12/30 Python
完美解决keras 读取多个hdf5文件进行训练的问题
2020/07/01 Python
HTML5各种头部meta标签的功能(推荐)
2017/03/13 HTML / CSS
ONLY瑞典官网:世界知名服装品牌
2018/06/19 全球购物
Kipling澳洲官网:购买凯浦林包包
2020/12/17 全球购物
是否有自动比较结构的方法
2015/06/03 面试题
能否解释一下XSS cookie盗窃是什么意思
2012/06/02 面试题
学年自我鉴定范文
2013/10/01 职场文书
自主招生自荐信
2013/12/08 职场文书
天鹅的故事教学反思
2014/02/04 职场文书
《夕阳真美》教学反思
2014/04/27 职场文书
财务会计实训报告
2014/11/05 职场文书
2014财产信托协议书范本
2014/11/18 职场文书
构建和谐校园倡议书
2015/01/19 职场文书
2015年家长学校工作总结
2015/04/22 职场文书
2015教师个人德育工作总结
2015/07/22 职场文书
银行文明优质服务培训心得体会
2016/01/09 职场文书