Trae 测评,联手 AI 五分钟用 Vue 实现划拳游戏

639 阅读4分钟

速览

我正在参加 Trae「超级体验官」创意实践征文,本文所使用的 Trae 免费下载链接:www.trae.ai/?utm_source…

最近,DeepSeek 火爆全球,GPT 等大模型在 IDE 中的应用也日益成熟。

我选择的是字节的 Trae AI 编辑器来测评,因为它除了兼容 Mac/Windows 多种操作系统之外,还可以让我们免费白嫖 DeepSeek 和 GPT-4o 等大模型。最重要的是,Trae 还支持一键导入 VSCode 的配置,只需要使用 GitHub 登录就能无缝切换,不需要从零开始重新配置自己的 IDE。

刚好我在油管上看到一个使用原生 JS 的剪刀石头布小游戏,决定试试联手 AI 编辑器使用 Vue 自己也实现一下,这是最终效果:

guess.gif

快速起步

由于测评期间,DeepSeek 开源周过于火爆,结果瘫痪了,所以我退而求其次选择了 GPT-4o 模型。

首先使用 Vite 快速搭建一个 Vue 项目,你也可以使用 React 或 Vue 的 JSX 插件来试试:

npm init vite@latest

在提示中选择项目名称和框架(选择 Vue),依赖安装完毕后,我们就可以开始写代码了。

如果忘记了上述流程,也不需要亲自去查 Vite 官网,在 Trae 中免费向 GPT 聊天就会直接告诉你终端命令和基本流程:

vite.png

功能实现

划拳游戏的基本原理并不复杂,我们使用 Math.random() 伪装 AI 人机,产生一个随机的手势,然后再让它和玩家点击选择的手势进行比较,判断胜负即可。

整个算法能且仅能产生三种结果:

  • 双方手势相同,平局;
  • 玩家获胜;
  • AI 获胜。

这里主要使用到 v-for 指令来生成可供玩家选择的手势列表,然后使用 v-on 指令来绑定点击事件,玩家选中手势后触发,然后使用 setTimeout() 开始定时器生成 AI 的手势,两者比较胜负即可。

在 DOM 操作中,经常会出现一些性能有害的写法,比如我们可能下意识地在每个手势上绑定了点击事件,浪费性能。

性能更友好的方案是利用事件委托机制,即只在父元素上绑定一次点击事件,然后在事件处理函数中判断点击的目标元素是否是我们需要的手势元素,如果是,再触发相应的操作。

我们可以询问 Trae 如何使用 Vue 在 v-for 列表上高效地绑定事件,它会给出一个解决方案:

click.png

这里另一个问题在于,获取手势的 DOM 元素时,一般我们可以使用 ref() 来获取,并自定义一些真实 DOM 的操作。但是,如果还需要这个 ref 对应的父级元素 —— 即整个 v-for 的列表元素时,我们该怎么实现呢?

这里分享一个 Trae 和 GPT 模型提供的新版 Vue 小技巧,可以使用 useTemplateRef() 来获取 v-for 列表元素的父级元素。

ref.png

然后再结合使用 ref() 在事件处理程序中自定义操作。

<script setup>
  import { ref, useTemplateRef } from 'vue'

  const main = useTemplateRef('main')
  const user = useTemplateRef('user')
  const ai = useTemplateRef('ai')
  const result = useTemplateRef('result')
  const imgs = useTemplateRef('imgs')

  function onClick(e, idx) {
    e.target.classList.add('active')
    user.value.src = ai.value.src = '/images/rock.png'
    result.textContent = '稍等一下...'
    imgs.value.forEach((el, index) => {
      idx !== index && el.classList.remove('active')
    })
    main.value.classList.add('start')
    // add animateion
    let time = setTimeout(() => {
      let imageSrc = e.target.querySelector('img').src
      user.value.src = imageSrc
      main.value.classList.remove('start')

      let randomNumber = Math.floor(Math.random() * 3)
      let cpuImages = [
        '/images/rock.png',
        '/images/paper.png',
        '/images/scissor.png',
      ]
      ai.value.src = cpuImages[randomNumber]
      let cpuValue = ['R', 'P', 'S'][randomNumber]
      let useValue = ['R', 'P', 'S'][idx]
      // create an object with all possible outcomes
      let outcomes = {
        RR: 'Draw',
        RP: 'AI',
        RS: '你',
        PP: 'Draw',
        PR: '你',
        PS: 'AI',
        SS: 'Draw',
        SR: 'AI',
        SP: '你',
      }
      // look up the outcome value based on user and CPU options
      let outComeValue = outcomes[useValue + cpuValue]
      result.value.textContent =
        useValue === cpuValue ? '平手' : `${outComeValue}胜出!`
    }, 2500)
  }

  let items = ref([
    { text: '石头', src: '/images/rock.png' },
    { text: '布', src: '/images/paper.png' },
    { text: '剪刀', src: '/images/scissor.png' },
  ])
</script>

<template>
  <section class="container" ref="main">
    <div class="result_field">
      <div class="result_images">
        <span class="user_result">
          <img src="/images/rock.png" ref="user" />
        </span>
        <span class="cpu_result">
          <img src="/images/rock.png" ref="ai" />
        </span>
      </div>
      <div class="result" ref="result">点击出手!</div>
    </div>
    <div class="option_images">
      <span
        class="option_image"
        v-for="(el, idx) in items"
        @click="onClick($event, idx)"
        ref="imgs"
      >
        <img :src="el.src" />
        <p>{{ el.text }}</p>
      </span>
    </div>
  </section>
</template>

核心算法和基本功能实现之后,设计自己的喜欢的样式即可,我只是简单地使用了油管上的同款样式。

如果你想尝试更加前沿的方案,CSS 样式方面,可以引入 UnoCSS/Tailwind CSS 等原子 CSS 框架;其次,如果图片方面也想优化,可以使用 icon 相关的库引入 SVG,打包体积方面会有一定的优势。

总结

guess.gif

本文我们联手 Trae AI 编辑器使用 Vue 重构了一个划拳游戏,实现了基本的功能和样式,也展示了如何使用 Vue 来高效地绑定事件和新 API useTemplateRef()

Trae 目前的大模型是我比较喜欢的 DeepSeek 和 GPT,使用起来更加得心应手。除了可以在 IDE 中免费白嫖主流的大模型,Trae 还支持一键导入 VSCode 的配置和 GitHub 的一件登录,这种无缝衔接的用户体验非常棒。