鸿蒙小案例-五子棋

news2025/2/28 6:38:20

鸿蒙小案例-五子棋

1.准备组件(组件布局)
2.下棋功能实现
3.机器人下棋功能实现
4.赢棋功能实现
5.附属功能实现

刚开始以为挺简单的,越写越…emo

因为代码有点多,所以这里就简单讲下逻辑,文末贴上代码

逻辑只是我个人想的,不代表只有这一种实现方式,有其他想法可以在下面留言

另外功能做的比较简单,有一些没实现,但是基本功能都有,大家可以自行优化


1.组件的准备

组件就比较简单,采用Canvas就可以,画出一个棋盘的布局

画布是一个300*300的,所以可下棋点位都可以计算出来

在这里插入图片描述


2.功能

1.前置状态校验


校验是否开始游戏,棋子颜色是否选择,没有选择给出弹窗提醒


2.校正触摸点的坐标

触摸点的坐标肯定不是精准的数字,要把它校正为符合棋盘规则的坐标

比如 53.666666666=》50,采用四舍五入方式


3.校验当前修正后的坐标点位是否有棋子

那么之前每一步的棋子要先加入一个全局变量,黑色和白色的还要再次单独区分并加入单独的变量

在绘制棋子


4.判断人工下棋完成后是否赢棋

因为我们的画布长宽都是固定的,所以每一个坐标点位都可以推断出来

在这里我们计算当前坐标横向,纵向,西北,东北四个方向,每个方向5种赢棋情况的坐标点位

每个方向的5种赢棋情况应为:

当前坐标分别处于第一位,第二位,第三位,第四位,第五位时,如下图

在这里插入图片描述

以上的情况已经包含了所有的赢棋情况

当所有坐标点位拿到后,判断每个方向的4个坐标点是否全部在已落子坐标数据变量中,如果有一个方向是,就赢,1个都没有那就继续下棋

(这点比较难理解,可以参考代码实现)


5.机器下棋

当走到这一步时肯定没有赢棋了,那么就该继续下棋了

首先需要获取到人工落子坐标周围的8个坐标点,结合实时更新的已落子坐标点位,拿到人工坐标周边的空余可下棋坐标点位,随机(这里是决定机器人智能程度的关键,我只做了最简单的)生成1个位置,绘制坐标

绘制完后,还要判断机器人的是否赢棋,调用方法即可

到这里功能基本都完了


6.小功能实现

开始游戏/重新开始:清理棋盘

白棋/黑棋:选中人工下棋的棋色

悔棋:结合已落子坐标后退两步

结束游戏:清理棋盘

认输:清理棋盘

demo写的比较简单,但鉴于时间关系还是有一些功能没实现,写在下面,有需要的可以自行优化

待完成功能:
1.判断赢棋的条件不精准:有时候(偶发)4个也会显示胜利
2.刚下完的棋子要给加亮处理
3.悔棋功能的书写
4.棋子最外边一层,不允许落子
5.赢棋后,需要加亮显示赢棋的那一条线
6.机器人的智能不高,需要判断对方3个或者双3的情况去堵它

针对第六点,大家可以接入AI大模型,实时对战更刺激

当然也可以改造成联网,真人对战的,那这里就要用到数据库了,每下一步棋都要同步到数据库,并且要同步到正在下棋的两个人那里,这个就看大家的精力了


完整代码如下:

import promptAction from '@ohos.promptAction';
@Entry
@Preview
@Component
struct Wuziqi {
  private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(new RenderingContextSettings(true))

  /**
   * 待完成功能:
   * 1,判断赢棋的条件不精准:有时候4个也会显示胜利
   * 2.刚下完的棋子要给加亮处理
   * 3.悔棋功能的书写
   * 4.棋子最外边一层,不允许落子
   * 5.赢棋后,需要加亮显示赢棋的那一条线
   * 6.AI的智能不高,需要判断对方3个或者双3的情况去堵它
   */
  //棋盘宽度
  qpWidth: number = 300
  //棋盘高度
  qpHeight: number = 300

