【python+情人节】玩个俄罗斯方块都是爱你的形状——四、动画展示

别再花钱买商业软件了!这4款免费DIC工具,从散斑生成到应变分析全搞定 本文介绍了4款免费开源的DIC(数字图像相关技术)工具,涵盖从散斑生成到应变分析的全流程,帮助用户零成本构建专业级DIC工作流。这些工具在精度、算法透明度和生态整合方面具有优势,适用于材料力学和实验力学研究,可替代昂贵的商业软件。 阅读详情

本项目效果如图
动画过程已投稿b站:https://www.bilibili.com/video/av88671119

在这里插入图片描述

目录

一、思路分析

二、手动拼图

三、自动拼图

四、动画展示

======================= 大爽歌作,made by big shuang =======================

四、动画展示

1、介绍

动画视频已投稿到我的b站,点击观看视频
动画只展示拼图结果,不展示结果的求解方法
结果的求解方法见之前的二三部分
这里为了好看,简单修改了下颜色和样式
最后展示后的结果如最上方的图
本部分代码是在第二部分手动拼图的代码基础上完成的
感兴趣的可以两个对照看看
其中新增py文件:
puzzle_show.py: 主入口,展示绘制动画
修改py代码:
drawer.py: 用于绘制的画板类
constants.py: 记录要用到的常量
results.py: 拼图结果
未修改的代码和文件
util.py: 用于绘制的画板类
love3.txt: 迷宫文本

2、代码

各个文件的代码如下
puzzle_show.py:

# usr/bin/env python
# -*- coding:utf-8- -*-

import tkinter as tk
import time
import turtle


from drawer import Drawer
from util import *
from constants import CELL_SIZE, C, R, SHAPE_LIST, SHAPES, FPS
from results import *


