[Python black technology] tkinter library actual combat "Lianliankan" game (nanny graphics + implementation code)

Welcome to pay attention "Python black technology" series , continuously updating
Welcome to pay attention "Python black technology" series , continuously updating

Realization effect

Realization idea

link: https://pan.baidu.com/s/1Q6peGnZe0k0zBalAGaJ8wg?pwd=pdux 
Extraction code: pdux

Make a bunch of pictures_ 00-----bar_ 09.png
It would be better if we could find gif

imgs = [PhotoImage(file='images\\bar_0' + str(i) + '.png') for i in range(0, 10)]  # All icon patterns

Classic continuous view, randomly generate picture elements, and the marks of adjacent picture elements are the same, which can be eliminated.

Implementation code


# @Time    : 2022/2/9 20:22
# @Author: Nanli
# @FileName: Lianliankan py
from tkinter import *
from tkinter.messagebox import *
from threading import Timer
import time
import random


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

# --------------------------------------




'''
Judge whether the selected two squares can be eliminated
'''


def IsLink(p1, p2):
    if lineCheck(p1, p2):
        return True
    if OneCornerLink(p1, p2):  # One turn (break point) connection mode
        return True
    if TwoCornerLink(p1, p2):  # Connection mode of two turns (break points)
        return True
    return False

# ---------------------------
def IsSame(p1, p2):
    if map[p1.x][p1.y] == map[p2.x][p2.y]:
        print("clicked at IsSame")
        return True
    return False


def callback(event):  # Left mouse button event code
    global Select_first, p1, p2
    global firstSelectRectId, SecondSelectRectId
    # print ("clicked at", event.x, event.y,turn)
    x = (event.x) // 40 # converted chessboard coordinates
    y = (event.y) // 40
    print("clicked at", x, y)

    if map[x][y] == " ":
        showinfo(title="Tips", message="There are no squares here")
    else:

        if Select_first == False:
            p1 = Point(x, y)
            # Draw a border at the selected (x1,y1)
            firstSelectRectId = cv.create_rectangle(x * 40, y * 40, x * 40 + 40, y * 40 + 40, width=2, outline="blue")
            Select_first = True
        else:
            p2 = Point(x, y)
            # Judge whether the box clicked for the second time has been selected by the first click. If so, return.
            if (p1.x == p2.x) and (p1.y == p2.y):
                return
            # Draw a border at the selected (x2,y2)
            print('Second click box', x, y)
            # SecondSelectRectId=cv.create_rectangle(100,20,x*40+40,y*40+40,width=2,outline="yellow")
            SecondSelectRectId = cv.create_rectangle(x * 40, y * 40, x * 40 + 40, y * 40 + 40, width=2,
                                                     outline="yellow")
            print('Second click box', SecondSelectRectId)
            cv.pack()
            # Judge whether it is connected
            if IsSame(p1, p2) and IsLink(p1, p2):
                print('connected', x, y)
                Select_first = False
                # Draw the connecting line between the selected boxes
                drawLinkLine(p1, p2)
                # clearTwoBlock()
                # time.sleep(0.6)
                # clearFlag=True
                t = Timer(timer_interval, delayrun)  # Timing function
                t.start()


            else:  # Reselect the first box
                # Clear first selected wireframe
                cv.delete(firstSelectRectId)
                cv.delete(SecondSelectRectId)
                # print('clear first selected border ')
                # firstSelectRectId=SecondSelectRectId
                # p1=Point(x,y)           #Sets the coordinates of the first square to be reselected
                Select_first = False


timer_interval = 0.3  # 0.3 seconds


# --------------------------------------
def delayrun():
    clearTwoBlock()  # Clear lines and blocks

def clearTwoBlock():  # Clear lines and blocks
    # Delay 0.1 second
    # time.sleep(0.1)
    # Clears the first selected border
    cv.delete(firstSelectRectId)
    # Clears the second selected border
    cv.delete(SecondSelectRectId)
    # Clear the value of the record box
    map[p1.x][p1.y] = " "
    cv.delete(image_map[p1.x][p1.y])
    map[p2.x][p2.y] = " "
    cv.delete(image_map[p2.x][p2.y])
    Select_first = False
    undrawConnectLine()  # Clear the connection line between the selected boxes


def drawQiPan():  # Draw a chessboard
    for i in range(0, 15):
        cv.create_line(20, 20 + 40 * i, 580, 20 + 40 * i, width=2)
    for i in range(0, 15):
        cv.create_line(20 + 40 * i, 20, 20 + 40 * i, 580, width=2)
    cv.pack()