  //白旗下棋坐标集合,悔棋使用
  @State
  hqzbList: qpzbClass[] = []
  //黑旗下棋坐标集合,悔棋使用
  @State
  bqzbList: qpzbClass[] = []
  //已经占用的坐标集合
  @State
  comzbList: qpzbClass[] = []
  //棋盘允许下棋的坐标点集合
  @State
  qpZbList: qpzbClass[] = []
  //是否开始游戏,游戏进行状态
  @State
  isStatus: boolean = false
  //当前用户选择的 棋色,''代表初始,还未选择颜色
  @State
  nowColor: Color.White | Color.Black | '' = ''
  //棋盘内网格线的颜色,黑色
  qpLineColor: string = Color.Black
  //角标坐标集合
  jbList: qpzbClass[] = [{ x: 60, y: 60 }, { x: 200, y: 60 }, { x: 60, y: 200 }, { x: 200, y: 200 }]
  //当前棋子的坐标
  @State
  zb: qpzbClass = { x: 0, y: 0 }

  //赢棋的常量
  isWinPD(tszb: qpzbClass[]) {
    let x: number = this.zb.x
    let y: number = this.zb.y
    //横向
    let conZbList1: qpzbClass[] = [{ x: x + 20, y: y }, { x: x + 40, y: y }, { x: x + 60, y: y }, { x: x + 80, y: y }]
    let conZbList2: qpzbClass[] = [{ x: x - 20, y: y }, { x: x + 20, y: y }, { x: x + 40, y: y }, { x: x + 60, y: y }]
    let conZbList3: qpzbClass[] = [{ x: x - 40, y: y }, { x: x - 20, y: y }, { x: x + 20, y: y }, { x: x + 40, y: y }]
    let conZbList4: qpzbClass[] = [{ x: x - 60, y: y }, { x: x - 40, y: y }, { x: x - 20, y: y }, { x: x + 20, y: y }]
    let conZbList5: qpzbClass[] = [{ x: x - 80, y: y }, { x: x - 60, y: y }, { x: x - 40, y: y }, { x: x - 20, y: y }]
    //竖向
    let conZbList6: qpzbClass[] = [{ x: x, y: y + 20 }, { x: x, y: y + 40 }, { x: x, y: y + 60 }, { x: x, y: y + 80 }]
    let conZbList7: qpzbClass[] = [{ x: x, y: y - 20 }, { x: x, y: y + 20 }, { x: x, y: y + 40 }, { x: x, y: y + 60 }]
    let conZbList8: qpzbClass[] = [{ x: x, y: y - 40 }, { x: x, y: y - 20 }, { x: x, y: y + 20 }, { x: x, y: y + 40 }]
    let conZbList9: qpzbClass[] = [{ x: x, y: y - 60 }, { x: x, y: y - 40 }, { x: x, y: y - 20 }, { x: x, y: y + 20 }]
    let conZbList10: qpzbClass[] = [{ x: x, y: y - 80 }, { x: x, y: y - 60 }, { x: x, y: y - 40 }, { x: x, y: y - 20 }]
    //西北
    let conZbList11: qpzbClass[] = [{ x: x + 20, y: y + 20 }, { x: x + 40, y: y + 40 }, { x: x + 60, y: y + 60 }, {
      x: x + 80,
      y: y + 80
    }]
    let conZbList12: qpzbClass[] = [{ x: x - 20, y: y - 20 }, { x: x + 20, y: y + 20 }, { x: x + 40, y: y + 40 }, {
      x: x + 60,
      y: y + 60
    }]
    let conZbList13: qpzbClass[] = [{ x: x - 40, y: y - 40 }, { x: x - 20, y: y - 20 }, { x: x + 20, y: y + 20 }, {
      x: x + 40,
      y: y + 40
    }]
    let conZbList14: qpzbClass[] = [{ x: x - 60, y: y - 60 }, { x: x - 40, y: y - 40 }, { x: x - 20, y: y - 20 }, {
      x: x + 20,
      y: y + 20
    }]
    let conZbList15: qpzbClass[] = [{ x: x - 80, y: y - 80 }, { x: x - 60, y: y - 60 }, { x: x - 40, y: y - 40 }, {
      x: x - 20,
      y: y - 20
    }]
    //东北
    let conZbList16: qpzbClass[] = [{ x: x - 20, y: y + 20 }, { x: x - 40, y: y + 40 }, { x: x - 60, y: y + 60 }, {
      x: x - 80,
      y: y + 80
    }]
    let conZbList17: qpzbClass[] = [{ x: x + 20, y: y - 20 }, { x: x - 20, y: y + 20 }, { x: x - 40, y: y + 40 }, {
      x: x - 60,
      y: y + 60
    }]
    let conZbList18: qpzbClass[] = [{ x: x + 40, y: y - 40 }, { x: x + 20, y: y - 20 }, { x: x - 20, y: y + 20 }, {
      x: x - 40,
      y: y + 40
    }]
    let conZbList19: qpzbClass[] = [{ x: x + 60, y: y - 60 }, { x: x + 40, y: y - 40 }, { x: x + 20, y: y - 20 }, {
      x: x - 20,
      y: y + 20
    }]
    let conZbList20: qpzbClass[] = [{ x: x + 80, y: y - 80 }, { x: x + 60, y: y - 60 }, { x: x + 40, y: y - 40 }, {
      x: x + 20,
      y: y + 20
    }]
    //获取这4位坐标是否全部存在 存在,即获胜,整个for循环直接停掉,结束,
    // AlertDialog.show({message:'tszb:'+JSON.stringify(tszb)+';conZbList1:'+JSON.stringify(conZbList1)})
    if (this.arr1Containarr2(tszb, conZbList1) || this.arr1Containarr2(tszb, conZbList2) ||
    this.arr1Containarr2(tszb, conZbList3) || this.arr1Containarr2(tszb, conZbList4)
    || this.arr1Containarr2(tszb, conZbList5) || this.arr1Containarr2(tszb, conZbList6)
    || this.arr1Containarr2(tszb, conZbList7) || this.arr1Containarr2(tszb, conZbList8)
    || this.arr1Containarr2(tszb, conZbList9) || this.arr1Containarr2(tszb, conZbList10)
    || this.arr1Containarr2(tszb, conZbList11) || this.arr1Containarr2(tszb, conZbList12)
    || this.arr1Containarr2(tszb, conZbList13) || this.arr1Containarr2(tszb, conZbList14)
    || this.arr1Containarr2(tszb, conZbList15) || this.arr1Containarr2(tszb, conZbList16)
    || this.arr1Containarr2(tszb, conZbList17) || this.arr1Containarr2(tszb, conZbList18)
    || this.arr1Containarr2(tszb, conZbList19) || this.arr1Containarr2(tszb, conZbList20)
    ) {
      return true
    }
    return false
  }
  //判断是否赢棋
  isWin(zb: qpzbClass, color: string) {
    //需要判断4个方向,每个方向5种情况的  赢棋情况
    //当前需要用到的颜色的棋子的坐标集合
    let tszb: qpzbClass[] = color === Color.White ? this.bqzbList : this.hqzbList
    if (this.isWinPD(tszb)) {
      AlertDialog.show({ message: color === Color.White ? '白棋胜利' : '黑棋胜利' })
      this.isStatus = false
      return true
    }
    return false
  }

