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

Unity教程(九)角色攻击的改进

Unity开发2D类银河恶魔城游戏学习笔记

Unity教程(零)Unity和VS的使用相关内容
Unity教程(一)开始学习状态机
Unity教程(二)角色移动的实现
Unity教程(三)角色跳跃的实现
Unity教程(四)碰撞检测
Unity教程(五)角色冲刺的实现
Unity教程(六)角色滑墙的实现
Unity教程(七)角色蹬墙跳的实现
Unity教程(八)角色攻击的基本实现
Unity教程(九)角色攻击的改进

Unity教程(十)Tile Palette搭建平台关卡


如果你更习惯用知乎
Unity开发2D类银河恶魔城游戏学习笔记目录


文章目录

  • Unity开发2D类银河恶魔城游戏学习笔记
  • 前言
  • 一、概述
  • 二、基础攻击的改进
    • (1)调整动画提升流畅度
    • (2)解决攻击时滑动的问题
    • (3)解决两次攻击间角色移动的问题
    • (4)攻击间移动
    • (5)添加攻击方向
    • (6)加速操作(不需要做)
  • 三、代码整理
  • 总结 完整代码
    • Player.cs
    • PlayerPrimaryAttackState.cs
    • PlayerIdleState.cs


前言

本文为Udemy课程The Ultimate Guide to Creating an RPG Game in Unity学习笔记,如有错误,欢迎指正。

本节进行角色基本攻击的改进。
对应b站视频:
【Unity教程】从0编程制作类银河恶魔城游戏P40
【Unity教程】从0编程制作类银河恶魔城游戏P41


一、概述

本节主要进行角色基本攻击的改进。
空闲状态到移动状态之间的转换添加条件 ! isBusy
在这里插入图片描述
本节改进了基本攻击的小问题,添加了攻击移动和攻击方向,提升了动画流畅度。在最后对代码进行了一些整理。整体结构如下:
在这里插入图片描述


二、基础攻击的改进

(1)调整动画提升流畅度

调整三个攻击动画的采样率,并且将最后一个攻击动画事件提前。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

(2)解决攻击时滑动的问题

现在我们攻击时角色会来回滑动,因为我们的角色还保持着移动的速度但已经播放攻击动画了。
在这里插入图片描述
这里教程中的解决方式是在攻击时将角色速度置为0。
但我个人感觉这种处理方式会让攻击缺少一些灵活性。但如果想实现边移动边攻击就需要有另外的动画和另外的逻辑来实现,需要另行设计,所以在此先按教程中的实现。
此外,我们可以在进入时给stateTimer赋一个值,让角色停顿一下再攻击,做出惯性的效果。
在PlayerPrimaryAttack中修改:

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);stateTimer = 0.1f;}// 更新public override void Update(){base.Update();if (stateTimer < 0)rb.velocity = new Vector2(0, 0);if(triggerCalled)stateMachine.ChangeState(player.idleState);}

在这里插入图片描述

(3)解决两次攻击间角色移动的问题

我依然认为这种处理方法缺乏灵活性,但可以先学习一下他的处理方式。
如果需要解决这个问题,我们可以使用协程。我参照了以下文章的讲解:
进程、线程和协程之间的区别和联系
Unity 协程(Coroutine)原理与用法详解
Unity官方手册

协程是通过迭代器来实现功能的,通过关键字IEnumerator来定义。

