Python实现自动玩连连看的脚本分享


Posted in Python onApril 04, 2022

序言

最近女朋友在玩连连看,玩了一个星期了还没通关,真的是菜。

我实在是看不过去了,直接用python写了个脚本代码,一分钟一把游戏。

快是快,就是联网玩容易被骂,嘿嘿~

实现步骤

模块导入

import cv2
import numpy as np
import win32api
import win32gui
import win32con
from PIL import ImageGrab
import time
import random

窗体标题 用于定位游戏窗体

WINDOW_TITLE = "连连看"

时间间隔随机生成 [MIN,MAX]

TIME_INTERVAL_MAX = 0.06
TIME_INTERVAL_MIN = 0.1

游戏区域距离顶点的x偏移

MARGIN_LEFT = 10

游戏区域距离顶点的y偏移

MARGIN_HEIGHT = 180

横向的方块数量

H_NUM = 19

纵向的方块数量

V_NUM = 11

方块宽度

POINT_WIDTH = 31

方块高度

POINT_HEIGHT = 35

空图像编号

EMPTY_ID = 0

切片处理时候的左上、右下坐标:

SUB_LT_X = 8
SUB_LT_Y = 8
SUB_RB_X = 27
SUB_RB_Y = 27

游戏的最多消除次数

MAX_ROUND = 200

获取窗体坐标位置

def getGameWindow():
    # FindWindow(lpClassName=None, lpWindowName=None)  窗口类名 窗口标题名
    window = win32gui.FindWindow(None, WINDOW_TITLE)

    # 没有定位到游戏窗体
    while not window:
        print('Failed to locate the game window , reposition the game window after 10 seconds...')
        time.sleep(10)
        window = win32gui.FindWindow(None, WINDOW_TITLE)

    # 定位到游戏窗体
    # 置顶游戏窗口
    win32gui.SetForegroundWindow(window)
    pos = win32gui.GetWindowRect(window)
    print("Game windows at " + str(pos))
    return (pos[0], pos[1])

获取屏幕截图

def getScreenImage():
    print('Shot screen...')
    # 获取屏幕截图 Image类型对象
    scim = ImageGrab.grab()
    scim.save('screen.png')
    # 用opencv读取屏幕截图
    # 获取ndarray
    return cv2.imread("screen.png")

从截图中分辨图片 处理成地图

def getAllSquare(screen_image, game_pos):
    print('Processing pictures...')
    # 通过游戏窗体定位
    # 加上偏移量获取游戏区域
    game_x = game_pos[0] + MARGIN_LEFT
    game_y = game_pos[1] + MARGIN_HEIGHT

    # 从游戏区域左上开始
    # 把图像按照具体大小切割成相同的小块
    # 切割标准是按照小块的横纵坐标
    all_square = []
    for x in range(0, H_NUM):
        for y in range(0, V_NUM):
            # ndarray的切片方法 : [纵坐标起始位置:纵坐标结束为止,横坐标起始位置:横坐标结束位置]
            square = screen_image[game_y + y * POINT_HEIGHT:game_y + (y + 1) * POINT_HEIGHT,
                     game_x + x * POINT_WIDTH:game_x + (x + 1) * POINT_WIDTH]
            all_square.append(square)

    # 因为有些图片的边缘会造成干扰,所以统一把图片往内缩小一圈
    # 对所有的方块进行处理 ,去掉边缘一圈后返回
    finalresult = []
    for square in all_square:
        s = square[SUB_LT_Y:SUB_RB_Y, SUB_LT_X:SUB_RB_X]
        finalresult.append(s)
    return finalresult

判断列表中是否存在相同图形

存在返回进行判断图片所在的id

否则返回-1

def isImageExist(img, img_list):
    i = 0
    for existed_img in img_list:
        # 两个图片进行比较 返回的是两个图片的标准差
        b = np.subtract(existed_img, img)
        # 若标准差全为0 即两张图片没有区别
        if not np.any(b):
            return i
        i = i + 1
    return -1

获取所有的方块类型

def getAllSquareTypes(all_square):
    print("Init pictures types...")
    types = []
    # number列表用来记录每个id的出现次数
    number = []
    # 当前出现次数最多的方块
    # 这里我们默认出现最多的方块应该是空白块
    nowid = 0;
    for square in all_square:
        nid = isImageExist(square, types)
        # 如果这个图像不存在则插入列表
        if nid == -1:
            types.append(square)
            number.append(1);
        else:
            # 若这个图像存在则给计数器 + 1
            number[nid] = number[nid] + 1
            if (number[nid] > number[nowid]):
                nowid = nid
    # 更新EMPTY_ID
    # 即判断在当前这张图中的空白块id
    global EMPTY_ID
    EMPTY_ID = nowid
    print('EMPTY_ID = ' + str(EMPTY_ID))
    return types

