当前位置: 首页 > news >正文

井字棋--课后程序(Python程序开发案例教程-黑马程序员编著-第7章-课后作业)

实例2:井字棋

井字棋是一种在3 * 3格子上进行的连珠游戏,又称井字游戏。井字棋的游戏有两名玩家,其中一个玩家画圈,另一个玩家画叉,轮流在3 * 3格子上画上自己的符号,最先在横向、纵向、或斜线方向连成一条线的人为胜利方。如图1所示为画圈的一方为胜利者。

 

图1 井字棋

本实例要求编写程序,实现具有人机交互功能的井字棋。

实例目标

  1. 理解面向对象的思想
  2. 能独立设计类
  3. 掌握类的继承和父类方法的重写

实例分析

根据实例描述的井字棋游戏的规则,下面模拟一次游戏的流程如图2所示。

 

图2 井字棋游戏流程

图2中的描述的游戏流程如下:

  1. 重置棋盘数据,清理之前一轮的对局数据,为本轮对局做好准备。
  2. 显示棋盘上每个格子的编号,让玩家熟悉落子位置。
  3. 根据系统随机产生的结果确定先手玩家(先手使用X)。
  4. 当前落子一方落子。
  5. 显示落子后的棋盘。
  6. 判断落子一方是否胜利?若落子一方取得胜利,修改玩家得分,本轮对局结束,跳转至第(9)步。
  7. 判断是否和棋?若出现和棋,本轮对局结束,跳转至第(9)步。
  8. 交换落子方,跳转至第(4)步,继续本轮游戏。
  9. 显示玩家当前对局比分。

以上流程中,落子是游戏中的核心功能,如何落子则是体现电脑智能的关键步骤,实现智能落子有策略可循的。按照井字棋的游戏规则:当玩家每次落子后,玩家的棋子在棋盘的水平、垂直或者对角线任一方向连成一条直线,则表示玩家获胜。因此,我们可以将电脑的落子位置按照优先级分成以下三种:

(1)必胜落子位置

我方在该位置落子会获胜。一旦出现这种情况,显然应该毫不犹豫在这个位置落子。

(2)必救落子位置

对方在该位置落子会获胜。如果我方暂时没有必胜落子位置,那么应该在必救落子位置落子,以阻止对方获胜。

(3)评估子力价值

评估子力价值,就是如果在该位置落子获胜的几率越高,子力价值就越大;获胜的几率越低,子力价值就越小。

如果当前的棋盘上,既没有必胜落子位置,也没有必救落子位置,那么就应该针对棋盘上的每一个空白位置寻找子力价值最高的位置落子。

要编写一个评估子力价值的程序,需要考虑诸多因素,这里我们选择了一种简单评估子力价值的方式——只考虑某个位置在空棋盘上的价值,而不考虑已有棋子以及落子之后的盘面变化。下面来看一下在空棋盘上不同位置落子的示意图,如图3所示。

 

图3 棋盘落子示意图

观察图3不难发现,玩家在空棋盘上落子的位置可分为以下3种情况:

  1. 中心点,这个位置共有4个方向可能和其它棋子连接成直线,获胜的几率最高。
  2. 4个角位,这4个位置各自有3个方向可能和其它棋子连接成直线,获胜几率中等。
  3. 4个边位,这4个位置各自有2个方向可能和其它棋子连接成直线,获胜几率最低。

综上所述,如果电脑在落子时,既没有必胜落子位置,也没有必救落子位置时,我们就可以让电脑按照胜率的高低来选择落子位置,也就是说,若棋盘的中心点没有棋子,则选择中心点作为落子位置;若中心点已有棋子,而角位没有棋子,则随机选择一个没有棋子的角位作为落子位置;若中心点和四个角位都有棋子,而边位没有棋子,则随机选择一个没有棋子的边位作为落子位置。

井字棋游戏一共需要设计4个类,不同的类创建的对象承担不同的职责,分别是:

(1)游戏类(Game):负责整个游戏流程的控制,是该游戏的入口。

(2)棋盘类(Board):负责显示棋盘、记录本轮对局数据、以及判断胜利等和对弈相关的处理工作。

(3)玩家类(Player):负责记录玩家姓名、棋子类型和得分、以及实现玩家在棋盘上落子。

(4)电脑玩家类(AIPlayer):是玩家类的子类。在电脑玩家类类中重写玩家类的落子方法,在重写的方法中实现电脑智能选择落子位置的功能。

设计后的类图如图4所示。

 

图4 类结构图

本实例中涉及到多个类,为保证程序具有清晰的结构,可以将每个类的相关代码分别放置到与其同名的py文件中。另外,由于Player和AIPlayer类具有继承关系,可以将这两个类的代码放置到player.py文件中。

代码实现

本实例的实现过程如下所示。

  1. 创建项目

使用PyCharm创建一个名为“井字棋V1.0”的文件夹,在该文件夹下分别创建3个py文件,分别为board.py、game.py与player.py,此时程序的目录结构如图5所示。

 

图5 井字棋文件目录

由于棋盘类是井字棋游戏的重点,因此我们先开发Board类。

  1. 设计Board

(1)属性

井字棋的棋盘上共有9个格子落子,落子也是有位置可循的,因此这里使用列表作为棋盘的数据结构,列表中的元素则是棋盘上的棋子,它有以下三种取值:

  1. " " 表示没有落子,是初始值;
  2. "X" 表示玩家在该位置下了一个X的棋子;
  3. "O" 表示玩家在该位置下了一个O的棋子。

其中列表中的元素为" "的位置才允许玩家落子。为了让玩家明确可落子的位置,需要增加可落子列表。根据图4中设计的类图,在board.py文件中定义Board类,并在该类的构造方法中添加属性board_data和movable_list,具体代码如下。

class Board(object):

    """棋盘类"""

    def __init__(self):

        self.board_data = [" "] * 9          # 棋盘数据

        self.movable_list = list(range(9))  # 可移动列表

(2)show_board()方法

show_board()方法实现创建一个九宫格棋盘的功能。游戏过程中显示的棋盘分为两种情况,一种是新一轮游戏开始前显示的有索引的棋盘,让玩家明确棋盘格子与序号的对应关系;另一种是游戏中显示当前落子情况的棋盘,会在玩家每次落子后展示。在Board类中添加show_board()方法,并在该方法中传递一个参数show_index,用于设置是否在棋盘中显示索引(默认为False,表示不显示索引),具体代码如下。

def show_board(self, show_index=False):

    """显示棋盘

    :param show_index: True 表示显示索引 / False 表示显示数据

    """

    for i in (0, 3, 6):

        print("       |       |")

        if show_index:

            print("   %d   |   %d   |   %d" % (i, i + 1, i + 2))

        else:

            print("   %s   |   %s   |   %s" % (self.board_data[i],

                                             self.board_data[i + 1],

                                             self.board_data[i + 2]))

        print("       |       |")

        if i != 6:

            print("-" * 23)

(3)move_down ()方法

move_down ()方法实现在指定的位置落子的功能,该方法接收两个参数,分别是表示落子位置的index和表示落子类型(X或者O)的chess,接收的这些参数都是落子前需要考虑的必要要素,具体代码如下。

def move_down(self, index, chess):

    """在指定位置落子

    :param index: 列表索引

    :param chess: 棋子类型 X O

    """

    # 1. 判断 index 是否在可移动列表中

    if index not in self.movable_list:

        print("%d 位置不允许落子" % index)

        return

    # 2. 修改棋盘数据

    self.board_data[index] = chess

    # 3. 修改可移动列表

    self.movable_list.remove(index)

以上代码首先判断落子位置是否可以落子,如果可以就将棋子添加到board_data列表的对应位置,并从movable_list列表中删除。

(4)is_draw ()方法

