Vue2模拟俄罗斯方块小游戏

news2024/11/25 16:57:38

目录

一、效果展示

二、代码分享

三、原理分析

3.1、界面搭建

3.2、方块创建

3.3、方块旋转

3.4、方块移动

3.5、移动判断

3.6、下落判断与清除

3.7、得分计算

一、效果展示

二、代码分享

<template>
  <div class="game">
    <div class="game-div">
      <div class="game-min">
        <div class="row" v-for="(row, i) in frame" :key="i">
          <p
            class="element"
            v-for="(col, j) in row"
            :key="j"
            :style="{ background: col.bg }"
          ></p>
        </div>
      </div>
      <!-- 小屏幕 -->
      <div class="right-div">
        <div class="ass">
          <div class="row" v-for="(row, i) in ass" :key="i">
            <p
              class="element"
              v-for="(col, j) in row"
              :key="j"
              :style="{ background: col.bg }"
            ></p>
          </div>
        </div>
        <!-- 分数计算 -->
        <div class="score-div">
          <div>
            <p>
              <span>得分:</span>&emsp;<span style="color: red">{{
                score
              }}</span>
            </p>
          </div>
          <div>
            <p>
              <span>等级:</span>&emsp;<span style="color: red">{{
                level
              }}</span>
            </p>
          </div>
          <div>
            <p>
              <span>消除:</span>&emsp;<span style="color: red">{{
                times
              }}</span>
            </p>
          </div>
          <div class="ztks" @click="stopGame">暂停/开始</div>
        </div>
      </div>
    </div>
    <!-- 控制台 -->
    <div class="control">
      <p @click="change1">变换</p>
      <div class="control-center">
        <div @click="moveLeft">向左</div>
        <div @click="moveRight">向右</div>
      </div>
      <p @click="moveDown">向下</p>
    </div>
  </div>
</template>