  //判断1个数组是否全部存在另一个数组中
  arr1Containarr2(arr1: qpzbClass[], arr2: qpzbClass[]) {
    if (arr2.length > 1) {
      for (let i: number = 0; i < arr2.length; i++) {
        if (!this.arr1Containarr2(arr1, [arr2[i]])) {
          return false
        }
      }
    } else {
      for (let i: number = 0; i < arr1.length; i++) {
        if (JSON.stringify(arr1[i]) === JSON.stringify(arr2[0])) {
          return true
        }
      }
      return false
    }
    return true
  }
  //校验下棋的前置状态
  checkBeforeStatus() {
    //校验各项状态
    if (this.nowColor === '') {
      AlertDialog.show({ message: '请先选择棋色' })
      return false
    }
    if (!this.isStatus) {
      AlertDialog.show({ message: '未开始游戏' })
      return false
    }
    return true
  }
  //下棋操作
  running(qz: qpzbClass) {
      //计算触摸点的坐标点为 最近的可落子的坐标点
      qz = this.conuntNowZb(qz)
      this.zb = qz
      //校验当前坐标是否有棋子
      if (this.checkZb(qz)) {
        promptAction.showToast({ message: '点击无效' })
        return
      }
      //记录棋子的坐标,分别记录黑白色的
      this.nowColor === Color.White ? this.bqzbList.push(qz) : this.hqzbList.push(qz)
      this.drowQz(qz, this.nowColor)
      if (!this.isWin(qz, this.nowColor)) {
        //机器人下棋
        this.aiRunning(qz)
      }
  }
  //校验当前坐标是否有棋子
  checkZb(qz: qpzbClass) {
    let st: boolean = false
    this.comzbList.some(ev => {
      if (JSON.stringify(ev) === JSON.stringify(qz)) {
        st = true
        return true
      }
    })
    return st
  }
  //机器人下棋
  aiRunning(qz: qpzbClass) {
    //获取当前人工棋子周围可落子坐标点,需要去除已经落子的坐标
    let pZb: qpzbClass[] = this.countPeripheryZb(qz)
    let random: number = Math.floor(Math.random() * pZb.length)
    let p: qpzbClass = pZb[random]
    this.drowQz(p, this.nowColor === Color.White ? Color.Black : Color.White)
    this.zb = p
    if (!this.isWin(p, this.nowColor)) {
        this.nowColor === Color.White ? this.hqzbList.push(p) : this.bqzbList.push(p)
    }
  }
  //获取一个坐标的8个周边 坐标点
  getZbZb(qz: qpzbClass) {
    let x: number = qz.x
    let y: number = qz.y
    let pZb: qpzbClass[] = [{ x: x - 20, y: y }, { x: x + 20, y: y }, { x: x - 20, y: y - 20 }, { x: x, y: y - 20 },
      { x: x + 20, y: y - 20 }, { x: x - 20, y: y + 20 }, { x: x, y: y + 20 }, { x: x + 20, y: y + 20 }]
    return pZb
  }
  //获取当前人工棋子周围  可落子坐标点
  countPeripheryZb(qz: qpzbClass) {
    //固定写死的周边 坐标点
    let pZb: qpzbClass[] = this.getZbZb(qz)
    //校验位置是否有棋子
    let duplicates: qpzbClass[] = [...pZb]
    for (let i = duplicates.length - 1; i >= 0; i--) {
      // 检查当前A数组的子数组是否在B数组中存在
      let found = this.comzbList.some(subB => JSON.stringify(subB) === JSON.stringify(duplicates[i]));
      if (found) {
        duplicates.splice(i, 1);
      }
    }
    return duplicates
  }

