Python 围棋

效果图

python 围棋

完整代码

源码地址:Python 围棋

# 使用Python内置GUI模块tkinter  
from tkinter import *  
# ttk覆盖tkinter部分对象,ttk对tkinter进行了优化  
from tkinter.ttk import *  
# 深拷贝时需要用到copy模块  
import copy  
import tkinter.messagebox  
  
# 默认9路  
MODE_NUM = 9  
NEW_APP = False  
  
  
# 围棋应用对象定义  
class Application(Tk):  
    # 初始化棋盘,默认九路棋盘  
    def __init__(self, my_mode_num=9):  
        Tk.__init__(self)  
        # 模式,九路棋:9,十三路棋:13,十九路棋:19  
        self.mode_num = my_mode_num  
        # 窗口尺寸设置,默认:1.8  
        self.size = 1.8  
        # 棋盘每格的边长  
        self.dd = 360 * self.size / (self.mode_num - 1)  
        # 相对九路棋盘的矫正比例  
        self.p = 1 if self.mode_num == 9 else (2 / 3 if self.mode_num == 13 else 4 / 9)  
        # 定义棋盘阵列,超过边界:-1,无子:0,黑棋:1,白棋:2  
        self.positions = [[0 for i in range(self.mode_num + 2)] for i in range(self.mode_num + 2)]  
        # 初始化棋盘,所有超过边界的值置-1  
        for m in range(self.mode_num + 2):  
            for n in range(self.mode_num + 2):  
                if m * n == 0 or m == self.mode_num + 1 or n == self.mode_num + 1:  
                    self.positions[m][n] = -1  
        # 拷贝三份棋盘“快照”,悔棋和判断“打劫”时需要作参考  
        self.last_3_positions = copy.deepcopy(self.positions)  
        self.last_2_positions = copy.deepcopy(self.positions)  
        self.last_1_positions = copy.deepcopy(self.positions)  
        # 记录鼠标经过的地方,用于显示shadow时  
        self.cross_last = None  
        # 当前轮到的玩家,黑:0,白:1,执黑先行  
        self.present = 0  
        # 设置先手  
        self.fm = -1  
        # 棋子阴影  
        self.cross = None  
  
        # 记录空位置  
        self.image_added = None  
        self.image_added_sign = None  
        # 初始停止运行,点击“开始游戏”运行游戏  
        self.stop = True  
        # 悔棋次数,次数大于0才可悔棋,初始置0(初始不能悔棋),悔棋后置0,下棋或弃手时恢复为1,以禁止连续悔棋  
        self.regret_chance = 0  
        # 图片资源,存放在当前目录下的/images/中  
        self.image_W = PhotoImage(file="./images/WD-9.png")  
        self.image_B = PhotoImage(file="./images/BD-9.png")  
        self.image_BD = PhotoImage(file="./images/" + "BD" + "-" + str(self.mode_num) + ".png")  
        self.image_WD = PhotoImage(file="./images/" + "WD" + "-" + str(self.mode_num) + ".png")  
        self.image_BU = PhotoImage(file="./images/" + "BU" + "-" + str(self.mode_num) + ".png")  
        self.image_WU = PhotoImage(file="./images/" + "WU" + "-" + str(self.mode_num) + ".png")  
        # 用于黑白棋子图片切换的列表  
        self.chequer_wbu_list = [self.image_BU, self.image_WU]  
        self.chequer_wbd_list = [self.image_BD, self.image_WD]  
        # 窗口大小  
        self.geometry(str(int(600 * self.size)) + 'x' + str(int(400 * self.size)))  
        # 画布控件,作为容器  
        self.canvas_bottom = Canvas(self, bg='#585858', bd=0, width=600 * self.size, height=400 * self.size)  
        self.canvas_bottom.place(x=0, y=0)  
        # 几个功能按钮  
        self.startButton = Button(self, text='开始游戏', command=self.start)  
        self.startButton.place(x=480 * self.size, y=200 * self.size)  
        self.giveUpButton = Button(self, text='弃一手', command=self.give_up)  
        self.giveUpButton.place(x=480 * self.size, y=225 * self.size)  
        self.regretButton = Button(self, text='悔棋', command=self.regret_chess)  
        self.regretButton.place(x=480 * self.size, y=250 * self.size)  
        # 初始悔棋按钮禁用  
        self.regretButton['state'] = DISABLED  
        self.replayButton = Button(self, text='重新开始', command=self.reload)  
        self.replayButton.place(x=480 * self.size, y=275 * self.size)  
        self.newGameButton1 = Button(self, text=('十三' if self.mode_num == 9 else '九') + '路棋', command=self.new_game_one)  
        self.newGameButton1.place(x=480 * self.size, y=300 * self.size)  
        self.newGameButton2 = Button(self, text=('十三' if self.mode_num == 19 else '十九') + '路棋',  
                                     command=self.new_game_second)  
        self.newGameButton2.place(x=480 * self.size, y=325 * self.size)  
        self.quitButton = Button(self, text='退出游戏', command=self.quit)  
        self.quitButton.place(x=480 * self.size, y=350 * self.size)  
        # 画棋盘,填充颜色  
        self.canvas_bottom.create_rectangle(0 * self.size, 0 * self.size, 400 * self.size, 400 * self.size, fill='#d0892e')  
        # 刻画棋盘线及九个点  
        # 先画外框粗线  
        self.canvas_bottom.create_rectangle(20 * self.size, 20 * self.size, 380 * self.size, 380 * self.size, width=3)  
        # 棋盘上的九个定位点,以中点为模型,移动位置,以作出其余八个点  
        for m in [-1, 0, 1]:  
            for n in [-1, 0, 1]:  
                self.original = self.canvas_bottom.create_oval(  
                    200 * self.size - self.size * 2,  
                    200 * self.size - self.size * 2,  
                    200 * self.size + self.size * 2,  
                    200 * self.size + self.size * 2, fill='#000')  
                self.canvas_bottom.move(  
                    self.original,  
                    m * self.dd * (2 if self.mode_num == 9 else (3 if self.mode_num == 13 else 6)),  
                    n * self.dd * (2 if self.mode_num == 9 else (3 if self.mode_num == 13 else 6)))  
        # 画中间的线条  
        for i in range(1, self.mode_num - 1):  
            self.canvas_bottom.create_line(20 * self.size, 20 * self.size + i * self.dd, 380 * self.size,  
                                           20 * self.size + i * self.dd, width=2)  
            self.canvas_bottom.create_line(20 * self.size + i * self.dd, 20 * self.size, 20 * self.size + i * self.dd,  
                                           380 * self.size, width=2)  
        # 放置右侧初始图片  
        self.pW = None  
        # 默认黑棋先手  
        self.pB = self.canvas_bottom.create_image(500 * self.size + 11, 65 * self.size, image=self.image_B)  
        # 每张图片都添加image标签,方便reload函数删除图片  
        self.canvas_bottom.addtag_withtag('image', self.pB)  
        self.bButton = Button(self, text='黑棋先手', command=self.first_b)  
        self.bButton.place(x=480 * self.size, y=100 * self.size)  
        self.wButton = Button(self, text='白棋先手', command=self.first_w)  
        self.wButton.place(x=480 * self.size, y=120 * self.size)  
        # 鼠标移动时,调用shadow函数,显示随鼠标移动的棋子  
        self.canvas_bottom.bind('<Motion>', self.shadow)  
        # 鼠标左键单击时,调用get_down函数,放下棋子  
        self.canvas_bottom.bind('<Button-1>', self.get_down)  
        # 设置退出快捷键<Ctrl>+<D>,快速退出游戏  
        self.bind('<Control-KeyPress-d>', self.keyboard_quit)  
  
    def first_b(self):  
        """  
        @summary: 黑棋先手  
        :return:  
        """        self.present = 0  
        self.create_pb()  
        self.del_pw()  
        if self.stop:  
            self.bButton['state'] = DISABLED  
            self.wButton['state'] = NORMAL  
        else:  
            self.bButton['state'] = DISABLED  
            self.wButton['state'] = DISABLED  
  
    def first_w(self):  
        """  
        @summary: 白棋先手  
        :return:  
        """        self.present = 1  
        self.create_pw()  
        self.del_pb()  
        if self.stop:  
            self.wButton['state'] = DISABLED  
            self.bButton['state'] = NORMAL  
        else:  
            self.bButton['state'] = DISABLED  
            self.wButton['state'] = DISABLED  
  
    # 开始游戏函数,点击“开始游戏”时调用  
    def start(self):  
        # 禁止选先手  
        self.bButton['state'] = DISABLED  
        self.wButton['state'] = DISABLED  
        # 利用右侧图案提示开始时谁先落子  
        if self.present == 0:  
            self.create_pb()  
            self.del_pw()  
        else:  
            self.create_pw()  
            self.del_pb()  
        # 开始标志,解除stop  
        self.stop = None  
  
    # 放弃一手函数,跳过落子环节  
    def give_up(self):  
        # 悔棋恢复  
        if not self.regret_chance == 1:  
            self.regret_chance += 1  
        else:  
            self.regretButton['state'] = NORMAL  
        # 拷贝棋盘状态,记录前三次棋局  
        self.last_3_positions = copy.deepcopy(self.last_2_positions)  
        self.last_2_positions = copy.deepcopy(self.last_1_positions)  
        self.last_1_positions = copy.deepcopy(self.positions)  
        self.canvas_bottom.delete('image_added_sign')  
        # 轮到下一玩家  
        if self.present == 0:  
            self.create_pw()  
            self.del_pb()  
            self.present = 1  
        else:  
            self.create_pb()  
            self.del_pw()  
            self.present = 0  
  
    # 悔棋函数,可悔棋一回合,下两回合不可悔棋  
    def regret_chess(self):  
        # 判定是否可以悔棋,以前第三盘棋局复原棋盘  
        if self.regret_chance == 1:  
            self.regret_chance = 0  
            self.regretButton['state'] = DISABLED  
            list_of_b = []  
            list_of_w = []  
            self.canvas_bottom.delete('image')  
            if self.present == 0:  
                self.create_pb()  
            else:  
                self.create_pw()  
            for m in range(1, self.mode_num + 1):  
                for n in range(1, self.mode_num + 1):  
                    self.positions[m][n] = 0  
            for m in range(len(self.last_3_positions)):  
                for n in range(len(self.last_3_positions[m])):  
                    if self.last_3_positions[m][n] == 1:  
                        list_of_b += [[n, m]]  
                    elif self.last_3_positions[m][n] == 2:  
                        list_of_w += [[n, m]]  
            self.recover(list_of_b, 0)  
            self.recover(list_of_w, 1)  
            self.last_1_positions = copy.deepcopy(self.last_3_positions)  
            for m in range(1, self.mode_num + 1):  
                for n in range(1, self.mode_num + 1):  
                    self.last_2_positions[m][n] = 0  
                    self.last_3_positions[m][n] = 0  
  
    # 重新加载函数,删除图片,序列归零,设置一些初始参数,点击“重新开始”时调用  
    def reload(self):  
        if self.stop == 1:  
            self.stop = 0  
        self.canvas_bottom.delete('image')  
        self.regret_chance = 0  
        self.present = 0  
        self.create_pb()  
        for m in range(1, self.mode_num + 1):  
            for n in range(1, self.mode_num + 1):  
                self.positions[m][n] = 0  
                self.last_3_positions[m][n] = 0  
                self.last_2_positions[m][n] = 0  
                self.last_1_positions[m][n] = 0  
  
    # 以下四个函数实现了右侧太极图的动态创建与删除  
    def create_pw(self):  
        """  
        @summary: 创建白棋  
        :return:  
        """        self.pW = self.canvas_bottom.create_image(500 * self.size + 11, 65 * self.size, image=self.image_W)  
        self.canvas_bottom.addtag_withtag('image', self.pW)  
  
    def create_pb(self):  
        """  
        @summary: 创建黑棋  
        :return:  
        """        self.pB = self.canvas_bottom.create_image(500 * self.size + 11, 65 * self.size, image=self.image_B)  
        self.canvas_bottom.addtag_withtag('image', self.pB)  
  
    def del_pw(self):  
        if self.pW:  
            self.canvas_bottom.delete(self.pW)  
  
    def del_pb(self):  
        if self.pB:  
            self.canvas_bottom.delete(self.pB)  
  
    # 显示鼠标移动下棋子的移动  
    def shadow(self, event):  
        if not self.stop:  
            # 找到最近格点,在当前位置靠近的格点出显示棋子图片,并删除上一位置的棋子图片  
            if (20 * self.size < event.x < 380 * self.size) and (20 * self.size < event.y < 380 * self.size):  
                dx = (event.x - 20 * self.size) % self.dd  
                dy = (event.y - 20 * self.size) % self.dd  
                self.cross = self.canvas_bottom.create_image(  
                    event.x - dx + round(dx / self.dd) * self.dd + 22 * self.p,  
                    event.y - dy + round(dy / self.dd) * self.dd - 27 * self.p,  
                    image=self.chequer_wbu_list[self.present])  
                self.canvas_bottom.addtag_withtag('image', self.cross)  
                if self.cross_last is not None:  
                    self.canvas_bottom.delete(self.cross_last)  
                self.cross_last = self.cross  
  
    # 落子,并驱动玩家的轮流下棋行为  
    def get_down(self, event):  
        if not self.stop:  
            # 先找到最近格点  
            if (20 * self.size - self.dd * 0.4 < event.x < self.dd * 0.4 + 380 * self.size) and \  
                    (20 * self.size - self.dd * 0.4 < event.y < self.dd * 0.4 + 380 * self.size):  
                dx = (event.x - 20 * self.size) % self.dd  
                dy = (event.y - 20 * self.size) % self.dd  
                x = int((event.x - 20 * self.size - dx) / self.dd + round(dx / self.dd) + 1)  
                y = int((event.y - 20 * self.size - dy) / self.dd + round(dy / self.dd) + 1)  
                # 判断位置是否已经被占据  
                if self.positions[y][x] == 0:  
                    # 未被占据,则尝试占据,获得占据后能杀死的棋子列表  
                    self.positions[y][x] = self.present + 1  
                    self.image_added = self.canvas_bottom.create_image(  
                        event.x - dx + round(dx / self.dd) * self.dd + 4 * self.p,  
                        event.y - dy + round(dy / self.dd) * self.dd - 5 * self.p,  
                        image=self.chequer_wbd_list[self.present])  
                    self.canvas_bottom.addtag_withtag('image', self.image_added)  
                    # 棋子与位置标签绑定,方便“杀死”  
                    self.canvas_bottom.addtag_withtag('position' + str(x) + str(y), self.image_added)  
                    dead_list = self.get_dead_list(x, y)  
                    self.kill(dead_list)  
                    # 判断是否重复棋局  
                    if not self.last_2_positions == self.positions:  
                        # 判断是否属于有气和杀死对方其中之一  
                        if len(dead_list) > 0 or self.if_dead([[x, y]], self.present + 1, [x, y]) == False:  
                            # 当不重复棋局,且属于有气和杀死对方其中之一时,落下棋子有效  
                            if not self.regret_chance == 1:  
                                self.regret_chance += 1  
                            else:  
                                self.regretButton['state'] = NORMAL  
                            self.last_3_positions = copy.deepcopy(self.last_2_positions)  
                            self.last_2_positions = copy.deepcopy(self.last_1_positions)  
                            self.last_1_positions = copy.deepcopy(self.positions)  
                            # 删除上次的标记,重新创建标记  
                            self.canvas_bottom.delete('image_added_sign')  
                            self.image_added_sign = self.canvas_bottom.create_oval(  
                                event.x - dx + round(dx / self.dd) * self.dd + 0.5 * self.dd,  
                                event.y - dy + round(dy / self.dd) * self.dd + 0.5 * self.dd,  
                                event.x - dx + round(dx / self.dd) * self.dd - 0.5 * self.dd,  
                                event.y - dy + round(dy / self.dd) * self.dd - 0.5 * self.dd, width=3, outline='#3ae')  
                            self.canvas_bottom.addtag_withtag('image', self.image_added_sign)  
                            self.canvas_bottom.addtag_withtag('image_added_sign', self.image_added_sign)  
                            if self.present == 0:  
                                self.create_pw()  
                                self.del_pb()  
                                self.present = 1  
                            else:  
                                self.create_pb()  
                                self.del_pw()  
                                self.present = 0  
                        else:  
                            # 不属于杀死对方或有气,则判断为无气,警告并弹出警告框  
                            self.positions[y][x] = 0  
                            self.canvas_bottom.delete('position' + str(x) + str(y))  
                            self.bell()  
                            self.show_warning_box('无气', "你被包围了!")  
                    else:  
                        # 重复棋局,警告打劫  
                        self.positions[y][x] = 0  
                        self.canvas_bottom.delete('position' + str(x) + str(y))  
                        self.recover(dead_list, (1 if self.present == 0 else 0))  
                        self.bell()  
                        self.show_warning_box("打劫", "此路不通!")  
                else:  
                    # 覆盖,声音警告  
                    self.bell()  
            else:  
                # 超出边界,声音警告  
                self.bell()  
  
    def if_dead(self, dead_list, your_chess, your_position):  
        """  
        判断棋子(种类为 your_chess,位置为 your_position)是否无气(死亡)。  
        如果棋子有气,则返回 False,表示棋子存活。  
        如果棋子无气,则返回包含所有无气棋子位置的列表。  
        参数:  
        - dead_list: 一个列表,初始时包含当前正在检查的棋子的位置。  
        - your_chess: 当前正在检查的棋子的种类。  
        - your_position: 当前正在检查的棋子的位置。  
  
        返回值:  
        - 如果棋子有气,返回 False。  
        - 如果棋子无气,返回包含所有无气棋子位置的列表。  
  
        函数逻辑:  
        1. 检查当前棋子周围是否有空位,如果有,则棋子有气,返回 False。  
        2. 如果周围没有空位,检查周围是否有同类棋子,如果有,则递归调用 if_dead 函数检查这些棋子是否有气。  
        3. 如果递归调用返回 False,表示至少有一个同类棋子有气,当前棋子也有气,返回 False。  
        4. 如果递归调用返回一个列表,表示所有检查的同类棋子都无气,将这些棋子的位置添加到 dead_list 中。  
        5. 如果所有周围的同类棋子都检查完毕且都无气,返回 dead_list,表示当前棋子无气。  
        """        # 检查上下左右四个方向是否有空位  
        for i in [-1, 1]:  
            # 检查上方和下方  
            if [your_position[0] + i, your_position[1]] not in dead_list:  
                if self.positions[your_position[1]][your_position[0] + i] == 0:  
                    return False  # 如果有空位,当前棋子有气  
            # 检查左侧和右侧  
            if [your_position[0], your_position[1] + i] not in dead_list:  
                if self.positions[your_position[1] + i][your_position[0]] == 0:  
                    return False  # 如果有空位,当前棋子有气  
  
        # 检查四个方向上是否有同类棋子,并递归检查这些棋子是否有气  
        # 上方的同类棋子  
        if ([your_position[0] + 1, your_position[1]] not in dead_list) and (  
                self.positions[your_position[1]][your_position[0] + 1] == your_chess):  
            mid = self.if_dead(dead_list + [[your_position[0] + 1, your_position[1]]], your_chess,  
                               [your_position[0] + 1, your_position[1]])  
            if not mid:  
                return False  # 如果上方同类棋子有气,则当前棋子也有气  
            else:  
                dead_list += copy.deepcopy(mid)  # 如果无气,将棋子位置添加到列表中  
        # 下方的同类棋子,逻辑同上  
        # ...  
        # 左侧的同类棋子,逻辑同上  
        # ...  
        # 右侧的同类棋子,逻辑同上  
        # ...  
  
        # 如果所有检查都完成,没有找到有气的同类棋子,则当前棋子无气,返回包含所有无气棋子位置的列表  
        return dead_list  
  
    # 警告消息框,接受标题和警告信息  
    def show_warning_box(self, title, message):  
        self.canvas_bottom.delete(self.cross)  
        tkinter.messagebox.showwarning(title, message)  
  
    # 落子后,依次判断四周是否有棋子被杀死,并返回死棋位置列表  
    def get_dead_list(self, x, y):  
        dead_list = []  
        for i in [-1, 1]:  
            if self.positions[y][x + i] == (2 if self.present == 0 else 1) and ([x + i, y] not in dead_list):  
                kill = self.if_dead([[x + i, y]], (2 if self.present == 0 else 1), [x + i, y])  
                if kill:  
                    dead_list += copy.deepcopy(kill)  
            if self.positions[y + i][x] == (2 if self.present == 0 else 1) and ([x, y + i] not in dead_list):  
                kill = self.if_dead([[x, y + i]], (2 if self.present == 0 else 1), [x, y + i])  
                if kill:  
                    dead_list += copy.deepcopy(kill)  
        return dead_list  
  
    # 恢复位置列表list_to_recover为b_or_w指定的棋子  
    def recover(self, list_to_recover, b_or_w):  
        if len(list_to_recover) > 0:  
            for i in range(len(list_to_recover)):  
                self.positions[list_to_recover[i][1]][list_to_recover[i][0]] = b_or_w + 1  
                self.image_added = self.canvas_bottom.create_image(  
                    20 * self.size + (list_to_recover[i][0] - 1) * self.dd + 4 * self.p,  
                    20 * self.size + (list_to_recover[i][1] - 1) * self.dd - 5 * self.p,  
                    image=self.chequer_wbd_list[b_or_w])  
                self.canvas_bottom.addtag_withtag('image', self.image_added)  
                self.canvas_bottom.addtag_withtag('position' + str(list_to_recover[i][0]) + str(list_to_recover[i][1]),  
                                                  self.image_added)  
  
    # 杀死位置列表killList中的棋子,即删除图片,位置值置0  
    def kill(self, kill_list):  
        if len(kill_list) > 0:  
            for i in range(len(kill_list)):  
                self.positions[kill_list[i][1]][kill_list[i][0]] = 0  
                self.canvas_bottom.delete('position' + str(kill_list[i][0]) + str(kill_list[i][1]))  
  
    # 键盘快捷键退出游戏  
    def keyboard_quit(self, event):  
        self.quit()  
  
    # 以下两个函数修改全局变量值,newApp使主函数循环,以建立不同参数的对象  
    def new_game_one(self):  
        global MODE_NUM, NEW_APP  
        MODE_NUM = (13 if self.mode_num == 9 else 9)  
        NEW_APP = True  
        self.quit()  
  
    def new_game_second(self):  
        global MODE_NUM, NEW_APP  
        MODE_NUM = (13 if self.mode_num == 19 else 19)  
        NEW_APP = True  
        self.quit()  
  
  