is_draw ()方法实现判断游戏是否平局的功能,该方法会查看可落子索引列表中是否有值,若没有值表示棋盘中的棋子已经落满了,说明游戏平局,具体代码如下。

def is_draw(self):

    """是否平局"""

    return not self.movable_list

(5)is_win ()方法

is_draw ()方法实现判断游戏是否胜利的功能,该方法会先定义方向列表,再遍历方向列表判断游戏是否胜利,胜利则返回True,否则返回False,具体代码如下。

def is_win(self, chess, ai_index=-1):

    """是否胜利

    :param chess: 玩家的棋子

    :param ai_index: 预判索引,-1 直接判断当前棋盘数据

    """

    # 1. 定义检查方向列表

    check_dirs = [[0, 1, 2], [3, 4, 5], [6, 7, 8],

                     [0, 3, 6], [1, 4, 7], [2, 5, 8],

                     [0, 4, 8], [2, 4, 6]]

    # 2. 定义局部变量记录棋盘数据副本

    data = self.board_data.copy()

    # 判断是否预判胜利

    if ai_index > 0:

        data[ai_index] = chess

    # 3. 遍历检查方向列表判断是否胜利

    for item in check_dirs:

        if (data[item[0]] == chess and

            data[item[1]] == chess

                and data[item[2]] == chess):

            return True

    return False

注意,is_win()方法的ai_index参数的默认值为-1,表示无需进行预判,即提示玩家最有利的落子位置;若该参数不为-1时,表示需要进行预判。

(6)reset_board ()方法

reset_board ()方法实现清空棋盘的功能,该方法中会先清空movable_list,再将棋盘上的数据全部置为初始值,最后往movable_list中添加0~8的数字,具体代码如下。

def reset_board(self):

    """重置棋盘"""

    # 1. 清空可移动列表数据

    self.movable_list.clear()

    # 2. 重置数据

    for i in range(9):

        self.board_data[i] = " "

        self.movable_list.append(i)

  1. 设计Player

根据图4中设计的类图,在player.py文件中定义Player类,分别在该类中添加属性和方法,具体内容如下。

(1)属性

在Player类中添加name、score、chess属性,具体代码如下。

import board

import random

class Player(object):

    """玩家类"""

    def __init__(self, name):

        self.name = name     # 姓名

        self.score = 0       # 成绩

        self.chess = None   # 棋子

(2)move()方法

move()方法实现玩家在指定位置落子的功能,该方法中会先提示用户棋盘上可落子的位置,之后使棋盘根据用户选择的位置重置棋盘数据后进行显示,具体代码如下。

def move(self, chess_board):

    """在棋盘上落子

    :param chess_board:

    """

    # 1. 由用户输入要落子索引

    index = -1

    while index not in chess_board.movable_list:

        try:

            index = int(input(" %s 输入落子位置 %s" %

                (self.name, chess_board.movable_list)))

        except ValueError:

            pass

    # 2. 在指定位置落子

    chess_board.move_down(index, self.chess)

  1. 设计AIPlayer

根据图4中设计的类图,在player.py文件中定义继承自Player类的子类AIPlayer。AIPlayer类中重写了父类的move()方法,在该方法中需要增加分析中的策略,使得计算机玩家变得更加聪明,具体代码如下。

class AIPlayer(Player):

    """智能玩家"""

    def move(self, chess_board):

        """在棋盘上落子

        :param chess_board:

        """

        print("%s 正在思考落子位置..." % self.name)

        # 1. 查找我方必胜落子位置

        for index in chess_board.movable_list:

            if chess_board.is_win(self.chess, index):

                print("走在 %d 位置必胜!!!" % index)

                chess_board.move_down(index, self.chess)

                return

        # 2. 查找地方必胜落子位置-我方必救位置

        other_chess = "O" if self.chess == "X" else "X"

        for index in chess_board.movable_list:

            if chess_board.is_win(other_chess, index):

                print("敌人走在 %d 位置必输,火速堵上!" % index)

                chess_board.move_down(index, self.chess)

                return

        # 3. 根据子力价值选择落子位置

        index = -1

        # 没有落子的角位置列表

        corners = list(set([0, 2, 6, 8]).intersection(

chess_board.movable_list))

        # 没有落子的边位置列表

        edges = list(set([1, 3, 5, 7]).intersection(

chess_board.movable_list))

        if 4 in chess_board.movable_list:

            index = 4

        elif corners:

            index = random.choice(corners)

        elif edges:

            index = random.choice(edges)

        # 在指定位置落子

        chess_board.move_down(index, self.chess)

  1. 设计Game