启动协程:
StartCoroutine(IEnumerator routine:通过方法形式调用
StartCoroutine(string methodName,object values):带参数的通过方法名进行调用

停止携程:
StopCoroutine(string methodName:通过方法名(字符串)来进行
StopCoroutine(IEnumerator routine:通过方法形式来调用
StopCoroutine(Coroutine routine):通过指定的协程来关闭

yield方法:
yield return null; 暂停协程等待下一帧继续执行
yield return 0或其他数字; 暂停协程等待下一帧继续执行
yield return new WairForSeconds(时间); 等待规定时间后继续执行
yield return StartCoroutine(“协程方法名”); 开启一个协程(嵌套协程)

在Player中创建一个参数isBusy,并定义BusyFor函数

    public bool isBusy { get; private set; }public IEnumerator BusyFor(float _seconds){isBusy = true;yield return new WaitForSeconds(_seconds);isBusy = false;}

在每次攻击结束时调用,在PlayerPriamaryAttack

    //退出public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", 0.15f);comboCounter++;lastTimeAttacked = Time.time;}

然后给空闲状态转到移动状态添加一个 ! Busy 的条件:

    //更新public override void Update(){base.Update();//切换到移动状态if(xInput!=0 && !player.isBusy)stateMachine.ChangeState(player.moveState);}

在攻击期间即使我一直按着移动键,角色也不能移动了,效果如下:
在这里插入图片描述

(4)攻击间移动

给连击中的每一段设置一个位移。
在Player中添加变量攻击位移数组

    [Header("Attack details")]public float[] attackMovement;

在开始攻击时设置位移

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);player.SetVelocity(player.attackMovement[comboCounter] * player.facingDir, rb.velocity.y);stateTimer = 0.1f;}

给数列赋值,调整数值直到你想要的效果
在这里插入图片描述
在这里插入图片描述

(5)添加攻击方向

现在的攻击还有一个小问题,在攻击后马上按相反方向键向角色身后攻击,我们会发现角色完全没有转向。
因为我们在攻击时始终是向着角色面向的方向,没有翻转。
我们在PlayerPrimaryAttack中添加这个功能:

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);float attackDir = player.facingDir;if (xInput != 0)attackDir = xInput;player.SetVelocity(player.attackMovement[comboCounter].x * attackDir, player.attackMovement[comboCounter].y);stateTimer = 0.1f;}

当没有输入时,向角色面向方向攻击;当有输入时,向输入方向攻击。现在角色可以迅速回身攻击了。
在这里插入图片描述

(6)加速操作(不需要做)

教程中顺便讲到了使所有动画加速的操作。这个操作可以实现不同武器不同攻速等操作,或者实现整体加速。
用player.anim.speed 进行实现,在进入攻击状态时加速,在退出时恢复原速。

    //进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);player.anim.speed = 3.0f;player.SetVelocity(player.attackMovement[comboCounter].x * player.facingDir, player.attackMovement[comboCounter].y);stateTimer = 0.1f;}//退出public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", 0.15f);player.anim.speed = 1.0f;comboCounter++;lastTimeAttacked = Time.time;}

为了效果明显,我调了三倍速。
在这里插入图片描述

三、代码整理

速度置零的操作,我们在Player中写一个函数ZeroVelocity()用来调用

    //速度置零public void ZeroVelocity() => rb.velocity = new Vector2(0, 0);

在PlayerPrimaryAttack中改为调用函数

//PlayerPrimaryAttackState:基本攻击状态// 更新public override void Update(){base.Update();if (stateTimer < 0)player.ZeroVelocity();if(triggerCalled)stateMachine.ChangeState(player.idleState);}

Player中代码划分区域
速度设置

    #region 速度设置//速度置零public void ZeroVelocity() => rb.velocity = new Vector2(0, 0);//设置速度public void SetVelocity(float _xVelocity, float _yVelocity){rb.velocity = new Vector2(_xVelocity, _yVelocity);FlipController(_xVelocity);}#endregion

翻转

    #region 翻转//翻转实现public void Flip(){facingDir = -1 * facingDir;facingRight = !facingRight;transform.Rotate(0, 180, 0);}//翻转控制public void FlipController(float _x){if (_x > 0 && !facingRight)Flip();else if(_x < 0 && facingRight)Flip();}#endregion

碰撞

    #region 碰撞//碰撞检测public bool isGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);public bool isWallDetected() => Physics2D.Raycast(wallCheck.position,Vector2.right * facingDir,wallCheckDistance,whatIsGround);//绘制碰撞检测private void OnDrawGizmos(){Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x+ wallCheckDistance, wallCheck.position.y));}#endregion

在这里插入图片描述
给PlayerPrimaryAttack改名为PlayerPrimaryAttackState
右键状态名->重命名->Enter
在这里插入图片描述
在这里插入图片描述

总结 完整代码

Player.cs

添加攻击位移变量
添加isBusy和协程

