云开发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小时极速开发

相关推荐
腾讯云云开发6 小时前
云开发CloudBase实战:从0到1打造2D枪战游戏指南
ai编程·游戏开发·小程序·云开发
AI算力小知识6 小时前
深度学习场景下显卡性能实测
ai编程
信码由缰6 小时前
AI智能体是加速器,而非开发者替代品
ai编程
用户4099322502127 小时前
子查询总拖慢查询?把它变成连接就能解决?
后端·ai编程·trae
蛋先生DX10 小时前
RAG 切片利器 LumberChunker 是如何智能地把文档切割成 LLM 爱吃的块
llm·aigc·ai编程
土丁爱吃大米饭10 小时前
AIGC工具助力2D游戏美术全流程
aigc·小游戏·游戏开发·ai助力
腾讯云云开发11 小时前
Gemini CLI接入CloudBase-AI-Toolkit(MCP)保姆级教程
ai编程·小程序·云开发·gemini
木建隶13 小时前
AI 食用指南--更好的用AI编程
人工智能·ai编程
Aitter1 天前
PDF和Word文件转换为Markdown的技术实现
前端·ai编程