python 图形界面“诈金花”游戏,更新了!附完整代码

news2024/12/24 21:22:53

旧版本的代码请见上一篇博文: 

python 从一道作业题到制作一个图形界面的“诈金花”游戏_Hann Yang的博客-CSDN博客Player1: ('♥Q', '♣2', '♣8') - 单张Player2: ('♦10', '♥7', '♠6') - 单张Player3: ('♣4', '♠4', '♦2') - 对子Player4: ('♠5', '♠9', '♥6') - 单张Player5: ('♠7', '♠3', '♣5') - 单张【Player3 win!】--> ('♣4', '♠4', '♦2') 对子(16.94%)https://blog.csdn.net/boysoft2002/article/details/128146513本文尝试在旧版本的基础上,“升级”以下几个部分:

一、图形的旋转,模拟四个玩家两两面对围坐在牌桌上

旋转方法 rotate(angle) 本文只用到转动角度这一个参数,角度正值表示逆时针转动;负值表示顺时针转动。

method rotate in module PIL.Image:

rotate(angle, resample=0, expand=0, center=None, translate=None, fillcolor=None) method of PIL.Image.Image instance
    Returns a rotated copy of this image.  This method returns a copy of this image, rotated the given number of degrees counter clockwise around its centre.
    :param angle: In degrees counter clockwise.
    :param resample: An optional resampling filter.  This can be one of :py:data: `PIL.Image.NEAREST`  (use nearest neighbour), :py:data:`PIL.Image.BILINEAR` (linear interpolation in a 2x2 environment), or :py:data:`PIL.Image.BICUBIC`
       (cubic spline interpolation in a 4x4 environment).
       If omitted, or if the image has mode "1" or "P", it is set to :py:data: `PIL.Image.NEAREST`. See :ref:`concept-filters`.
    :param expand: Optional expansion flag.  If true, expands the output image to make it large enough to hold the entire rotated image.
       If false or omitted, make the output image the same size as the input image.  Note that the expand flag assumes rotation around the center and no translation.
    :param center: Optional center of rotation (a 2-tuple).  Origin is the upper left corner.  Default is the center of the image.
    :param translate: An optional post-rotate translation (a 2-tuple).
    :param fillcolor: An optional color for area outside the rotated image.
    :returns: An :py:class:`~PIL.Image.Image` object.

如不是正方形图片,转动角度不是180度的话,就会被截掉一部分。效果如下: 

演示代码:

import tkinter as tk
from PIL import Image,ImageTk

def load(i=0):
    img = Image.open("pokers.png").resize((375,150))
    box = img.rotate(90*i)
    res = ImageTk.PhotoImage(image=box)
    img.close()
    return res

if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('800x480')
    root.title('图片旋转')
    cv = tk.Canvas(root, width=1600, height=800, bg='darkgreen')
    cv.pack()

    png = [None]*4
    coord = ((i,j) for j in (120,345) for i in (200,600))
    for i,xy in enumerate(coord):
        png[i] = load(i)
        cv.create_image(xy, image=png[i])
        cv.create_text(xy[0],xy[1]+95, text=f'逆时针转动{i*90}度',fill='white')
    
    root.mainloop()

为保存全图在转动之前,设置一个正方形框 box = img.crop((0,0,375,375)).rotate(-90*i),顺时针转动的效果如下:

演示代码:

import tkinter as tk
from PIL import Image,ImageTk

def load(i=0):
    img = Image.open("pokers.png").resize((375,150))
    box = img.crop((0,0,375,375)).rotate(-90*i)
    res = ImageTk.PhotoImage(image=box)
    img.close()
    return res

if __name__ == '__main__':
    root = tk.Tk()
    root.geometry('800x800')
    root.title('图片旋转')
    cv = tk.Canvas(root, width=1600, height=800, bg='darkgreen')
    cv.pack()

    png = []
    coord = ((i,j) for j in (200,600) for i in (200,600))
    for i,xy in enumerate(coord):
        png.append(load(i))
        cv.create_image(xy, image=png[i])
    
    root.mainloop()

然后再用crop()方法来截取出黑色背景除外的部分,就是所需的转动四个方向上的图像;最后把这些图片再次分割成一张张小纸牌,存入一个三维列表备用。 