  //计算触摸点的坐标点为 最近的可落子的坐标点
  conuntNowZb(qz: qpzbClass) {
    return { x: Math.round(Math.round(qz.x) / 20) * 20, y: Math.round(Math.round(qz.y) / 20) * 20 }
  }
  //绘制角标
  drowJb() {
    for (let index: number = 0; index < this.jbList.length; index++) {
      this.context.beginPath()
      let x: number = this.jbList[index].x
      let y: number = this.jbList[index].y
      this.context.arc(x, y, 4, 0, 10)
      this.context.strokeStyle = this.qpLineColor //角标边框颜色
      this.context.stroke()
      this.context.closePath()
    }
  }
  //绘制棋子
  drowQz(qz: qpzbClass, color: string) {
    this.context.beginPath()
    this.context.arc(qz.x, qz.y, 8, 0, 10)
    this.context.fillStyle = color
    this.context.fill() //填充颜色
    this.context.strokeStyle = Color.YELLOW//棋子边框颜色
    this.context.stroke()
    this.context.closePath()
    //记录已经占用的棋子位置
    this.comzbList.push(qz)
  }
  //计算棋盘内可落子的 坐标点
  countZb(i: number) {
    for (let i2 = 1; i2 <= 13; i2++) {
      this.qpZbList.push({ x: i2 * 20, y: i * 20 })
    }
  }
  //棋盘绘制
  qpCreate() {
    this.context.beginPath();
    //设置棋盘内网格线的颜色
    this.context.strokeStyle = this.qpLineColor
    this.context.fill()
    //横向棋线
    for (let i: number = 1; i <= 15; i++) {
      this.context.moveTo(0, i * 20);
      this.context.lineTo(this.qpWidth - 20, i * 20);
      this.context.stroke();
      this.countZb(i)
    }
    //纵向棋线
    for (let i: number = 1; i <= 15; i++) {
      this.context.moveTo(i * 20, 0);
      this.context.lineTo(i * 20, this.qpHeight - 20);
      this.context.stroke();
    }
    this.context.closePath();
    //设置角标
    this.drowJb()
  }
  //棋盘,棋子,清除
  clearQp() {
    this.hqzbList = []
    this.bqzbList = []
    this.comzbList = []
    this.context.clearRect(0, 0, this.qpWidth, this.qpHeight) //清理画布内绘画
    this.qpCreate() //重新绘制棋盘
  }