将二维图片矩阵转换为二维数字矩阵

注意因为在上面对截屏切片时是以列为优先切片的

所以生成的record二维矩阵每行存放的其实是游戏屏幕中每列的编号

换个说法就是record其实是游戏屏幕中心对称后的列表

def getAllSquareRecord(all_square_list, types):
    print("Change map...")
    record = []
    line = []
    for square in all_square_list:
        num = 0
        for type in types:
            res = cv2.subtract(square, type)
            if not np.any(res):
                line.append(num)
                break
            num += 1
        # 每列的数量为V_NUM
        # 那么当当前的line列表中存在V_NUM个方块时我们认为本列处理完毕
        if len(line) == V_NUM:
            print(line);
            record.append(line)
            line = []
    return record

判断给出的两个图像能否消除

def canConnect(x1, y1, x2, y2, r):
    result = r[:]

    # 如果两个图像中有一个为0 直接返回False
    if result[x1][y1] == EMPTY_ID or result[x2][y2] == EMPTY_ID:
        return False
    if x1 == x2 and y1 == y2:
        return False
    if result[x1][y1] != result[x2][y2]:
        return False
    # 判断横向连通
    if horizontalCheck(x1, y1, x2, y2, result):
        return True
    # 判断纵向连通
    if verticalCheck(x1, y1, x2, y2, result):
        return True
    # 判断一个拐点可连通
    if turnOnceCheck(x1, y1, x2, y2, result):
        return True
    # 判断两个拐点可连通
    if turnTwiceCheck(x1, y1, x2, y2, result):
        return True
    # 不可联通返回False
    return False

判断横向联通

def horizontalCheck(x1, y1, x2, y2, result):
    if x1 == x2 and y1 == y2:
        return False
    if x1 != x2:
        return False
    startY = min(y1, y2)
    endY = max(y1, y2)
    # 判断两个方块是否相邻
    if (endY - startY) == 1:
        return True
    # 判断两个方块通路上是否都是0,有一个不是,就说明不能联通,返回false
    for i in range(startY + 1, endY):
        if result[x1][i] != EMPTY_ID:
            return False
    return True

判断纵向联通

def verticalCheck(x1, y1, x2, y2, result):
    if x1 == x2 and y1 == y2:
        return False

    if y1 != y2:
        return False
    startX = min(x1, x2)
    endX = max(x1, x2)
    # 判断两个方块是否相邻
    if (endX - startX) == 1:
        return True
    # 判断两方块儿通路上是否可连。
    for i in range(startX + 1, endX):
        if result[i][y1] != EMPTY_ID:
            return False
    return True

判断一个拐点可联通

def turnOnceCheck(x1, y1, x2, y2, result):
    if x1 == x2 or y1 == y2:
        return False

    cx = x1
    cy = y2
    dx = x2
    dy = y1
    # 拐点为空,从第一个点到拐点并且从拐点到第二个点可通,则整条路可通。
    if result[cx][cy] == EMPTY_ID:
        if horizontalCheck(x1, y1, cx, cy, result) and verticalCheck(cx, cy, x2, y2, result):
            return True
    if result[dx][dy] == EMPTY_ID:
        if verticalCheck(x1, y1, dx, dy, result) and horizontalCheck(dx, dy, x2, y2, result):
            return True
    return False

判断两个拐点可联通

def turnTwiceCheck(x1, y1, x2, y2, result):
    if x1 == x2 and y1 == y2:
        return False

    # 遍历整个数组找合适的拐点
    for i in range(0, len(result)):
        for j in range(0, len(result[1])):
            # 不为空不能作为拐点
            if result[i][j] != EMPTY_ID:
                continue
            # 不和被选方块在同一行列的不能作为拐点
            if i != x1 and i != x2 and j != y1 and j != y2:
                continue
            # 作为交点的方块不能作为拐点
            if (i == x1 and j == y2) or (i == x2 and j == y1):
                continue
            if turnOnceCheck(x1, y1, i, j, result) and (
                    horizontalCheck(i, j, x2, y2, result) or verticalCheck(i, j, x2, y2, result)):
                return True
            if turnOnceCheck(i, j, x2, y2, result) and (
                    horizontalCheck(x1, y1, i, j, result) or verticalCheck(x1, y1, i, j, result)):
                return True
    return False

