Python 贪吃蛇

文章目录

  • 效果图:
  • 项目目录结构
    • main.py
    • game/apple.py
    • game/base.py
    • game/snake.py
    • constant.py

效果图:

请添加图片描述

项目目录结构

在这里插入图片描述

main.py

from snake.game.apple import Apple  # 导入苹果类
from snake.game.base import *  # 导入游戏基类
from snake.game.snake import Snake  # 导入蛇类


class SnakeGame(GameBase):
    """贪吃蛇游戏"""

    def __init__(self):
        """初始化游戏"""
        super(SnakeGame, self).__init__(
            game_name=GAME_NAME, icon=ICON,  # 调用基类的初始化方法
            screen_size=SCREEN_SIZE,
            display_mode=DISPLAY_MODE,
            loop_speed=LOOP_SPEED,
            font_size=FONT_SIZE,
            background=WHITE,
            font_name=None
        )
        # 绘制背景
        self.prepare_background()
        # 创建游戏对象
        self.apple_count = 0  # 苹果计数器
        self.high_score = 0  # 记录最高分
        self.snake = Snake(self)  # 创建蛇对象
        self.apple = Apple(self)  # 创建苹果对象
        # 绑定按键事件
        self.add_key_binding(KEY_UP, self.snake.turn, direction=UP)  # 绑定上方向键
        self.add_key_binding(KEY_DOWN, self.snake.turn, direction=DOWN)  # 绑定下方向键
        self.add_key_binding(KEY_LEFT, self.snake.turn, direction=LEFT)  # 绑定左方向键
        self.add_key_binding(KEY_RIGHT, self.snake.turn, direction=RIGHT)  # 绑定右方向键
        self.add_key_binding(KEY_RESTART, self.restart)  # 绑定R键(重启游戏)
        self.add_key_binding(KEY_PAUSE, self.pause)  # 绑定R键(重启游戏)
        self.add_key_binding(KEY_EXIT, self.quit)  # 绑定退出键
        # 添加绘图函数
        self.add_draw_action(self.draw_score)  # 添加绘制分数的函数

    def prepare_background(self):
        """准备背景"""
        self.background.fill(BACKGROUND_COLOR)  # 用背景颜色填充背景
        for _ in range(CELL_SIZE, SCREEN_WIDTH, CELL_SIZE):  # 绘制垂直网格线
            self.draw.line(self.background, GRID_COLOR, (_, 0), (_, SCREEN_HEIGHT))
        for _ in range(CELL_SIZE, SCREEN_HEIGHT, CELL_SIZE):  # 绘制水平网格线
            self.draw.line(self.background, GRID_COLOR, (0, _), (SCREEN_WIDTH, _))

    def restart(self):
        """重启游戏"""
        if not self.snake.is_alive:  # 如果蛇已经死亡
            self.apple_count = 0  # 重置苹果计数器
            self.apple.drop()  # 重新放置苹果
            self.snake.restart_pawn()  # 重生蛇
            self.running = True  # 继续游戏循环

    def draw_score(self):
        """绘制分数"""
        text = f"Apple: {self.apple_count}"  # 准备要绘制的文本
        self.high_score = max(self.high_score, self.apple_count)  # 更新最高分
        self.draw_text(text, (0, 0), (255, 255, 33))  # 绘制文本

        if not self.snake.is_alive:  # 如果蛇已经死亡
            self.draw_text(" 游戏结束 ", (SCREEN_WIDTH / 2 - 54, SCREEN_HEIGHT / 2 - 10),  # 绘制游戏结束文本
                           (255, 33, 33), WHITE)

            self.draw_text(" 按R键重启 ", (SCREEN_WIDTH / 2 - 85, SCREEN_HEIGHT / 2 + 20),  # 绘制重启提示文本
                           GREY, DARK_GREY)

            self.draw_text(f"当前最高分: {self.high_score}", (SCREEN_WIDTH / 2 - 114, SCREEN_HEIGHT / 2 + 50),  # 绘制最高分文本
                           (255, 33, 33), WHITE)  # 展示最高分

        if not self.running and self.snake.is_alive:  # 如果游戏暂停且蛇还活着
            self.draw_text("游戏暂停 ", (SCREEN_WIDTH / 2 - 55, SCREEN_HEIGHT / 2 - 10),  # 绘制游戏暂停文本
                           LIGHT_GREY, DARK_GREY)