根据图4中设计的类图,在game.py文件中定义Game类,分别在该类中添加属性和方法,具体内容如下。

(1)属性

在Game类中添加chess_board、human、computer属性,具体代码如下。

import random

import board

import player

class Game(object):

    """游戏类"""

    def __init__(self):

        self.chess_board = board.Board()          # 棋盘对象

        self.human = player.Player("玩家")        # 人类玩家对象

        self.computer = player.AIPlayer("电脑")  # 电脑玩家对象

(2)random_player()方法

random_player()方法实现随机生成先手玩家的功能,该方法中会先随机生成0和1两个数,选到数字1的玩家为先手玩家,然后再为两个玩家设置棋子类型,即先手玩家为“X”,对手玩家为“O”,具体代码如下。

def random_player(self):

    """随机先手玩家

    :return: 落子先后顺序的玩家元组

    """

    # 随机到 1 表示玩家先手

    if random.randint(0, 1) == 1:

        players = (self.human, self.computer)

    else:

        players = (self.computer, self.human)

    # 设置玩家棋子

    players[0].chess = "X"

    players[1].chess = "O"

    print("根据随机抽取结果 %s 先行" % players[0].name)

    return players

(3)play_round ()方法

play_round ()方法实现一轮完整对局的功能,该方法的逻辑可按照实例分析的一次流程完成,具体代码如下。

def play_round(self):

    """一轮完整对局"""

    # 1. 显示棋盘落子位置

    self.chess_board.show_board(True)

    # 2. 随机决定先手

    current_player, next_player = self.random_player()

    # 3. 两个玩家轮流落子

    while True:

        # 下子方落子

        current_player.move(self.chess_board)

        # 显示落子结果

        self.chess_board.show_board()

        # 是否胜利?

        if self.chess_board.is_win(current_player.chess):

            print("%s 战胜 %s" % (current_player.name, next_player.name))

            current_player.score += 1

            break

        # 是否平局

        if self.chess_board.is_draw():

            print("%s %s 战成平局" % (current_player.name,

next_player.name))

            break

        # 交换落子方

        current_player, next_player = next_player, current_player

    # 4. 显示比分

    print("[%s] 对战 [%s] 比分是 %d : %d" % (self.human.name,

                                        self.computer.name,

                                        self.human.score,

                                        self.computer.score))

从上述代码可以看出,大部分的功能都是通过游戏中各个对象访问属性或调用方法实现的,这正好体现了类的封装性的特点,即每个类分工完成各自的任务。

(4)start ()方法

start ()方法实现循环对局的功能,该方法中会在每轮对局结束之后询问玩家是否再来一局,若玩家选择是,则重置棋盘数据后开始新一轮对局;若玩家选择否,则会退出游戏,具体代码如下。

def start(self):

    """循环开始对局"""

    while True:

        # 一轮完整对局

        self.play_round()

        # 询问是否继续

        is_continue = input("是否再来一盘(Y/N)?").upper()

        # 判断玩家输入

        if is_continue != "Y":

            break

        # 重置棋盘数据

        self.chess_board.reset_board()

最后在game.py文件中通过Game类对象调用start()方法启动井字棋游戏,具体代码如下。

if __name__ == '__main__':

    Game().start()

代码测试