# 声明全局变量,用于新建Application对象时切换成不同模式的游戏  
  
if __name__ == '__main__':  
    # 循环,直到不切换游戏模式  
    while True:  
        NEW_APP = False  
        app = Application(MODE_NUM)  
        app.title('围棋')  
        app.mainloop()  
        if NEW_APP:  
            app.destroy()  
        else:  
            break

源码地址:Python 围棋

在这里插入图片描述

实现思路

这段 Python 代码实现了一个基于 tkinter 的围棋游戏 GUI。以下是实现的主要思路:

  1. 初始化界面:创建一个 Tk 窗口,设置窗口大小,并加载所需的图片资源。

  2. 棋盘和棋子:初始化一个二维数组来表示棋盘,数组中的元素表示棋盘上的位置状态(空、黑棋、白棋)。使用 Canvas 控件绘制棋盘和棋子。

  3. 棋子下法:通过鼠标点击画布来放置棋子。棋子的放置逻辑包括判断位置是否有效、是否被占据,以及放置后是否形成打劫(即重复之前的局面)。

  4. 悔棋功能:允许玩家悔棋,即撤销上一步操作。悔棋后棋盘状态回退到前一次的状态。

  5. 重新开始游戏:允许玩家重新开始游戏,重置棋盘状态和界面元素。

  6. 切换棋盘大小:支持 9 路、13 路和 19 路棋盘,玩家可以通过按钮切换棋盘大小。

  7. 玩家交替落子:通过变量 present 来记录当前轮到哪个玩家落子,0 表示黑棋,1 表示白棋。

  8. 判断死活:实现了一个递归函数 if_dead 来判断棋子是否被完全包围(即无气),如果是,则认为该棋子死亡。

  9. 界面交互:包括开始游戏、弃一手(跳过当前回合)、悔棋、重新开始、切换棋盘大小和退出游戏等按钮。

  10. 图形用户界面元素:使用 tkinter 的 ButtonCanvas 等组件来构建用户界面。

  11. 事件绑定:通过绑定鼠标事件和键盘事件来响应用户的交互操作。

  12. 辅助功能:包括显示警告框、声音提示等,以增强用户体验。