if __name__ == '__main__':
    SnakeGame().run()  # 运行游戏

game/apple.py

from random import randint
from snake.constant import *


class Apple:
    """
    苹果类:表示游戏中的苹果,蛇吃到苹果会增长身体长度。
    """

    def __init__(self, game):
        """
        初始化苹果对象。
        :param game: 游戏对象。
        """
        self.game = game
        self.x = self.y = 0  # 苹果的初始位置
        self.game.add_draw_action(self.draw)  # 将 draw 方法添加到游戏的绘制动作列表中
        self.drop()  # 生成一个新的苹果

    def drop(self):
        """
        生成一个新的苹果,确保苹果不在蛇的身体上。
        """
        snake = self.game.snake.body + [self.game.snake.head]  # 获取蛇的身体和头部的所有位置
        while True:
            (x, y) = randint(0, COLUMNS - 1), randint(0, ROWS - 1)  # 随机生成一个位置
            if (x, y) not in snake:  # 如果这个位置不在蛇的身体上
                self.x, self.y = x, y  # 将苹果的位置设置为这个位置
                break  # 退出循环

    def draw(self):
        """
        绘制苹果。
        """
        self.game.draw_cell(
            (self.x, self.y),  # 苹果的位置
            CELL_SIZE,  # 每个单元格的大小
            APPLE_COLOR_SKIN,  # 苹果的外框颜色
            APPLE_COLOR_BODY  # 苹果的主体颜色
        )

game/base.py

import os
import sys
import time
from snake.constant import *

# 使窗口居中
os.environ["SDL_VIDEO_CENTERED"] = "1"

# MyGame 默认值
GAME_NAME = "贪吃蛇 By stormsha"
SCREEN_SIZE = 640, 480
DISPLAY_MODE = pygame.HWSURFACE | pygame.DOUBLEBUF
LOOP_SPEED = 60
# noinspection SpellCheckingInspection
FONT_NAME = "resources/MONACO.ttf"
FONT_SIZE = 16
KEY_PAUSE = pygame.K_PAUSE