<script>
import { color, blockMod, transition } from "@/utils/ykdata.js";
export default {
  data() {
    return {
      row: 20, //行
      col: 10, //列
      frame: [], //界面
      ass: [], //副屏幕
      bg: "#eee",
      block: [], //基本方块集合
      now: { b: 0, c: 0 }, //当前方块以及其旋转角度
      next: { b: 0, c: 0 }, //下一个方块以及其旋转角度
      nowBlock: [], //当前形状数据
      nextBlock: [], //下一个形状数据
      xz: 0, //当前旋转角度
      timer: "", //自动下落
      speed: 800, //速度
      score: 0, //得分
      level: 1, //等级
      times: 0, //消除次数
      stop: true, //是否停止
      removeRow: [], //消除的行记录
    };
  },
  mounted() {
    this.gameFrame();
    this.getBlock(0);
    this.getNext();
    this.init();
  },
  methods: {
    // 游戏框架
    gameFrame() {
      //主屏幕
      for (let i = 0; i < this.row; i++) {
        let a = [];
        for (let j = 0; j < this.col; j++) {
          let b = {
            data: 0,
            bg: this.bg,
          };
          a.push(b);
        }
        this.frame.push(a);
      }
      //副屏幕
      for (let i = 0; i < 4; i++) {
        let a = [];
        for (let j = 0; j < 4; j++) {
          let b = {
            data: 0,
            bg: this.bg,
          };
          a.push(b);
        }
        this.ass.push(a);
      }
      // 模拟格子被占用
      // this.frame[4][4].bg = "#00aaee";
      // this.frame[4][4].data = 1;
    },
    // 渲染方块
    getBlock(e) {
      this.block = blockMod(color[e]);
    },
    // 下一个形状
    async getNext() {
      // 随机获取形状
      this.next.b = Math.floor(Math.random() * this.block.length);
      this.next.c = Math.floor(Math.random() * 4);
    },
    // 渲染当前形状
    init() {
      // 获取到下一个形状数据
      this.now = JSON.parse(JSON.stringify(this.next));
      this.xz = this.now.c;
      // 当前形状数据
      this.nowBlock = JSON.parse(JSON.stringify(this.block[this.now.b]));
      //   渲染形状数据
      //   let c = this.nowBlock.site;
      //   for (let i = 0; i < c.length; i += 2) {
      //     this.frame[c[i]][c[i + 1]].bg = this.nowBlock.color;
      //   }
      this.renderBlock(this.nowBlock, this.frame, 1);
      // 旋转
      if (this.now.c > 0) {
        for (let i = 0; i < this.now.c; i++) {
          this.change(this.nowBlock, this.frame, this.now, i);
        }
      }
      this.getNext().then(() => {
        if (this.nextBlock.site) {
          this.renderBlock(this.nextBlock, this.ass, 0);
        }
        //   下一个形状
        this.nextBlock = JSON.parse(JSON.stringify(this.block[this.next.b]));
        this.renderBlock(this.nextBlock, this.ass, 1);
        // 旋转
        if (this.next.c > 0) {
          for (let i = 0; i < this.next.c; i++) {
            this.change(this.nextBlock, this.ass, this.next, i);
          }
        }
      });
    },
    // 渲染形状
    // b:方块,d:位置,n:0擦除,1生成,2确定落到最下层
    renderBlock(b, d, n) {
      let c = b.site;
      if (n == 0) {
        for (let i = 0; i < c.length; i += 2) {
          d[c[i]][c[i + 1]].bg = this.bg; //0擦除
        }
      } else if (n == 1) {
        for (let i = 0; i < c.length; i += 2) {
          d[c[i]][c[i + 1]].bg = b.color; //1生成
        }
      } else if (n == 2) {
        for (let i = 0; i < c.length; i += 2) {
          d[c[i]][c[i + 1]].data = 1; //2确定落到最下层
        }
      }
    },
    // 旋转 b:当前方块   d:渲染的位置   z:渲染的对象现在还是下一个  xz:当前旋转角度
    change(b, d, z, xz) {
      this.renderBlock(b, d, 0); //先清空再旋转
      // 记录第一块位置
      const x = b.site[0];
      const y = b.site[1];
      for (let i = 0; i < b.site.length; i += 2) {
        let a = b.site[i];
        b.site[i] = b.site[i + 1] - y + x + transition[z.b][xz].x;
        b.site[i + 1] = -(a - x) + y + transition[z.b][xz].y;
      }
      xz++;
      if (xz == 4) {
        xz = 0;
      }
      this.renderBlock(b, d, 1);
    },
    // 向下移动
    moveDown() {
      if (this.canMove(3)) {
        // 先清空
        this.renderBlock(this.nowBlock, this.frame, 0);
        for (let i = 0; i < this.nowBlock.site.length; i += 2) {
          // 向下移动一位
          this.nowBlock.site[i]++;
        }
        this.renderBlock(this.nowBlock, this.frame, 1); //再渲染数据
      } else {
        // 已经不能下落了
        this.renderBlock(this.nowBlock, this.frame, 2);
        // 判断是否可以消除
        this.removeBlock();
      }
    },
    // 向左移动
    moveLeft() {
      if (this.canMove(2)) {
        // 先清空
        this.renderBlock(this.nowBlock, this.frame, 0);
        for (let i = 0; i < this.nowBlock.site.length; i += 2) {
          // 向左移动一位
          this.nowBlock.site[i + 1]--;
        }
        this.renderBlock(this.nowBlock, this.frame, 1); //再渲染数据
      }
    },
    // 向右移动
    moveRight() {
      if (this.canMove(1)) {
        this.renderBlock(this.nowBlock, this.frame, 0);
        for (let i = 0; i < this.nowBlock.site.length; i += 2) {
          this.nowBlock.site[i + 1]++;
        }
        this.renderBlock(this.nowBlock, this.frame, 1); //再渲染数据
      }
    },
    // 是否可移动判断
    // 预判能否移动或变化   e:1右移  2左移  3下移  4变化
    canMove(e) {
      let c = this.nowBlock.site;
      let d = 0;
      switch (e) {
        case 1:
          for (let i = 0; i < c.length; i += 2) {
            if (c[i + 1] >= this.col - 1) {
              return false;
            }
            // 判断下一个位置是否被占用
            d += this.frame[c[i]][c[i + 1] + 1].data;
          }
          if (d > 0) {
            return false;
          }
          break;
        case 2:
          for (let i = 0; i < c.length; i += 2) {
            if (c[i + 1] <= 0) {
              return false;
            }
            // 判断下一个位置是否被占用
            d += this.frame[c[i]][c[i + 1] - 1].data;
          }
          if (d > 0) {
            return false;
          }
          break;
        case 3:
          for (let i = 0; i < c.length; i += 2) {
            if (c[i] >= this.row - 1) {
              return false;
            }
            // 判断下一个位置是否被占用(防穿透)
            d += this.frame[c[i] + 1][c[i + 1]].data;
          }
          if (d > 0) {
            return false;
          }
          break;
        // case 4:
        //   for (let i = 0; i < c.length; i += 2) {
        //     if (c[i + 1] >= this.col - 1) {
        //       return false;
        //     }
        //   }
        //   break;
      }
      return true;
    },
    // 下落时旋转
    // 旋转 b:当前方块  xz:当前旋转角度
    change1() {
      const b = JSON.parse(JSON.stringify(this.nowBlock));
      // 记录第一块位置
      const x = b.site[0];
      const y = b.site[1];
      let n = true;
      for (let i = 0; i < b.site.length; i += 2) {
        let a = b.site[i];
        b.site[i] = b.site[i + 1] - y + x + transition[this.now.b][this.xz].x;
        b.site[i + 1] = -(a - x) + y + transition[this.now.b][this.xz].y;
        // 判断旋转后该点是否合理
        if (
          b.site[i + 1] < 0 ||
          b.site[i + 1] >= this.col ||
          b.site[i] >= this.row ||
          this.frame[b.site[i]][b.site[i + 1]].data > 0
        ) {
          n = false;
        }
      }
      // 符合条件
      if (n) {
        this.renderBlock(this.nowBlock, this.frame, 0); //先清空
        this.xz++;
        if (this.xz == 4) {
          this.xz = 0;
        }
        this.nowBlock = b;
        this.renderBlock(this.nowBlock, this.frame, 1); //再旋转
      }
    },
    // 到底部:确定位置不能再动,保证上面其他方块下落时不会将它穿透
    // 自动下落
    autoMoveDown() {
      this.timer = setInterval(() => {
        this.moveDown();
      }, this.speed);
    },
    // 开始与暂停
    stopGame() {
      this.stop = !this.stop;
      if (this.stop) {
        clearInterval(this.timer);
      } else {
        this.autoMoveDown();
      }
    },
    // 判断是否可以消除
    removeBlock() {
      // 遍历整个界面
      for (let i = 0; i < this.row; i++) {
        let a = 0;
        for (let j = 0; j < this.col; j++) {
          if (this.frame[i][j].data == 1) {
            a++;
          }
        }
        if (a == this.col) {
          // 说明该行已经占满可以消除
          this.removeRow.push(i);
        }
      }
      // 获取是否可以消除行
      if (this.removeRow.length > 0) {
        let l = this.removeRow;
        for (let i = 0; i < l.length; i++) {
          let j = 0;
          let timer = setInterval(() => {
            this.frame[l[i]][j] = { bg: this.bg, data: 0 };
            j++;
            if (j == this.col) {
              clearInterval(timer);
            }
          }, 20);
        }
        setTimeout(() => {
          // 上面方块下移,从下往上判断
          for (let i = this.row - 1; i >= 0; i--) {
            let a = 0;
            for (let j = 0; j < l.length; j++) {
              if (l[j] > i) {
                a++;
              }
            }
            if (a > 0) {
              for (let k = 0; k < this.col; k++) {
                if (this.frame[i][k].data == 1) {
                  // 先向下移动
                  this.frame[i + a][k] = this.frame[i][k];
                  // 再清除当前
                  this.frame[i][k] = { bg: this.bg, data: 0 };
                }
              }
            }
          }
          this.removeRow = []; //清除行记录
          // 生成下一个
          this.init();
        }, 20 * this.col);
        // 数据处理
        // 消除次数+1
        this.times++;
        // 等级向下取整+1
        let lev =  Math.floor(this.times / 10) + 1;
        if (lev > this.level) {
          this.level = lev;
          // 速度
          if (this.level < 21) {
            // 20级以内做减法
            this.speed = 800 - (this.level - 1) * 40;
          } else {
            this.speed = 30;
          }
          // 清除当前下落
          clearInterval(this.timer);
          // 加速
          this.autoMoveDown();
        }
        this.level = this.times;
        // 分数消除一行100,两行300,三行600,四行1000
        this.score += ((l.length * (l.length + 1)) / 2) * 100 * this.level;
      } else {
        this.init();
      }
    },
  },
};
</script>