二、增加筹码变量,使得比大小游戏有累积输赢过程

在玩家文本框后各添加一个筹码文本框,动态显示每一局的输赢情况;各玩家的筹码值存放于全局变量Money列表中,主要代码如下:

    ALL, ONE = 1000, 200 #筹码初始值、单次输赢值
    Money = [ALL]*4 #设置各方筹码初始值
    ...
    ...
    cv.create_text(tx,ty, text=f'Player{x+1}', fill='white') #玩家1-4显示文本框
    txt.append(cv.create_text(tx+60,ty, fill='gold',text=Money[x])) #筹码显示框
    ...
    ...
    Money[idx] += ONE*4 #每次赢ONE*3,多加自己的一份
    for i in range(4):
        Money[i] -= ONE #多加的在此扣减
        cv.itemconfig(txt[i], text=str(Money[i])) #修改各方的筹码值
    cv.update()

三、界面增加下拉式菜单,菜单项调用的绑定函数

显示效果见题图左上角,主要代码如下:

    btnCmd = '发牌',dealCards,'开牌',playCards,'洗牌',Shuffle
    Menu = tk.Menu(root)
    menu = tk.Menu(Menu, tearoff = False)
    for t,cmd in zip(btnCmd[::2],btnCmd[1::2]):
        menu.add_radiobutton(label = t, command = cmd)
    menu.add_separator() #菜单分割线
    menu.add_command(label = "退出", command = ExitApp)
    Menu.add_cascade(label="菜单",menu = menu)
    root.config(menu = Menu)

四、导入信息框库,增加提示信息框的使用

使用了2种信息框类型:提示showinfo()和确认选择askokcancel()

tkinter.messagebox库共有8种信息框类型,其使用方法基本相同,只是显示的图标有区别:

Help on module tkinter.messagebox in tkinter:

NAME
    tkinter.messagebox

FUNCTIONS
    askokcancel(title=None, message=None, **options)
        Ask if operation should proceed; return true if the answer is ok
    
    askquestion(title=None, message=None, **options)
        Ask a question
    
    askretrycancel(title=None, message=None, **options)
        Ask if operation should be retried; return true if the answer is yes
    
    askyesno(title=None, message=None, **options)
        Ask a question; return true if the answer is yes
    
    askyesnocancel(title=None, message=None, **options)
        Ask a question; return true if the answer is yes, None if cancelled.
    
    showerror(title=None, message=None, **options)
        Show an error message
    
    showinfo(title=None, message=None, **options)
        Show an info message
    
    showwarning(title=None, message=None, **options)
        Show a warning message

DATA
    ABORT = 'abort'
    ABORTRETRYIGNORE = 'abortretryignore'
    CANCEL = 'cancel'
    ERROR = 'error'
    IGNORE = 'ignore'
    INFO = 'info'
    NO = 'no'
    OK = 'ok'
    OKCANCEL = 'okcancel'
    QUESTION = 'question'
    RETRY = 'retry'
    RETRYCANCEL = 'retrycancel'
    WARNING = 'warning'
    YES = 'yes'
    YESNO = 'yesno'
    YESNOCANCEL = 'yesnocancel'

:发牌、开牌、洗牌按钮可否点击,由两个全局变量控制,当不能使用时弹出提示信息框。但更好方式通常是设置按钮的state状态,在 tk.DISABLED 和 tk.NORMAL 之间切换,用以下代码:

if btn[0]['state'] == tk.DISABLED:
	btn[0]['state'] = tk.NORMAL
else:
	btn[0]['state'] = tk.DISABLED  #使得按钮灰化,无法被按下

#或者在初始按钮时使用:
tk.Button(root,text="点不了",command=test,width=10,state=tk.DISABLED)

“诈金花”完整源代码