//Player:玩家
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class Player : MonoBehaviour
{[Header("Attack details")]public Vector2[] attackMovement;public bool isBusy { get; private set; }[Header("Move Info")]public float moveSpeed = 8f;public int facingDir { get; private set; } = 1;private bool facingRight = true;public float jumpForce = 12f;[Header("Dash Info")][SerializeField] private float dashCoolDown;private float dashUsageTimer;public float dashSpeed=25f;public float dashDuration=0.2f;public float dashDir {  get; private set; }[Header("Collision Info")][SerializeField] private Transform groundCheck;[SerializeField] private float groundCheckDistance;[SerializeField] private Transform wallCheck;[SerializeField] private float wallCheckDistance;[SerializeField] private LayerMask whatIsGround;#region 组件public Animator anim { get; private set; }public Rigidbody2D rb { get; private set; }#endregion#region 状态public PlayerStateMachine StateMachine { get; private set; }public PlayerIdleState idleState { get; private set; }public PlayerMoveState moveState { get; private set; }public PlayerJumpState jumpState { get; private set; }public PlayerAirState airState { get; private set; }public PlayerDashState dashState { get; private set; }public PlayerWallSlideState wallSlideState { get; private set; }public PlayerWallJumpState wallJumpState { get; private set; }public PlayerPrimaryAttack primaryAttack { get; private set; }  #endregion//创建对象private void Awake(){StateMachine = new PlayerStateMachine();idleState = new PlayerIdleState(StateMachine, this, "Idle");moveState = new PlayerMoveState(StateMachine, this, "Move");jumpState = new PlayerJumpState(StateMachine, this, "Jump");airState = new PlayerAirState(StateMachine, this, "Jump");dashState = new PlayerDashState(StateMachine, this, "Dash");wallSlideState = new PlayerWallSlideState(StateMachine, this, "WallSlide");wallJumpState = new PlayerWallJumpState(StateMachine, this, "Jump");primaryAttack = new PlayerPrimaryAttack(StateMachine, this, "Attack");anim = GetComponentInChildren<Animator>();rb = GetComponent<Rigidbody2D>();}// 设置初始状态private void Start(){StateMachine.Initialize(idleState);}// 更新private void Update(){StateMachine.currentState.Update();CheckForDashInput();}public IEnumerator BusyFor(float _seconds){isBusy = true;yield return new WaitForSeconds(_seconds);isBusy = false;}//设置触发器public void AnimationTrigger() => StateMachine.currentState.AnimationFinishTrigger();//检查冲刺输入public void CheckForDashInput(){dashUsageTimer -= Time.deltaTime;if (Input.GetKeyDown(KeyCode.LeftShift) && dashUsageTimer<0){dashUsageTimer = dashCoolDown;dashDir = Input.GetAxisRaw("Horizontal");if (dashDir == 0)dashDir = facingDir;StateMachine.ChangeState(dashState);}}#region 速度设置//速度置零public void ZeroVelocity() => rb.velocity = new Vector2(0, 0);//设置速度public void SetVelocity(float _xVelocity, float _yVelocity){rb.velocity = new Vector2(_xVelocity, _yVelocity);FlipController(_xVelocity);}#endregion#region 翻转//翻转实现public void Flip(){facingDir = -1 * facingDir;facingRight = !facingRight;transform.Rotate(0, 180, 0);}//翻转控制public void FlipController(float _x){if (_x > 0 && !facingRight)Flip();else if(_x < 0 && facingRight)Flip();}#endregion#region 碰撞//碰撞检测public bool isGroundDetected() => Physics2D.Raycast(groundCheck.position, Vector2.down, groundCheckDistance, whatIsGround);public bool isWallDetected() => Physics2D.Raycast(wallCheck.position,Vector2.right * facingDir,wallCheckDistance,whatIsGround);//绘制碰撞检测private void OnDrawGizmos(){Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x+ wallCheckDistance, wallCheck.position.y));}#endregion
}

PlayerPrimaryAttackState.cs

攻击时速度置零
添加协程
添加攻击位移
添加攻击方向

//PlayerPrimaryAttackState:基本攻击状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;public class PlayerPrimaryAttackState : PlayerState
{private int comboCounter;private float lastTimeAttacked;private float comboWindow = 2;public PlayerPrimaryAttackState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName){}//进入public override void Enter(){base.Enter();if (comboCounter > 2 || Time.time > lastTimeAttacked + comboWindow)comboCounter = 0;player.anim.SetInteger("comboCounter",comboCounter);float attackDir = player.facingDir;if (xInput != 0)attackDir = xInput;player.SetVelocity(player.attackMovement[comboCounter].x * attackDir, player.attackMovement[comboCounter].y);stateTimer = 0.1f;}//退出public override void Exit(){base.Exit();player.StartCoroutine("BusyFor", 0.15f);comboCounter++;lastTimeAttacked = Time.time;}// 更新public override void Update(){base.Update();if (stateTimer < 0)player.ZeroVelocity();if(triggerCalled)stateMachine.ChangeState(player.idleState);}
}

PlayerIdleState.cs

修改转到移动状态的条件