<style lang='less' scoped>
.game {
  .game-div {
    display: flex;
    .game-min {
      .row {
        display: flex;
        padding-top: 2px;
        .element {
          width: 20px;
          height: 20px;
          padding: 0;
          margin: 0 2px 0 0;
        }
      }
    }
    .right-div {
      padding-left: 20px;
      .ass {
        .row {
          display: flex;
          padding-top: 2px;
          .element {
            width: 20px;
            height: 20px;
            padding: 0;
            margin: 0 2px 0 0;
          }
        }
      }
      .score-div {
        div {
          height: 20px;
          line-height: 20px;
        }
        .ztks {
          width: 100px;
          height: 40px;
          margin-bottom: 10px;
          background-color: palevioletred;
          text-align: center;
          line-height: 40px;
        }
      }
    }
  }
  .control {
    width: 220px;
    p {
      width: 220px;
      height: 40px;
      text-align: center;
      line-height: 40px;
      background-color: #B940EF;
      margin-bottom: 20px;
    }
    .control-center {
      align-items: center;
      display: flex;
      justify-content: space-between;
      margin-bottom: 20px;
      div {
        width: 90px;
        height: 40px;
        text-align: center;
        line-height: 40px;
        background-color: #B940EF;
      }
    }
  }
}
</style>

 工具函数:

//渐变色
export const color = [
  [
    'linear-gradient(180deg, #FFA7EB 0%, #F026A8 100%)',
    'linear-gradient(180deg, #DFA1FF 0%, #9A36F0 100%)',
    'linear-gradient(180deg, #9EAAFF 0%, #3846F4 100%)',
    'linear-gradient(180deg, #7BE7FF 2%, #1E85E2 100%)',
    'linear-gradient(180deg, #89FED8 0%, #18C997 100%)',
    'linear-gradient(180deg, #FFED48 0%, #FD9E16 100%)',
    'linear-gradient(180deg, #FFBA8D 1%, #EB6423 100%)',
  ],
  [
    '#2B7AF5','#2B9DF5','#79CFFF','#1B67DD','#4F94FF','#2180F2','#3FD0FF',
  ],
];

//7种方块元素
export const blockMod = (color) => {
  let a = {
    site: [0, 1, 0, 2, 1, 2, 2, 2],
    color: color[0],
  };
  let b = {
    site: [0, 1, 1, 1, 1, 2, 2, 2],
    color: color[1],
  };
  let c = {
    site: [1, 1, 1, 2, 2, 1, 2, 2],
    color: color[2],
  };
  let d = {
    site: [1, 0, 1, 1, 1, 2, 1, 3],
    color: color[3],
  };
  let e = {
    site: [0, 2, 1, 1, 1, 2, 2, 1],
    color: color[4],
  };
  let f = {
    site: [0, 1, 0, 2, 1, 1, 2, 1],
    color: color[5],
  };
  let g = {
    site: [1, 1, 2, 0, 2, 1, 2, 2],
    color: color[6],
  };
  return ([a, b, c, d, e, f, g]);
};