整体上,这段代码通过 tkinter 模块实现了一个基本的围棋游戏,包括棋盘的绘制、棋子的下法、悔棋功能以及基本的用户交互。代码结构清晰,功能模块化,易于理解和扩展。

源码地址:Python 围棋

Python 爱心代码:https://stormsha.blog.csdn.net/article/details/138199890
Python 植物大战僵尸:https://stormsha.blog.csdn.net/article/details/138405944
Python 开心消消乐:https://stormsha.blog.csdn.net/article/details/139220748

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

机器学习课程复习——奇异值分解

1. 三种奇异值分解 奇异值分解&#xff08;Singular Value Decomposition, SVD&#xff09;包含了&#xff1a; 完全奇异值分解&#xff08;Complete Singular Value Decomposition, CSVD&#xff09;紧奇异值分解&#xff08;Tight Singular Value Decomposition, TSVD&…

赶快收藏!全网最佳 WebSocket 封装:完美支持断网重连、自动心跳!

文章目录 一、WebSocket 基础WebSocket 的基本使用 二、封装 WebSocket 客户端WebSocketClient 类使用 WebSocketClient 类解释代码实现 三、总结优点未来改进 &#x1f389;欢迎来到SpringBoot框架学习专栏~ ☆* o(≧▽≦)o *☆嗨~我是IT陈寒&#x1f379;✨博客主页&#xff…