//PlayerIdleState:空闲状态
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.XR;public class PlayerIdleState : PlayerGroundedState
{//构造函数public PlayerIdleState(PlayerStateMachine _stateMachine, Player _player, string _animBoolName) : base(_stateMachine, _player, _animBoolName){}//进入public override void Enter(){base.Enter();player.SetVelocity(0, rb.velocity.y);}//退出public override void Exit(){base.Exit();}//更新public override void Update(){base.Update();//切换到移动状态if(xInput!=0 && !player.isBusy)stateMachine.ChangeState(player.moveState);}
}

相关文章:

Unity教程(九)角色攻击的改进

Unity开发2D类银河恶魔城游戏学习笔记 Unity教程&#xff08;零&#xff09;Unity和VS的使用相关内容 Unity教程&#xff08;一&#xff09;开始学习状态机 Unity教程&#xff08;二&#xff09;角色移动的实现 Unity教程&#xff08;三&#xff09;角色跳跃的实现 Unity教程&…...

宠物空气净化器真的能除毛吗?有哪些选购技巧和品牌推荐修改版

夏日炎炎&#xff0c;有猫超甜。作为一名资深铲屎官&#xff0c;家里养有猫让我倍感幸福&#xff0c;夏天里有空调、有西瓜、有猫&#xff0c;这几个搭配在一起真的是超级爽。但在这么高温的夏天&#xff0c;家里养有宠物还是有不少烦恼的。比如家里的浮毛一直飘&#xff0c;似…...

Qt自定义注释

前言 是谁在Qt中编写代码&#xff0c;函数注释&#xff0c;类注释时&#xff0c;注释符号一个一个的敲&#xff1f; comment注释brief简洁的 Detailed详细的 第一步&#xff1a; 打开Qt 工具->选项->文本编辑器->片段 第二步&#xff1a; 点击添加 然后点击OK…...

【模电笔记】——信号的运算和处理电路(含电压比较器)

tips&#xff1a;本章节的笔记已经打包到word文档里啦&#xff0c;建议大家下载文章顶部资源&#xff08;有时看不到是在审核中&#xff0c;等等就能下载了。手机端下载后里面的插图可能会乱&#xff0c;建议电脑下载&#xff0c;兼容性更好且易于观看&#xff09;&#xff0c;…...

Java之 equals()与==

目录 运算符用途&#xff1a;用于比较两个引用是否指向同一个对象。比较内容&#xff1a;比较的是内存地址&#xff08;引用&#xff09;。适用范围&#xff1a;适用于基本数据类型和对象引用 equals() 方法用途&#xff1a;用于比较两个对象的内容是否相同。比较内容&#xf…...

Ubuntu20.04 运行深蓝路径规划hw1

前言 环境&#xff1a; ubuntu 20.04 &#xff1b; ROS版本&#xff1a; noetic&#xff1b; 问题 1、出现PCL报错&#xff1a;#error PCL requires C14 or above catkin_make 编译时&#xff0c;出现如下错误 解决&#xff1a; 在grid_path_searcher文件夹下面的CMakeLis…...

企业如何组建安全稳定的跨国通信网络

当企业在海外设有分公司时&#xff0c;如何建立一个安全且稳定的跨国通信网络是一个关键问题。为了确保跨国通信的安全和稳定性&#xff0c;可以考虑以下几种方案。 首先&#xff0c;可以在分公司之间搭建虚拟专用网络。虚拟专用网络通过对传输数据进行加密&#xff0c;保护通信…...

WordPress原创插件:Download-block-plugin下载按钮图标美化

WordPress原创插件&#xff1a;Download-block-plugin下载按钮图标美化 https://download.csdn.net/download/huayula/89632743...

前端【详解】缓存

HTTP 缓存 https://blog.csdn.net/weixin_41192489/article/details/136446539 CDN 缓存 CDN 全称 Content Delivery Network,即内容分发网络。 用户在浏览网站的时候&#xff0c;CDN会选择一个离用户最近的CDN边缘节点来响应用户的请求 CDN边缘节点的缓存机制与HTTP 缓存相同…...

P5821 【LK R-03】密码串匹配

[题目通道](【L&K R-03】密码串匹配 - 洛谷) 一道神题。 如果没有修改操作&#xff0c;翻转A数组或B数组后就是裸的FFT了 如果每次操作都暴力修改FFT时间复杂度显然爆炸 如果每次操作都不修改&#xff0c;记下修改序列&#xff0c;询问时加上修改序列的贡献&#xff0c;…...

httpx,一个网络请求的 Python 新宠儿