//旋转规则
export const transition = [
  [
    {
      x: 1, y: 1,
    }, {
      x: 1, y: 0,
    }, {
      x: 0, y: -2,
    }, {
      x: -2, y: 1,
    }
  ],
  [
    {
      x: 1, y: 1,
    }, {
      x: 1, y: 0,
    }, {
      x: 0, y: -2,
    }, {
      x: -2, y: 1,
    }
  ],
  [
    {
      x: 0, y: 1,
    }, {
      x: 1, y: 0,
    }, {
      x: 0, y: -1,
    }, {
      x: -1, y: 0,
    }
  ],
  [
    {
      x: -1, y: 2,
    }, {
      x: 1, y: 1,
    }, {
      x: 2, y: -1,
    }, {
      x: -2, y: -2,
    }
  ],
  [
    {
      x: 2, y: 0,
    }, {
      x: 0, y: -1,
    }, {
      x: -1, y: -1,
    }, {
      x: -1, y: 2,
    }
  ],
  [
    {
      x: 1, y: 1,
    }, {
      x: 1, y: 0,
    }, {
      x: 0, y: -2,
    }, {
      x: -2, y: 1,
    }
  ],
  [
    {
      x: 0, y: 0,
    }, {
      x: 1, y: 0,
    }, {
      x: -1, y: 0,
    }, {
      x: 0, y: 0,
    }
  ],
]

三、原理分析

3.1、界面搭建

  主界面的20X10,类似贪吃蛇,副界面的随机方块,则是4x4,都是双重for循环。初始化的时候调用gameFrame()即可。

3.2、方块创建

  主要说明一下随机生成的方块,每个都是有4个小方格组成,组成了7种基本样式,在自身基础上进行四个方向的旋转,就是下落的所有可能性。参考坐标如右图所示:

3.3、方块旋转

  旋转 b:当前方块   d:渲染的位置   z:渲染的对象现在还是下一个  xz:当前旋转角度,在change(b, d, z, xz)里进行旋转,这里用到了工具函数里的transition,旋转核心就是找到一个固定的点,看出x和Y坐标的变化,即(x=y,y=-x),加上工具函数里的blockMod,就可以依次生成对应的下落方块。

3.4、方块移动

  在生成一个的同时,要考虑的下一个方块的生成与随机旋转,所以 b:方块,d:位置,n:0擦除,1生成,2确定落到最下层,在renderBlock(b, d, n)方法里进行形状的渲染。

  我们有三个方向:moveDown()、moveLeft()、moveRight(),这里的原理和贪吃蛇基本类似,不过在向下移动时考虑因素较多,下落时旋转要考虑 b:当前方块  xz:当前旋转角度change1()方法,为了保持原来的形状,所以多处用到了深拷贝。

3.5、移动判断

  预判能否移动或变化   e:1右移  2左移  3下移  4变化,在 canMove(e)方法里实现。主要是判断下一个位置是否被占用,到了底部:确定位置不能再动,保证上面其他方块下落时不会将它穿透,是要考虑的问题。

3.6、下落判断与清除

  判断是否可以消除:遍历整个界面,当一行被占满,将该行的方块依次删去,并保留上面附着的方块位置不变,形成“被吞噬”的现象。在消掉满了的一行时,要让上面方块下移,从下往上判断,再清除当前方块,避免冲突。

3.7、得分计算


  分数消除一行100,两行300,三行600,四行1000,消掉一行,带分数增加,以此同时,随着等级的增加,速度也会越来越快,难度增加。

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

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

相关文章

调整IoTDB堆内存

最关键的是 MAX_DIRECT_MEMORY_SIZE &#xff0c;他等于MAX_HEAP_SIZE变量。 再往上翻又等于 max_heap_size_in_mb M大小 继续上翻 system_memory_in_mb 很明显就是系统内存&#xff0c;单位是M quarter_ 四分之一内存&#xff0c; half_ 一半内存。 假设物理内存为8G&a…

