震惊!可以用云开发AI助手Copilot生成2048小游戏

震惊!可以用云开发AI助手Copilot生成2048小游戏

一、介绍

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

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

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

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

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

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

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

附带主页 - 微搭低代码 - 控制台

二、简单试试

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

image-20241210160439784

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

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

image-20241210162227584

点击生成,静静等待
在这里插入图片描述

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

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

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

image-20241210170515550

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

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

image-20241210170704063

发布完成后,我手机扫码预览下效果
在这里插入图片描述

三、2048

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

image-20241210180704394

image-20241210180834994

image-20241210182446322

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

image-20241210182516913

// @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一条指令,让这个按钮放到上面去;

重新生成的结果如下

image-20241210182923143

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

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

生成代码如下

// @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));
    }
  }
};

image-20241210190159802

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

image-20241210190428981

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

运行查看效果,如下

在这里插入图片描述

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

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

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

// @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,结构清晰,也非常容易修改;

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值