  @Styles
  buttonStyle_height20(){
    .height(20)
    .backgroundColor(Color.White)
  }

  @Styles
  buttonStyle_height35(){
    .height(35)
    .backgroundColor(Color.White)
  }

  @Styles
  rowPadding(){
    .padding({
      top: 20,
      bottom: 20
    })
  }

  build() {

    Column() {
      //上功能区
      Row({ space: 20 }) {
        Button('白棋')
          .buttonStyle_height20()
          .fontWeight(FontWeight.Bold)
          .fontSize(25)
          .fontColor(Color.Black)
          .onClick(() => {
            if (this.nowColor === '' || this.comzbList.length<1) {
              this.nowColor = Color.White
            }else{
              promptAction.showToast({message:'点击无效'})
            }
          })
          .backgroundColor(this.nowColor === Color.White ? Color.YELLOW : '')
        Button(this.nowColor!=='' && this.comzbList.length>1?'重新开始':'开始游戏')
          .buttonStyle_height35()
          .fontWeight(FontWeight.Bold)
          .fontSize(35)
          .fontColor(Color.Black)
          .onClick(() => {
            this.isStatus = true
            this.clearQp()
          })
        Button('黑棋')
          .buttonStyle_height20()
          .fontWeight(FontWeight.Bold)
          .fontSize(25)
          .fontColor(Color.Black)
          .onClick(() => {
            if (this.nowColor === '' || this.comzbList.length<1 ) {
              this.nowColor = Color.Black
            }else{
              promptAction.showToast({message:'点击无效'})
            }
          })
          .backgroundColor(this.nowColor === Color.Black ? Color.YELLOW : '')
      }.justifyContent(FlexAlign.SpaceBetween).height(50)
      //棋盘位置
      Row() {
        Column() {
          Canvas(this.context) {

          }
          .onTouch((event: TouchEvent) => {
            //按下时触发,就近坐标点,绘制一个圆块
            if (event.type === TouchType.Up) {
              if (this.checkBeforeStatus()) {
                this.running({ x: event.touches[0].x, y: event.touches[0].y })
              }
            }
          })
          .onReady(() => {
            //设置绘画边框宽度
            this.context.lineWidth = 1
            this.qpCreate()
          })
          .backgroundColor(Color.Yuanm)
          .margin({
            top: 15,
            bottom: 15
          })
          .border({
            width: 1,
            color: Color.Black
          })
        }
        .width(this.qpWidth)
        .height(this.qpHeight)
        .border({
          width: 5,
          color: Color.Black,
          radius: 1,
          style: BorderStyle.Solid
        })
        .padding({
          left: 15,
          right: 15
        })
      }
      .justifyContent(FlexAlign.Center)
      .alignItems(VerticalAlign.Center)
      .width('100%')
      .height(450)
      .rowPadding()
      .backgroundColor(Color.Yuanm)
      //下功能区
      Row({ space: 20 }) {
        Button('悔棋')
          .buttonStyle_height20()
          .fontWeight(FontWeight.Bold)
          .fontSize(25)
          .fontColor(Color.Black)
          .onClick(() => {
            //悔棋操作
            AlertDialog.show({message:'功能待开发'})
          })
        Button('结束游戏')
          .buttonStyle_height35()
          .fontWeight(FontWeight.Bold)
          .fontSize(35)
          .fontColor(Color.Black)
          .onClick(() => {
            //结束游戏
            this.isStatus = false
            //清理棋盘,重新绘制棋盘
            this.clearQp()
          })
        Button('认输')
          .buttonStyle_height20()
          .fontWeight(FontWeight.Bold)
          .fontSize(25)
          .fontColor(Color.Black)
          .onClick(() => {
            //认输
            this.isStatus = false
            //清理棋盘,重新绘制棋盘
            this.clearQp()
          })
      }.justifyContent(FlexAlign.SpaceBetween).height(50)
    }
    .width('100%')
    .height('100%')
    .rowPadding()
  }
}