PMP证书含金量如何?到底有啥用处?

01PMP是什么&#xff1f; | PMP是指项目管理专业人士资格认证。 | 美国项目管理协会&#xff08;PMI&#xff09;举办的项目管理专业人员&#xff08;PMP&#xff09;认证考试。 | 是目前项目管理领域含金量很高的认证。 国内很多媒体也把PMP称为继MBA、MPA之后的三大金字招…

KW 新闻 | KaiwuDB 发布智慧矿山解决方案

5月21日&#xff0c;天津第七届世界智能大会&#xff08;WIC&#xff09;圆满落幕。作为智能领域的国家级盛会&#xff0c;WIC 汇聚了全球知名院士、顶级学者、产业领袖分享先进技术和实践经验&#xff0c;推进智能技术创新合作。KaiwuDB 受邀出席大会并正式发布智慧矿山解决方…

软件测试现状以及行业分析

大家都知道最近 ChatGPT 爆火&#xff0c;国外巨头争相宣布自己的相关计划&#xff0c;国内有点实力的企业也在亦步亦趋地跟进。不出意料的是&#xff0c;关于测试职业要被淘汰的话题又&#xff08;为什么要说又&#xff1f;&#xff09;在扎堆出现&#xff0c;内容跟之前还是大…

“大模型+小模型”新纪元开启,AI基础软件定义AI未来

5月30日&#xff0c;由中国信息通信研究院、浙江省经济和信息化厅、杭州市人民政府、中国人工智能产业发展联盟主办的“杭州通用人工智能论坛”盛大召开。杭州市人民政府党组成员、副市长孙旭东&#xff0c;浙江省经信厅总工程师李永伟&#xff0c;中国信息通信研究院党委副书记…

检索项目中冗余的图片

说在前面 平时在项目中我们会使用到一些图片&#xff0c;很多时候我们会直接将图片打包到项目中去&#xff0c;随着项目的更新迭代&#xff0c;我们可能会删除一些图片的引用&#xff0c;但没将图片源文件删除&#xff0c;这个时候没有被引用到的图片就会成为冗余的文件&#…

一位十年测试的修炼之路,希望能帮你点清现实

对于刚进入软件测试工作岗位的新人&#xff0c;如何快速、健康的在职业道路上成长&#xff0c;作者谈了几点自己看法&#xff1a; 1、兴趣是最好的老师 对于软件测试工作&#xff0c;通常是比较枯燥的&#xff0c;如果没有兴趣很难做到持久。 我最近参与了一个软件测试项目&a…

Android AIDL跨进程通信

一、前言 什么是AIDL&#xff1f;AIDL用来做什么的&#xff1f;怎么使用AIDL&#xff1f; AIDL是Android的一种接口定义语言&#xff0c;语法跟java接口定义类似&#xff0c;文件格式为 .aidl 非 .java 。AIDL主要是用来实现跨进程通信&#xff0c;AIDL的本质也是通过Binder机…

【集群】Haproxy搭建Web群集

文章目录 一、Haproxy 相关概念1. Haproxy 的概述2. Haproxy 的主要特性3. 常见的 Web 集群调度器4. 常见的应用分析4.1 LVS 应用4.2 Haproxy 应用4.3 LVS、Nginx、Haproxy的区别 5. Haproxy 调度算法原理5.1 roundrobin5.2 static-rr5.3 leastconn5.4 source5.5 uri5.6 url_pa…

【1 TypeScript - TypeScript语法的类型】

1 认识TypeScript 主要是为了解决类型检查的痛点.是拥有类型的JavaScript超集,虽然编写的是Typescript,但是最终仍然会编译成JavaScript代码. 2 TypeScript的运行环境 使用ts-node 3 变量的声明 变量的类型推导&#xff08;推断&#xff09; 4 JavaScript类型 – Array类…

