用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=true
        break
      }
     
    }
    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=true
    return 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=true
      return collideCheckInfo
    }
  }
  // 检测是否吃到东西
  if(newHead.x===food.x&&newHead.y===food.y){
    collideCheckInfo.isEat=true
    score++
  }
  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=true
        break
      }
     
    }
    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=true
    return 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=true
      return collideCheckInfo
    }
  }
  // 检测是否吃到东西
  if(newHead.x===food.x&&newHead.y===food.y){
    collideCheckInfo.isEat=true
    score++
  }
  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=0
      console.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

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

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

相关文章

multipass launch失败:Could not generate a new UUID vboxmanage添加环境变量path

C:\WINDOWS\system32>multipass launch [2024-05-06T15:48:54.320] [error] [relished-jerboa] Could not unregister VM: Process failed to start: 系统找不到指定的文件。 launch failed: Could not generate a new UUID: Process failed to start: 系统找不到指定的文件…

服务攻防-数据库安全RedisCouchDBH2database未授权访问CVE漏洞

#知识点&#xff1a; 1、数据库-Redis-未授权RCE&CVE 2、数据库-Couchdb-未授权RCE&CVE 3、数据库-H2database-未授权RCE&CVE#章节点&#xff1a; 1、目标判断-端口扫描&组合判断&信息来源 2、安全问题-配置不当&CVE漏洞&弱口令爆破 3、复现对象-数…

Chat2DB Pro 重磅发布 !!!

在过去的几个月中&#xff0c;我们的团队一直默默耕耘&#xff0c;全心投入到Chat2DB Pro版本的开发之中。这段时间里&#xff0c;我们暂停了新动态的发布&#xff0c;以至于有趣的误解在社群中出现&#xff0c;有人调侃我们是否“倒闭”了。然而&#xff0c;我们今天携带着全新…

C++ | Leetcode C++题解之第71题简化路径

题目&#xff1a; 题解&#xff1a; class Solution { public:string simplifyPath(string path) {auto split [](const string& s, char delim) -> vector<string> {vector<string> ans;string cur;for (char ch: s) {if (ch delim) {ans.push_back(mov…

Docker——consul的容器服务更新与发现

一、什么是服务注册与发现 服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的&#xff0c;不保障高可用性&#xff0c;也不考虑服务的压力承载&#xff0c;服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构&#xff0c;起初的解决手段…

密码学《图解密码技术》 记录学习 第十五章

目录 十五章 15.1本章学习的内容 15.2 密码技术小结 15.2.1 密码学家的工具箱 15.2.2 密码与认证 15.2.3 密码技术的框架化 15.2.4 密码技术与压缩技术 15.3 虚拟货币——比特币 15.3.1 什么是比特币 15.3.2 P2P 网络 15.3.3地址 15.3.4 钱包 15.3.5 区块链 15.3.…

力扣每日一题114:二叉树展开为链表

题目 中等 提示 给你二叉树的根结点 root &#xff0c;请你将它展开为一个单链表&#xff1a; 展开后的单链表应该同样使用 TreeNode &#xff0c;其中 right 子指针指向链表中下一个结点&#xff0c;而左子指针始终为 null 。展开后的单链表应该与二叉树 先序遍历 顺序相同…

JavaScript基础(五)