class qpzbClass {
  x: number = 0
  y: number = 0
}


//颜色枚举
enum Color {
  Black = '#000000',
  White = '#FFFFFF',
  Yuanm = 'RGB(245,173,96)',
  YELLOW = 'RGB(218, 165, 32)'
}

代码可能稍微有点乱,没有时间去做精细的优化,本来就是个小demo,凑合着用吧-

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Learn HTML in 1 hour

website address https://www.youtube.com/watch?vHD13eq_Pmp8 excerpt All right, what’s going on? everybody. It’s your Bro, hope you’re doing well, and in this video I’m going to help you started with html; so sit back, relax and enjoy the show. If y…

ABAP 导入Excel表示例程序

目录 ABAP 导入excel示例程序创建程序使用的结构上传下载模板 ABAP 导入excel示例程序 批量导入程序&#xff0c;需要使用到导入模板&#xff0c;首先需要创建程序&#xff0c;之后是需要创建excel导入模板&#xff0c;并且需要将excel导入模板上传到SAP系统里面&#xff0c;之…

【linux】查看openssl程序的安装情况

【linux】查看openssl程序的安装情况 1、查看安装包信息 $ rpm -qa |grep openssl 2、安装路径 $ rpm -ql openssl $ rpm -ql openssl-libs $ rpm -ql openssl-devel 3、相关文件和目录 /usr/bin/openssl /usr/include/openssl /usr/lib64/libssl.so.* /usr/lib64/libcrypto…

idea自动导包。已经无用导包自动移除

1.setting中勾选这两项&#xff0c;然后点击apply即可

【DDD】学习笔记-薪资管理系统的场景驱动设计

场景驱动设计的起点是领域场景&#xff0c;它不一定需要与事件风暴结合&#xff0c;只要识别并确定了领域场景&#xff0c;就可以进行任务分解。每个分解出来的子任务都可以视为是职责。分配职责时&#xff0c;场景驱动设计规定了履行职责的角色构造型&#xff0c;其中&#xf…

MongoDB 权限管理

文章目录 前言1. 权限控制1.1 MongoDB 默认角色1.1.1 读写角色1.1.2 管理角色1.1.3 其他角色1.1.4 超级用户角色 1.2 用户管理1.2.1 查看用户1.2.2 创建新用户1.2.3 调整角色1.2.4 删除用户1.2.4 修改密码 前言 上一篇 《MongoDB 单机安装部署》 文章中&#xff0c;为 MongoDB…

[SwiftUI]启动页LaunchScreen.storyboard中适配状态栏加安全区域的高度

如下图&#xff0c;我有一个需求。在启动页&#xff08;LaunchScreen.storyboard&#xff09;和引导页&#xff08;GuideView&#xff09;的黑色背景上&#xff0c;使用了同一张正方形图片。要求从启动页切换到引导页时&#xff0c;这两张相同的图片的过渡要无缝衔接&#xff0…

三防加固平板在房地产行业的应用|亿道三防onerugged

近期&#xff0c;有一款引人注目的解决方案——亿道三防onerugged平板电脑&#xff0c;它以其出色的性能和多功能的设计&#xff0c;为房地产行业带来了全新的应用体验。 首先&#xff0c;亿道三防onerugged平板电脑的NFC功能在小区业主身份验证中发挥着重要作用。传统的身份验…

Spring Boot项目中TaskDecorator的应用实践

一、前言 TaskDecorator是一个执行回调方法的装饰器&#xff0c;主要应用于传递上下文&#xff0c;或者提供任务的监控/统计信息&#xff0c;可以用于处理子线程与主线程间数据传递的问题。 二、开发示例 1.自定义TaskDecorator import org.springframework.core.task.Task…

小程序--模板语法

一、插值{{}}语法 1、内容绑定 <view>{{iptValue}}</view> 2、属性绑定 <switch checked"{{true}}" /> Page({data: {iptValue: 123} }) 二、简易双向数据绑定 model:value&#xff1a;支持双向数据绑定 注&#xff1a;仅input和textarea支持&a…