class PuzzleApp:
    def __init__(self, c, r, txt_path, res):
        self.win = tk.Tk()
        self.love_list = read_love_from_txt(txt_path)

        # 获取love_list 的长宽
        self.love_r = len(self.love_list)
        self.love_c = len(self.love_list[0])

        self.r = r
        self.c = c
        self.pr = r - self.love_r
        self.pc = (c - self.love_c) // 2

        self.generate_board()

        self.drawer = Drawer(self.win, self.c, self.r, CELL_SIZE)
        self.drawer.draw_background(self.board)

        self.block_id = -1  # 记录是第几个俄罗斯方块
        self.block = {}  # 俄罗斯方块的信息
        self.block_list = []  # 记录已经着陆的俄罗斯方块

        self.res = res
        self.show_over = False

    def print_block_list(self, event):
        if self.block_list:
            print('[')
            for block in self.block_list:
                print(block)
            print(']')

    def generate_board(self):
        # 生成全空的二维列表 board
        self.board  = [
            ['' for ci in range(self.c)] for ri in range(self.r)
        ]
        # 生成全空的二维列表 block_blard ,用于记录俄罗斯方块的存储情况
        self.block_board = [
            ['' for ci in range(self.c)] for ri in range(self.r)
        ]

        # 二维列表 board 中记录 love_list,将里面的粉红色方格记录为'R'
        for ri in range(len(self.love_list)):
            for ci in range(len(self.love_list[0])):
                if self.love_list[ri][ci] == "1":
                    self.board [ri+self.pr][ci + self.pc] = "R"

    def generate_new_block(self):
        self.block_id += 1
        cr = [self.pc + self.love_c // 2, 2]
        _kind = SHAPE_LIST[0]
        self.block = {
            'cr': cr,
            'kind': _kind,
            'cell_list': SHAPES[_kind],
            'angle': 0,  # 角度
        }
        self.drawer.draw_block(self.block, self.block_id)

    def check_move(self, cr, cell_list, direction):
        # 判断某个俄罗斯方块的方格能否在某个位置摆放
        cc, cr = cr
        cell_list = cell_list

        for cell in cell_list:
            cell_c, cell_r = cell
            c = cell_c + cc + direction[0]
            r = cell_r + cr + direction[1]
            # 判断该位置是否超出左右边界,以及下边界
            # 一般不判断上边界,因为俄罗斯方块生成的时候,可能有一部分在上边界之上还没有出来
            if c < 0 or c >= self.c or r >= self.r:
                return False

            # 必须要判断r不小于0才行,具体原因你可以不加这个判断,试试会出现什么效果
            if r >= 0 and self.block_board[r][c] not in ['', 'R']:
                return False

        return True

    def move_block(self, direction):
        """
        向指定方向移动俄罗斯方块
        """
        cr = self.block['cr']
        cell_list = self.block['cell_list']

        if self.check_move(cr, cell_list, direction):
            # 先清除原有的
            self.drawer.clean_by_block_id(self.block_id)
            # 再绘制新的
            new_cr = [cr[0]+direction[0], cr[1]+direction[1]]
            self.block['cr'] = new_cr
            self.drawer.draw_block(self.block, self.block_id)
            self.win.update()

    def rotate_block(self):
        angle = self.block['angle']
        angle += 1
        angle %= 4  # 除4取余数,避免角度超过4
        cell_list = self.block['cell_list']
        rotate_list = get_cell_list_by_angle(cell_list, 1)

        if self.check_move(self.block['cr'], rotate_list, [0, 0]):
            # 先清除原有的
            self.drawer.clean_by_block_id(self.block_id)
            # 再绘制新的
            self.block['angle'] = angle
            self.block['cell_list'] = rotate_list
            self.drawer.draw_block(self.block, self.block_id)
            self.win.update()

    def change_block(self):
        kind_index = SHAPE_LIST.index(self.block['kind'])
        next_kind = SHAPE_LIST[(kind_index + 1) % len(SHAPE_LIST)]

        if self.check_move(self.block['cr'], SHAPES[next_kind], [0, 0]):
            # 先清除原有的
            self.drawer.clean_by_block_id(self.block_id)
            # 再绘制新的
            self.block['angle'] = 0
            self.block['kind'] = next_kind
            self.block['cell_list'] = SHAPES[next_kind]
            self.drawer.draw_block(self.block, self.block_id)
            self.win.update()

    def land(self):
        # 俄罗斯方块直接着陆
        c, r = self.block['cr']
        cell_list = self.block['cell_list']

        new_r = self.get_land_r(cell_list, c)
        while r < new_r:
            # 先清除原有的
            self.drawer.clean_by_block_id(self.block_id)
            # 再绘制新的
            r += 1
            self.block['cr'] = [c, r]
            self.drawer.draw_block(self.block, self.block_id)
            self.win.update()
            time.sleep(0.01)

        self.drawer.draw_block_line(self.block, self.block_id)

        self.block_list.append(self.block)
        self.refresh_block_board()
        self.win.update()

    def get_land_r(self, cell_list, ci):
        # 获取当前俄罗斯方块降落后的行位置
        ri = 0
        for ri in range(2, self.r):
            # 从上到下依次尝试能否移动该行,如果这行移动不到,则说明上一行是降落的着陆点
            if not self.check_move((ci, ri), cell_list, (0, 0)):
                return ri - 1

        return self.r - 1

    def refresh_block_board(self):
        self.block_board = [
            ['' for ci in range(self.c)] for ri in range(self.r)
        ]

        for block in self.block_list:
            shape_type = block['kind']
            cc, cr = block['cr']
            cell_list = block['cell_list']

            for cell in cell_list:
                cell_c, cell_r = cell
                c = cell_c + cc
                r = cell_r + cr

                self.block_board[r][c] = shape_type

    def back(self, event):
        if self.block_id>0:
            # 先隐藏当前的俄罗斯方块
            self.drawer.clean_by_block_id(self.block_id)

            # 再回退到上一个俄罗斯方块
            self.block = self.block_list.pop()
            self.block['cr'][1] = 2
            self.drawer.clean_by_block_id(self.block_id-1)
            self.block_id -= 1
            self.drawer.draw_block(self.block, self.block_id)
            self.refresh_block_board()
            self.win.update()

    def game_loop(self):
        if self.show_over:
            return
        elif self.block:
            self.move_block_to_res()
        else:
            self.get_next_block()

        self.win.after(FPS, self.game_loop)

    def move_block_to_res(self):
        if self.block['kind'] != self.block['res_kind']:
            self.change_block()
        elif self.block['angle'] != self.block['res_angle']:
            self.rotate_block()
        elif self.block['cr'][0] != self.block['res_cr'][0]:
            c = self.block['cr'][0]
            rc = self.block['res_cr'][0]
            if c < rc:
                # 右移
                self.move_block([1, 0])
            elif c > rc:
                self.move_block([-1, 0])
        elif self.block['cr'][1] != self.block['res_cr'][1]:

            self.land()
            self.block = {}

    def get_next_block(self):
        # 从已保存的结果中取出下一个block
        self.block_id += 1
        if self.block_id >= len(self.res):
            # 所有block均被取出,演示完毕
            self.show_over = True
            return

        self.block = self.res[self.block_id]
        self.block['res_angle'] = self.block['angle']
        self.block['angle'] = 0

        c, r = self.block['cr']

        self.block['res_cr'] = [c+self.pc, r + self.pr]
        self.block['cr'] = [self.pc + self.love_c // 2, 2]

        self.block['res_kind'] = self.block['kind']
        self.block['kind'] = SHAPE_LIST[0]
        self.block['cell_list'] = SHAPES[SHAPE_LIST[0]]

        self.drawer.draw_block(self.block, self.block_id)

if __name__ == '__main__':
    txt_path = "love3.txt"
    app = PuzzleApp(C, R, txt_path, res2)
    app.game_loop()
    app.win.mainloop()

drawer.py:

# usr/bin/env python
# -*- coding:utf-8- -*-

import tkinter as tk
from constants import ALL_COLORS, DIRECTION


class Drawer(tk.Canvas):
    def __init__(self, master, c, r, cell_size):
        self.c = c
        self.r = r
        self.cell_size = cell_size
        height = r * cell_size
        width = c * cell_size
        super().__init__(master, width=width, height=height)
        self.pack()

    def draw_background(self, board):
        for ri in range(self.r):
            for ci in range(self.c):
                color = ALL_COLORS[board[ri][ci]]
                self.draw_cell_by_cr(ci, ri, color)

    def draw_cell_by_cr(self,c, r, color, tag=None):
        x0 = c * self.cell_size
        y0 = r * self.cell_size
        x1 = c * self.cell_size + self.cell_size
        y1 = r * self.cell_size + self.cell_size
        # tag用于在后面删除指定tag的方格
        if tag is None:
            # 没有tag代表的是背景色
            self.create_rectangle(x0, y0, x1, y1, fill=color, outline="white", width=2)
        else:
            # 有tag 代表的是俄罗斯方块
            _tag = "b%s" % tag
            self.create_rectangle(x0, y0, x1, y1, fill=color,
                                  outline=color, tag=_tag)

    def draw_block(self, block, block_id):
        c, r = block['cr']
        shape_type = block['kind']
        cell_list = block['cell_list']
        for cell in cell_list:
            cell_c, cell_r = cell
            ci = cell_c + c
            ri = cell_r + r
            # 判断该位置方格在画板内部(画板外部的方格不再绘制)
            if 0 <= c < self.c and 0 <= r < self.r:
                self.draw_cell_by_cr(ci, ri, ALL_COLORS[shape_type], block_id)

    def clean_by_block_id(self, block_id):
        _tag = "b%s" % block_id
        self.delete(_tag)

    def draw_line(self, c, r, d, color, block_id):
        if d == "W":
            x0 = c * self.cell_size
            y0 = r * self.cell_size
            x1 = c * self.cell_size + self.cell_size
            y1 = y0
        elif d == "S":
            x0 = c * self.cell_size
            y0 = r * self.cell_size + self.cell_size
            x1 = c * self.cell_size + self.cell_size
            y1 = y0
        elif d == "A":
            x0 = c * self.cell_size
            y0 = r * self.cell_size
            x1 = x0
            y1 = r * self.cell_size + self.cell_size
        elif d == "D":
            x0 = c * self.cell_size + self.cell_size
            y0 = r * self.cell_size
            x1 = x0
            y1 = r * self.cell_size + self.cell_size

        # tag用于在后面删除指定的线
        _tag = "b%s" % block_id
        self.create_line(x0, y0, x1, y1, fill=color, width=2, tag=_tag)

    def draw_block_line(self, block, block_id):
        c, r = block['cr']
        shape_type = block['kind']
        cell_list = block['cell_list']
        for cell in cell_list:
            for d in DIRECTION:
                dcr = DIRECTION[d]
                d_cell = (cell[0] + dcr[0], cell[1] + dcr[1])
                if d_cell not in cell_list:
                    # draw line
                    self.draw_line(c+cell[0], r++cell[1], d, ALL_COLORS["line"], block_id)

constants.py

# usr/bin/env python
# -*- coding:utf-8- -*-

C = 20
R = 20
CELL_SIZE = 30

FPS = 100

# 定义各种形状
SHAPES = {
    "O": [(-1, -1), (0, -1), (-1, 0), (0, 0)],
    "S": [(-1, 0), (0, 0), (0, -1), (1, -1)],
    "T": [(-1, 0), (0, 0), (0, -1), (1, 0)],
    "I": [(0, 1), (0, 0), (0, -1), (0, -2)],
    "L": [(-1, 0), (0, 0), (-1, -1), (-1, -2)],
    "J": [(-1, 0), (0, 0), (0, -1), (0, -2)],
    "Z": [(-1, -1), (0, -1), (0, 0), (1, 0)],
}

# 定义各种颜色,用于给第二第三阶段拼图上色
# ALL_COLORS = {
#     # 七种俄罗斯方块的颜色
#     "O": "#d25b6a",
#     "S": "#d2835b",
#     "T": "#e5e234",
#     "I": "#83d05d",
#     "L": "#2862d2",
#     "J": "#35b1c0",
#     "Z": "#5835c0",
# 
#     # 其他颜色
#     "": "#CCCCCC",
#     "R": "#ffcccc",
#     "D": "#ff3366",
#     "line": "red"
# }

# 绘制动画时将七种俄罗斯方块全部换成深红色
ALL_COLORS = {
    # 七种俄罗斯方块的颜色
    "O": "#ff3366",
    "S": "#ff3366",
    "T": "#ff3366",
    "I": "#ff3366",
    "L": "#ff3366",
    "J": "#ff3366",
    "Z": "#ff3366",

    # 其他颜色
    "": "#CCCCCC",
    "R": "#ffcccc",
    "D": "#ff3366",
    "line": "red"
}

SHAPE_LIST = ["O", "S", "T", "I", "L", "J", "Z"]

DIRECTION = {
    "W": (0, -1),
    "S": (0, 1),
    "A": (-1, 0),
    "D": (1, 0),
}

result.py

#usr/bin/env python
#-*- coding:utf-8- -*-

res1 = [
    {'cr': [10, 18], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [10, 16], 'kind': 'I', 'cell_list': [(0, 1), (0, 0), (0, -1), (0, -2)], 'angle': 0},
    {'cr': [9, 17], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [12, 17], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [7, 15], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [13, 15], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [9, 14], 'kind': 'S', 'cell_list': [(0, 1), (0, 0), (-1, 0), (-1, -1)], 'angle': 1},
    {'cr': [12, 14], 'kind': 'Z', 'cell_list': [(-1, 1), (-1, 0), (0, 0), (0, -1)], 'angle': 1},
    {'cr': [13, 14], 'kind': 'J', 'cell_list': [(0, -1), (0, 0), (1, 0), (2, 0)], 'angle': 3},
    {'cr': [7, 13], 'kind': 'L', 'cell_list': [(0, 1), (0, 0), (-1, 1), (-2, 1)], 'angle': 1},
    {'cr': [5, 13], 'kind': 'T', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, 0)], 'angle': 0},
    {'cr': [15, 13], 'kind': 'T', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, 0)], 'angle': 0},
    {'cr': [4, 12], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [17, 12], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [14, 12], 'kind': 'S', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, -1)], 'angle': 0},
    {'cr': [6, 12], 'kind': 'Z', 'cell_list': [(-1, -1), (0, -1), (0, 0), (1, 0)], 'angle': 0},
    {'cr': [10, 13], 'kind': 'T', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, 0)], 'angle': 0},
    {'cr': [9, 12], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [12, 12], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [10, 10], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [13, 10], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [7, 10], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [13, 8], 'kind': 'L', 'cell_list': [(0, 1), (0, 0), (-1, 1), (-2, 1)], 'angle': 1},
    {'cr': [7, 9], 'kind': 'J', 'cell_list': [(0, -1), (0, 0), (1, 0), (2, 0)], 'angle': 3},
    {'cr': [16, 10], 'kind': 'T', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, 0)], 'angle': 0},
    {'cr': [4, 10], 'kind': 'T', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, 0)], 'angle': 0},
    {'cr': [6, 9], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [15, 9], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
]