class GameBase(object):
    """pygame模板类"""

    def __init__(self, **kwargs):
        """初始化

        可选参数:
            game_name       游戏名称
            icon            图标文件名
            screen_size     画面大小
            display_mode    显示模式
            loop_speed      主循环速度
            font_name       字体文件名
            font_size       字体大小
        """
        pygame.init()
        pygame.mixer.init()
        self.game_name = kwargs.get("game_name") or GAME_NAME
        pygame.display.set_caption(self.game_name)
        self.screen_size = kwargs.get("screen_size") or SCREEN_SIZE
        self.screen_width, self.screen_height = self.screen_size
        self.display_mode = kwargs.get("display_mode") or DISPLAY_MODE
        self.images = {}
        self.sounds = {}
        self.musics = {}
        self.icon = kwargs.get("icon") or None
        self.icon and pygame.display.set_icon(pygame.image.load(self.icon))
        self.screen = pygame.display.set_mode(self.screen_size,
                                              self.display_mode)
        self.loop_speed = kwargs.get("loop_speed") or LOOP_SPEED
        self.font_size = kwargs.get("font_size") or FONT_SIZE
        self.background = None

        # noinspection SpellCheckingInspection
        ''' 支持中文的字体
        新细明体:PMingLiU
        细明体:MingLiU
        标楷体:DFKai - SB
        黑体:SimHei
        宋体:SimSun
        新宋体:NSimSun
        仿宋:FangSong
        楷体:KaiTi
        仿宋_GB2312:FangSong_GB2312
        楷体_GB2312:KaiTi_GB2312
        微软正黑体:Microsoft JhengHei
        微软雅黑体:Microsoft YaHei
        '''
        self.font_name = kwargs.get("font_name") or pygame.font.match_font('SimHei')  # 获取系统字体

        self.font = pygame.font.Font(self.font_name, self.font_size)
        self.clock = pygame.time.Clock()
        self.now = 0
        self.background_color = kwargs.get("background") or BLACK
        self.set_background()
        self.key_bindings = {}  # 按键与函数绑定字典
        self.add_key_binding(KEY_PAUSE, self.pause)

        self.game_actions = {}  # 游戏数据更新动作

        self.draw_actions = [self.draw_background]  # 画面更新动作列表

        self.running = True
        self.draw = pygame.draw

    def run(self):
        """主循环"""
        while True:
            self.now = pygame.time.get_ticks()
            self.process_events()
            if self.running:
                self.update_game_data()
            self.update_display()
            self.clock.tick(self.loop_speed)

    def pause(self):
        """暂停游戏"""
        self.running = not self.running
        if self.running:
            for action in self.game_actions.values():
                if action["next_time"]:
                    action["next_time"] = self.now + action["interval"]

    def process_events(self):
        """事件处理"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                self.quit()
            elif event.type == pygame.KEYDOWN:
                action, kwargs = self.key_bindings.get(event.key, (None, None))
                # noinspection all
                action(**kwargs) if kwargs else action() if action else None

    def update_game_data(self):
        """更新游戏数据"""
        for action in self.game_actions.values():
            if not action["next_time"]:
                action["run"]()
            elif self.now >= action["next_time"]:
                action["next_time"] += action["interval"]
                action["run"]()

    def update_display(self):
        """更新画面显示"""
        for action in self.draw_actions:
            action()
        pygame.display.flip()

    def draw_background(self):
        """绘制背景"""
        self.screen.blit(self.background, (0, 0))

    def add_key_binding(self, key, action, **kwargs):
        """增加按键绑定"""
        self.key_bindings[key] = action, kwargs

    # TODO: 更新动作若有次序要求,则用字典保存不合适
    def add_game_action(self, name, action, interval=0):
        """添加游戏数据更新动作"""
        next_time = self.now + interval if interval else None
        self.game_actions[name] = dict(
            run=action,
            interval=interval,
            next_time=next_time)

    def add_draw_action(self, action):
        """添加画面更新动作"""
        self.draw_actions.append(action)

    def draw_text(self, text, loc, color, bgcolor=None):
        if bgcolor:
            surface = self.font.render(text, True, color, bgcolor)
        else:
            surface = self.font.render(text, True, color)
        self.screen.blit(surface, loc)

    def draw_cell(self, xy, size, color1, color2=None):
        x, y = xy
        rect = pygame.Rect(x * size, y * size, size, size)
        self.screen.fill(color1, rect)
        if color2:
            self.screen.fill(color2, rect.inflate(-4, -4))

    @staticmethod
    def quit():
        """退出游戏"""
        pygame.quit()
        sys.exit(0)

    @staticmethod
    def load_music(filename):
        pygame.mixer.music.load(filename)

    @staticmethod
    def play_music():
        pygame.mixer.music.play(-1)

    @staticmethod
    def pause_music():
        pygame.mixer.music.pause()

    @staticmethod
    def resume_music():
        pygame.mixer.music.unpause()

    @staticmethod
    def stop_music():
        pygame.mixer.music.stop()

    def save_screenshots(self):
        filename = time.strftime('screenshots/%Y%m%d%H%M%S.png')
        pygame.image.save(self.screen, filename)

    def load_images(self, filename, sub_img=None):
        sub_img = sub_img or {}
        image = pygame.image.load(filename).convert_alpha()  # 文件打开失败
        for name, rect in sub_img.items():
            x, y, w, h = rect
            self.images[name] = image.subsurface(pygame.Rect((x, y), (w, h)))

    def set_background(self, background=None):
        if isinstance(background, str):
            self.background = pygame.image.load(background)
        else:
            self.background = pygame.Surface(self.screen_size)
            self.background_color = background \
                if isinstance(background, tuple) else (0, 0, 0)
            self.background.fill(self.background_color)

    def load_sounds(self, **sounds):
        """
        @summary: 加载音乐
        :param sounds:
        :return:
        """
        for name, filename in sounds.items():
            self.sounds[name] = pygame.mixer.Sound(filename)

    def play_sound(self, name):
        self.sounds[name].play()


if __name__ == '__main__':
    GameBase().run()

game/snake.py

import pygame

from snake import constant


class Snake:
    """贪吃蛇"""

    def __init__(self, game):
        self.game = game
        self.sound_hit = pygame.mixer.Sound("resources/hit.wav")
        self.sound_eat = pygame.mixer.Sound("resources/eat.wav")
        self.game.add_draw_action(self.draw)

        # 初始化数据
        self.head = (constant.SNAKE_X, constant.SNAKE_Y)  # 蛇头当前位置
        self.body = [(-1, -1)] * constant.SNAKE_BODY_LENGTH  # 蛇身长度
        self.direction = constant.SNAKE_DIRECTION  # 当前方向
        self.new_direction = constant.SNAKE_DIRECTION  # 移动方向
        self.speed = constant.SNAKE_SPEED  # 移动速度
        self.is_alive = True  # 是否存活

    def set_speed(self, speed):
        """
        @summary: 设置蛇的移动速度
        :param speed: 移动速度
        :return:
        """
        self._speed = speed
        self.game.add_game_action("snake.move", self.move, 1000 // speed)

    def get_speed(self):
        """
        @summary: 获取当前蛇的移动速度
        :return:
        """
        return self._speed

    @property
    def speed(self):
        return self._speed

    @speed.setter
    def speed(self, speed):
        self._speed = speed
        self.game.add_game_action("snake.move", self.move, 1000 // speed)

    def draw(self):
        """
        @summary: 绘制小蛇
        :return: 
        """
        skin_color = constant.SNAKE_COLOR_SKIN if self.is_alive else constant.SNAKE_COLOR_SKIN_DEAD
        body_color = constant.SNAKE_COLOR_BODY if self.is_alive else constant.SNAKE_COLOR_BODY_DEAD
        head_color = constant.SNAKE_COLOR_HEAD if self.is_alive else constant.SNAKE_COLOR_HEAD_DEAD
        for cell in self.body:
            self.game.draw_cell(cell, constant.CELL_SIZE, skin_color, body_color)
        self.game.draw_cell(self.head, constant.CELL_SIZE, skin_color, head_color)

    def turn(self, direction):
        """
        @summary: 改变小蛇方向
        :param direction: 
        :return: 
        """
        if (self.direction in (constant.LEFT, constant.RIGHT) and direction in (constant.UP, constant.DOWN) or
                self.direction in (constant.UP, constant.DOWN) and direction in (constant.LEFT, constant.RIGHT)):
            self.new_direction = direction

    def move(self):
        """
        @summary: 移动小蛇
        :return: 
        """
        if not self.is_alive:
            return
        # 设定方向
        self.direction = self.new_direction
        # 检测前方
        x, y = meeting = (
            self.head[0] + self.direction[0],
            self.head[1] + self.direction[1]
        )
        # 死亡判断
        if meeting in self.body or x not in range(constant.COLUMNS) or y not in range(constant.ROWS):
            self.die()
            return
        # 判断是否吃了苹果
        if meeting == (self.game.apple.x, self.game.apple.y):
            self.sound_eat.play()
            self.game.apple.drop()
            self.game.apple_count += 1
        else:
            self.body.pop()
        # 蛇头变成脖子
        self.body = [self.head] + self.body
        # 蛇头移动到新位置
        self.head = meeting

    def restart_pawn(self):
        """重生"""
        self.head = (constant.SNAKE_X, constant.SNAKE_Y)
        self.body = [(-1, -1)] * constant.SNAKE_BODY_LENGTH
        self.direction = constant.SNAKE_DIRECTION
        self.new_direction = constant.SNAKE_DIRECTION
        self.speed = constant.SNAKE_SPEED
        self.is_alive = True

    def die(self):
        self.sound_hit.play()
        self.is_alive = False

constant.py

import pygame

# 颜色设定
BLACK = 0, 0, 0
WHITE = 255, 255, 255
DARK_GREY = 33, 33, 33
GREY = 127, 127, 127
LIGHT_GREY = 192, 192, 192
BACKGROUND_COLOR = BLACK
GRID_COLOR = DARK_GREY
APPLE_COLOR_SKIN = 255, 127, 127
APPLE_COLOR_BODY = 255, 66, 66
SNAKE_COLOR_SKIN = 33, 255, 33
SNAKE_COLOR_BODY = 33, 192, 33
SNAKE_COLOR_HEAD = 192, 192, 33
SNAKE_COLOR_SKIN_DEAD = LIGHT_GREY
SNAKE_COLOR_BODY_DEAD = GREY
SNAKE_COLOR_HEAD_DEAD = DARK_GREY

# 一般设定
GAME_NAME = "SnakeGame"
SCREEN_SIZE = SCREEN_WIDTH, SCREEN_HEIGHT = 640, 480
CELL_SIZE = 20
COLUMNS, ROWS = SCREEN_WIDTH // CELL_SIZE, SCREEN_HEIGHT // CELL_SIZE
DISPLAY_MODE = pygame.HWSURFACE | pygame.DOUBLEBUF
LOOP_SPEED = 60
# noinspection SpellCheckingInspection
FONT_NAME = "resources/MONACO.TTF"
FONT_SIZE = 16
# noinspection SpellCheckingInspection
ICON = "resources/snake.png"
UP, DOWN, LEFT, RIGHT = (0, -1), (0, 1), (-1, 0), (1, 0)

# 按键设定
KEY_EXIT = pygame.K_ESCAPE
KEY_UP = pygame.K_UP
KEY_DOWN = pygame.K_DOWN
KEY_LEFT = pygame.K_LEFT
KEY_RIGHT = pygame.K_RIGHT
KEY_RESTART = pygame.K_r
K_PAUSE = pygame.K_PAUSE

# 蛇的默认值
SNAKE_X = 0
SNAKE_Y = 0
SNAKE_BODY_LENGTH = 5
SNAKE_DIRECTION = RIGHT
SNAKE_SPEED = 10

源码地址:https://gitcode.com/stormsha1/games/overview

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

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

相关文章

Linux之命令行参数与环境变量

命令行参数&环境变量 命令行参数 main函数也是一个函数,其实也可以携带参数的 int main( int argc, char *argv[ ], char *envp[ ] ) {program-statements } 那这里是有三个参数的: 第一个参数: argc 是个整型变量,表示命令行参数的个数…

WIFI/BT中蓝牙的硬件资源是如何调度的 UART和PCM接口传输的是什么信号

安卓或IOS手机中,wifi/bt中的蓝牙是如何调度硬件资源的,尤其是UART和PCM是如何分配的。M.2 wifi/bt模块或其他形式的模块中,蓝牙是如何调度硬件资源的,尤其是UART和PCM是如何分配的。今天我们就图文并茂的解决这个问题。 蓝牙文件…

SQL 基础 | AS 的用法介绍

SQL(Structured Query Language)是一种用于管理和操作数据库的标准编程语言。 在SQL中,AS关键字有几种不同的用法,主要用于重命名表、列或者查询结果。 以下是AS的一些常见用法: 重命名列:在SELECT语句中&a…

Vue生命周期都有哪些?

定义 Vue的生命周期就是实例从创建到销毁的一个过程&#xff0c;即从创建、初始化数据、编译模板、挂载Dom($el)->渲染、更新->渲染&#xff0c;卸载等一系列的过程。el是挂载点如<div id"app"></div>。 Vue的生命周期分为八个阶段 1.beforeCreate…

重看Spring聚焦BeanDefinition分析和构造

目录 一、对BeanDefinition的理解 &#xff08;一&#xff09;理解元信息 &#xff08;二&#xff09;BeanDefinition理解分析 二、BeanDefinition的结构设计分析 &#xff08;一&#xff09;整体结构体会 &#xff08;二&#xff09;重要接口和类分析 三、构造 BeanDef…

保姆级IDEA安装与配置教程(含视频+资料)

课程简介 本套课程主要针对 Java 基础开发相关的工具安装和使用&#xff0c;主要包含有 IDEA 的下载、安装、配置、使用、快捷键的使用等。 本套视频是作为新手最为实用的课程&#xff0c;IDEA 是 Java 企业级开发最为常用的继承开发环境。如果熟练使用 IDEA 的话&#xff0c…

【中断】【ARM64】学习总结

optee中的异常向量表解读–中断处理解读 https://mp.weixin.qq.com/s/gBsy4YDYTHGRsy2zcVr6Vg

c# winform快速建websocket服务器源码 wpf快速搭建websocket服务 c#简单建立websocket服务 websocket快速搭建

完整源码下载----->点击 随着互联网技术的飞速发展&#xff0c;实时交互和数据推送已成为众多应用的核心需求。传统的HTTP协议&#xff0c;基于请求-响应模型&#xff0c;无法满足现代Web应用对低延迟、双向通信的高标准要求。在此背景下&#xff0c;WebSocket协议应运而生…

Polardb集中式部署体验

前言说明 PolarDB是阿⾥云数据库团队⾃主开发的云原⽣数据库。据了解PolarDB是产品品牌统称&#xff0c;云上PolarDB提供了Polardb MySQL版&#xff08;集中式数据库&#xff09;&#xff0c;PolarDB PostgreSQL版&#xff08;集中式数据库&#xff09;和PolarDB分布式版&…

人工智能论文:BERT和GPT, GPT-2, GPT-3 的简明对比和主要区别

在BERT的论文里面&#xff1a; 2018.10 BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding&#xff0c;BERT已经解释了BERT&#xff0c;GPT&#xff0c;ELMo的区别。 *ELMo为双向RNN&#xff0c;请忽略。 主要区别&#xff1a; BERT使用的是…

机器学习:深入解析SVM的核心概念【四、软间隔与正则化】

软间隔与正则化 问题一&#xff1a;优化目标函数是如何得到的&#xff1f;得到的过程是怎样的&#xff1f;问题二&#xff1a;拉格朗日乘子法计算详细过程问题三&#xff1a;KKT条件求解过程问题四&#xff1a;结构风险最小化&#xff08;SRM&#xff09;的原理 在前面的讨论中…

批量视频剪辑新选择:一键式按照指定秒数分割视频并轻松提取视频中的音频,让视频处理更高效!

是否经常为大量的视频剪辑工作感到头疼&#xff1f;还在一个个手动分割、提取音频吗&#xff1f;现在&#xff0c;我们为你带来了一款全新的视频批量剪辑神器&#xff0c;让你轻松应对各种视频处理需求&#xff01; 首先&#xff0c;进入媒体梦工厂的主页面&#xff0c;并在板…

机器学习之基于Tensorflow(LSTM)进行多变量时间序列预测股价

欢迎大家点赞、收藏、关注、评论啦 &#xff0c;由于篇幅有限&#xff0c;只展示了部分核心代码。 文章目录 一项目简介 二、功能三、系统四. 总结 一项目简介 项目简介&#xff1a;机器学习之基于TensorFlow&#xff08;LSTM&#xff09;进行多变量时间序列预测股价 一、项目…

【Java从入门到精通】Java 正则表达式

目录 正则表达式实例 &#x1f349;java.util.regex 包 &#x1f349;实例 &#x1f349;捕获组 &#x1f349;实例 &#x1f349;RegexMatches.java 文件代码&#xff1a; &#x1f349;正则表达式语法 &#x1f349;Matcher 类的方法 &#x1f349;索引方法 &#…

【Qt QML】QLibrary加载共享库中的类

QLibrary是一个用于加载动态链接库&#xff08;或称为共享库&#xff09;的类。它提供了一种独立于平台的方式来访问库中的功能。 在QLibrary中&#xff0c;可以通过构造函数或setFileName()方法设置要加载的库文件名。当加载库文件时&#xff0c;QLibrary会搜索所有平台特定的…

消失的VCC和VEE,取而代之的VDD和VSS

一直以来&#xff0c;这些电源电压&#xff08;Vdd 和 Vss&#xff09;或&#xff08;Vcc 和 Vee&#xff09;的命名都有点耐人寻味&#xff0c;甚至令人困惑。但为什么呢&#xff1f; It has always been a bit intriguing and even confusing the nomenclature of these powe…

Unreal 编辑器工具 批量重命名资源

右键 - Editor Utilities - Editor Utility Blueprint&#xff0c;基类选择 Asset Action Utility 在类默认值内&#xff0c;可以添加筛选器&#xff0c;筛选指定的类型 然后新建一个函数&#xff0c;加上4个输入&#xff1a;ReplaceFrom&#xff0c;ReplaceTo&#xff0c;Add…

多国语言免费在线客服系统源码,网站在线客服系统,网页在线客服软件在线聊天通讯平台

详情介绍 多国语言免费在线客服系统源码,网站在线客服系统,网页在线客服软件在线聊天通讯平台 新款在线客服系统全开源无加密:多商户、国际化多语言、智能机器人、自动回复、语音聊天、 文件发送、系统强力防黑加固、不限坐席、国际外贸、超多功能 支持手机移动端和PC网页…

安装ESXI 7.0的系统盘小于120G,安装后无本地datastore存储的处理办法

1、应用场景 在全新安装ESXI 7.0后&#xff0c;系统将会划分120G空间作为虚拟闪存&#xff0c;在大容量硬盘的设备中&#xff0c;120G无足轻重&#xff0c;但是当ESXI系统盘容量非常小的时候会导致无可用本地存储空间。 我这里的情况就是服务器里内置了2个120G的硬盘&#xff…

文章解读与仿真程序复现思路——电力自动化设备EI\CSCD\北大核心《计及高阶方程分段线性化的港口电-氢综合能源系统优化调度》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…