自动消除

def autoRelease(result, game_x, game_y):
    # 遍历地图
    for i in range(0, len(result)):
        for j in range(0, len(result[0])):
            # 当前位置非空
            if result[i][j] != EMPTY_ID:
                # 再次遍历地图 寻找另一个满足条件的图片
                for m in range(0, len(result)):
                    for n in range(0, len(result[0])):
                        if result[m][n] != EMPTY_ID:
                            # 若可以执行消除
                            if canConnect(i, j, m, n, result):
                                # 消除的两个位置设置为空
                                result[i][j] = EMPTY_ID
                                result[m][n] = EMPTY_ID
                                print('Remove :' + str(i + 1) + ',' + str(j + 1) + ' and ' + str(m + 1) + ',' + str(
                                    n + 1))

                                # 计算当前两个位置的图片在游戏中应该存在的位置
                                x1 = game_x + j * POINT_WIDTH
                                y1 = game_y + i * POINT_HEIGHT
                                x2 = game_x + n * POINT_WIDTH
                                y2 = game_y + m * POINT_HEIGHT

                                # 模拟鼠标点击第一个图片所在的位置
                                win32api.SetCursorPos((x1 + 15, y1 + 18))
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x1 + 15, y1 + 18, 0, 0)
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x1 + 15, y1 + 18, 0, 0)

                                # 等待随机时间 ,防止检测
                                time.sleep(random.uniform(TIME_INTERVAL_MIN, TIME_INTERVAL_MAX))

                                # 模拟鼠标点击第二个图片所在的位置
                                win32api.SetCursorPos((x2 + 15, y2 + 18))
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x2 + 15, y2 + 18, 0, 0)
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x2 + 15, y2 + 18, 0, 0)
                                time.sleep(random.uniform(TIME_INTERVAL_MIN, TIME_INTERVAL_MAX))
                                # 执行消除后返回True
                                return True
    return False

效果的话得上传视频,截图展现不出来效果,大家可以自行试试。

全部代码

# -*- coding:utf-8 -*-
import cv2
import numpy as np
import win32api
import win32gui
import win32con
from PIL import ImageGrab
import time
import random

# 窗体标题  用于定位游戏窗体
WINDOW_TITLE = "连连看"
# 时间间隔随机生成 [MIN,MAX]
TIME_INTERVAL_MAX = 0.06
TIME_INTERVAL_MIN = 0.1
# 游戏区域距离顶点的x偏移
MARGIN_LEFT = 10
# 游戏区域距离顶点的y偏移
MARGIN_HEIGHT = 180
# 横向的方块数量
H_NUM = 19
# 纵向的方块数量
V_NUM = 11
# 方块宽度
POINT_WIDTH = 31
# 方块高度
POINT_HEIGHT = 35
# 空图像编号
EMPTY_ID = 0
# 切片处理时候的左上、右下坐标:
SUB_LT_X = 8
SUB_LT_Y = 8
SUB_RB_X = 27
SUB_RB_Y = 27
# 游戏的最多消除次数
MAX_ROUND = 200


def getGameWindow():
    # FindWindow(lpClassName=None, lpWindowName=None)  窗口类名 窗口标题名
    window = win32gui.FindWindow(None, WINDOW_TITLE)

    # 没有定位到游戏窗体
    while not window:
        print('Failed to locate the game window , reposition the game window after 10 seconds...')
        time.sleep(10)
        window = win32gui.FindWindow(None, WINDOW_TITLE)

    # 定位到游戏窗体
    # 置顶游戏窗口
    win32gui.SetForegroundWindow(window)
    pos = win32gui.GetWindowRect(window)
    print("Game windows at " + str(pos))
    return (pos[0], pos[1])

def getScreenImage():
    print('Shot screen...')
    # 获取屏幕截图 Image类型对象
    scim = ImageGrab.grab()
    scim.save('screen.png')
    # 用opencv读取屏幕截图
    # 获取ndarray
    return cv2.imread("screen.png")