res2 = [
    {'cr': [10, 18], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [10, 16], 'kind': 'I', 'cell_list': [(0, 1), (0, 0), (0, -1), (0, -2)], 'angle': 0},
    {'cr': [9, 17], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [12, 17], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [7, 16], 'kind': 'L', 'cell_list': [(0, -1), (0, 0), (1, -1), (2, -1)], 'angle': 3},
    {'cr': [13, 15], 'kind': 'J', 'cell_list': [(0, 1), (0, 0), (-1, 0), (-2, 0)], 'angle': 1},
    {'cr': [6, 14], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [14, 14], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [8, 14], 'kind': 'Z', 'cell_list': [(-1, -1), (0, -1), (0, 0), (1, 0)], 'angle': 0},
    {'cr': [12, 14], 'kind': 'S', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, -1)], 'angle': 0},
    {'cr': [10, 13], 'kind': 'T', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, 0)], 'angle': 0},
    {'cr': [16, 12], 'kind': 'L', 'cell_list': [(0, 1), (0, 0), (-1, 1), (-2, 1)], 'angle': 1},
    {'cr': [4, 13], 'kind': 'J', 'cell_list': [(0, -1), (0, 0), (1, 0), (2, 0)], 'angle': 3},
    {'cr': [13, 11], 'kind': 'L', 'cell_list': [(0, 1), (0, 0), (-1, 1), (-2, 1)], 'angle': 1},
    {'cr': [7, 12], 'kind': 'J', 'cell_list': [(0, -1), (0, 0), (1, 0), (2, 0)], 'angle': 3},
    {'cr': [12, 11], 'kind': 'S', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, -1)], 'angle': 0},
    {'cr': [8, 11], 'kind': 'Z', 'cell_list': [(-1, -1), (0, -1), (0, 0), (1, 0)], 'angle': 0},
    {'cr': [10, 10], 'kind': 'T', 'cell_list': [(1, 0), (0, 0), (0, 1), (-1, 0)], 'angle': 2},
    {'cr': [6, 12], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [15, 12], 'kind': 'O', 'cell_list': [(-1, -1), (0, -1), (-1, 0), (0, 0)], 'angle': 0},
    {'cr': [17, 11], 'kind': 'T', 'cell_list': [(0, 1), (0, 0), (-1, 0), (0, -1)], 'angle': 1},
    {'cr': [3, 11], 'kind': 'T', 'cell_list': [(0, -1), (0, 0), (1, 0), (0, 1)], 'angle': 3},
    {'cr': [6, 9], 'kind': 'L', 'cell_list': [(0, 1), (0, 0), (-1, 1), (-2, 1)], 'angle': 1},
    {'cr': [5, 9], 'kind': 'S', 'cell_list': [(-1, 0), (0, 0), (0, -1), (1, -1)], 'angle': 0},
    {'cr': [13, 8], 'kind': 'L', 'cell_list': [(0, 1), (0, 0), (-1, 1), (-2, 1)], 'angle': 1},
    {'cr': [7, 9], 'kind': 'J', 'cell_list': [(0, -1), (0, 0), (1, 0), (2, 0)], 'angle': 3},
    {'cr': [14, 10], 'kind': 'J', 'cell_list': [(0, -1), (0, 0), (1, 0), (2, 0)], 'angle': 3},
    {'cr': [15, 9], 'kind': 'Z', 'cell_list': [(-1, -1), (0, -1), (0, 0), (1, 0)], 'angle': 0},
]