三目运算符 用于判断并赋值 语法: 判断条件?条件成立执行语句:条件不成立执行语句; (条件&#xff1f;"true":"false";) 例: <script> var age prompt(请输入年龄) var name (age>18)?"已成年":"未成年禁止登录" a…

Spring与AI结合-spring boot3整合AI组件

⛰️个人主页: 蒾酒 &#x1f525;系列专栏&#xff1a;《spring boot实战》 目录 写在前面 spring ai简介 单独整合al接口 整合Spring AI组件 起步条件 ​编辑 进行必要配置 写在最后 写在前面 本文介绍了springboot开发后端服务中&#xff0c;AI组件(Spring A…

笔试强训Day15 二分 图论

平方数 题目链接&#xff1a;平方数 (nowcoder.com) 思路&#xff1a;水题直接过。 AC code&#xff1a; #include<iostream> #include<cmath> using namespace std; int main() {long long int n; cin >> n;long long int a sqrtl(n);long long int b …

【1】STM32·FreeRTOS·新建工程模板【一步到位】

目录 一、获取FreeRTOS源码 二、FreeRTOS源码简介 2.1、FreeRTOS源码文件内容 2.2、FreeRTOS内核 2.3、Source文件夹 2.4、portable文件夹 三、FreeRTOS手把手移植 3.1、FreeRTOS移植准备 3.2、FreeRTOS移植步骤 3.2.1、将 FreeRTOS 源码添加至基础工程、头文件路径等…

LLaMA 羊驼系大语言模型的前世今生

关于 LLaMA LLaMA是由Meta AI发布的大语言系列模型&#xff0c;完整的名字是Large Language Model Meta AI&#xff0c;直译&#xff1a;大语言模型元AI。Llama这个单词本身是指美洲大羊驼&#xff0c;所以社区也将这个系列的模型昵称为羊驼系模型。 Llama、Llama2 和 Llama3…

修改idea缓存的默认存储位置

打开idea.properties 找到 # idea.config.path${user.home}/.IntelliJIdea/config # idea.system.path${user.home}/.IntelliJIdea/system 将${user.home}替换成你要存储到的路径 再次打开idea时会弹出消息&#xff0c;点击ok即可。

电脑c盘太满了,如何清理 电脑杀毒软件哪个好用又干净免费 电脑预防病毒的软件 cleanmymacX有必要买吗 杀毒软件排行榜第一名

杀毒软件通常集成监控识别、病毒扫描和清除、自动升级、主动防御等功能&#xff0c;有的杀毒软件还带有数据恢复、防范黑客入侵、网络流量控制等功能&#xff0c;是计算机防御系统的重要组成部分。 那么&#xff0c;对于Mac电脑用户来说&#xff0c;哪款电脑杀毒软件更好呢&a…

虚幻引擎5 Gameplay框架(二)

Gameplay重要类及重要功能使用方法&#xff08;一&#xff09; 配置LOG类及PlayerController的网络机制 探索验证GamePlay重要函数、类的执行顺序与含义 我们定义自己的日志&#xff0c;专门建立一个存放自己日志的类&#xff0c;这个类继承自BlueprintFunctionLibrary 然后…

Prometheus 2: 一个专门评估其他语言模型的开源语言模型(续集)

普罗米修斯的续集来了。 专有的语言模型如 GPT-4 经常被用来评估来自各种语言模型的回应品质。然而,透明度、可控制性和可负担性等考虑强烈促使开发专门用于评估的开源语言模型。另一方面,现有的开源评估语言模型表现出关键的缺点:1) 它们给出的分数与人类给出的分数存在显著差…

[Android]四大组件简介

在 Android 开发中&#xff0c;“四大组件”&#xff08;Four Major Components&#xff09;是指构成 Android 应用程序的四种核心组件&#xff0c;它们通过各自的方式与系统交互&#xff0c;实现应用的多样功能。这些组件是&#xff1a;Activity、Service、Broadcast Receiver…

用 node 写一个命令行工具,全局安装可用

现在&#xff0c;不管是前端项目还是 node 项目&#xff0c;一般都会用 npm 做包管理工具&#xff0c;而 package.json 是其相关的配置信息。 对 node 项目而言&#xff0c;模块导出入口文件由 package.json 的 main 字段指定&#xff0c;而如果是要安装到命令行的工具&#x…

28 - 算术运算指令

---- 整理自B站UP主 踌躇月光 的视频 文章目录 1. ALU改进2. CPU 整体电路3. 程序4. 实验结果 1. ALU改进 此前的 ALU&#xff1a; 改进后的 ALU&#xff1a; 2. CPU 整体电路 3. 程序 # pin.pyMSR 1 MAR 2 MDR 3 RAM 4 IR 5 DST 6 SRC 7 A 8 B 9 C 10 D 11 DI 1…

在.NET架构的Winform项目中引入“异步编程”思想和技术

在.NET架构的Winform项目中引入“异步编程”思想和技术 一、异步编程引入&#xff08;1&#xff09;异步编程引入背景&#xff08;2&#xff09;异步编程程序控制流图&#xff08;3&#xff09;异步编程前置知识&#xff1a; 二、异步编程demo步骤1&#xff1a;步骤2&#xff1…