【复旦邱锡鹏教授《神经网络与深度学习公开课》笔记】卷积

卷积经常用在信号处理中&#xff0c;用于计算信号的延迟累积。假设一个信号发射器每个时刻 t t t产生一个信号 x t x_t xt​&#xff0c;其信息的衰减率为 w k w_k wk​&#xff0c;即在 k − 1 k-1 k−1个时间步长后&#xff0c;信息为原来的 w k w_k wk​倍&#xff0c;时刻 …

电脑图片压缩方法哪个好?这几个压缩方法必看

大家是否经常因为图片文件过大而无法轻松分享或上传而感到困扰&#xff1f;这说明你需要一款高效的图片压缩工具了。 无论是为了节省存储空间还是快速分享图片&#xff0c;拥有一款功能强大的图片压缩软件将极大地助你保存和分享图片。 今天&#xff0c;本文将介绍几款图片压…

QT自定义信号和槽函数

在QT中最重要也是必须要掌握的机制&#xff0c;就是信号与槽机制&#xff0c;在MFC上也就是类型的机制就是消息与响应函数机制 在QT中我们不仅要学会如何使用信号与槽机制&#xff0c;还要会自定义信号与槽函数&#xff0c;要自定义的原因是系统提供的信号&#xff0c;在一些情…