Linux(五)__系统管理

介绍 通常&#xff0c; Windows 中使用"任务管理器"主要有 3 个目的&#xff1a; 利用"应用程序"和"进程"标签来査看系统中到底运行了哪些程序和进程&#xff1b;利用"性能"和"用户"标签来判断服务器的健康状态&#xff1…

MySQL锁相关总结|悲观锁、乐观锁、读锁、写锁、表锁、行锁、页面锁、间隙锁、临键锁

MySQL锁总体结构 MySQL 的锁上可以分成三类:总体、类型、粒度。 总体上分成两种:乐观锁和悲观锁类型上也是两种:读锁和写锁锁的粒度上可以分成五种:表锁,行锁,页面锁,间隙锁,临键锁下面我们就来详细讲一下这些锁 1. 悲观锁 悲观锁对于数据库中数据的读写持悲观态度,即…

无人机的视频图传技术有哪些?

在操控无人机时&#xff0c;视频图传技术显得尤为关键。通过这项技术&#xff0c;无人机的摄像头所捕捉的画面能实时回传至遥控器&#xff0c;使操作者全面掌握无人机的拍摄情况。同时&#xff0c;无人机图传技术也是衡量无人机性能的重要标准&#xff0c;它关乎飞行距离与时间…

shapely 笔记 voronoi图

Voronoi 图是一种将平面分割成区域的方法&#xff0c;每个区域包含一个输入点&#xff0c;任何在该区域内的点都比其他输入点更接近该区域的输入点 1 基本使用方法 shapely.ops.voronoi_diagram(geom, envelopeNone, tolerance0.0, edgesFalse) 2 参数说明 geom任何几何类型…

算法——数值算法——牛顿迭代法

目录 牛顿迭代法 一、1021: [编程入门]迭代法求平方根 牛顿迭代法 迭代法&#xff08;Iteration&#xff09;是一种通过反复递推计算来逼近解的方法。而牛顿迭代法&#xff08;Newtons method&#xff09;则是一种特定的迭代法&#xff0c;用于求解方程或函数的根、最小值、最…

Word 文档中的图片另存为 .jpg 格式图片

Word 文档中的图片另存为 .jpg 格式图片 1. Office 按钮 -> 另存为2. 筛选过的网页 (*.htm;*.html)3. 查看生成文件夹References 1. Office 按钮 -> 另存为 2. 筛选过的网页 (*.htm;*.html) ​​​ 3. 查看生成文件夹 References [1] Yongqiang Cheng, https://yongq…

WEB APIs (3)

事件对象 事件对象有事件触发时的相关信息&#xff0c;如点击事件中事件对象储存了鼠标点在哪个位置的信息 场景&#xff1a; 用户按下了哪个键&#xff0c;按下回车键可以发布新闻 鼠标点击了哪个元素&#xff0c;从而做哪些操作 参数e为事件对象 常用属性 type 获取当前…

游戏行业洞察:分布式开源爬虫项目在数据采集与分析中的应用案例介绍

前言 我在领导一个为游戏行业巨头提供数据采集服务的项目中&#xff0c;我们面临着实时数据需求和大规模数据处理的挑战。我们构建了一个基于开源分布式爬虫技术的自动化平台&#xff0c;实现了高效、准确的数据采集。通过自然语言处理技术&#xff0c;我们确保了数据的质量和…

Vue封装全局公共方法

有的时候,我们需要在多个组件里调用一个公共方法,这样我们就能将这个方法封装成全局的公共方法。 我们先在src下的assets里新建一个js文件夹,然后建一个common.js的文件,如下图所示: 然后在common.js里写我们的公共方法,比如这里我们写了一个testLink的方法,然后在main…

二叉树OJ题(2)——二叉树的四种遍历

前序 -> 深度优先遍历dfs 层序 -> 广度优先遍历bfs 6 二叉树的前序遍历 OJ链接 思路分析 开辟一个数组&#xff0c;然后把前序遍历树的顺序放入数组即可。 把根的val放入数组第一个元素接着放入左右&#xff08;递归下去&#xff09; 代码实现 int TreeSize(struct Tr…