剩下的util.py和love3.txt未做修改,和之前是一样的
util.py:

# usr/bin/env python
# -*- coding:utf-8- -*-


def read_love_from_txt(txt_path):
    # 从txt中读取二维爱心列表,并返回
    with open(txt_path, 'r') as f:
        fl = f.readlines()

    love_list = []
    for line in fl:
        line = line.strip('\n')
        new_line = line.split(' ')
        love_list.append(new_line)

    return love_list


def get_cell_list_by_angle(cell_list, angle):
    # 将当前的 cell_list旋转指定的角度
    angle_dict = {
        0: (1, 0, 0, 1),
        1: (0, 1, -1, 0),
        2: (-1, 0, 0, -1),
        3: (0, -1, 1, 0),
    }
    a, b, c, d = angle_dict[angle]
    if angle == 0:
        return cell_list

    rotate_cell_list = []
    for cell in cell_list:
        cc, cr = cell
        rc, rr = a * cc + b * cr, c*cc+d*cr
        rotate_cell_list.append((rc, rr))

    return rotate_cell_list

love3.txt:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 1 1 1 0 0 0 0 0 1 1 1 0 0 0 0
0 0 0 0 1 1 1 1 1 1 0 1 1 1 1 1 1 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0
0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0
0 0 0 0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0 0
0 0 0 0 0 0 0 1 1 1 1 1 1 1 0 0 0 0 0 0
0 0 0 0 0 0 0 0 1 1 1 1 1 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 1 1 1 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0
ISO18000-6B/6C(EPC C1G2)两个射频识别(RFID)标准协议的技术特点 目前读写器基本上是采用IMPINJ的R2000芯片和E710芯片开发,因为ISO18000-6B标准的现在应用很少,E710芯片已经不再支持ISO18000-6B标准,选择上就只有采用R2000芯片开发的UR6258超高频读写器以及手持机,这个在项目应用上需要留意。尽管ISO18000-6B标准具有上述优点,但也存在一些不足之处,特别是多标签阅读性能远远满足不了现在的应用需求,近年来发展停滞,绝大部分应用已经被ISO18000-6C(EPC C1G2)取代;#RFID# #物联网# #标准协议# 阅读详情