def getAllSquare(screen_image, game_pos):
    print('Processing pictures...')
    # 通过游戏窗体定位
    # 加上偏移量获取游戏区域
    game_x = game_pos[0] + MARGIN_LEFT
    game_y = game_pos[1] + MARGIN_HEIGHT

    # 从游戏区域左上开始
    # 把图像按照具体大小切割成相同的小块
    # 切割标准是按照小块的横纵坐标
    all_square = []
    for x in range(0, H_NUM):
        for y in range(0, V_NUM):
            # ndarray的切片方法 : [纵坐标起始位置:纵坐标结束为止,横坐标起始位置:横坐标结束位置]
            square = screen_image[game_y + y * POINT_HEIGHT:game_y + (y + 1) * POINT_HEIGHT,
                     game_x + x * POINT_WIDTH:game_x + (x + 1) * POINT_WIDTH]
            all_square.append(square)

    # 因为有些图片的边缘会造成干扰,所以统一把图片往内缩小一圈
    # 对所有的方块进行处理 ,去掉边缘一圈后返回
    finalresult = []
    for square in all_square:
        s = square[SUB_LT_Y:SUB_RB_Y, SUB_LT_X:SUB_RB_X]
        finalresult.append(s)
    return finalresult


# 判断列表中是否存在相同图形
# 存在返回进行判断图片所在的id
# 否则返回-1
def isImageExist(img, img_list):
    i = 0
    for existed_img in img_list:
        # 两个图片进行比较 返回的是两个图片的标准差
        b = np.subtract(existed_img, img)
        # 若标准差全为0 即两张图片没有区别
        if not np.any(b):
            return i
        i = i + 1
    return -1

def getAllSquareTypes(all_square):
    print("Init pictures types...")
    types = []
    # number列表用来记录每个id的出现次数
    number = []
    # 当前出现次数最多的方块
    # 这里我们默认出现最多的方块应该是空白块
    nowid = 0;
    for square in all_square:
        nid = isImageExist(square, types)
        # 如果这个图像不存在则插入列表
        if nid == -1:
            types.append(square)
            number.append(1);
        else:
            # 若这个图像存在则给计数器 + 1
            number[nid] = number[nid] + 1
            if (number[nid] > number[nowid]):
                nowid = nid
    # 更新EMPTY_ID
    # 即判断在当前这张图中的空白块id
    global EMPTY_ID
    EMPTY_ID = nowid
    print('EMPTY_ID = ' + str(EMPTY_ID))
    return types


# 将二维图片矩阵转换为二维数字矩阵
# 注意因为在上面对截屏切片时是以列为优先切片的
# 所以生成的record二维矩阵每行存放的其实是游戏屏幕中每列的编号
# 换个说法就是record其实是游戏屏幕中心对称后的列表
def getAllSquareRecord(all_square_list, types):
    print("Change map...")
    record = []
    line = []
    for square in all_square_list:
        num = 0
        for type in types:
            res = cv2.subtract(square, type)
            if not np.any(res):
                line.append(num)
                break
            num += 1
        # 每列的数量为V_NUM
        # 那么当当前的line列表中存在V_NUM个方块时我们认为本列处理完毕
        if len(line) == V_NUM:
            print(line);
            record.append(line)
            line = []
    return record

def canConnect(x1, y1, x2, y2, r):
    result = r[:]

    # 如果两个图像中有一个为0 直接返回False
    if result[x1][y1] == EMPTY_ID or result[x2][y2] == EMPTY_ID:
        return False
    if x1 == x2 and y1 == y2:
        return False
    if result[x1][y1] != result[x2][y2]:
        return False
    # 判断横向连通
    if horizontalCheck(x1, y1, x2, y2, result):
        return True
    # 判断纵向连通
    if verticalCheck(x1, y1, x2, y2, result):
        return True
    # 判断一个拐点可连通
    if turnOnceCheck(x1, y1, x2, y2, result):
        return True
    # 判断两个拐点可连通
    if turnTwiceCheck(x1, y1, x2, y2, result):
        return True
    # 不可联通返回False
    return False

def horizontalCheck(x1, y1, x2, y2, result):
    if x1 == x2 and y1 == y2:
        return False
    if x1 != x2:
        return False
    startY = min(y1, y2)
    endY = max(y1, y2)
    # 判断两个方块是否相邻
    if (endY - startY) == 1:
        return True
    # 判断两个方块通路上是否都是0,有一个不是,就说明不能联通,返回false
    for i in range(startY + 1, endY):
        if result[x1][i] != EMPTY_ID:
            return False
    return True