import tkinter as tk
import tkinter.messagebox as msg
from PIL import Image,ImageTk
from time import sleep
from random import shuffle as DealCards
#代码中所有print()语句行测试用都可删除
def loadCards():
    PngList = []
    infile = Image.open("pokers.png") 
    for k in range(4):
        box = 0,0,1500,1500 #设置正方形区域存放图片旋转后的状态
        box = infile.crop(box).rotate(90*k) #图片逆时间旋转90度的整数倍
        if   k==0: rng = (0,0,1500,600)
        elif k==1: rng = (0,0,600,1500)
        elif k==2: rng = (0,900,1500,1500)
        elif k==3: rng = (900,0,1500,1500)
        box = box.crop(rng) #截取掉旋转产生的黑色背景
        images = []
        for j in range(4): #分割所有纸牌的图像存入三维列表
            image = []
            for i in range(15):
                if k%2:
                    rng = (j*150,i*100,j*150+150,i*100+100)
                else:
                    rng = (i*100,j*150,i*100+100,j*150+150)
                img = ImageTk.PhotoImage(image=box.crop(rng))
                image.append(img)
            images.append(image)
        PngList.append(images)
    '''调整并统一各方向上的纸牌图像顺序'''
    PngList[0],PngList[2] = PngList[2],PngList[0]
    for i in range(4):
        for j in range(2):
            PngList[j][i]=PngList[j][i][::-1]
    for i in range(0,4,3):
        PngList[i]=PngList[i][::-1]
    infile.close()
    return PngList
 
def initCards():
    global P
    P = [f+v for f in F for v in V]
    DealCards(P)
    print('洗牌结果:\n',P)

def clearCards():
    global cv
    cv.itemconfig(txt1, text="")
    cv.itemconfig(txt2, text="")
    if len(Pokers):
        for j in range(3):
            for i in range(4):
                cv.itemconfig(cards[i][j], image=Cards[i][0][0])
                cv.update()
        sleep(0.3)

def dealCards():
    global cv,isReady1,isReady2
    if not isReady1:
        showInfo('不要重复发牌,发牌结束后请开牌!')
        return
    clearCards()
    isReady1 = False
    for j in range(3):
        for i in range(4):
            cv.itemconfig(cards[i][j], image=Cards[i][1][0])
            cv.update()
            sleep(0.2)
    if len(P)<12: initCards()
    isReady2 = False
 
def playCards():
    global cv,isReady1,isReady2,P,Pokers
    if isReady1:
        showInfo('还没发牌,请发牌或者洗牌!')
    elif isReady2:
        showInfo('发牌还未结束,请勿开牌!')
    else:
        P = Result(P)
        isReady1,isReady2 = True,True
        for i,pok in enumerate(Pokers):
            for j,p in enumerate(pok):
                x,y = F.index(p[0]), V.index(p[1])
                cv.itemconfig(cards[i][j], image=Cards[i][x][y+2])
                cv.update()
        for i in range(4):
            cv.itemconfig(txt[i], text=str(Money[i])) #修改各方的筹码值
            cv.update()
        if min(Money)<=0: #统计输赢成绩
            zero = [f'Player{i}' for i,j in enumerate(Money,1) if j<=0]
            winner = [f'Player{i}({j})' for i,j in enumerate(Money,1) if j>ALL]
            info = '、'.join(zero)+'已输光筹码,点击确定重新开始!\n\n'
            info += f'本轮胜者(筹码多于初始值):'+'、'.join(winner)
            sleep(1)
            msg.showinfo(title = '提示',message=info)
            for i in range(4):
                Money[i] = ALL #重置各方筹码初始值
                cv.itemconfig(txt[i], text=str(Money[i])) 
                cv.update()
            clearCards()
            initCards()
            isReady1,isReady2 = True,False
 
def Scores(pokers):
    f,p = [],[]
    for poker in pokers:
        f.append(F.index(poker[0])+1)
        p.append(V.index(poker[1])+2)
    t = sorted(p)
    intSame = len(set(t))
    isFlush = int(len(set(f))==1)
    isStraight = t[0]+1==t[1]==t[2]-1
    if intSame==1:
        return 500_0000+t[0] #豹子
    elif intSame==2: #对子一样大比较剩下的单张
        return (100+t[1])*10000+(t[2] if t[0]==t[1] else t[0])
    else: #顺金(同花顺)顺子 else #单张或金花
        Straight = 200_0000*(1+isFlush)+t[2]
        Flush = ((300*isFlush+t[2])*100+t[1])*100+t[0] 
        return Straight if isStraight else Flush
 