相关推荐

Android GWP-Asan机制详解

基本用途:GWP-ASan是一种原生内存分配器功能,在内存分配时额外记录一些信息,用于检测DOUBLE_FREE、USE_AFTER_FREE、INVALID_FREE、BUFFER_OVERFLOW、BUFFER_UNDERFLOW五种内存错误问题。

专注于系统快稳省领域 4145

程序员的七夕,用30行代码让Python化身表白神器

转眼又到了咱们中国传统的情人节七夕了,今天笔者就带大家来领略一下用Python表白的方式。让程序员的恋人们感受一下IT人的浪漫。 一、词云制作 首先咱们可以用之前介绍过的wordcould包制作词云。wordcloud包安装十分简单。pip即可完成安装 pip install wordcloud 然后需要制作一个背景图片,为了应急我用艺术字做了个七夕的图片,如果大家来不及...

Python爱好者的专栏 1万+

MTK6769平台Type-C充电全解析:从硬件管脚到PD协议实战(Android15环境)

本文深入解析了MTK6769平台在Android 15环境下Type-C充电的完整链路。从硬件管脚(特别是核心的CC引脚)功能与连接,到USB-PD协议报文抓取与实战分析,并结合MTK平台PD芯片驱动与充电IC驱动的软件框架,提供了从硬件设计到软件调试的系统性解决方案和常见问题排查案例。