def print_map():  # Output map
    global image_map
    for x in range(0, Width):  # 0--14
        for y in range(0, Height):  # 0--14
            if (map[x][y] != ' '):
                img1 = imgs[int(map[x][y])]
                id = cv.create_image((x * 40 + 20, y * 40 + 20), image=img1)
                image_map[x][y] = id
    cv.pack()
    for y in range(0, Height):  # 0--14
        for x in range(0, Width):  # 0--14
            print(map[x][y], end=' ')
        print(",", y)


'''
* Principle of elimination method for the same row and column: if the number of spaces between two identical eliminated elements
spaceCount Equal to their (row)/Column difference-1)Then the two can be eliminated
* x Representative column, y Representative bank
* param p1 The first point object that saves the coordinates of the last selected point
* param p2 The second point object that saves the coordinates of the last selected point
'''


# Direct connection
def lineCheck(p1, p2):
    absDistance = 0
    spaceCount = 0
    if (p1.x == p2.x or p1.y == p2.y):  # Is it in the same line?
        print("Same row and same column------")
        # Same column
        if (p1.x == p2.x and p1.y != p2.y):
            print("Same column")
            # Absolute distance (number of spaces between)
            absDistance = abs(p1.y - p2.y) - 1
            # Positive and negative value
            if p1.y - p2.y > 0:
                zf = -1
            else:
                zf = 1
            for i in range(1, absDistance + 1):
                if (map[p1.x][p1.y + i * zf] == " "):
                    # Number of spaces plus 1
                    spaceCount += 1
                else:
                    break;  # If you encounter obstacles, you don't have to detect them anymore
        # Situation of peers
        elif (p1.y == p2.y and p1.x != p2.x):
            print(" Situation of peers")
            absDistance = abs(p1.x - p2.x) - 1
            # Positive and negative value
            if p1.x - p2.x > 0:
                zf = -1
            else:
                zf = 1
            for i in range(1, absDistance + 1):
                if (map[p1.x + i * zf][p1.y] == " "):
                    # Number of spaces plus 1
                    spaceCount += 1
                else:
                    break;  # If you encounter obstacles, you don't have to detect them anymore
        if (spaceCount == absDistance):
            # Unicom
            print(absDistance, spaceCount)
            print("that 's ok/Columns can be connected directly")
            return True
        else:
            print("that 's ok/Column cannot be eliminated!")
            return False
    else:
        # It is not in the same row and column, so it directly returns false
        return False;
    # --------------------------------------

# Second, right angle connection
'''
Right angle connection, i.e X,Y If the coordinates are different, you can try to connect with this method
 param first:First point selected
 param second:Second point selected
'''


def OneCornerLink(p1, p2):
    # The first right angle checkpoint. If it is empty, the same value will be given for inspection
    checkP = Point(p1.x, p2.y)
    # The second right angle checkpoint. If it is empty, the same value will be given for inspection
    checkP2 = Point(p2.x, p1.y);
    # First right angle point detection
    if (map[checkP.x][checkP.y] == " "):
        if (lineCheck(p1, checkP) and lineCheck(checkP, p2)):
            linePointStack.append(checkP)
            print("Right angle elimination ok", checkP.x, checkP.y)
            return True
    # Second right angle point detection
    if (map[checkP2.x][checkP2.y] == " "):
        if (lineCheck(p1, checkP2) and lineCheck(checkP2, p2)):
            linePointStack.append(checkP2)
            print("Right angle elimination ok", checkP2.x, checkP2.y)
            return True
    print("Cannot be eliminated at right angles")
    return False;

# -----------------------------------------
'''
#Third, double right angle connection
 The judgment of double right angle connection can be divided into two steps:
1. stay p1 Look for spaces in 4 directions around the dot checkP
2. call OneCornerLink(checkP, p2)
3. Traversal p1 4 Space in two directions to make it checkP,Then call OneCornerLink(checkP, 
p2)Determine whether it is true. If it is true, double right angles can be used together. Otherwise, when all spaces are traversed and not found
 To one checkP send OneCornerLink(checkP, p2)If true, the two points cannot be combined
 Specific code:

Double right angle connection method
@param p1 First point
@param p2 Second point
'''