基于Python的求职招聘管理系统【附源码】

摘 要 随着互联网技术的不断发展&#xff0c;人类的生活已经逐渐离不开网络了&#xff0c;在未来的社会中&#xff0c;人类的生活与工作都离不开数字化、网络化、电子化与虚拟化的数字技术。从互联网的发展历史、当前的应用现状和发展趋势来看&#xff0c;我们完全可以肯定&…

前后端交互的弯弯绕绕

前后端交互&#xff1a; &#x1f197;&#xff0c;收拾一下心情让我们来聊一聊AJax吧&#xff0c;随着前端的飞速发展&#xff0c;前后的交互也发生了天翻地覆的变化&#xff1a; 前后端交互的方式有很多&#xff1a; AJAX、表单提交、WebSocket、RESTful API、... 这对新入…

九、(正点原子)Linux定时器

一、Linux中断简介 1、中断号 每个中断都有一个中断号&#xff0c;通过中断号即可区分不同的中断&#xff0c;有的资料也把中断号叫做中断线。在 Linux 内核中使用一个 int 变量表示中断号。在Linux中&#xff0c;我们可以使用已经编写好的API函数来申请中断号&#xff0c;定义…

微服务中不同服务使用openfeign 相互调用

首先 我们上文 已经知道了 nacos 的注册服务&#xff0c;现在 我们 在不同服务中相互调用就可以使用openfeign 直接调用&#xff0c;而不是 再写冗余的调用代码啦 首先 我们的微服务组件如下 因为我这个微服务是我在 员工登录demo 中 拆出来的&#xff0c;在userlogin模块中…