ol78901234的博客 311

【python+情人节】玩个俄罗斯方块都是爱你的形状——二、手动拼图(通过gui辅助实现)

本项目效果如图 动画过程已投稿b站:https://www.bilibili.com/video/av88671119 目录 一、思路分析 二、手动拼图 三、自动拼图 四、动画展示 ======================= 大爽歌作,made by big shuang ======================= 二、手动拼图 1、介绍 手动拼图这里通过一个gui来辅助实现 这个g...

大爽老师的博客 1399

Android Camera性能优化概述

做camera性能优化方面的工作有几年了,想写一篇文章简单介绍一下其中涉及到的具体技术,这篇文章会大概介绍一下涉及到的技术。

weixin_42136255的博客 4023

16、保障Azure应用安全:密钥管理与身份认证

本文深入探讨了保障Azure应用安全的关键措施,包括使用网络安全工具(如Application Gateway和Azure Front Door)防范攻击,解决传统密钥和机密存储方式的安全隐患,以及通过Azure Key Vault实现敏感信息的安全管理。同时,介绍了使用托管标识实现Azure资源间安全访问的方法,并结合实际操作步骤展示了如何配置Key Vault、设置访问策略、存储机密以及授予Web应用对SQL Server的访问权限。最后,对不同安全措施进行了比较,并提出了在开发、测试及生产环境中的综合

rock5的博客 72

【python+情人节】玩个俄罗斯方块都是爱你的形状——一、思路分析

本项目效果如图 动画过程已投稿b站:https://www.bilibili.com/video/av88671119 目录 一、思路分析 二、自动拼图 三、手动拼图 四、动画展示 ======================= 大爽歌作,made by big shuang ======================= 0、项目介绍 如最上面的图所示,本项目实际上就是通过俄罗斯方块拼出一...

大爽老师的博客 2572

10、硬件工程师笔试面试——继电器(2025版本)

在设计电路时,应综合考虑SSR的优势和局限性,确保选择合适的型号,并采取适当的设计措施来优化性能和可靠性。继电器的主要功能是利用较小的电流或电压来控制较大电流或电压的电路,实现信号的放大和隔离。在处理继电器故障时,应综合考虑电源、线圈、触点和负载等因素,及时进行故障诊断和处理,以确保电路系统的稳定性和安全性。由于汽车电子系统的复杂性,继电器的设计和选择必须考虑到系统的特定要求,包括电流容量、电压等级、环境条件(如温度、湿度、振动)以及所需的保护和隔离功能。确定线圈的工作电压或电流,以及吸合电压或电流。

XU157303764的博客 3733

python表白神器_送你个情人节礼物:Python版抖音同款表白神器

又到了一年一度的情人节!大家都准备送什么给自己心仪的对象呢?鲜花、巧克力都太俗套了,今天给大家带来一个抖音上看到的表白神器 — 用Python写一个告白程序,让她看到你满满的爱(tao)意(lu)。先上效果:视频版:代码:from tkinter import *from tkinter import messageboximport randomdef no_close():return#关闭所...

weixin_39625864的博客 213

ICLR 2025 | MambaPEFT: 探索针对Mamba的参数高效微调方法

通过利用海量数据构建大型模型,基于Transformer的模型生态系统已逐步确立。参数高效微调(PEFT)是一项至关重要的技术,它能以最低成本将这些模型应用于下游任务,同时实现高效的性能表现。最近,基于状态空间模型(SSM)的Mamba模型作为Transformer的潜在替代方案受到了广泛关注。尽管已经提出了许多基于Mamba的大规模模型,但如何高效地将预训练的Mamba模型应用于下游任务仍有待研究。在本文中,作者对适用于Mamba的PEFT方法展开了探索性分析。

小白学视觉 326

ORB-SLAM2算法4之KITTI开源数据集运行ORB-SLAM2生成轨迹并用evo工具评估轨迹

