云开发Copilot实战:AI生成2048小游戏开发指南

本文介绍了使用Python构建智能食品消费偏好预测模型的流程,并详细演示了如何利用Copilot和微搭低代码平台快速生成和优化前端页面及2048小游戏的核心逻辑,提升了开发效率和体验。

一、介绍

对于后端开发人员来说,处理数据这些不是什么难事;难得往往是界面设计上的问题,展示归展示,丑是真的丑。

还面临着,前端不熟悉,遇到问题到处询问的痛点。

但现在,大人,时代变了;我们有了微搭低代码平台,可以轻轻松松的将组件像搭积木一样搭成小程序和网页。

有人说,这种低代码学习成本,且可玩性不高。

以前我会说是的,但现在,不需要很懂,就能轻轻松松使用。

原因就是有了Copilot ,这是一个云开发低代码AI助手

那么,我们先试试这个AI助手有多么厉害吧

二、简单试试

首先打开云开发,低代码应用列表,点击从AI创建

进入到页面,简简单单试下猫咪领养的小程序,输入下面这段提示词

生成一个流浪猫领养官网,支持领养、云领养、云投喂等功能

点击生成,静静等待

如果不满意,我们可以修改提示词继续让AI生成;

我们这边,直接点击使用该生成效果保存精调,它会自动给我们创建一个应用,来搭载这个项目。

进入下面这个页面,可以在此进行调整

我什么修改都不做,直接发布一下,在右上角可以选择进行发布

可以选择小程序、web网页应用

发布完成后,我手机扫码预览下效果

三、2048

上面只是开胃小菜,我们现在来试试使用Copilot生成2048小游戏,话不多说,直接展示

代码会程序生成,我们看看效果,结构有模有样

ini 复制代码
 // @ts-ignore;
 import React, { useState } from 'react';
 // @ts-ignore;
 import { Button, Card, CardContent, CardHeader, CardTitle, Grid, GridItem } from '@/components/ui';
 ​
 const getRandomInt = (min, max) => {
   return Math.floor(Math.random() * (max - min + 1)) + min;
 };
 const startGame = (setBoard, setGameStarted) => {
   let newBoard = Array.from({
     length: 4
   }, () => Array(4).fill(''));
   let positions = [];
   while (positions.length < 2) {
     let row = getRandomInt(0, 3);
     let col = getRandomInt(0, 3);
     if (!positions.some(pos => pos[0] === row && pos[1] === col)) {
       positions.push([row, col]);
       newBoard[row][col] = Math.random() < 0.9 ? 2 : 4;
     }
   }
   setBoard(newBoard);
   setGameStarted(true);
 };
 const generateNewNumber = board => {
   let emptyCells = [];
   for (let row = 0; row < 4; row++) {
     for (let col = 0; col < 4; col++) {
       if (board[row][col] === '') {
         emptyCells.push({
           row: row,
           col: col
         });
       }
     }
   }
   if (emptyCells.length > 0) {
     let randomIndex = Math.floor(Math.random() * emptyCells.length);
     let selectedCell = emptyCells[randomIndex];
     board[selectedCell.row][selectedCell.col] = Math.random() < 0.9 ? 2 : 4;
   }
   return board;
 };
 const handleMove = (direction, setBoard, setGameStarted) => {
   // TODO: Implement the logic for moving the tiles
 };
 export default function Game2048(props) {
   const [board, setBoard] = useState(Array.from({
     length: 4
   }, () => Array(4).fill('')));
   const [gameStarted, setGameStarted] = useState(false);
   return <Card className="p-4">
       <CardHeader>
         <div className="flex items-center space-x-4">
           <CardTitle>2048 Game</CardTitle>
         </div>
       </CardHeader>
       <CardContent>
         <Grid className="grid-cols-4 gap-2">
           {board.map((row, rowIndex) => <div key={rowIndex} className="flex flex-row">
               {row.map((cell, colIndex) => <GridItem key={`${rowIndex}-${colIndex}`} className={`border p-2 w-16 h-16`}>
                   {cell}
                 </GridItem>)}
             </div>)}
         </Grid>
         <div className="mt-4 flex space-x-4">
           <Button onClick={() => handleMove('up', setBoard, setGameStarted)}>上</Button>
           <Button onClick={() => handleMove('left', setBoard, setGameStarted)}>左</Button>
           <Button onClick={() => handleMove('right', setBoard, setGameStarted)}>右</Button>
           <Button onClick={() => handleMove('down', setBoard, setGameStarted)}>下</Button>
         </div>
         {!gameStarted && <Button onClick={() => startGame(setBoard, setGameStarted)}>开始游戏</Button>}
       </CardContent>
     </Card>;
 }

看不爽这个开始游戏在下面,我们再给Copilot一条指令,让这个按钮放到上面去;

重新生成的结果如下