基于4G工业路由器的连锁品牌店铺组网监测

基于4G工业路由器的连锁品牌店铺组网监测是智慧城市建设中至关重要的任务&#xff0c;它涉及到营运管理等多方面&#xff0c;应用物联网技术可确保店铺运营的高效、安全和可靠。 连锁品牌店铺遍布城市各领域&#xff0c;甚至跨城市部署&#xff0c;分布广泛。这对集团总部的管…

HTTP/2 头部压缩 Header Compress(HPACK)详解

文章目录 1. HPACK 的工作原理1.1 静态表1.2 动态表 2. 压缩过程2.1 编码过程2.2 解码过程 3. HPACK 的优势 在HTTP1.0中&#xff0c;我们使用文本的形式传输header&#xff0c;在header中携带cookie的话&#xff0c;每次都需要重复传输几百到几千的字节&#xff0c;这着实是一…

JavaWeb——MySQL:navicate客户端工具简单使用

目录 1. 连接 2. 新建数据库 3. 使用数据库 4. 新建表 5.使用表 6. 导出数据库 我这里是英文版&#xff0c;没有进行汉化。 1. 连接 点击左上角Connection&#xff0c;选择MySQL&#xff0c;&#xff08;我连接的是自己计算机上的数据库&#xff09;连接名输入&#x…