ORB-SLAM2算法1 已成功编译安装ORB-SLAM2到本地,本篇目的是用KITTI开源数据来运行ORB-SLAM2,并生成轨迹,最后用evo评估工具来评估ORB-SLAM2生成的轨迹和真值轨迹。

重点记录机器人和自动驾驶相关领域的技术,尤其是计算机视觉,视觉SLAM等,不仅有前言文献或必备算法的学习,也会有实际应用的点滴经验 2326

【python+情人节】玩个俄罗斯方块都是爱你的形状

修改py代码: drawer.py:用于绘制的画板类 constants.py:记录要用到的常量 results.py: 拼图结果 未修改的代码和文件 util.py:用于绘制的画板类 love3.txt: 迷宫文本 各个文件的代码如下 puzzle_show.py: # usr/bin/env python # -*- coding:utf-8- -*- import tkinter as tk import time import turtle from drawer im..

shunshunss的博客 627

【人工智能】全面盘点国内AI九大模型:各擅胜场的智能先锋(豆包、文心一言、讯飞星火、通义千问、Kimi、智谱清言、腾讯元宝、秘塔、天工AI)

追求性价比与全能:选豆包,适合个人与中小企业日常使用;侧重中文创作与理解:选文心一言,文学与商业文案创作首选;需要专业语音交互:选讯飞星火,智能客服、车载场景必备;看重生态与多场景:选通义千问,适配电商、办公等企业需求;处理超长文本任务:选Kimi,文档分析、学术研究的利器;专注深度推理创作:选智谱清言,学术与创意写作的伙伴;依赖腾讯生态协同:选腾讯元宝,日常轻量需求的便捷之选;深耕法律学术领域:选秘塔,专业文本处理的权威工具;布局前沿技术体验:选天工AI,享受接近国际顶尖的智能服务。

奶爸的编程之路,也就一周冷个三天 1121

【python+情人节】玩个俄罗斯方块都是爱你的形状——三、自动拼图

本项目效果如图 动画过程已投稿b站:https://www.bilibili.com/video/av88671119 目录 一、思路分析 二、手动拼图 三、自动拼图 四、动画展示 ======================= 大爽歌作,made by big shuang ======================= 三、自动拼图 1、介绍分析 这里再先介绍一遍 本部分要通过算法实现俄...

大爽老师的博客 2423

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Houdini通过回溯法将特定碎块进行拼贴

优点:可以通过大量生成,并自动过滤掉小碎块较多的拼贴方式,方便从剩下的优质方案中筛选更为合理的结果。 上图: 思路借鉴了:【python+情人节】玩个俄罗斯方块都是爱你的形状——三、自动拼图_大爽歌的博客-优快云博客 ...

kraka的博客 674

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

python求婚创意_用css3做一个求婚小动画