运行程序,对战一局游戏的结果如下所示:

       |       |

   0   |   1   |   2

       |       |

-----------------------

       |       |

   3   |   4   |   5

       |       |

-----------------------

       |       |

   6   |   7   |   8

       |       |

根据随机抽取结果 电脑 先行

电脑 正在思考落子位置...

       |       |

       |       |   

       |       |

-----------------------

       |       |

       |   X   |   

       |       |

-----------------------

       |       |

       |       |   

       |       |

玩家输入落子位置 [0, 1, 2, 3, 5, 6, 7, 8]0

       |       |

   O   |       |   

       |       |

-----------------------

       |       |

       |   X   |   

       |       |

-----------------------

       |       |

       |       |   

       |       |

电脑 正在思考落子位置...

       |       |

   O   |       |   

       |       |

-----------------------

       |       |

       |   X   |   

       |       |

-----------------------

       |       |

   X   |       |   

       |       |

玩家输入落子位置 [1, 2, 3, 5, 7, 8]2

       |       |

   O   |       |   O

       |       |

-----------------------

       |       |

       |   X   |   

       |       |

-----------------------

       |       |

   X   |       |   

       |       |

电脑 正在思考落子位置...

敌人走在 1 位置必输,火速堵上!

       |       |

   O   |   X   |   O

       |       |

-----------------------

       |       |

       |   X   |   

       |       |

-----------------------

       |       |

   X   |       |   

       |       |

玩家输入落子位置 [3, 5, 7, 8]7

       |       |

   O   |   X   |   O

       |       |

-----------------------

       |       |

       |   X   |   

       |       |

-----------------------

       |       |

   X   |   O   |   

       |       |

电脑 正在思考落子位置...

       |       |

   O   |   X   |   O

       |       |

-----------------------

       |       |

       |   X   |   

       |       |

-----------------------

       |       |

   X   |   O   |   X

       |       |

玩家输入落子位置 [3, 5]5

       |       |

   O   |   X   |   O

       |       |

-----------------------

       |       |

       |   X   |   O

       |       |

-----------------------

       |       |

   X   |   O   |   X

       |       |

电脑 正在思考落子位置...

       |       |

   O   |   X   |   O

       |       |

-----------------------

       |       |

   X   |   X   |   O

       |       |

-----------------------

       |       |

   X   |   O   |   X

       |       |

电脑 玩家 战成平局

[玩家] 对战 [电脑] 比分是 0 : 0

是否再来一盘(Y/N)?n

相关文章:

井字棋--课后程序(Python程序开发案例教程-黑马程序员编著-第7章-课后作业)

实例2:井字棋 井字棋是一种在3 * 3格子上进行的连珠游戏,又称井字游戏。井字棋的游戏有两名玩家,其中一个玩家画圈,另一个玩家画叉,轮流在3 * 3格子上画上自己的符号,最先在横向、纵向、或斜线方向连成一条…...

谷粒学院开发(三):统一日志、异常及前端准备工作