def TwoCornerLink(p1, p2):
    checkP = Point(p1.x, p1.y)
    # Four way detection starts
    for i in range(0, 4):
        checkP.x = p1.x
        checkP.y = p1.y
        # down
        if (i == 3):
            checkP.y += 1
            while ((checkP.y < Height) and map[checkP.x][checkP.y] == " "):
                linePointStack.append(checkP)
                if (OneCornerLink(checkP, p2)):
                    print("Lower detection OK")
                    return True
                else:
                    linePointStack.pop()
                checkP.y += 1
            print("ssss", checkP.y, Height - 1)
            # The two additional break points are outside the bottom side of the game area
            if checkP.y == Height:  # Out of the bottom, we only need to judge whether p2 can also reach the bottom boundary
                z = Point(p2.x, Height - 1)  # Bottom boundary point
                if lineCheck(z, p2):  # The two break points are on the bottom side outside the area
                    linePointStack.append(Point(p1.x, Height))
                    linePointStack.append(Point(p2.x, Height))
                    print("The outside of the game area is detected OK")
                    return True
        # towards the right
        elif (i == 2):
            checkP.x += 1
            while ((checkP.x < Width) and map[checkP.x][checkP.y] == " "):
                linePointStack.append(checkP)
                if (OneCornerLink(checkP, p2)):
                    print("Right detection OK")
                    return True
                else:
                    linePointStack.pop()
                checkP.x += 1
            # The two additional break points are outside the right side of the game area
            if checkP.x == Width:  # Out of the right side, it is only necessary to judge whether p2 can also reach the right boundary
                z = Point(Width - 1, p2.y)  # Right boundary point
                if lineCheck(z, p2):  # The two break points are on the bottom side outside the area
                    linePointStack.append(Point(Width, p1.y))
                    linePointStack.append(Point(Width, p2.y))
                    print("Right detected outside the game area OK")
                    return True
        # towards the left
        elif (i == 1):
            checkP.x -= 1
            while ((checkP.x >= 0) and map[checkP.x][checkP.y] == " "):
                linePointStack.append(checkP)
                if (OneCornerLink(checkP, p2)):
                    print("Left detection OK")
                    return True
                else:
                    linePointStack.pop()
                checkP.x -= 1
        # Upward
        elif (i == 0):
            checkP.y -= 1
            while ((checkP.y >= 0) and map[checkP.x][checkP.y] == " "):
                linePointStack.append(checkP)
                if (OneCornerLink(checkP, p2)):
                    print("Upper detection OK")
                    return True
                else:
                    linePointStack.pop()
                checkP.y -= 1
    # No suitable checkP point was found after searching in all four directions
    print("Two right angle connections did not find a suitable one checkP spot")
    return False;

# ---------------------------
# Draw a connecting line
def drawLinkLine(p1, p2):
    if (len(linePointStack) == 0):
        Line_id.append(drawLine(p1, p2))
    else:
        print(linePointStack, len(linePointStack))
    if (len(linePointStack) == 1):
        z = linePointStack.pop()
        print("One break connected point z", z.x, z.y)
        Line_id.append(drawLine(p1, z))
        Line_id.append(drawLine(p2, z))
    if (len(linePointStack) == 2):
        z1 = linePointStack.pop()
        print("2 Broken connected point z1", z1.x, z1.y)
        Line_id.append(drawLine(p2, z1))
        z2 = linePointStack.pop()
        print("2 Broken connected point z2", z2.x, z2.y)
        Line_id.append(drawLine(z1, z2))
        Line_id.append(drawLine(p1, z2))

# Delete connector
def undrawConnectLine():
    while len(Line_id) > 0:
        idpop = Line_id.pop()
        cv.delete(idpop)


def drawLine(p1, p2):
    print("drawLine p1,p2", p1.x, p1.y, p2.x, p2.y)
    # cv.create_line( 40+20, 40+20,200,200,width=5,fill='red')
    id = cv.create_line(p1.x * 40 + 20, p1.y * 40 + 20, p2.x * 40 + 20, p2.y * 40 + 20, width=5, fill='red')
    # cv.pack()
    return id

# --------------------------------------
def create_map():  # Generate map map
    global map
    # Generate random map
    # Put all matched pairs of animal species into a temporary map
    tmpMap = []
    m = (Width) * (Height) // 10
    print('m=', m)
    for x in range(0, m):
        for i in range(0, 10):  # There are 10 squares of each type
            tmpMap.append(x)
    random.shuffle(tmpMap)
    for x in range(0, Width):  # 0--14
        for y in range(0, Height):  # 0--14
            map[x][y] = tmpMap[x * Height + y]