def verticalCheck(x1, y1, x2, y2, result):
    if x1 == x2 and y1 == y2:
        return False

    if y1 != y2:
        return False
    startX = min(x1, x2)
    endX = max(x1, x2)
    # 判断两个方块是否相邻
    if (endX - startX) == 1:
        return True
    # 判断两方块儿通路上是否可连。
    for i in range(startX + 1, endX):
        if result[i][y1] != EMPTY_ID:
            return False
    return True


def turnOnceCheck(x1, y1, x2, y2, result):
    if x1 == x2 or y1 == y2:
        return False

    cx = x1
    cy = y2
    dx = x2
    dy = y1
    # 拐点为空,从第一个点到拐点并且从拐点到第二个点可通,则整条路可通。
    if result[cx][cy] == EMPTY_ID:
        if horizontalCheck(x1, y1, cx, cy, result) and verticalCheck(cx, cy, x2, y2, result):
            return True
    if result[dx][dy] == EMPTY_ID:
        if verticalCheck(x1, y1, dx, dy, result) and horizontalCheck(dx, dy, x2, y2, result):
            return True
    return False


def turnTwiceCheck(x1, y1, x2, y2, result):
    if x1 == x2 and y1 == y2:
        return False

    # 遍历整个数组找合适的拐点
    for i in range(0, len(result)):
        for j in range(0, len(result[1])):
            # 不为空不能作为拐点
            if result[i][j] != EMPTY_ID:
                continue
            # 不和被选方块在同一行列的不能作为拐点
            if i != x1 and i != x2 and j != y1 and j != y2:
                continue
            # 作为交点的方块不能作为拐点
            if (i == x1 and j == y2) or (i == x2 and j == y1):
                continue
            if turnOnceCheck(x1, y1, i, j, result) and (
                    horizontalCheck(i, j, x2, y2, result) or verticalCheck(i, j, x2, y2, result)):
                return True
            if turnOnceCheck(i, j, x2, y2, result) and (
                    horizontalCheck(x1, y1, i, j, result) or verticalCheck(x1, y1, i, j, result)):
                return True
    return False


def autoRelease(result, game_x, game_y):
    # 遍历地图
    for i in range(0, len(result)):
        for j in range(0, len(result[0])):
            # 当前位置非空
            if result[i][j] != EMPTY_ID:
                # 再次遍历地图 寻找另一个满足条件的图片
                for m in range(0, len(result)):
                    for n in range(0, len(result[0])):
                        if result[m][n] != EMPTY_ID:
                            # 若可以执行消除
                            if canConnect(i, j, m, n, result):
                                # 消除的两个位置设置为空
                                result[i][j] = EMPTY_ID
                                result[m][n] = EMPTY_ID
                                print('Remove :' + str(i + 1) + ',' + str(j + 1) + ' and ' + str(m + 1) + ',' + str(
                                    n + 1))

                                # 计算当前两个位置的图片在游戏中应该存在的位置
                                x1 = game_x + j * POINT_WIDTH
                                y1 = game_y + i * POINT_HEIGHT
                                x2 = game_x + n * POINT_WIDTH
                                y2 = game_y + m * POINT_HEIGHT

                                # 模拟鼠标点击第一个图片所在的位置
                                win32api.SetCursorPos((x1 + 15, y1 + 18))
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x1 + 15, y1 + 18, 0, 0)
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x1 + 15, y1 + 18, 0, 0)

                                # 等待随机时间 ,防止检测
                                time.sleep(random.uniform(TIME_INTERVAL_MIN, TIME_INTERVAL_MAX))

                                # 模拟鼠标点击第二个图片所在的位置
                                win32api.SetCursorPos((x2 + 15, y2 + 18))
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN, x2 + 15, y2 + 18, 0, 0)
                                win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP, x2 + 15, y2 + 18, 0, 0)
                                time.sleep(random.uniform(TIME_INTERVAL_MIN, TIME_INTERVAL_MAX))
                                # 执行消除后返回True
                                return True
    return False


def autoRemove(squares, game_pos):
    game_x = game_pos[0] + MARGIN_LEFT
    game_y = game_pos[1] + MARGIN_HEIGHT
    # 重复一次消除直到到达最多消除次数
    while True:
        if not autoRelease(squares, game_x, game_y):
            # 当不再有可消除的方块时结束 , 返回消除数量
            return