特定异常处理 ControllerAdvice public class GlobalExceptionHandler {ExceptionHandler(Exception.class) // 指定出现什么异常会被处理ResponseBody // 为了能够返回数据public R error(Exception e) {e.printStackTrace();return R.error().message("执行了全局异常…...

华为OD机试题 - 招聘(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:招聘题目输入输出示例一输入输出说明示例二输入输出说明示例三输…...

关于SQL优化的几点说明

1. ORACLE DBA是如何进行SQL优化的 作为一个Oracle数据库管理员(DBA),SQL优化是他们的日常工作之一,主要目标是优化查询性能,减少查询时间,并提高数据库的整体性能。 以下是Oracle DBA如何进行SQL优化的一般流程: 监控…...

使用高精度秒表StopWatch测试DateTime.Now的精度

StopWatch使用的命名空间:using System.Diagnostics;StopWatch的使用方法:创建Stopwatch对象:stopwatch;stopwatch计时表开启:stopwatch.Start();stopwatch计时表关闭:stopwatch.Stop();计算stopwatch.Stop…...

【C++】vector的使用及其模拟实现

这里写目录标题一、vector的介绍及使用1. vector的介绍2. 构造函数3. 遍历方式4. 容量操作及空间增长问题5. 增删查改6. vector二维数组二、vector的模拟实现1. 构造函数2. 迭代器和基本接口3. reserve和resize4. push_back和pop_back5. insert和erase5. 迭代器失效问题5. 浅拷…...

[洛谷-P2585][ZJOI2006]三色二叉树(树形DP+状态机DP)

[洛谷-P2585][ZJOI2006]三色二叉树(树形DP状态机DP)一、题目题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1提示数据规模与约定二、分析1、递归建树2、树形DP 状态机DP(1)状态表示(2)状态转移三、…...

BI技巧丨计算组

PowerBI有三大工具,分别是DAX Studio,Tabular Editor和Bravo。 DAX Studio通常我们会用来进行性能分析和DAX调优使用,Bravo一般用来批量格式化DAX,而Tabular Editor主要的功能就是计算组。 计算组这个名词,相信很多小伙…...

PMP项目管理项目范围管理

目录1 项目范围管理概述2 规划范围管理3 收集需求4 定义范围5 创建 WBS6 确认范围7 控制范围1 项目范围管理概述 项目范围管理包括确保项目做且只做所需的全部工作,以成功完成项目的各 个过程。管理项目范围主要在于定义和控制哪些工作应在项目内,哪些工…...

Flink 定时加载数据源

一、简介 flink 自定义实时数据源使用流处理比较简单,比如 Kafka、MQ 等,如果使用 MySQL、redis 批处理也比较简单 如果需要定时加载数据作为 flink 数据源使用流处理,比如定时从 mysql 或者 redis 获取一批数据,传入 flink 做处…...

ChatGPT、人工智能、人类和一些酒桌闲聊

© 2023 Conmajia Initiated 10th March, 2023 昨天跟某化学家喝酒,期间提到了 ChatGPT。他的评价是:这鬼东西大量输出毫无意义、错漏百出甚至是虚假的信息,“in a confident accent”。例如某次 GPT 针对“描述某某记者”这一问题&#…...

WebRTC开源库内部调用abort函数引发程序发生闪退问题的排查

目录 1、初始问题描述 2、使用Process Explorer工具查看到处理音视频业务的rtcmpdll.dll模块没有加载起来 3、使用Dependency Walker工具查看到rtcmpdll.dll依赖的库有问题 4、更新库之后Debug程序启动时就发生异常,程序闪退 5、VS调试时看不到有效的函数调用堆…...

Golang并发编程

Golang并发编程 文章目录Golang并发编程1. 协程2. channel2.1 channel的创建2.2 使用waitGroup实现同步3. 并发编程3.1 并发编程之runtime包3.2 mutex互斥锁3.3 channel遍历3.3.1 for if遍历3.3.2 for range3.4 select switch3.5 Timer3.5.1 time.NewTimer()3.5.2 Stop、reset…...

windows+Anaconda环境下安装BERT成功安装方法及问题汇总

前言 在WindowsAnaconda环境下安装BERT,遇到各种问题,几经磨难,最终成功。接下来,先介绍成功的安装方法,再附上遇到的问题汇总 成功的安装方法 1、创建虚拟环境 注意:必须加上python3.7.12以创建环境&a…...

git - 简易指南

git - 简易指南 创建新仓库 创建新文件夹,打开,然后执行 git init 以创建新的 git 仓库。 检出仓库 执行如下命令以创建一个本地仓库的克隆版本: git clone /path/to/repository 如果是远端服务器上的仓库,你的命令会是这个样…...

[论文笔记]Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context

引言 我们知道Transformer很好用,但它设定的最长长度是512。像一篇文章超过512个token是很容易的,那么我们在处理这种长文本的情况下也想利用Transformer的强大表达能力需要怎么做呢? 本文就带来一种处理长文本的Transformer变种——Transf…...

华为OD机试题 - 找目标字符串(JavaScript)| 机考必刷

更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:找目标字符串题目输入输出示例一输入输出说明Code解题思路版权说…...

C++面向对象编程之六:重载操作符(<<,>>,+,+=,==,!=,=)

重载操作符C允许我们重新定义操作符(例如:,-,*,/)等,使其对于我们自定义的类类型对象,也能像内置数据类型(例如:int,float,double&…...

JS_wangEditor富文本编辑器

官网&#xff1a;https://www.wangeditor.com/ 引入 CSS 定义样式 <link href"https://unpkg.com/wangeditor/editorlatest/dist/css/style.css" rel"stylesheet"> <style>#editor—wrapper {border: 1px solid #ccc;z-index: 100; /* 按需定…...

Django实践-06导出excel/pdf/echarts

文章目录Django实践-06导出excel/pdf/echartsDjango实践-06导出excel/pdf/echarts导出excel安装依赖库修改views.py添加excel导出函数修改urls.py添加excel/运行测试导出pdf安装依赖库修改views.py添加pdf导出函数修改urls.py添加pdf/生成前端统计图表修改views.py添加get_teac…...

java并发入门(一)共享模型—Synchronized、Wait/Notify、pack/unpack

一、共享模型—管程 1、共享存在的问题 1.1 共享变量案例 package com.yyds.juc.monitor;import lombok.extern.slf4j.Slf4j;Slf4j(topic "c.MTest1") public class MTest1 {static int counter 0;public static void main(String[] args) throws InterruptedEx…...

Ast2500增加用户自定义功能

备注&#xff1a;这里使用的AMI的开发环境MegaRAC进行AST2500软件开发&#xff0c;并非openlinux版本。1、添加上电后自动执行的任务在PDKAccess.c中列出了系统启动过程中的所有任务&#xff0c;若需要添加功能&#xff0c;在相应的任务中添加自定义线程。一般在两个任务里面添…...

用Python暴力求解德·梅齐里亚克的砝码问题

文章目录固定个数的砝码可称量重量砝码的组合方法40镑砝码的组合问 一个商人有一个40磅的砝码&#xff0c;由于跌落在地而碎成4块。后来&#xff0c;称得每块碎片的重量都是整磅数&#xff0c;而且可以用这4 块来称从1 至40 磅之间的任意整数磅的重物。问这4 块砝码片各重多少&…...

离散Hopfield神经网络的分类——高校科研能力评价

离散Hopfield网络离散Hopfield网络是一种经典的神经网络模型&#xff0c;它的基本原理是利用离散化的神经元和离散化的权值矩阵来实现模式识别和模式恢复的功能。它最初由美国物理学家John Hopfield在1982年提出&#xff0c;是一种单层的全连接神经网络&#xff0c;被广泛应用于…...

Retrofit核心源码分析(三)- Call逻辑分析和扩展机制

在前面的两篇文章中&#xff0c;我们已经对 Retrofit 的注解解析、动态代理、网络请求和响应处理机制有了一定的了解。在这篇文章中&#xff0c;我们将深入分析 Retrofit 的 Call 逻辑&#xff0c;并介绍 Retrofit 的扩展机制。 一、Call 逻辑分析 Call 是 Retrofit 中最基本…...

源码分析spring如和对@Component注解进行BeanDefinition注册的

Spring ioc主要职责为依赖进行处理&#xff08;依赖注入、依赖查找&#xff09;、容器以及托管的(java bean、资源配置、事件)资源声明周期管理&#xff1b;在ioc容器启动对元信息进行读取&#xff08;比如xml bean注解等&#xff09;、事件管理、国际化等处理&#xff1b;首先…...

C语言--字符串函数1

目录前言strlenstrlen的模拟实现strcpystrcatstrcat的模拟实现strcmpstrcmp的模拟实现strncpystrncatstrncmpstrstrstrchr和strrchrstrstr的模拟实现前言 本章我们将重点介绍处理字符和字符串的库函数的使用和注意事项。 strlen 我们先来看一个我们最熟悉的求字符串长度的库…...

Webstorm使用、nginx启动、FinalShell使用

文章目录 主题设置FinalShellFinalShell nginx 启动历史命令Nginx页面发布配置Webstorm的一些常用快捷键代码生成字体大小修改Webstorm - gitCode 代码拉取webstorm 汉化webstorm导致CPU占用率高方法一 【忽略node_modules】方法二 【设置 - 代码编辑 - 快速预览文档 - 关闭】主…...

源码分析Spring @Configuration注解如何巧夺天空,偷梁换柱。

前言 回想起五年前的一次面试&#xff0c;面试官问Configuration注解和Component注解有什么区别&#xff1f;记得当时的回答是&#xff1a; 相同点&#xff1a;Configuration注解继承于Component注解&#xff0c;都可以用来通过ClassPathBeanDefinitionScanner装载Spring bean…...

vector的使用及模拟实现

目录 一.vector的介绍及使用 1.vector的介绍 2.vector的使用 1.vector的定义 2.vector iterator的使用 3. vector 空间增长问题 4.vector 增删查改 3.vector 迭代器失效问题&#xff08;重点&#xff09; 1. 会引起其底层空间改变的操作 2.指定位置元素的删除操作--erase 3. Li…...

公司怎么建设网站/关注公众号一单一结兼职

目录 1、程序计数器 2、Java虚拟机栈 3、本地方法栈 4、Java堆 5、方法区 6、运行时常量 7、直接内存 8、对象的创建 对于Java程序员来说&#xff0c;在虚拟机自动内存管理机制的帮助下&#xff0c;不在需要为每一个new操作去写配对的delete/free代码&#xff0c;不容易…...

网站制作潍坊/北京百度seo关键词优化

刚開始学习Android&#xff0c;因为之前比較熟悉OpenCV&#xff0c;于是就想先在Android上执行OpenCV试试 1.环境配置 JDKEclipseADTCDTAndroid SDKAndroid NDKcygwinOpenCV for Android 2.4.9这部分网上非常多。我就不再赘述了&#xff0c;能够參考&#xff1a;http://blog.c…...

app制作公司哪个好/朝阳seo

服务器linux环境运行php&#xff0c;如何配置&#xff1f;单机下Linux下部署PHP环境说白了就是在Linux系统上安装apche或者nginx和mysql数据库以及php运行环境这些都可以在网上单独下载安装包去安装但是需要自己去一个一个下载安装设置调试等傻瓜式的有lnmp和lamp一键安装包大多…...

c语言哪个网站可以做测试题/seo推广怎么做

获取修改元素属性 javaScript可以修改DOM节点属性。 操作属性的方法有: 方法说明getAttribute() 获取属性值 hasAttribute()检查元素节点是否包含特定属性setAttribute()设置属性值removeAttribute从元素节点移除属性修改属性 <!DOCTYPE html><html> <head> …...

网站站点创建成功了该怎么做/网络营销课程速成班

Dispatcher 在Envoy的代码中Dispatcher是随处可见的&#xff0c;可以说在Envoy中有着举足轻重的地位&#xff0c;一个Dispatcher就是一个EventLoop&#xff0c;其承担了任务队列、网络事件处理、定时器、信号处理等核心功能。在Envoy threading model这篇文章所提到的EventLoop…...

五金 东莞网站建设/自媒体平台app

转 《“笨办法”学Python(第3版)》简介及PDF电子格式 内容简介&#xff1a; 《“笨办法”学Python&#xff08;第3版&#xff09;》是一本Python入门书籍&#xff0c;适合对计算机了解不多&#xff0c;没有学过编程&#xff0c;但对编程感兴趣的读者学习使用。《“笨办法”学…...