def Result(P):
    global cv,Pokers
    Pokers,Winner = [],[]
    for i in range(0,3*4,3):
        Pokers.append(P[i:i+3])
    for i,p in enumerate(Pokers,1):
        win = Scores(p)
        idx = win//100_0000
        print(f"Player{i}: {*p,} - {W[idx]}".replace('T','10'))
        Winner.append(win)
    win = max(Winner) #没有判断“一样大”,如是则谁在前谁为大
    idx = Winner.index(win)
    big = win//10000
    win = big//100
    per = X[win] if win else Y[big-5]
    pok = W[win] if win else '单'+V[big-2]
    text1 = f"【Player{idx+1} win!】"
    text2 = f"{pok}{*Pokers[idx],} {per}%\n".replace('T','10')
    print(text1,'--> ',text2)
    cv.itemconfig(txt1, text=text1)
    cv.itemconfig(txt2, text=text2)
    Money[idx] += ONE*4 #每次赢ONE*3,多加自己的一份
    for i in range(4): Money[i] -= ONE #多加的在此扣减
    return P[3*4:] #去掉一局已发的牌
 
def Shuffle():
    global isReady1
    if isReady1:
        clearCards()
        initCards()
        showInfo('已重新洗牌,请发牌!')
    else:
        showInfo('还没开牌呢,请勿洗牌!')

def showInfo(info):
    msg.showinfo(title='提示',message=info)

def ExitApp():
    if msg.askokcancel(title='确认',message='确定要退出吗?'):
        root.destroy()  #关闭窗口退出程序

if __name__ == '__main__':
    W = "单张","对子","顺子","金花","顺金","豹子" #牌型
    X = 74.38, 16.94, 3.26, 4.96, 0.22, 0.24  #各牌型出现概率
    Y = 0.54, 1.36, 2.44, 3.8, 5.43, 7.33, 9.5, 11.95, 14.66, 17.38 #单张概率
    V = *(str(i) for i in range(2,10)),*'TJQKA' #T代表10
    F = '♠', '♥', '♣', '♦'
    ALL, ONE = 1000, 200 #筹码初始值、单次输赢值
    Money = [ALL]*4 #设置各方筹码初始值
    '''Written by HannYang@CSDN, 2022.12.03'''
    root = tk.Tk()
    root.title('诈金花')
    root.geometry('1024x768')
    root.resizable(0,0) #禁止窗体改变大小
    cv = tk.Canvas(root, width=1024, height=680, bg='darkgreen')
    cv.pack()
    Pokers = []
    initCards()
    Cards = loadCards()
    isReady1,isReady2 = True,True #发牌、开牌的准备标记
    cards = [[None]*3 for _ in range(4)]
    '''设置发牌区域'''
    x1, x2, x3, dx = 400, 180, 830, 105
    y1, y2, y3 = 100, 550, 220 #调整坐标,使左右两家的牌横向显示
    imgxy = [[(x1,y1),(x1+dx,y1),(x1+2*dx,y1)],
             [(x3,y3),(x3,y3+dx),(x3,y3+2*dx)],
             [(x1,y2),(x1+dx,y2),(x1+2*dx,y2)],
             [(x2,y3),(x2,y3+dx),(x2,y3+2*dx)]]
    btn,txt = [],[]
    for x,lst in enumerate(imgxy):
        for y,coord in enumerate(lst):
            cards[x][y] = cv.create_image(coord, image=Cards[x][0][0])
            x1,y1,x2,y2 = coord[0]-50,coord[1]-50,coord[0]+50,coord[1]+50
            if x%2:
                cv.create_rectangle(x1-25,y1,x2+25,y2) #纸牌外框
            else:
                cv.create_rectangle(x1,y1-25,x2,y2+25)
        if x%2:
            tx,ty = coord[0]-25,coord[1]+65 #玩家、筹码的显示坐标
        else:
            tx,ty = coord[0]-130,coord[1]+90
        cv.create_text(tx,ty, text=f'Player{x+1}', fill='white') #玩家1-4显示文本框
        txt.append(cv.create_text(tx+60,ty, fill='gold',text=Money[x])) #筹码显示框
    '''设置显示每次开牌的胜者、牌型和出现概率的文本框'''
    txt1 = cv.create_text(510,300, fill='tomato', font=("宋体", 24))
    txt2 = cv.create_text(510,360, fill='yellow', font=("宋体", 12))
    '''设置命令按钮和菜单'''
    btnCmd = '发牌',dealCards,'开牌',playCards,'洗牌',Shuffle
    for i in range(3):
        btn.append(tk.Button(root,text=btnCmd[i*2],command=btnCmd[i*2+1],width=10))
        btn[i].place(y=710, x=350+i*110)
    Menu = tk.Menu(root)
    menu = tk.Menu(Menu, tearoff = False)
    for t,cmd in zip(btnCmd[::2],btnCmd[1::2]):
        menu.add_radiobutton(label = t, command = cmd)
    menu.add_separator() #菜单分割线
    menu.add_command(label = "退出", command = ExitApp)
    Menu.add_cascade(label="菜单",menu = menu)
    root.config(menu = Menu)
    ''''''
    root.mainloop()