大家好&#xff01;我是爱摸鱼的小鸿&#xff0c;关注我&#xff0c;收看每期的编程干货。 一个简单的库&#xff0c;也许能够开启我们的智慧之门&#xff0c; 一个普通的方法&#xff0c;也许能在危急时刻挽救我们于水深火热&#xff0c; 一个新颖的思维方式&#xff0c;也许能…...

计算机网络408考研 2014

1 计算机网络408考研2014年真题解析_哔哩哔哩_bilibili 1 111 1 11 1...

JavaScript 资源大全中文版

目录 JavaScript资源大全中文版 包管理器加载器组件管理器打包工具测试框架QA工具MVC 框架和库基于 Node 的 CMS 框架模板引擎文章和帖子数据可视化 时间轴电子表格 编辑器文档工具 文件函数式编程响应式编程数据结构日期字符串数字存储颜色国际化和本地化控制流路由安全性日志…...

如何获取能直接在浏览器打开的播放地址?

背景&#xff1a;需要在浏览器上直接打开设备的画面&#xff0c;但又不想二次开发 本文介绍一种极简的取流方式&#xff0c;不需要掌握前端开发知识&#xff0c;按照本文档拼接就能得到设备的播放地址 一、准备工作 1.将设备接入到萤石账号下。萤石设备接入指南&#xff1a;h…...

如何用 LangChain 实现一个Zero Shot智能决策器(附源码)

写在前面 最近一直在研究Agent和Tool的使用&#xff0c;今天给大家带来一篇何枝大佬&#xff08;知乎何枝&#xff09;的文章《如何用LangChain实现一个Zero Shot智能决策器》&#xff0c;并附上源码。 知乎&#xff1a;https://zhuanlan.zhihu.com/p/627333499LangChain是当…...

读完这本书,我终于搞懂了Transformer、BERT和GPT!【附PDF】

前言 《Transformer、BERT和GPT: 包括ChatGPT和提示工程》 是一本深入浅出地介绍自然语言处理领域前沿技术的专著&#xff0c;全书一共379页PDF&#xff0c;是截止到目前比较系统介绍NLP和GPT融合领域的书籍。 全书共十章&#xff0c;内容丰富&#xff0c;结构清晰&#xff0c…...

仿RabbitMq简易消息队列基础篇(Muduo库的使用)

TOC Muduo库简介 Muduo由陈硕⼤佬开发&#xff0c;是⼀个基于⾮阻塞IO和事件驱动的C⾼并发TCP⽹络编程库。他是一款基于主从Reactor模型的网络库&#xff0c;其使用的线程模型是one loop per thread, 所谓 one loop per thread 指的是&#xff1a; 一个线程只能有一个事件循…...

.net SqlSugarHelper

NuGet安装&#xff1a; SqlSugarCore using SqlSugar; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace Namespace {public class SqlSugarHelper{public string _connectionString Custom…...

“AI能不能代替某某职业”,到底谁在破防?

前几天&#xff0c;公司在午间分享时谈到一个有趣的辩题&#xff1a;“AI能不能代替产品经理”&#xff0c;不仅双方辩手打了个你来我往&#xff0c;就连下面的吃瓜群众也进入红温状态。 “AI能不能代替xx”已经成为一个普遍的话题&#xff0c;在某乎上随手一刷就是不同的职业…...

智慧图书馆:构建高效视频智能管理方案,提升图书馆个性化服务

一、背景分析 随着信息技术的飞速发展&#xff0c;智慧图书馆作为现代公共文化服务的重要载体&#xff0c;正逐步从传统的纸质阅读空间向数字化、智能化方向转型。其中&#xff0c;视频智能管理方案作为智慧图书馆安全管理体系的重要组成部分&#xff0c;不仅能够有效提升图书…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

DockerHub与私有镜像仓库在容器化中的应用与管理

哈喽&#xff0c;大家好&#xff0c;我是左手python&#xff01; Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库&#xff0c;用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

微服务通信安全:深入解析mTLS的原理与实践

&#x1f525;「炎码工坊」技术弹药已装填&#xff01; 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、引言&#xff1a;微服务时代的通信安全挑战 随着云原生和微服务架构的普及&#xff0c;服务间的通信安全成为系统设计的核心议题。传统的单体架构中&…...

数据库——redis

一、Redis 介绍 1. 概述 Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的、高性能的内存键值数据库系统&#xff0c;具有以下核心特点&#xff1a; 内存存储架构&#xff1a;数据主要存储在内存中&#xff0c;提供微秒级的读写响应 多数据结构支持&…...