F5《企业DNS建设白皮书》中的DNS解析服务器最佳实践

在这个数字化转型加速的时代&#xff0c;DNS&#xff08;域名系统&#xff09;的重要性不言而喻。每一次重大事件都凸显了DNS的可靠性和安全性问题。对企业而言&#xff0c;它不仅关系到业务连续性&#xff0c;更是提供永续数字服务的关键。本文根据F5公司发布的《企业DNS建设白…

Mybatis-Plus学习|快速入门CRUD、主键生成策略(雪花算法、主键自增等)、自动填充、乐观锁、分页插件、逻辑删除

MyBatisPlus概述 为什么要学习它呢?MyBatisPlus可以节省我们大量工作时间&#xff0c;所有的CRUD代码它都可以自动化完成! JPA、tk-mapper、MyBatisPlus 偷懒的! MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff…

基于JSP的列车票务信息管理系统

开头语&#xff1a; 你好&#xff0c;我是专注于计算机科学与技术研究的学长。如果你对列车票务信息管理系统感兴趣或有相关需求&#xff0c;欢迎联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;IDE、数据库管理工具…

spring boot jar 启动报错 Zip64 archives are not supported

spring boot jar 启动报错 Zip64 archives are not supported 原因、解决方案问题为什么 spring boot 不支持 zip64zip、zip64 功能上的区别zip 的文件格式spring-boot-loader 是如何判断是否是 zip64 的&#xff1f; 参考 spring boot 版本是 2.1.8.RELEASE&#xff0c;引入以…