# --------------------------------------
def find2Block(event):  # Auto find
    global firstSelectRectId, SecondSelectRectId
    m_nRoW = Height
    m_nCol = Width
    bFound = False;
    # The first box starts at position 0 on the map
    for i in range(0, m_nRoW * m_nCol):
        # If found, jump out of the loop
        if (bFound):
            break

        # Calculate the corresponding virtual row and column position
        x1 = i % m_nCol
        y1 = i // m_nCol
        p1 = Point(x1, y1)
        # Non patterned square skip
        if (map[x1][y1] == ' '):
            continue
        # The second box starts from the back of the previous box
        for j in range(i + 1, m_nRoW * m_nCol):
            # Calculate the corresponding virtual row and column position
            x2 = j % m_nCol
            y2 = j // m_nCol
            p2 = Point(x2, y2)
            # The second box is not empty and is the same as the animal in the first box
            if (map[x2][y2] != ' ' and IsSame(p1, p2)):
                # Judge whether it can be connected
                if (IsLink(p1, p2)):
                    bFound = True
                    break
    # Automatically eliminate after finding
    if (bFound):  # p1 (x1,y1) is connected with p2 (x2,y2)
        print('After finding', p1.x, p1.y, p2.x, p2.y)
        # Draw a border at the selected (x1,y1)
        firstSelectRectId = cv.create_rectangle(x1 * 40, y1 * 40, x1 * 40 + 40, y1 * 40 + 40, width=2, outline="red")
        # Draw a border at the selected (x2,y2)
        secondSelectRectId = cv.create_rectangle(x2 * 40, y2 * 40, x2 * 40 + 40, y2 * 40 + 40, width=2, outline="red")
        # t=Timer(timer_interval,delayrun)#Timing function
        # t.start()
    return bFound

# Game main logic
root = Tk()
root.title("Python Look again and again ")
imgs = [PhotoImage(file='images\\bar_0' + str(i) + '.png') for i in range(0, 10)]  # All icon patterns
Select_first = False  # Has the first block been selected
firstSelectRectId = -1  # The first map object selected
SecondSelectRectId = -1  # Selected second map object
clearFlag = False
linePointStack = []
Line_id = []
Height = 10
Width = 10
map = [[" " for y in range(Height)] for x in range(Width)]
image_map = [[" " for y in range(Height)] for x in range(Width)]
cv = Canvas(root, bg='green', width=440, height=440)
# drawQiPan( )
cv.bind("<Button-1>", callback)  # Left mouse button event
cv.bind("<Button-3>", find2Block)  # Right mouse button event
cv.pack()
create_map()  # Generate map map
print_map()  # Print map
root.mainloop()

summary

If you like, give me a 👍, Pay attention! Share more interesting Python black technology!

Welcome to pay attention "Python black technology" series , continuously updating
Welcome to pay attention "Python black technology" series , continuously updating
[Python black technology] a collection of 7 small projects in tkinter Library (nanny graphics + implementation code)
[Python black technology] tkinter library actually makes a calculator (nanny graphic + implementation code)
[Python black technology] tkinter library actually makes a notepad (nanny graphic + implementation code)
[Python black technology] registration and login of actual users of tkinter Library (nanny graphics + implementation code)
[Python black technology] tkinter library actual combat "2048" game (nanny graphics + implementation code)
[Python black technology] tkinter library actual combat "Tetris" game (nanny graphic + implementation code)
[Python black technology] tkinter library actual combat "greedy snake" game (nanny graphic + implementation code)
[Python black technology] tkinter library actual combat "Lianliankan" game (nanny graphics + implementation code)

[Python installs a third-party library with a one-line command to permanently increase the speed]
[package exe with PyInstaller]
[one click download of Zhihu article pictures without login crawler (nanny graphic + implementation code)]
[lonely programmers chat with AI robot friends to relieve boredom (free interface + nanny level graphics + implementation code comments)]
[draw gif dynamic diagram with a few lines of code (nanny level picture and text + implementation code)]
[several lines of code to realize regular and cyclic screenshots of online class and save important knowledge points (nanny level graphics and text + implementation code)]
[common user_agent browser head crawler simulates users (nanny level graphics + implementation code)]
[more details]

Keywords: Python

Added by zartzar on Sun, 06 Mar 2022 02:35:23 +0200