运行结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/66657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SSM框架-SpringMVC(二)

目录 1 SpringMVC处理Ajax请求 1.1 RequestBody 1.2 RequestBody获取json格式的请求参数 1.3 ResponseBody 1.4、ResponseBody响应浏览器json数据 1.5 RestController注解 2 文件上传和下载 2.1 文件下载 2.2 上传文件 3 拦截器 3.1 拦截器的三个抽象方法 3.2 拦截器…

技术分享 | ClickHouse 冷热存储分离方案线上实践

作者&#xff1a;任坤 现居珠海&#xff0c;先后担任专职 Oracle 和 MySQL DBA&#xff0c;现在主要负责 MySQL、mongoDB 和 Redis 维护工作。 本文来源&#xff1a;原创投稿 *爱可生开源社区出品&#xff0c;原创内容未经授权不得随意使用&#xff0c;转载请联系小编并注明来源…

母胎级教学,工业路由器远程维护PLC详细操作指南

1、前言随着工业4.0大力推进&#xff0c;对工业现场设备的稳定性提出了更高的要求&#xff0c;大多数的设备制造商不能持续监测及管理设备&#xff0c;因为现场设备分布比较分散&#xff0c;客户不能集中管理&#xff0c;如果通过视频或电话沟通问题&#xff0c;则准确度不够&a…

【安卓学习之常见问题】jar文件中Class转java文件不准(不同软件打开的class文件不一样)

█ jar文件中Class转java文件不准 █ 系列文章目录 提示&#xff1a;这里是收集了和文件分享有关的文章 【安卓学习之常见问题】android路径及文件问题 【安卓学习之常见问题】文件分享–文件不存在 【安卓学习之常见问题】自定义组件-刷新后跳到第一行 【安卓学习之常见问题…

K_A08_005 基于 STM32等单片机驱动XY-160D模块按键控制直流电机正反转加减速启停

目录 一、资源说明 二、基本参数 四、部分代码说明 接线说明 1、STC89C52RCXY-160D模块 2、STM32F103C8T6XY-160D模块 五、基础知识学习与相关资料下载 六、视频效果展示与程序资料获取 七、项目所有材料清单 八、注意事项 九、接线表格 一、资源说明 单片机型号 测试…

【UNIAPP】APP快速免费生成一键发布页面

参考官方文档&#xff1a;https://uniapp.dcloud.net.cn/uniCloud/hosting.html# 效果预览地址&#xff1a;https://hellouniapp.dcloud.net.cn/portal 一、创建并运行uni-admin 1、创建项目 2、运行项目 3、关联到浏览器打开。 二、登录后台界面 1、进入主页面 2、如…

[附源码]Python计算机毕业设计Django校园帮平台管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

【2023-Pytorch-分类教程】手把手教你使用Pytorch训练自己的分类模型

之前更新过一起tf版本的训练自己的物体分类模型&#xff0c;但是很多兄弟反应tf版本的代码在GPU上无法运行&#xff0c;这个原因是tf在30系显卡上没有很好的支持。所以我们重新更新一期Pytorch版本的物体分类模型训练教程&#xff0c;在这个教程里面&#xff0c;你将会学会物体…

[附源码]计算机毕业设计面向高校活动聚AppSpringboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【电商项目实战】新增收货地址(详细篇)