到了现在,比较重要的是handleMove()这个函数,我们给与下面这样的提示词

请帮忙生成2048小游戏核心逻辑,只需要生成handleMove函数,不考虑游戏结构

生成代码如下

ini 复制代码
 // @ts-ignore;
 import React from 'react';
 ​
 const handleMove = (direction, setBoard, setGameStarted) => {
   let newBoard = [...board];
   let moved = false;
   switch (direction) {
     case 'up':
       for (let col = 0; col < 4; col++) {
         let lastMergedRow = -1;
         for (let row = 1; row < 4; row++) {
           if (newBoard[row][col] !== '') {
             let current = newBoard[row][col];
             newBoard[row][col] = '';
             let targetRow = row;
             while (targetRow > 0 && newBoard[targetRow - 1][col] === '') {
               targetRow--;
             }
             if (targetRow === lastMergedRow) {
               newBoard[targetRow - 1][col] += current;
               lastMergedRow = -1;
             } else if (targetRow !== row) {
               newBoard[targetRow][col] = current;
               lastMergedRow = targetRow;
             } else {
               lastMergedRow = row;
             }
           }
         }
       }
       break;
     case 'down':
       for (let col = 0; col < 4; col++) {
         let lastMergedRow = 4;
         for (let row = 2; row >= 0; row--) {
           if (newBoard[row][col] !== '') {
             let current = newBoard[row][col];
             newBoard[row][col] = '';
             let targetRow = row;
             while (targetRow < lastMergedRow - 1 && newBoard[targetRow + 1][col] === '') {
               targetRow++;
             }
             if (targetRow === lastMergedRow - 1) {
               newBoard[targetRow + 1][col] += current;
               lastMergedRow = targetRow;
             } else if (targetRow !== row) {
               newBoard[targetRow][col] = current;
               lastMergedRow = targetRow + 1;
             } else {
               lastMergedRow = row;
             }
           }
         }
       }
       break;
     case 'left':
       for (let row = 0; row < 4; row++) {
         let lastMergedCol = -1;
         for (let col = 1; col < 4; col++) {
           if (newBoard[row][col] !== '') {
             let current = newBoard[row][col];
             newBoard[row][col] = '';
             let targetCol = col;
             while (targetCol > 0 && newBoard[row][targetCol - 1] === '') {
               targetCol--;
             }
             if (targetCol === lastMergedCol) {
               newBoard[row][targetCol - 1] += current;
               lastMergedCol = -1;
             } else if (targetCol !== col) {
               newBoard[row][targetCol] = current;
               lastMergedCol = targetCol;
             } else {
               lastMergedCol = col;
             }
           }
         }
       }
       break;
     case 'right':
       for (let row = 0; row < 4; row++) {
         let lastMergedCol = 4;
         for (let col = 2; col >= 0; col--) {
           if (newBoard[row][col] !== '') {
             let current = newBoard[row][col];
             newBoard[row][col] = '';
             let targetCol = col;
             while (targetCol < lastMergedCol - 1 && newBoard[row][targetCol + 1] === '') {
               targetCol++;
             }
             if (targetCol === lastMergedCol - 1) {
               newBoard[row][targetCol + 1] += current;
               lastMergedCol = targetCol;
             } else if (targetCol !== col) {
               newBoard[row][targetCol] = current;
               lastMergedCol = targetCol + 1;
             } else {
               lastMergedCol = col;
             }
           }
         }
       }
       break;
   }
   if (moved) {
     setBoard(newBoard);
     if (!newBoard.flat().some(cell => cell === '')) {
       // No empty cells, game over or win condition
     } else {
       setBoard(generateNewNumber(newBoard));
     }
   }
 };

处理结束后,点击预览查看效果

格子没有颜色,不友好,我们添加背景颜色,直接和Copliot说,这一块就不展示了

运行查看效果,如下

发现点击按钮后,数字在格子中是一格一格移动的,这不是我们想要的

但我这一块给指令,生成的效果实在不怎么理想,试过了好多次

最终还是回到了第一版,自己改改用数组当队列来用,好吧我们来看看全部代码

