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

用js代码实现贪吃蛇小游戏

js已经学了大部分了,现在就利用我所学的js知识试试做贪吃蛇小游戏吧

以下部分相关图片以及思路笔记均出自渡一陈老师的视频

首先制作简单的静态页面,添加贪吃蛇移动的背景和相关图片,比如开始游戏等等

将各个功能均封装在函数中,利用主函数调用分函数会使结构更清晰

初始化游戏

初始化地图

地图坐标

 

  //1.初始化地图for(let i=0;i<tr;i++){for(let j=0;j<td;j++){gridData.push({x:j,y:i})}}

绘制蛇

  • 在游戏相关配置文件(js文件)中定义蛇的身体大小,以及蛇的相关位置信息(位置坐标,对应身体还是头部标志,身体元素相关元素标签)
  • 在index.js文件中遍历snake的位置信息,若domContent(身体元素相关元素标签)为空,就添加元素标签,给标签设置定位,并设置每个元素的left和top为身体大小*x或者*y,并且判断身体元素是蛇头还是身体,是蛇头就添加蛇头的背景,是身体就添加背景颜色并设置圆角边框
  • 判断是否第一次创建蛇后,在容器中append创建的元素
// 蛇的身体大小
let snakeBody=20
// 蛇相关的配置信息
let snake={// 蛇的初始位置snakePos:[//domContent为蛇的相应dom元素 flag根据身体还是蛇头分别渲染{x:0,y:0,domContent:"",flag:'body'},{x:1,y:0,domContent:"",flag:'body'},{x:2,y:0,domContent:"",flag:'body'},{x:3,y:0,domContent:"",flag:'head'}]
}
/***绘制蛇的方法*  @param {*} snake* */
function drawSnake(snake){for(let i=0;i<snake.snakePos.length;i++){if(!snake.snakePos[i].domContent){// 如果进入此if,说明是第一次创建蛇snake.snakePos[i].domContent=document.createElement("div")snake.snakePos[i].domContent.style.position="absolute"snake.snakePos[i].domContent.style.width=snakeBody+"px"snake.snakePos[i].domContent.style.height=snakeBody+"px"snake.snakePos[i].domContent.style.left=snake.snakePos[i].x*snakeBody+"px"snake.snakePos[i].domContent.style.top=snake.snakePos[i].y*snakeBody+"px"if(snake.snakePos[i].flag==='head'){// 说明当前是蛇头snake.snakePos[i].domContent.style.background=`url("../images/snake.png") center/contain no-repeat`}else{// 说明是蛇身snake.snakePos[i].domContent.style.background="#9ddbb1"snake.snakePos[i].domContent.style.borderRadius='50%'}}// 需要将创建的DOM元素添加到container 容器上面document.querySelector(".container").append(snake.snakePos[i].domContent)}
}

添加几个蛇身后效果如图所示:

绘制食物

  • 其过程和绘制蛇过程基本类似,先在配置文件中声明食物的相关配置信息,食物对象中不需要标志元素
  • 要求食物不可出现在蛇头蛇身以及container外面区域,生成随机数在while中循环无限循环,直到坐标符合条件退出循环,利用一个变量判断是否需要退出循环
  • 生成正确的坐标后,就创建一个新的变量,设置绝对定位,宽高,背景,最后append到container中,当然,要先判断food.domContent是否为空,为空才可创建,创建之后只是改变食物的位置,不会再继续创建元素,故设置食物的elft和top要在判断条件外执行
// 整个网格的行与列
const tr=30
const td=30// 食物相关的配置信息
let food={x:0,y:0,domContent:""
}function drawFood(){// 食物的坐标是随机的 但食物不可生成在蛇头 蛇身 以及container之外的区域while(true){// 构成一个死循环,直到生成符合要求的坐标才能退出该循环let isRepeat=false //默认生成的坐标符合要求// 随机生成一个坐标food.x=Math.floor(Math.random()*tr)food.y=Math.floor(Math.random()*td)// 查看坐标是否符合要求(遍历蛇)for(let i=0;i<snake.snakePos.length;i++){if(snake.snakePos[i].x===food.x&&snake.snakePos[i].y===food.y){// 进入此if 说明当前生成的食物坐标和蛇的位置冲突isRepeat=truebreak}}if(!isRepeat){break}}// 整个while 循环跳出之后,食物的坐标一定是OK的if(!food.domContent){food.domContent=document.createElement("div")food.domContent.style.width=snakeBody+"px"food.domContent.style.height=snakeBody+"px"food.domContent.style.position="absolute"food.domContent.style.background=`url("../images/food.png") center/contain no-repeat`document.querySelector('.container').append(food.domContent)}food.domContent.style.left=food.x*snakeBody+"px"food.domContent.style.top=food.y*snakeBody+"px"
}

绑定事件

  • 按下键盘的上下左右时,蛇会上下左右移动,此时要添加相关配置信息,明确新蛇头和旧蛇头之间的位置关系,在确定新的蛇头坐标时,会用一个对象和旧蛇头进行计算
  • 绑定事件keydown
  • 同时在蛇的相关配置信息中添加方向
// 要明确新的蛇头和旧的蛇头之间的位置关系
// 我们在确定新的蛇头坐标的时候,会那下面的对象和旧蛇头做一个计算const directionNum={left:{x:-1,y:0,flag:'left'},right:{x:1,y:0,flag:'right'},top:{x:0,y:-1,flag:'top'},bottom:{x:0,y:1,flag:'bottom'}
}
// 蛇相关的配置信息
let snake={// 蛇一开始移动的方向direction:directionNum.right,//一开始向右边移动// 蛇的初始位置snakePos:[//domContent为蛇的相应dom元素 flag根据身体还是蛇头分别渲染{x:0,y:0,domContent:"",flag:'body'},{x:1,y:0,domContent:"",flag:'body'},{x:2,y:0,domContent:"",flag:'body'},{x:3,y:0,domContent:"",flag:'head'}]
}
/*** 绑定事件*/function bindEvent(){document.addEventListener('keydown',function(e){// console.log(e.key)if(e.key==='ArrowUp'||e.key.toLocaleLowerCase()==='w'){// 用户按的是上snake.direction=directionNum.top}if(e.key==='ArrowDown'||e.key.toLocaleLowerCase()==='s'){// 用户按的是下snake.direction=directionNum.bottom}if(e.key==='ArrowLeft'||e.key.toLocaleLowerCase()==='a'){// 用户按的是左snake.direction=directionNum.left}if(e.key==='ArrowRight'||e.key.toLocaleLowerCase()==='d'){// 用户按的是右snake.direction=directionNum.right}snakeMove()})
}

移动蛇

  • 声明一个新蛇头,新蛇头对象中包含snakePos中的所有,移动时要将新蛇头添加至snake.snakePos中,将旧蛇头变为蛇身,即把flag变为body,并将其相关属性变为身体的属性,最后重新绘制蛇即可
  • 注意,蛇头会随着方向的变化而变化,在drawSnack中添加switch,若方向为上,蛇头逆时针旋转90deg,其余以此类推
  • 碰撞检测:声明一个判断对象,里面包含两个判断,一个为是否吃到食物,一个判断是否碰撞墙壁或者碰到蛇身
  • 碰到墙壁即为新蛇头的位置坐标越界,碰到蛇身即为判断新蛇头是否和蛇身位置坐标冲突,冲突就说明碰到自己,吃到东西则为新蛇头的坐标和食物的坐标一致,吃到食物之后就重新生成食物的位置坐标
  • 蛇整体移动的过程为:每次触发键盘事件,蛇头改变,旧蛇头变为蛇身,若吃到苹果,不删除最后一个蛇身,若没有吃到苹果,则删除最后一个蛇身,即为snake.snakePos[0].domContent。
/**** 碰撞检测*/
function isCollide(newHead){let collideCheckInfo={isCollide:false,//是否碰撞墙壁 蛇身isEat:false//是否吃到食物}// 1.检测是否碰到墙壁if(newHead.x<0||newHead.x>=td||newHead.y<0||newHead.y>=tr){collideCheckInfo.isCollide=truereturn collideCheckInfo}// 检测是是否碰到自己for(let i=0;i<snake.snakePos.length;i++){if(snake.snakePos[i].x===newHead.x&&snake.snakePos[i].y===newHead.y){collideCheckInfo.isCollide=truereturn collideCheckInfo}}// 检测是否吃到东西if(newHead.x===food.x&&newHead.y===food.y){collideCheckInfo.isEat=truescore++}return collideCheckInfo
}/*** 蛇的移动方法*/
function snakeMove(){let oldHead=snake.snakePos[snake.snakePos.length-1]// 根据方向计算出新的蛇头的坐标let newHead={domContent:"",x:oldHead.x+snake.direction.x,y:oldHead.y+snake.direction.y,flag:'head'}// 接下来我们首先要做碰撞检测// 看计算出来的蛇头有没有碰上食物let collideCheckResult=isCollide(newHead)if(collideCheckResult.isCollide){//进入此if 说明撞墙了window.confirm(`游戏结束,您当前的得分为${score}分,是否要重新开始游戏`)alert("撞墙了")}// 将旧的头修改为身体oldHead.flag='body'oldHead.domContent.style.background="#9ddbb1"oldHead.domContent.style.borderRadius="50%"snake.snakePos.push(newHead)// 判断是否吃到东西if(collideCheckResult.isEat){// 1.重新生成新的食物drawFood()}else{// 说明没有吃到食物// 移除最后一个元素document.querySelector(".container").removeChild(snake.snakePos[0].domContent)snake.snakePos.shift();//删除第一个元素}drawSnake(snake)
}
  • 当游戏开始时,要让蛇自动沿着当前方向移动,使用间歇函数定时器来决定蛇移动的速度
  • 给用户选择当游戏结束时,是继续游戏还是结束游戏,继续游戏就初始化游戏,结束游戏就取消键盘事件,并停止计时器
  • 游戏进行中若点击container区域就先暂停游戏,暂停游戏时,要用到事件委托,因为当用户点击确定重新开始游戏时,会将container里的内容重置,此时的绑定事件已经不存在了,通过父亲找到儿子进行相关操作可避免直接给儿子添加绑定事件的缺点,暂停游戏时记得清除定时器,开始时再打开

相关效果如下所示:

代码:

index.html

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><link rel="stylesheet" href="../css/index.css"><title>Document</title>
</head>
<body><!-- 整个游戏按钮 --><div class="container"><!-- 开始按钮 --><button class="startBtn"></button><!-- 暂停按钮 --><button class="pauseBtn"></button></div><script src="../js/config.js"></script><script src="../js/index.js"></script>
</body>
</html>

index.css

*{/* 去除内外边距 */margin: 0;padding: 0;
}
/* 整体游戏容器样式 */
.container {position: relative;display: flex;justify-content: center;align-items: center;width: 600px;height: 600px;background-color: #225675;border: 20px solid #7dd9ff;margin: 20px auto;
}
.container button {border: none;outline: none;
}
/* 开始按钮 */
.startBtn {width: 200px;height: 80px;background: url(../images/startGame.png) center/contain no-repeat;display: block;
}
/* 暂停按钮 */
.pauseBtn {width: 70px;height: 70px;background: url(../images/start.png) center/contain no-repeat;display: none;
}

index.js

/***绘制蛇的方法*  @param {*} snake* */
function drawSnake(snake){for(let i=0;i<snake.snakePos.length;i++){if(!snake.snakePos[i].domContent){// 如果进入此if,说明是第一次创建蛇snake.snakePos[i].domContent=document.createElement("div")snake.snakePos[i].domContent.style.position="absolute"snake.snakePos[i].domContent.style.width=snakeBody+"px"snake.snakePos[i].domContent.style.height=snakeBody+"px"snake.snakePos[i].domContent.style.left=snake.snakePos[i].x*snakeBody+"px"snake.snakePos[i].domContent.style.top=snake.snakePos[i].y*snakeBody+"px"if(snake.snakePos[i].flag==='head'){// 说明当前是蛇头snake.snakePos[i].domContent.style.background=`url("../images/snake.png") center/contain no-repeat`// 根据方向进行一个旋转switch(snake.direction.flag){case 'top':{snake.snakePos[i].domContent.style.transform=`rotate(-90deg)`break}case 'bottom':{snake.snakePos[i].domContent.style.transform=`rotate(90deg)`break}case 'left':{snake.snakePos[i].domContent.style.transform=`rotate(-180deg)`break}case 'right':{snake.snakePos[i].domContent.style.transform=`rotate(0deg)`break}}}else{// 说明是蛇身snake.snakePos[i].domContent.style.background="#9ddbb1"snake.snakePos[i].domContent.style.borderRadius='50%'}}// 需要将创建的DOM元素添加到container 容器上面document.querySelector(".container").append(snake.snakePos[i].domContent)}
}
function drawFood(){// 食物的坐标是随机的 但食物不可生成在蛇头 蛇身 以及container之外的区域while(true){// 构成一个死循环,直到生成符合要求的坐标才能退出该循环let isRepeat=false //默认生成的坐标符合要求// 随机生成一个坐标food.x=Math.floor(Math.random()*tr)food.y=Math.floor(Math.random()*td)// 查看坐标是否符合要求(遍历蛇)for(let i=0;i<snake.snakePos.length;i++){if(snake.snakePos[i].x===food.x&&snake.snakePos[i].y===food.y){// 进入此if 说明当前生成的食物坐标和蛇的位置冲突isRepeat=truebreak}}if(!isRepeat){break}}// 整个while 循环跳出之后,食物的坐标一定是OK的if(!food.domContent){food.domContent=document.createElement("div")food.domContent.style.width=snakeBody+"px"food.domContent.style.height=snakeBody+"px"food.domContent.style.position="absolute"food.domContent.style.background=`url("../images/food.png") center/contain no-repeat`document.querySelector('.container').append(food.domContent)}food.domContent.style.left=food.x*snakeBody+"px"food.domContent.style.top=food.y*snakeBody+"px"
}
/**** 碰撞检测* @param {*} newHead 新计算出来的蛇头坐标*/
function isCollide(newHead){let collideCheckInfo={isCollide:false,//是否碰撞墙壁 蛇身isEat:false//是否吃到食物}// 1.检测是否碰到墙壁if(newHead.x<0||newHead.x>=td||newHead.y<0||newHead.y>=tr){collideCheckInfo.isCollide=truereturn collideCheckInfo}// 检测是是否碰到自己for(let i=0;i<snake.snakePos.length;i++){if(snake.snakePos[i].x===newHead.x&&snake.snakePos[i].y===newHead.y){collideCheckInfo.isCollide=truereturn collideCheckInfo}}// 检测是否吃到东西if(newHead.x===food.x&&newHead.y===food.y){collideCheckInfo.isEat=truescore++}return collideCheckInfo
}
function move(e){console.log(e.key)if((e.key==='ArrowUp'||e.key.toLocaleLowerCase()==='w')&&snake.direction.flag!=="bottom"){// 用户按的是上snake.direction=directionNum.top}if((e.key==='ArrowDown'||e.key.toLocaleLowerCase()==='s')&&snake.direction.flag!=="top"){// 用户按的是下snake.direction=directionNum.bottom}if((e.key==='ArrowLeft'||e.key.toLocaleLowerCase()==='a')&&snake.direction.flag!=="right"){// 用户按的是左snake.direction=directionNum.left}if((e.key==='ArrowRight'||e.key.toLocaleLowerCase()==='d')&&snake.direction.flag!=="left"){// 用户按的是右snake.direction=directionNum.right}snakeMove()
}
/*** 蛇的移动方法*/
function snakeMove(){let oldHead=snake.snakePos[snake.snakePos.length-1]// 根据方向计算出新的蛇头的坐标let newHead={domContent:"",x:oldHead.x+snake.direction.x,y:oldHead.y+snake.direction.y,flag:'head'}// 接下来我们首先要做碰撞检测// 看计算出来的蛇头有没有碰上食物let collideCheckResult=isCollide(newHead)if(collideCheckResult.isCollide){//进入此if 说明撞墙了if(window.confirm(`游戏结束,您当前的得分为${score}分,是否要重新开始游戏`)){// 重新开始游戏document.querySelector('.container').innerHTML=`<!-- 开始按钮 --><button class="startBtn" style="display:none"></button><!-- 暂停按钮 --><button class="pauseBtn" style="display:none"></button>`score=0console.log(score)// gridData=[]snake={// 蛇一开始移动的方向direction:directionNum.right,//一开始向右边移动// 蛇的初始位置snakePos:[//domContent为蛇的相应dom元素 flag根据身体还是蛇头分别渲染{x:0,y:0,domContent:"",flag:'body'},{x:1,y:0,domContent:"",flag:'body'},{x:2,y:0,domContent:"",flag:'body'},{x:3,y:0,domContent:"",flag:'head'}]}food={x:0,y:0,domContent:""}console.log("已初始化")initGame()return// drawSnake(snake)}else {// 结束游戏document.removeEventListener('keydown',move)// console.log("取消")clearInterval(timerStop)return}// alert("撞墙了")}// 将旧的头修改为身体oldHead.flag='body'oldHead.domContent.style.background="#9ddbb1"oldHead.domContent.style.borderRadius="50%"snake.snakePos.push(newHead)// 判断是否吃到东西if(collideCheckResult.isEat){// 1.重新生成新的食物drawFood()}else{// 说明没有吃到食物// 移除最后一个元素document.querySelector(".container").removeChild(snake.snakePos[0].domContent)snake.snakePos.shift();//删除第一个元素}drawSnake(snake)
}/*** 初始化游戏方法*/
function initGame(){//1.初始化地图for(let i=0;i<tr;i++){for(let j=0;j<td;j++){gridData.push({x:j,y:i})}}// 2.绘制蛇drawSnake(snake)// 3.绘制食物drawFood()
}
function startGame(){timerStop=setInterval(function(){snakeMove()},time)
}
/*** 绑定事件*/function bindEvent(){// 1.键盘事件document.addEventListener('keydown',move)// 2.计时器自动调用蛇移动的方法startGame();// 3.点击整个容器的时候,可以暂停和重新开始游戏document.querySelector('.container').addEventListener('click',function(e){// 通过事件委托的形式,判断用户点击的是container还是暂停按钮if(e.target.className ==="container"){document.querySelector('.pauseBtn').style.display='block'clearInterval(timerStop)}else {document.querySelector('.pauseBtn').style.display='none'startGame()}})// 4.给暂停按钮绑定事件// 点击子元素事件,冒泡后也会触发父元素点击事件
//   document.querySelector('.pauseBtn').addEventListener('click',function(e){
//     e.stopPropagation()//   })
}
/*** 游戏的主方法*/
function main(){// 用户点击了开始游戏之后,再做后续工作document.querySelector('.startBtn').addEventListener('click',function(e){e.stopPropagation()document.querySelector('.startBtn').style.display="none"// 1.首先初始化游戏initGame()// 2.绑定事件bindEvent()})
}main()

config.js

// 游戏相关配置文件
let gridData=[]//存储地图对象
// 整个网格的行与列
const tr=30
const td=30
// 蛇的身体大小
let snakeBody=20// 要明确新的蛇头和旧的蛇头之间的位置关系
// 我们在确定新的蛇头坐标的时候,会那下面的对象和旧蛇头做一个计算const directionNum={left:{x:-1,y:0,flag:'left'},right:{x:1,y:0,flag:'right'},top:{x:0,y:-1,flag:'top'},bottom:{x:0,y:1,flag:'bottom'}
}// 蛇相关的配置信息
let snake={// 蛇一开始移动的方向direction:directionNum.right,//一开始向右边移动// 蛇的初始位置snakePos:[//domContent为蛇的相应dom元素 flag根据身体还是蛇头分别渲染{x:0,y:0,domContent:"",flag:'body'},{x:1,y:0,domContent:"",flag:'body'},{x:2,y:0,domContent:"",flag:'body'},{x:3,y:0,domContent:"",flag:'head'}]
}
// 食物相关的配置信息
let food={x:0,y:0,domContent:""
}
// 游戏分数
let score=0
// 停止计时器
let timerStop=null
// 计时器事件
let time=300

相关文章:

用js代码实现贪吃蛇小游戏

js已经学了大部分了&#xff0c;现在就利用我所学的js知识试试做贪吃蛇小游戏吧 以下部分相关图片以及思路笔记均出自渡一陈老师的视频 首先制作简单的静态页面&#xff0c;添加贪吃蛇移动的背景和相关图片&#xff0c;比如开始游戏等等 将各个功能均封装在函数中&#xff0…...

微信小程序+esp8266温湿度读取

本文主要使用微信小程序显示ESP8266读取的温湿度并通过微信小程序控制LED灯。小程序界面如下图所示 原理讲解 esp8266 通过mqtt发布消息,微信小程序通过mqtt 订阅消息,小程序订阅后,就可以实时收到esp8266 传输来的消息。 个人可免费注册五个微信小程序账号,在微信小程序官…...

软考中级-软件设计师(十)网络与信息安全基础知识

一、网络概述 1.1计算机网络的概念 计算机网络的发展&#xff1a;具有通信功能的单机系统->具有通信功能的多机系统->以共享资源为目的的计算机网络->以局域网及因特网为支撑环境的分布式计算机系统 计算机网络的功能&#xff1a;数据通信、资源共享、负载均衡、高…...

推荐一个好用的命令行工具ShellGPT

ShellGPT 配置安装常用功能聊天写命令并执行 高级功能函数调用角色管理 总结 这两天突然想到&#xff0c;现有的很多工具都在被大模型重构&#xff0c;比如诞生了像perplexity.ai 这种新交互形式的搜索引擎&#xff0c;就连wps也推出了AI服务&#xff0c;甚至都可以直接生成ppt…...

Prompt提示词教程 | 提示工程指南 | 提示词示例 入门篇

在上一节中&#xff0c;我们介绍并给出了如何赋能大语言模型的基本示例。如果还没看而且是刚入门的同学建议看下&#xff0c;有个基本概念。 Prompt提示词教程 | 提示工程指南 | 提示工程简介https://blog.csdn.net/HRG520JN/article/details/138523705在本节中&#xff0c;我…...

uniapp + uView动态表单校验

项目需求&#xff1a;动态循环表单&#xff0c;并实现动态表单校验 页面&#xff1a; <u--form label-position"top" :model"tmForm" ref"tmForm" label-width"0px" :rulesrules><div v-for"(element, index) in tmForm…...

【Linux】HTTPS

欢迎来到Cefler的博客&#x1f601; &#x1f54c;博客主页&#xff1a;折纸花满衣 &#x1f3e0;个人专栏&#xff1a;Linux 目录 &#x1f449;&#x1f3fb;HTTPS协议概念&#x1f449;&#x1f3fb;加密为什么要进行加密 &#x1f449;&#x1f3fb;常见的加密方式对称加密…...

语音识别--使用YAMNet识别环境音

⚠申明&#xff1a; 未经许可&#xff0c;禁止以任何形式转载&#xff0c;若要引用&#xff0c;请标注链接地址。 全文共计3077字&#xff0c;阅读大概需要3分钟 &#x1f308;更多学习内容&#xff0c; 欢迎&#x1f44f;关注&#x1f440;【文末】我的个人微信公众号&#xf…...

前端JS必用工具【js-tool-big-box】,邮箱,手机,身份证号,ip地址等正则验证方法学习

这一小节&#xff0c;我们针对前端npm包 js-tool-big-box 的使用做一些讲解&#xff0c;主要是针对项目中&#xff0c;邮箱&#xff0c;手机号&#xff0c;身份证号&#xff0c;ip地址&#xff0c;url格式&#xff0c;邮政编码等验证的方法使用。 目录 1 安装和引入 2 邮箱验…...

notepad++安装 hex-editor插件

打开notepad 点击插件 搜索 hex-editor,点击右侧 安装install 安装成功后&#xff0c;在已安装插件中就有显示了...

Ubuntu18.04设置SSH密钥登录

我们一般使用 VSCode 、MobaXterm、PuTTY等 SSH 客户端来远程管理 Linux 服务器。但是&#xff0c;一般的密码方式登录&#xff0c;容易有密码被暴力破解的问题。所以&#xff0c;一般我们会将 SSH 的端口设置为默认的 22 以外的端口&#xff0c;或者禁用 root 账户登录。但是即…...

自动化运维管理工具----------Ansible模块详细解读

目录 一、自动化运维工具有哪些&#xff1f; 1.1Chef 1.2puppet 1.3Saltstack 二、Ansible介绍 2.1Ansible简介 2.2Ansible特点 2.3Ansible工作原理及流程 2.3.1内部流程 2.3.2外部流程 三、Ansible部署 3.1环境准备 3.2管理端安装 ansible 3.3Ansible相关文件 …...

零基础代码随想录【Day27】|| 39. 组合总和,40.组合总和II, 131.分割回文串

目录 DAY27 39. 组合总和 解题思路&代码 40.组合总和II 解题思路&代码 131.分割回文串 解题思路&代码 DAY27 39. 组合总和 力扣题目链接(opens new window) 给定一个无重复元素的数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有…...

实验15 MVC

二、实验项目内容&#xff08;实验题目&#xff09; 编写代码&#xff0c;掌握MVC的用法。 三、源代码以及执行结果截图&#xff1a; inputMenu.jsp&#xff1a; <% page contentType"text/html" %> <% page pageEncoding "utf-8" %> &…...

《Python编程从入门到实践》day21

# 昨日知识点回顾 设置背景颜色 在屏幕中央绘制飞船 # 今日知识点学习 12.5 重构&#xff1a;方法_check_events()和_update_screen() 12.5.1 方法_check_events() import sys import pygame from Settings import Settings from Ship import Shipclass AlienInvasion:"…...

上位机图像处理和嵌入式模块部署(树莓派4b镜像烧录经验总结)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 陆陆续续也烧录了好多次树莓派的镜像了&#xff0c;这里面有的时候很快&#xff0c;有的时候很慢。特别是烧录慢的时候&#xff0c;也不知道是自己…...

简单数据加解密,JS和JAVA同时实现

前端Vue调用Java后端接口中的数据进行加密&#xff0c;以避免敏感数据泄露。 现在实现一个高性能加密方法&#xff0c;用来对数据进行加密后传输。算法包括JS的加密和解密方法&#xff0c;也包括Java的加密解密方法。 可以在前端加密&#xff0c;后端解密。也可以在后端加密&…...

Android Framework中PackageManagerService的深度剖析

摘要 Android操作系统的核心服务之一——PackageManagerService(PMS)&#xff0c;扮演着至关重要的角色&#xff0c;负责维护系统中所有应用程序的生命周期管理。本文旨在全面探讨PMS的功能特性、工作流程、实际应用场景&#xff0c;并对其进行优劣分析&#xff0c;以期为开发者…...

(AI Web、ChatGPT Native、Ai Loading、AI Tools、知豆AI)

目录 1、AI Web 2、ChatGPT Native 3、Ai Loading 4、AI Tools 5、知豆AI 1、AI Web...

VBA 批量处理Excel文件

目录 一. 批量创建Excel文件1.1 VBA的方式1.2 Powershell方式 二. 批量删除文件三. 批量重命名文件四. 合并多个Excel数据到一个Excel文件中 一. 批量创建Excel文件 1.1 VBA的方式 Sub CreateFiles()Dim strPath As String, strFileName As StringDim i As Long, rDim pathSe…...

JavaSec-RCE

简介 RCE(Remote Code Execution)&#xff0c;可以分为:命令注入(Command Injection)、代码注入(Code Injection) 代码注入 1.漏洞场景&#xff1a;Groovy代码注入 Groovy是一种基于JVM的动态语言&#xff0c;语法简洁&#xff0c;支持闭包、动态类型和Java互操作性&#xff0c…...

盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来

一、破局&#xff1a;PCB行业的时代之问 在数字经济蓬勃发展的浪潮中&#xff0c;PCB&#xff08;印制电路板&#xff09;作为 “电子产品之母”&#xff0c;其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透&#xff0c;PCB行业面临着前所未有的挑战与机遇。产品迭代…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

Python实现prophet 理论及参数优化

文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候&#xff0c;写过一篇简单实现&#xff0c;后期随着对该模型的深入研究&#xff0c;本次记录涉及到prophet 的公式以及参数调优&#xff0c;从公式可以更直观…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

Golang——9、反射和文件操作

反射和文件操作 1、反射1.1、reflect.TypeOf()获取任意值的类型对象1.2、reflect.ValueOf()1.3、结构体反射 2、文件操作2.1、os.Open()打开文件2.2、方式一&#xff1a;使用Read()读取文件2.3、方式二&#xff1a;bufio读取文件2.4、方式三&#xff1a;os.ReadFile读取2.5、写…...

tomcat入门

1 tomcat 是什么 apache开发的web服务器可以为java web程序提供运行环境tomcat是一款高效&#xff0c;稳定&#xff0c;易于使用的web服务器tomcathttp服务器Servlet服务器 2 tomcat 目录介绍 -bin #存放tomcat的脚本 -conf #存放tomcat的配置文件 ---catalina.policy #to…...

苹果AI眼镜:从“工具”到“社交姿态”的范式革命——重新定义AI交互入口的未来机会

在2025年的AI硬件浪潮中,苹果AI眼镜(Apple Glasses)正在引发一场关于“人机交互形态”的深度思考。它并非简单地替代AirPods或Apple Watch,而是开辟了一个全新的、日常可接受的AI入口。其核心价值不在于功能的堆叠,而在于如何通过形态设计打破社交壁垒,成为用户“全天佩戴…...

Vue 模板语句的数据来源

&#x1f9e9; Vue 模板语句的数据来源&#xff1a;全方位解析 Vue 模板&#xff08;<template> 部分&#xff09;中的表达式、指令绑定&#xff08;如 v-bind, v-on&#xff09;和插值&#xff08;{{ }}&#xff09;都在一个特定的作用域内求值。这个作用域由当前 组件…...

DeepSeek源码深度解析 × 华为仓颉语言编程精粹——从MoE架构到全场景开发生态

前言 在人工智能技术飞速发展的今天&#xff0c;深度学习与大模型技术已成为推动行业变革的核心驱动力&#xff0c;而高效、灵活的开发工具与编程语言则为技术创新提供了重要支撑。本书以两大前沿技术领域为核心&#xff0c;系统性地呈现了两部深度技术著作的精华&#xff1a;…...