ThinkPHP5源码阅读-类的自动加载register与autoload的实现

文章目录 前言如何下载ThinkPHP5源码关于自动加载类类的准备进入base.phpLoader::register() 注册自动加载函数对composer 的支持对think和trait的支持对extend目录的支持 类的加载autoload方法class_alias的定义和使用findFile 查找类 作业&#xff1a;自定义一个可以被自动类…

Java设计模式—责任链模式(Chin of Responsibility)

目录 前言 一、责任链模式的简介 二、责任链模式的概念 三、责任链模式的作用 四、责任链模式的优、缺点 1.责任链模式的优点 2.责任链模式的缺点 五、责任链模式的应用场景 六、代码案例 UML类图 1.定义一个请求枚举类 2.定义一个请求类 3.定义一个抽象处理接口 4、…

TS中any与unknown详解,示例

文章目录 前言一、一个示例二、示例目的1、功能描述2、主要区别3、代码实现 总结 前言 本片文章主要是在写ts时遇到不知道类型&#xff0c;很容易就想到用any可以解决一切&#xff0c;但这样写并不好。所以今天就总结学习一下&#xff0c;比较好的处理任意类型的unknown。 一、…

2023年最新网络安全入门指南,保姆级教程!啃完这篇就够了

一、网络安全学习的误区 1.不要试图以编程为基础去学习网络安全 不要以编程为基础再开始学习网络安全&#xff0c;一般来说&#xff0c;学习编程不但学习周期长&#xff0c;且过渡到网络安全用到编程的用到的编程的关键点不多。一般人如果想要把编程学好再开始学习网络安全往…

大气污染扩散模型Calpuff教程

详情点击链接&#xff1a;大气污染扩散模型Calpuff教程一&#xff0c;Calpuff 1.Calpuff模型 2、Calpuff模型基础 3、Calpuff模型下载安装 1&#xff09;Calpro系统安装 2&#xff09;安装环境要求 3&#xff09;需安装的辅助软件二&#xff0c;数据预处理 1.网格设置 …

Vue3-04-生命周期

Vue 的生命周期描述组件从创建到销毁的全过程。Vue3 和 Vue2 的生命周期钩子非常像&#xff0c;我们仍然可以在相同的场景下使用相同的钩子函数。 Vue3 在设计时对先前的版本进行了向下兼容&#xff0c;如果你的项目还在使用选项式 API 进行构建&#xff0c;那么不需要修改生命…

【stable diffusion】图片批量自动打标签、标签批量修改(BLIP、wd14)用于训练SD或者LORA模型

参考&#xff1a; B站教学视频【&#xff1a;AI绘画】新手向&#xff01;Lora训练&#xff01;训练集准备、tag心得、批量编辑、正则化准备】官方教程&#xff1a;https://github.com/darkstorm2150/sd-scripts/blob/main/docs/train_README-en.md#automatic-captioning 一、…

Springboot全文链路id,并ELK搭建部署整合全文链路id

Springboot全文链路id,并ELK搭建部署整合全文链路id 1.docker-compose.yaml部署 version: 3 services:elasticsearch:image: elasticsearch:7.13.2container_name: elasticsearchenvironment:- "cluster.nameelasticsearch" #设置集群名称为elasticsearch- "d…

[笔记]C++并发编程实战 《五》C++内存模型和原子类型操作

文章目录 前言第5章 C内存模型和原子类型操作5.1 内存模型基础5.1.1 对象和内存位置5.1.2 对象、内存位置和并发5.1.3 修改顺序 5.2 C中的原子操作和原子类型5.2.1 标准原子类型 总结 前言 第5章 C内存模型和原子类型操作 本章主要内容&#xff1a; C11内存模型详解标准库提…

【Docker】子系统与其相关名词的界定、Control Groups等详细讲解

前言 Docker 是一个开源的应用容器引擎&#xff0c;让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。 &#x1f4d5;作者简介&#xff1a;热…