HBDNY-40/1端子排电压继电器 DC110V 导轨安装 约瑟JOSEF

HBDNY系列端子排型电压电流继电器 系列型号&#xff1a;&#xff08;3、4过/低电压型&#xff0c;5、6过/低电流型&#xff09; HBDNY-30/1端子排型电压继电器&#xff1b;HBDNY-30/2端子排型电压继电器&#xff1b; HBDNY-30/3端子排型电压继电器&#xff1b;HBDNY-30/4端子…

摩柏BI,轻松实现word报告自动更新

|| 导语 告别手工&#xff01;在数字化办公的今天&#xff0c;高效、准确的数据处理能力已经成为职场人士必备的技能之一。尤其是对于财务分析师、市场研究员和管理人员&#xff0c;他们需要处理的报告不仅数量庞大&#xff0c;而且对数据的准确性和实时性要求极高。传统WORD报…

python爬虫需要什么HTTP代理?

用来爬虫的话&#xff0c;还是建议用高匿名代理&#xff0c;但显然题主用了高匿名代理还是出现了一部分问题&#xff0c;我们可以先找到问题关键再解决它&#xff0c;一般爬虫用了高匿名代理出现被封会有以下几种原因&#xff1a; 1.代理IP的质量不过关 一般来说每个网站都有…

解锁小红书新玩法:中小企业出海营销的集成策略

随着全球数字化浪潮的推进&#xff0c;小红书作为生活方式分享平台的崛起&#xff0c;为中小企业提供了一个全新的营销舞台。NetFarmer&#xff0c;作为专注于企业数字化出海的服务商&#xff0c;深谙小红书的营销策略&#xff0c;并致力于通过HubSpot产品销售与实施&#xff0…