if __name__ == '__main__':
    random.seed()
    # i. 定位游戏窗体
    game_pos = getGameWindow()
    time.sleep(1)
    # ii. 获取屏幕截图
    screen_image = getScreenImage()
    # iii. 对截图切片,形成一张二维地图
    all_square_list = getAllSquare(screen_image, game_pos)
    # iv. 获取所有类型的图形,并编号
    types = getAllSquareTypes(all_square_list)
    # v. 讲获取的图片地图转换成数字矩阵
    result = np.transpose(getAllSquareRecord(all_square_list, types))
    # vi. 执行消除 , 并输出消除数量
    print('The total elimination amount is ' + str(autoRemove(result, game_pos)))

兄弟们快去试试吧

以上就是Python实现自动玩连连看的脚本分享的详细内容,更多关于Python连连看的资料请关注三水点靠木其它相关文章!

Python 相关文章推荐
在Python的Flask框架下收发电子邮件的教程
Apr 21 Python
Android模拟器无法启动,报错:Cannot set up guest memory ‘android_arm’ Invalid argument的解决方法
Jul 01 Python
Python使用flask框架操作sqlite3的两种方式
Jan 31 Python
Python matplotlib绘图可视化知识点整理(小结)
Mar 16 Python
Python用于学习重要算法的模块pygorithm实例浅析
Aug 16 Python
Pytorch保存模型用于测试和用于继续训练的区别详解
Jan 10 Python
python实现翻译word表格小程序
Feb 27 Python
Python实现电视里的5毛特效实例代码详解
May 15 Python
python判断all函数输出结果是否为true的方法
Dec 03 Python
python文件路径操作方法总结
Dec 21 Python
Python实战之用tkinter库做一个鼠标模拟点击器
Apr 27 Python
详解Python描述符的工作原理
Jun 11 Python
Python利用Turtle绘制哆啦A梦和小猪佩奇
Python必备技巧之函数的使用详解
Python批量解压&压缩文件夹的示例代码
Apr 04 #Python
Python调用腾讯API实现人脸身份证比对功能
Python字符串常规操作小结
Anaconda安装pytorch和paddle的方法步骤
python lambda 表达式形式分析
You might like
PHP合并数组+与array_merge的区别分析
2010/08/01 PHP
解析在PHP中使用全局变量的几种方法
2013/06/24 PHP
php去除二维数组的重复项方法
2015/11/03 PHP
javascript中的location用法简单介绍
2007/03/07 Javascript
JS 实现双色表格实现代码
2009/11/24 Javascript
使用JS进行目录上传(相当于批量上传)
2010/12/05 Javascript
基于jquery的关于动态创建DOM元素的问题
2010/12/24 Javascript
通过jquery的$.getJSON做一个跨域ajax请求试验
2011/05/03 Javascript
js批量设置样式的三种方法不推荐使用with
2013/02/25 Javascript
js实现收缩菜单效果实例代码
2013/10/30 Javascript
cookie中的path与domain属性详解
2013/12/18 Javascript
js中call与apply的用法小结
2013/12/28 Javascript
浅谈JavaScript中null和undefined
2015/07/09 Javascript
jQuery获取字符串中出现最多的数
2016/02/22 Javascript
js控件Kindeditor实现图片自动上传功能
2020/07/20 Javascript
AngularJS入门教程之过滤器详解
2016/08/19 Javascript
angular实现商品筛选功能
2017/02/01 Javascript
Angular4表单验证代码详解
2017/09/03 Javascript
JS实现合并json对象的方法
2017/10/10 Javascript
Angular 4中如何显示内容的CSS样式示例代码
2017/11/06 Javascript
jQuery.Sumoselect插件实现下拉复选框效果
2017/11/09 jQuery
JS实现json对象数组按对象属性排序操作示例
2018/05/18 Javascript
js/jQuery实现全选效果
2019/06/17 jQuery
js实现类选择器和name属性选择器的示例步骤
2021/02/07 Javascript
python使用sorted函数对列表进行排序的方法
2015/04/04 Python
在Django的session中使用User对象的方法
2015/07/23 Python
Python使用回溯法子集树模板解决迷宫问题示例
2017/09/01 Python
python爬虫之自动登录与验证码识别
2020/06/15 Python
用Python画小女孩放风筝的示例
2019/11/23 Python
python 弧度与角度互转实例
2020/04/15 Python
Python的in,is和id函数代码实例
2020/04/18 Python
Html5之title吸顶功能
2018/06/04 HTML / CSS
Mankind西班牙男士护肤品网站:购买皮肤护理、护发和剃须
2017/04/27 全球购物
网络艺术零售业的先驱者:artrepublic
2017/09/26 全球购物
程序员跳槽必看面试题总结
2013/06/28 面试题
React如何创建组件
2021/06/27 Javascript