&#x1f341;博客主页&#xff1a;&#x1f449;不会压弯的小飞侠 ✨欢迎关注&#xff1a;&#x1f449;点赞&#x1f44d;收藏⭐留言✒ ✨系列专栏&#xff1a;&#x1f449;SpringBoot电商项目实战 ✨学习社区&#xff1a; &#x1f449;不会压弯的小飞侠 ✨知足上进&#x…

刷爆力扣之最短无序连续子数组

刷爆力扣之最短无序连续子数组 HELLO&#xff0c;各位看官大大好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 今天阿呆继续记录下力扣刷题过程&#xff0c;收录在专栏算法中 &#x1f61c;&#x1f61c;&#x1f61c; 该专栏按照不同类别标签进行刷题&…

Windows+Visual stdio+CUDA编程方式及测试

目录一、visual stdio内针对工程的配置1、新建一个空项目2、配置CUDA生成依赖项3、配置基本库目录4、配置静态链接库路径5、配置源码文件风格6、扩展文件名配置二、样例测试测试样例1样例1问题&#xff1a;找不到helper_cuda.h文件测试样例2测试样例3一、visual stdio内针对工程…

Java餐厅点餐系统uniapp源码带安装教程

一套Java开发的餐厅点餐半成品系统&#xff0c;前端使用uniapp编写&#xff0c;经过本地测试&#xff0c;这套系统还有一些功能没完善好&#xff0c;有能力的朋友可以在这套系统基础上进行二次开发。 技术架构 后端技术框架&#xff1a;springboot shiro layui 前端技术框架…

springboot项目作为静态文件服务器

springboot项目作为静态文件服务器 springboot默认文件作用 使用 spring initialzr 创建 spring boot 项目 https://start.spring.io/ static 存放静态资源 template 存放模板页面 , 例如 thymeleaf 自定义静态文件存放目录 springboot 自动装配 , 默认静态资源的目录是 s…

Flink 知识点整理及八股文问题<第一部分 Flink简介>

本篇为Flink的第一大部分&#xff0c;初识Flink&#xff0c;全篇参考自 尚硅谷2022版1.13系列 整个系列的目录如下&#xff1a; <一>Flink简介 <二>Flink快速上手 <三>Flink 部署 <四>Flink 运行时架构 <五>DataStream API <六>Flin…

kubernetes—数据存储

数据存储 在前面已经提到&#xff0c;容器的生命周期可能很短&#xff0c;会被频繁地创建和销毁。那么容器在销毁时&#xff0c;保存在容器中的数据也会被清除。这种结果对用户来说&#xff0c;在某些情况下是不乐意看到的。为了持久化保存容器的数据&#xff0c;kubernetes引…

[附源码]计算机毕业设计旅游度假村管理系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

【Python项目】Python基于tkinter实现一个笔趣阁小说下载器 | 附源码

前言 halo&#xff0c;包子们上午好 笔趣阁小说应该很多小伙伴都知道 但是用Python实现一个笔趣阁小说下载器 那不是爽歪歪呀 基于tkinter实现的Python版本的笔趣阁小说下载器今天小编给大家实现了 相关文件 关注小编&#xff0c;私信小编领取哟&#xff01; 当然别忘了一件…

【多线程(四)】线程状态介绍、线程池基本原理、Executors默认线程池、ThreadPoolExecutor线程池

文章目录4.线程池4.1状态介绍4.2线程的状态-练习14.3线程的状态-练习24.4线程的状态-练习34.5线程池-基本原理4.6线程池-Executors默认线程池4.7线程池-Executors创建指定上限的线程池4.8线程池-ThreadPoolExecutor4.9线程池-参数详解4.10线程池-非默认任务拒绝策略总结4.线程池…

用一个原始密码针对不同软件生成不同密码并保证相对安全

使用一个密码并在数据泄漏时保护自己的其它账号 关于密码 现在好多软件&#xff0c;好多网站都需要我们设置密码&#xff0c;这个时候我们的处理办法一般分为2种。 对不同的软件设置不同的密码&#xff0c;这种理论上是最安全的&#xff0c;但是记不住啊&#xff0c;所以不实…