ini 复制代码
 // @ts-ignore;
 import React, { useState } from 'react';
 // @ts-ignore;
 import { Button, Card, CardContent, CardHeader, CardTitle, Grid, GridItem } from '@/components/ui';
 ​
 const getColorByValue = value => {
   switch (value) {
     case 2:
       return 'bg-gray-200';
     case 4:
       return 'bg-gray-300';
     case 8:
       return 'bg-gray-400';
     case 16:
       return 'bg-gray-500';
     case 32:
       return 'bg-gray-600';
     case 64:
       return 'bg-gray-700';
     case 128:
       return 'bg-gray-800';
     case 256:
       return 'bg-gray-900';
     case 512:
       return 'bg-gray-950';
     case 1024:
       return 'bg-gray-970';
     case 2048:
       return 'bg-gray-990';
     default:
       return '';
   }
 };
 const getRandomInt = (min, max) => {
   return Math.floor(Math.random() * (max - min + 1)) + min;
 };
 const startGame = (setBoard, setGameStarted) => {
   let newBoard = Array.from({
     length: 4
   }, () => Array(4).fill(''));
   let positions = [];
   while (positions.length < 2) {
     let row = getRandomInt(0, 3);
     let col = getRandomInt(0, 3);
     if (!positions.some(pos => pos[0] === row && pos[1] === col)) {
       positions.push([row, col]);
       newBoard[row][col] = 2;
     }
   }
   setBoard(newBoard);
   setGameStarted(true);
 };
 export default function Game2024(props) {
   const [board, setBoard] = useState(Array.from({
     length: 4
   }, () => Array(4).fill('')));
   const [gameStarted, setGameStarted] = useState(false);
   const handleMove = direction => {
     let newBoard = [...board];
     let didMove = false;
     switch (direction) {
       case 'up':
         for (let col = 0; col < 4; col++) {
           let lastMergedRow = [];
           let finalMergedRow = [];
           for (let row = 0; row < 4; row++) {
             if (newBoard[row][col] !== '') {
               lastMergedRow.push(newBoard[row][col]);
             }
           }
           for (let row = 0; row < lastMergedRow.length - 1; row++) {
             if (lastMergedRow[row] === lastMergedRow[row + 1]) {
               lastMergedRow[row] *= 2;
               lastMergedRow[row + 1] = '';
               didMove = true;
             }
           }
           for (let num of lastMergedRow) {
             if (num !== '') {
               finalMergedRow.push(num);
             }
           }
           while (finalMergedRow.length < 4) {
             finalMergedRow.push('');
           }
           for (let row = 0; row < 4; row++) {
             let oldNum = newBoard[row][col];
             let newNum = finalMergedRow[row];
             newBoard[row][col] = newNum;
             if (!didMove) {
               didMove = oldNum!=newNum;
             }
           }
         }
         break;
       case 'down':
         for (let col = 0; col < 4; col++) {
           let lastMergedRow = [];
           let finalMergedRow = [];
           for (let row = 3; row >= 0; row--) {
             if (newBoard[row][col] !== '') {
               lastMergedRow.push(newBoard[row][col]);
             }
           }
           for (let row = 0; row < lastMergedRow.length - 1; row++) {
             if (lastMergedRow[row] === lastMergedRow[row + 1]) {
               lastMergedRow[row] *= 2;
               lastMergedRow[row + 1] = '';
               didMove = true;
             }
           }
           for (let num of lastMergedRow) {
             if (num !== '') {
               finalMergedRow.push(num);
             }
           }
           while (finalMergedRow.length < 4) {
             finalMergedRow.push('');
           }
           for (let row = 0; row < 4; row++) {
             let oldNum = newBoard[3 - row][col];
             let newNum = finalMergedRow[row];
             newBoard[3 - row][col] = newNum;
             if (!didMove) {
               didMove = oldNum!=newNum;
             }
           }
         }
         break;
       case 'left':
         for (let row = 0; row < 4; row++) {
           let lastMergedCol = [];
           let finalMergedCol = [];
           for (let col = 0; col < 4; col++) {
             if (newBoard[row][col] !== '') {
               lastMergedCol.push(newBoard[row][col]);
             }
           }
           for (let col = 0; col < lastMergedCol.length - 1; col++) {
             if (lastMergedCol[col] === lastMergedCol[col + 1]) {
               lastMergedCol[col] *= 2;
               lastMergedCol[col + 1] = '';
               didMove = true;
             }
           }
           for (let num of lastMergedCol) {
             if (num !== '') {
               finalMergedCol.push(num);
             }
           }
           while (finalMergedCol.length < 4) {
             finalMergedCol.push('');
           }
           for (let col = 0; col < 4; col++) {
             let oldNum = newBoard[row][col];
             let newNum = finalMergedCol[col];
             newBoard[row][col] = newNum;
             if (!didMove) {
               didMove = oldNum!=newNum;
             }
           }
         }
         break;
       case 'right':
         for (let row = 0; row < 4; row++) {
           let lastMergedCol = [];
           let finalMergedCol = [];
           for (let col = 3; col >= 0; col--) {
             if (newBoard[row][col] !== '') {
               lastMergedCol.push(newBoard[row][col]);
             }
           }
           for (let col = 0; col < lastMergedCol.length - 1; col++) {
             if (lastMergedCol[col] === lastMergedCol[col + 1]) {
               lastMergedCol[col] *= 2;
               lastMergedCol[col + 1] = '';
               didMove = true;
             }
           }
           for (let num of lastMergedCol) {
             if (num !== '') {
               finalMergedCol.push(num);
             }
           }
           while (finalMergedCol.length < 4) {
             finalMergedCol.push('');
           }
           for (let col = 0; col < 4; col++) {
             let oldNum = newBoard[row][3 - col];
             let newNum = finalMergedCol[col];
             newBoard[row][3 - col] = newNum;
             if (!didMove) {
               didMove = oldNum!=newNum;
             }
           }
         }
         break;
     }
     console.log(didMove);
     console.log(newBoard);
     if (didMove) {
       generateNewNumber(newBoard);
     }
     console.log(newBoard);
     setBoard(newBoard);
   };
   const generateNewNumber = newBoard => {
     let emptyCells = [];
     for (let row = 0; row < 4; row++) {
         for (let col = 0; col < 4; col++) {
             if (newBoard[row][col] === '') {
                 emptyCells.push({row: row, col: col});
             }
         }
     }
     if (emptyCells.length > 0) {
         let randomIndex = Math.floor(Math.random() * emptyCells.length);
         let selectedCell = emptyCells[randomIndex];
         newBoard[selectedCell.row][selectedCell.col] = Math.random() < 0.9 ? 2 : 4;
     }
     return newBoard;
   };
   return <Card className="p-4">
     <CardHeader>
       <div className="flex items-center space-x-4">
         <CardTitle>2024 Game</CardTitle>
         <Button onClick={() => startGame(setBoard, setGameStarted)}>开始游戏</Button>
       </div>
     </CardHeader>
     <CardContent>
       <Grid className="grid-cols-4 gap-2">
         {board.map((row, rowIndex) => <div key={rowIndex} className="flex flex-row">
           {row.map((cell, colIndex) => <GridItem key={`${rowIndex}-${colIndex}`} className={`border p-2 w-16 h-16 ${getColorByValue(cell)}`}>
             {cell}
           </GridItem>)}
         </div>)}
       </Grid>
       <div className="mt-4 flex space-x-4">
         <Button onClick={() => handleMove('up')}>上</Button>
         <Button onClick={() => handleMove('left')}>左</Button>
         <Button onClick={() => handleMove('right')}>右</Button>
         <Button onClick={() => handleMove('down')}>下</Button>
       </div>
     </CardContent>
   </Card>;
 }