首先放张效果图然后一步步分析一下首先是刚出现的新郎的动画.w-m img{margin-right: 0;float: right;margin-top: 60px;animation: toWoman 0.5s ease .5s both;}@keyframes toWoman{0%{opacity: 0;transform: translate(-200px);}100%{opacity: 1...

weixin_28077113的博客 269

前端实现双人联机版俄罗斯方块小游戏2(实现双人联机)

基于websocket实现双人联机俄罗斯方块游戏,逻辑思路整理如下思路整理1.游戏开始,双方都收到start消息,同时调用start方法2.start方法中,调用game.init方法,同时发送init消息给server,server收到后会转发给另一个游戏玩家3.另一个游戏玩家在remote.js中接收init,会驱动对方去调用start方法(next消息同init消息) 思路整理 1.游戏开始,双方都收到start消息,同时调用start方法 socket.on('start', function ()

weixin_44584059的博客 2963

情人节找到一个好玩的

print('\n'.join([''.join([('Love'[(x-y) % len('Love')] if ((x*0.05)**2+(y*0.1)**2-1)**3-(x*0.05)**2*(y*0.1)**3 <= 0else ' ')#此处是根据心形曲线公式来的(x2+y2-1)3-x2y3=0 for x in range(-30, 30)])#定义高 for y in ra...

inhacker的博客 174

python练手--自制俄罗斯方块(文末附源码)

小白练手的俄罗斯方块,用python和pygame实现,欢迎指导,欢迎讨论!

highmiao的博客 3万+

自己写“俄罗斯方块”(二).加入OnTimer()函数,实现落地效果

在这里可能需要清楚的一点就是OnTimer()和按下方向键“下”的时候都会触发这个GoDown()函数,其实消息队列是一个队列,有先来后到之分,应用程序会根据消息依次调用GoDown()函数。 首先在TerisView.cpp文件中加入GoDown()函数的定义: bool CMy18TetrisView::GoDown() { //按下方向键“下”的时候,或者计时器触发时 for (int

I feel lost 551

python用matplotlib画五角星_Python+Matplotlib制作动画

注: 在“实验设计与数据处理”的课后作业中,有一个数据可视化的作业,利用课程上学习的某种方法找一个二维函数的最大值,并将这个寻找的过程可视化。在作业里面利用了Matplotlib的Animation类实现可视化的动态展示。1、引言利用Animation类制动画主要是参考了官方的教程:Matplotlib-Animation。为了更加清析说明Animation类是如何实现动画的,本文只简单地介绍一个...

weixin_39622521的博客 1137

python tkinter从入门到撩妹-整蛊弹窗-1

python版本:3.6 效果如图 动画见本人b站投稿 1实现一个无法关闭的窗体 使用tkinter实现基础窗体只需如下三行代码 import tkinter as tk win = tk.Tk() win.mainloop() 运行结果如下图 这是个没有任何内容的窗体,点击右上角的×会关闭这个窗体。 要实现整蛊,就必须让窗体无法通过这个×关闭 这里我们仔细看前面三行代码,会发现窗体是...

大爽老师的博客 2671

python从入门到撩妹 2 —— 30行代码实现520小彩蛋

作者自我介绍:大爽歌, b站小UP主 ,直播编程+红警三 ,python1对1辅导老师 。 本文对应视频版本: 520小彩蛋 python32行代码实现 —— python从入门到撩妹-2 1 彩蛋效果展示: 网页上展示的效果可能不齐, 但是python上的输出是对齐的。 可能是不同平台的空格宽度不同的缘故 祝祝祝 脱脱脱 单单单 祝     脱 单 单 祝祝祝 脱脱脱 单 单   祝 脱   单 单 祝祝祝 脱脱脱 单单单 我我我 爱爱爱 你你你 我     爱 你 你 我我我 爱爱爱 你 .

大爽老师的博客 677

python tkinter从入门到撩妹-整蛊弹窗-S特供版

这个版本其实网上也有很多,应我的直播间盟主假爱情邀请,我这也给大家写一个 版本说明,和之前的整蛊弹窗一版本的区别就是按钮没有对应的方法变了 版本1:鼠标移到按钮没有时,直接会跑开 版本S:鼠标点击按钮没有时,切换图片进行提醒 这里为了省事,就直接在我之前的整蛊弹窗一版本的代码的基础上写吧 整蛊弹窗一版本:https://blog.youkuaiyun.com/python1639er/article/de...

大爽老师的博客 626

AI全栈实战 | 3.9-01 爬虫入门:requests 加 BeautifulSoup 三分钟跑通,但 90% 的人栽在这 4 个“礼貌“问题上

⚠️:本文内容仅用于。请遵守目标站点的服务条款与相关法律法规,不得对目标服务造成负担,不得采集、传播个人隐私数据。技术是中性的,边界在你手里。爬虫的入门技术(requests 发请求 + BeautifulSoup 解析)三分钟就能学会。真正区分"会用爬虫"和"会做爬虫的人"的,是这篇我们跑通"请求→解析→存储"的最小闭环,然后重点把"合规与礼貌"这根弦给你绷上。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 411

从一段视频到可漫游的 4D 有声场景:思路拆解与最小复现手记

只需一段手机视频,你就能生成可"走进去"的 4D 有声场景:转头时狗叫声方向随之变化,走近时声音更清晰。本文拆解 Video-to-4DAVScene 的核心思路,手把手带你用几十行 Python 搭出最小管线,把视频中的运动物体变成带空间位置的声源,并附上三个真实踩坑的排障经验,代码可直接跑。🎧

helloagent的博客 235

【每天一个 Python 小案例30】Python 基础知识综合小项目:我的工具盒

作为系列收官,本篇把前 29 篇的知识点合成一个能直接用的命令行工具"我的工具盒":计算器(用 ast 解析表达式,不碰 eval)、单位换算与温度转换(一张换算表 + 特例分支)、记账与分类统计(Decimal + JSON 持久化)、以及用"字典当命令表"把菜单和业务逻辑解耦的主循环。文中对比了 eval 的安全隐患与 ast 白名单的做法,解释了 lambda 闭包在字典里的写法与晚绑定陷阱,并在最后给出整个系列的知识地图,把变量、数据结构、控制流、函数、类、异常、文件、标准库八块内容对应到具体篇目。

xinjiyaya的博客 427
上一篇: 【python+情人节】玩个俄罗斯方块都是爱你的形状——二、手动拼图(通过gui辅助实现)
下一篇: 【python+情人节】玩个俄罗斯方块都是爱你的形状——三、自动拼图
大爽歌
博客等级 码龄9年 422粉丝 92原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值