运行查看效果

四、最后

谈一下总体使用下来的感受

AI结合云开发低代码的使用体验,接触下来感觉非常棒

对于我这种后端来说,前端的设计开发,往往占据了大部分时间,更别提样式的调优了

而结合AI生成,给予提示词就能生成一个前端页面,然后结合微搭低代码平台,很快就能完成一个页面,非常地便捷;

再来说说,生成代码这一块,就体验生成2048小游戏来说,关键部分的逻辑我是反反复复一直给提示词生成

  • 上下文之间的关联不是很强(导致了关键逻辑生成受限,不能很好的运行)
  • 完整输出会超时(所以在上面给了不需要关注结构的提示词)
  • 提示词必须要准确(最好是一个简单的提示词,生成一个简陋,但能运行的代码;后面根据提示词进行优化细节)

总结一下,体验下来还是非常不错的

我以前不会写react代码,看了Copilot生成的react,结构清晰,也非常容易修改;

我很期待后面的优化,未来可期!!!

官网: tcb.cloud.tencent.com/

github: 腾讯云开发 Agent UI ,微信小程序/React AI 对话组件

相关推荐: # CloudBase + AI 游戏开发新范式,3小时极速开发

相关推荐
AndCo1 天前
和AI用TDD结对编程:1天开发一个完整的 Python 库
ai编程
Patrick_Wilson1 天前
AI会如何评价一名前端工程师的技术人格
前端·typescript·ai编程
量子位1 天前
李飞飞最新长文火爆硅谷
ai编程
量子位1 天前
从“给答案”到“教动脑”:这届小学生被AI教会主动思考
ai编程
用户4099322502121 天前
Vue3响应式系统中,对象新增属性、数组改索引、原始值代理的问题如何解决?
前端·ai编程·trae
信码由缰1 天前
使用 Java、Spring Boot 和 Spring AI 开发符合 A2A 标准的 AI 智能体
ai编程
飞哥数智坊2 天前
TRAE CN + K2 Thinking,我试着生成了一个简版的在线 PS
人工智能·ai编程·trae
YoungHong19922 天前
MiniMax-M2 全方位配置手册:覆盖 Claude Code, Cursor, Cline 等工具
ai编程
人工智能训练2 天前
如何在 Ubuntu 22.04 中安装 Docker 引擎和 Linux 版 Docker Desktop 桌面软件
linux·运维·服务器·数据库·ubuntu·docker·ai编程
数据智能老司机2 天前
Spring AI 实战——提交用于生成的提示词
spring·llm·ai编程