0


微信小程序 |做一款跟ChatGPT下五指棋的小程序

在这里插入图片描述

请添加图片描述

一、写在前面

敢问世间万物,何以解忧?

时下最为火爆的

ChatGPT

想必够资格来回答一下这个问题。

要想当年

AlphaGO

打败世界围棋高手李世石,就展露出AI的惊人实力,时隔多年,AI领域在憋了这么多年之后,现如今,

ChatGPT 4

大杀四方,各行各业无不为之震撼!

借用刚召开的新程序员大会中的模型发展架构,我们可以很清晰的看到大模型现阶段的研究进展以及商业化现状。

http://t.csdn.cn/8SlWM

ChatGPT问世以来的这么几个月里

,这种大模型在市场中的应用还是主要围绕在

AI绘图``AI聊天

以及一些

AI文本类型的工作

。就截至到目前,市面上对于大模型的实际生产应用仍然处在一个不断摸索的模糊地带。

回望

2006-2009年的移动互联网的爆发年代

,此时的跨时代的风口已经跃然纸上,

要如何抓住机会逆天改命?毋庸置疑,贴近时代脉搏,疯狂尝试!

为此,我们来做一个酷炫的东西,我们做一个可以跟GPT下棋的小程序!一起来感受一下GPT的棋艺如何! 😁😪🙄😏😥😮


二、项目原理与架构

2.1方案原理

要让

ChatGPT

遵从我们所设计的表盘五指棋的规则,首先个一个要点就是要让其知道我们的棋盘的底层设计是如何的

  • 那这就要说回到五指棋棋盘的实现原理了:五指棋棋盘从代码实现的角度来说就是一个二维数组,用户在棋盘的每一步操作都是在这个二维数组中对相应的元素坐标中的值进行设置(如我们在棋盘的第一个位置下了一个棋子,然后这个棋盘数组元素赋值就会变成: arr [1][1] = 1
  • 在明确了棋盘落子的基础之上,接下来还需要处理的就是让ChatGPT明白这个规则。通过借助ChatGPT所提供的API接口,我们将数组的边界值以及用户所进行的落子操作传递给模型,然后再实时地将模型所返回的值进行渲染到前端即可
    #mermaid-svg-3zpjoZ6jQWIqIvFC {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .error-icon{fill:#552222;}#mermaid-svg-3zpjoZ6jQWIqIvFC .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-3zpjoZ6jQWIqIvFC .marker{fill:#333333;stroke:#333333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .marker.cross{stroke:#333333;}#mermaid-svg-3zpjoZ6jQWIqIvFC svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-3zpjoZ6jQWIqIvFC .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .cluster-label text{fill:#333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .cluster-label span{color:#333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .label text,#mermaid-svg-3zpjoZ6jQWIqIvFC span{fill:#333;color:#333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .node rect,#mermaid-svg-3zpjoZ6jQWIqIvFC .node circle,#mermaid-svg-3zpjoZ6jQWIqIvFC .node ellipse,#mermaid-svg-3zpjoZ6jQWIqIvFC .node polygon,#mermaid-svg-3zpjoZ6jQWIqIvFC .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-3zpjoZ6jQWIqIvFC .node .label{text-align:center;}#mermaid-svg-3zpjoZ6jQWIqIvFC .node.clickable{cursor:pointer;}#mermaid-svg-3zpjoZ6jQWIqIvFC .arrowheadPath{fill:#333333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-3zpjoZ6jQWIqIvFC .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-3zpjoZ6jQWIqIvFC .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-3zpjoZ6jQWIqIvFC .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-3zpjoZ6jQWIqIvFC .cluster text{fill:#333;}#mermaid-svg-3zpjoZ6jQWIqIvFC .cluster span{color:#333;}#mermaid-svg-3zpjoZ6jQWIqIvFC div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-3zpjoZ6jQWIqIvFC :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
    操作数据

API数据发送

     用户
    

     棋盘小程序
    

     ChatGPT
    

     数据处理
    

ChatPGT如何下棋?

要跟

ChatGPT

下棋,其实就是跟它进行对话,让他在五指棋的规则约定下跟他对话:

  • 首先,我们先指定话题背景:我们现在开始采用传统的黑白棋子来下一盘五指棋,棋盘的大小是20*20。我是黑方,我将用坐标的形式来表示我下的位置。你需要采取进攻型的策略快速赢我,告诉我你的落子位置。
  • 然后,我们只需要输入我们的落子坐标:如:(10,10)
  • GPT就会根据五指棋的规则以及我们的落子坐标对棋盘进行分析,从而得出最佳的落子选择。

在这里插入图片描述


2.2 技术架构

(1)技术栈介绍

模块语言及框架涉及的技术要点小程序前端基于

VUE 2.0语法
  • Uni-app跨平台开发框架
    
    Http接口通信、Flex布局方式、uView样式库的使用、JSON数据解析、定时器的使用小程序接口服务端
    Python
    
    +
    Flask WEB框架
    
    rest接口的开发、 ChatGPT API接口的数据对接 、 前后端websocket实时通信

    (2)数据流转解析

从系统中的数据流向梳理整体的功能开发流程,进而把握开发重点🙄。
#mermaid-svg-9kcpZyJfSQLKWImw {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-9kcpZyJfSQLKWImw .error-icon{fill:#552222;}#mermaid-svg-9kcpZyJfSQLKWImw .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-9kcpZyJfSQLKWImw .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-9kcpZyJfSQLKWImw .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-9kcpZyJfSQLKWImw .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-9kcpZyJfSQLKWImw .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-9kcpZyJfSQLKWImw .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-9kcpZyJfSQLKWImw .marker{fill:#333333;stroke:#333333;}#mermaid-svg-9kcpZyJfSQLKWImw .marker.cross{stroke:#333333;}#mermaid-svg-9kcpZyJfSQLKWImw svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-9kcpZyJfSQLKWImw .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9kcpZyJfSQLKWImw text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-9kcpZyJfSQLKWImw .actor-line{stroke:grey;}#mermaid-svg-9kcpZyJfSQLKWImw .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-9kcpZyJfSQLKWImw .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-9kcpZyJfSQLKWImw #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-9kcpZyJfSQLKWImw .sequenceNumber{fill:white;}#mermaid-svg-9kcpZyJfSQLKWImw #sequencenumber{fill:#333;}#mermaid-svg-9kcpZyJfSQLKWImw #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-9kcpZyJfSQLKWImw .messageText{fill:#333;stroke:#333;}#mermaid-svg-9kcpZyJfSQLKWImw .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9kcpZyJfSQLKWImw .labelText,#mermaid-svg-9kcpZyJfSQLKWImw .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-9kcpZyJfSQLKWImw .loopText,#mermaid-svg-9kcpZyJfSQLKWImw .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-9kcpZyJfSQLKWImw .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-9kcpZyJfSQLKWImw .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-9kcpZyJfSQLKWImw .noteText,#mermaid-svg-9kcpZyJfSQLKWImw .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-9kcpZyJfSQLKWImw .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9kcpZyJfSQLKWImw .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9kcpZyJfSQLKWImw .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-9kcpZyJfSQLKWImw .actorPopupMenu{position:absolute;}#mermaid-svg-9kcpZyJfSQLKWImw .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-9kcpZyJfSQLKWImw .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-9kcpZyJfSQLKWImw .actor-man circle,#mermaid-svg-9kcpZyJfSQLKWImw line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-9kcpZyJfSQLKWImw :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}
用户

 五指棋小程序

 小程序后台服务

 ChatGPT服务

发送落子操作

同步用户的下棋位置

包装prompts语句,告诉GPT用户的下棋坐标

根据规则返回模型的下棋坐标

对返回的数据进行处理,封装小程序端的数据

对返回的数据进行处理,封装小程序端的数据

根据用户的下棋坐标以及前置的规则

直接返回模型的决策结果.

用户

五指棋小程序

小程序后台服务

ChatGPT服务

三、项目实现

3.1 ChatGPT API的接入

要接入ChatGPT API,需要按照以下步骤进行操作:

  1. 注册一个账号并登录到OpenAI的官网:https://openai.com/
  2. 在Dashboard页面上,创建一个API密钥。在“API Keys”选项卡下,点击“Generate New Key”按钮。将生成的密钥保存好,以备后续使用。
  3. 选择所需的API服务,例如“Completion” API,以使用OpenAI的文本生成功能。

在这里插入图片描述
使用

Python

调用

ChatGPT API

实现代码如下:

  • 方法一:使用request
import requests
import json

# 构建API请求
url ="https://api.openai.com/v1/engines/davinci-codex/completions"
headers ={"Content-Type":"application/json","Authorization":"Bearer YOUR_API_KEY"}
data ={"prompt":"Hello, my name is","max_tokens":5}# 发送API请求
response = requests.post(url, headers=headers, data=json.dumps(data))# 解析API响应
response_data = json.loads(response.text)
generated_text = response_data["choices"][0]["text"]print(generated_text)
  • 方式二:使用openAI库
from flask import Flask, request
import openai

app = Flask(__name__)

openai.api_key ="YOUR_API_KEY_HERE"@app.route("/")defhome():return"Hello, World!"@app.route("/chat", methods=["POST"])defchat():
    data = request.json
    response = openai.Completion.create(
        engine="davinci",
        prompt=data["message"],
        max_tokens=60)return response.choices[0].text

if __name__ =="__main__":
    app.run()

3.2 小程序端棋盘功能实现

主页正在下棋用户卡片等待下棋用户卡片在这里插入图片描述在这里插入图片描述在这里插入图片描述

  • 小程序界面实现代码如下:
<template><viewclass="chat-room"><gpt-card:show="showGPT"></gpt-card><viewclass="box"><viewclass="centent"><canvas@touchend="syncAction"canvas-id="canvas"class="canvas"style="width: 730rpx;height: 730rpx;"></canvas></view><view><view:class="value.class":style="{ left: value.left, top: value.top, transform: value.transform, boxShadow: value.boxShadow }"v-for="(value, index) in game.h":key="index">
                    {{ value.text }}
                </view></view><viewclass="winner"><viewclass="state-chess Bchess"></view><viewclass="chessName"></view></view></view><user-card:show="showUser"></user-card></view></template><script>import userCard from'@/components/infoCard/index.vue'import gptCard from'@/components/gptCard/index.vue'let goEasy =getApp().globalData.goEasy;let pubSub = goEasy.pubsub;exportdefault{data(){return{showGPT:false,showUser:true,userInfo:{chessRole:1,// 1为白棋,2为黑棋roundFlag:true,// 表示是否为自己的回合enemy:'',name:''},chessMassage:{body:'',playerA:'',playerB:'',chessRole:1,mode:1},MoveMode:{a2b:1,b2a:2},game:{ctx:null,e:0,chess_Board:[],chess_Name:['黑棋','白棋'],h:[],um:0,lianz:[],winXY:[[1,0],[0,1],[1,1],[1,-1]],chessOff:true},cName:'黑棋走',sChesee:'Bchess',currentRoom:null,// 道具展示propDisplay:{showPropType:0,play:false,timer:null},newMessageContent:"",// 道具类型Prop:{HEART:0,//桃心ROCKET:1//火箭},// 消息类型MessageType:{CHAT:0,//文字聊天PROP:1,//道具CHESS:2// 下棋}}},components:{userCard, gptCard},onLoad(options){//获取数据let roomToken =JSON.parse(options.roomToken);// 初始化roomthis.currentRoom ={roomId: roomToken.roomId,roomName: roomToken.roomName,onlineUsers:{count:0,users:[]},messages:[],currentUser:{id: roomToken.userId,nickname: roomToken.nickname,avatar: roomToken.avatar
                }};this.userInfo.name  = roomToken.nickname
            // 设置导航标题
            uni.setNavigationBarTitle({title: roomToken.roomName
            });// 连接goEasythis.connectGoEasy();// 监听用户上下线this.listenUsersOnlineOffline();// 加载最后10条消息历史this.loadHistory();// 监听新消息this.listenNewMessage();},onReady(){this.game.ctx = uni.createCanvasContext('canvas');this.drawLine();},onUnload(){// 断开连接
            goEasy.disconnect({onSuccess(){
                    console.log("GoEasy disconnect successfully");},onFailed(error){
                    console.log("GoEasy disconnect failed"+JSON.stringify(error));}});},methods:{// 连接goEasyconnectGoEasy(){let self =this;let userData ={avatar:this.currentRoom.currentUser.avatar,nickname:this.currentRoom.currentUser.nickname
                }
                goEasy.connect({id:this.currentRoom.currentUser.id,data: userData,onSuccess:function(){
                        console.log("GoEasy connect successfully.")// 加载在线用户列表
                        self.loadOnlineUsers();},onFailed:function(error){
                        console.log("Failed to connect GoEasy, code:"+error.code+",error:"+error.content);},onProgress:function(attempts){
                        console.log("GoEasy is connecting", attempts);}});},// 监听用户上下线listenUsersOnlineOffline(){let self =this;let roomId =this.currentRoom.roomId;
                pubSub.subscribePresence({channel: roomId,onPresence:function(presenceEvents){
                        self.currentRoom.onlineUsers.count = presenceEvents.clientAmount;
                        presenceEvents.events.forEach(function(event){let userData = event.data;if(event.action ==="join"|| event.action ==="online"){//进入房间let userId = event.id;let avatar = userData.avatar;let nickname = userData.nickname;let user ={id: userId,avatar: avatar,nickname: nickname
                                };//添加新用户
                                self.currentRoom.onlineUsers.users.push(user);//添加进入房间的消息let message ={content:" 进入房间",senderUserId: userId,senderNickname: nickname,type: self.MessageType.CHAT};
                                self.currentRoom.messages.push(message);}else{//退出房间
                                self.currentRoom.onlineUsers.users.forEach((user, index)=>{if(event.id === user.id){// 删除当前聊天室列表中离线的用户let offlineUser = self.currentRoom.onlineUsers.users.splice(index,1);let message ={content:" 退出房间",senderUserId: offlineUser[0].id,senderNickname: offlineUser[0].nickname,type: self.MessageType.CHAT};
                                        self.currentRoom.messages.push(message);}});}
                            self.scrollToBottom();});},onSuccess:function(){
                        console.log("用户上下线监听成功")},onFailed:function(error){
                        console.log("监听用户上下线失败, code:"+error.code+",content:"+error.content);}})},switchRound(){this.showGPT =!this.showGPT
                this.showUser =!this.showUser
            },// 监听新消息listenNewMessage(){// 监听当前聊天室的消息let self =this;let roomId =this.currentRoom.roomId;
                pubSub.subscribe({channel: roomId,onMessage:function(message){let messageContent ="";let content =JSON.parse(message.content);//聊天消息if(content.type === self.MessageType.CHAT){
                            messageContent = content.content;}//道具消息if(content.type === self.MessageType.PROP){if(content.content === self.Prop.ROCKET){
                                messageContent ="送出了一枚大火箭";}if(content.content === self.Prop.HEART){
                                messageContent ="送出了一个大大的比心";}}
                        
                         console.log("监听消息成功==",content)if(content.type === self.MessageType.CHESS){
                                                        
                            self.canvasClick(content.body,content.chessRole)
                            self.userInfo.roundFlag =true
                            self.switchRound()}//添加消息let newMessage ={content: messageContent,senderUserId: content.senderUserId,senderNickname: content.senderNickname,type: self.MessageType.CHAT};
                        self.currentRoom.messages.push(newMessage);if(content.type === self.MessageType.PROP){
                            self.propAnimation(parseInt(content.content))}
                        self.scrollToBottom();},onSuccess:function(){
                      console.log("监听新消息成功")},onFailed:function(error){
                        console.log("订阅消息失败, code:"+error.code+",错误信息:"+error.content);}})},// 加载在线用户列表loadOnlineUsers(){let self =this;let roomId =this.currentRoom.roomId;
                pubSub.hereNow({channels:[roomId],includeUsers:true,distinct:true,onSuccess:function(result){let users =[];let currentRoomOnlineUsers = result.content.channels[roomId];
                        currentRoomOnlineUsers.users.forEach(function(onlineUser){let userData = onlineUser.data;let user ={id: onlineUser.id,nickname: userData.nickname,avatar: userData.avatar
                            };
                            users.push(user);});
                        self.currentRoom.onlineUsers ={users: users,count: currentRoomOnlineUsers.clientAmount
                        };// 如果是第一个进房的就自动设为白棋// 如果是第二个进房的就是设为黑棋if(users.length==1){
                            self.userInfo.chessRole =1
                            self.userInfo.name = users[0].nickname
                        }if(users.length==2){
                            self.userInfo.chessRole =2
                            self.userInfo.name = users[1].nickname
                        }},onFailed:function(error){//获取失败
                        console.log("获取在线用户失败, code:"+ error.code +",错误信息:"+ error.content);}});},// 加载最后10条消息历史loadHistory(){let self =this;let roomId =this.currentRoom.roomId;
                pubSub.history({channel: roomId,//必需项limit:10,//可选项,返回的消息条数onSuccess:function(response){let messages =[];
                        response.content.messages.map(message=>{let historyMessage =JSON.parse(message.content);//道具消息if(historyMessage.type === self.MessageType.PROP){if(historyMessage.content === self.Prop.ROCKET){
                                    historyMessage.content ="送出了一枚大火箭";}if(historyMessage.content === self.Prop.HEART){
                                    historyMessage.content ="送出了一个大大的比心";}}
                            messages.push(historyMessage);});
                        self.currentRoom.messages = messages;},onFailed:function(error){
                        console.log("获取历史消息失败, code:"+ error.code +",错误信息:"+ error.content);}});},onInputMessage(event){//双向绑定消息 兼容this.newMessageContent = event.target.value;},sendMessage(messageType, content){//发送消息if(content ===""&& messageType ===this.MessageType.CHAT){return;}var message ={senderNickname:this.currentRoom.currentUser.nickname,senderUserId:this.currentRoom.currentUser.id,type: messageType,content: content
                };if(messageType ===this.MessageType.CHESS){this.chessMassage.body = content
                    this.chessMassage.chessRole =this.userInfo.chessRole
                    let userNum=this.currentRoom.onlineUsers.users.length
                    
                    message ={senderNickname:this.currentRoom.currentUser.nickname,senderUserId:this.currentRoom.currentUser.id,type: messageType,body:content,playerA:'',playerB:'',chessRole:this.userInfo.chessRole,mode:1,userNum:userNum
                    }}
                console.log("发送==",message);
                pubSub.publish({channel:this.currentRoom.roomId,message:JSON.stringify(message),onSuccess:function(){
                        console.log("发送成功");},onFailed:function(error){
                        console.log("消息发送失败,错误编码:"+ error.code +" 错误信息:"+ error.content);}});this.newMessageContent ="";},propAnimation(type){//道具动画//动画的实现if(this.propDisplay.timer){return;}this.propDisplay.showPropType = type;this.propDisplay.play =true;this.propDisplay.timer =setTimeout(()=>{this.propDisplay.play =false;this.propDisplay.timer =null;},2000)},scrollToBottom(){this.$nextTick(function(){
                    uni.pageScrollTo({scrollTop:2000000,duration:10})})},// ==== 五指棋控制逻辑  ===drawLine(){let s = uni.upx2px(730);let dis = Math.floor(s /15);let w = dis *14;for(let i =1; i <=14; i++){this.game.ctx.moveTo(i * dis +0.5, w);this.game.ctx.lineTo(i * dis +0.5, dis);this.game.ctx.moveTo(dis, i * dis +0.5);this.game.ctx.lineTo(w, i * dis +0.5);this.game.ctx.setStrokeStyle('#a5aa6b');this.game.ctx.stroke();}this.game.ctx.draw();for(let i =0; i <=13; i++){this.game.chess_Board[i]=[];this.game.lianz[i]=[];for(let j =0; j <=13; j++){this.game.chess_Board[i][j]=0;this.game.lianz[i][j]=0;}}},syncAction(e){if(this.userInfo.roundFlag){this.sendMessage(this.MessageType.CHESS,e)this.canvasClick(e,this.userInfo.cheeRole)this.userInfo.roundFlag =false}else{
                    uni.showModal({content:'还未到你的回合!'});}},canvasClick(e,chessRole){
                console.log(JSON.stringify(e));let s = uni.upx2px(730);let dis = Math.floor(s /15);let dx =parseInt(Math.floor(e.changedTouches[0].x + dis /2)/ dis);let dy =parseInt(Math.floor(e.changedTouches[0].y + dis /2)/ dis);let WBobj ={ox: dx * dis - dis /2+10,oy: dy * dis - dis /2+10,left: dx * dis - dis /2+10+'px',top: dy * dis - dis /2+10+'px',transform:'',boxShadow:'',text:'',mz:this.game.chess_Name[this.game.e %2],class:this.game.e %2==1?'Wchess':'Bchess',list:this.game.um++};if(dx <1||(dx > dis -1)|(dy <1)|| dy > dis -1)return;if(this.game.chess_Board[dx -1][dy -1]==0){this.game.h.push(WBobj);this.game.chess_Board[dx -1][dy -1]=this.game.chess_Name[this.game.e %2];this.game.lianz[dx -1][dy -1]= WBobj;this.win(dx -1, dy -1,this.game.chess_Name[this.game.e %2],this.game.winXY[0],this.game.e %2);this.win(dx -1, dy -1,this.game.chess_Name[this.game.e %2],this.game.winXY[1],this.game.e %2);this.win(dx -1, dy -1,this.game.chess_Name[this.game.e %2],this.game.winXY[2],this.game.e %2);this.win(dx -1, dy -1,this.game.chess_Name[this.game.e %2],this.game.winXY[3],this.game.e %2);this.cName =this.game.e %2==0?this.game.chess_Name[1]+'走':this.game.chess_Name[0]+'走';this.sChesee = chessRole==2?'Bchess':'Wchess';this.game.e++;}},win(x, y, c, m, li){let ms =1;var continuity =[];for(let i =1; i <5; i++){if(this.game.chess_Board[x + i * m[0]]){if(this.game.chess_Board[x + i * m[0]][y + i * m[1]]=== c){
                            continuity.push([x + i * m[0], y + i * m[1]]);
                            ms++;}else{break;}}}for(let i =1; i <5; i++){if(this.game.chess_Board[x - i * m[0]]){if(this.game.chess_Board[x - i * m[0]][y - i * m[1]]=== c){
                            continuity.push([x - i * m[0], y - i * m[1]]);
                            ms++;}else{break;}}}if(ms >=5){setTimeout(function(){
                        console.log(c +'赢了');},600);
                    continuity.push([x, y]);this.game.chessOff =false;let s =5;let ls =[270,300,330,360,390];let ls1 =[390,420,450,480,510];let _this =this;
                    continuity.forEach(function(value, index){let time =setInterval(function(){
                            _this.game.lianz[value[0]][value[1]].transform ='scale(0.9)';
                            _this.game.lianz[value[0]][value[1]].boxShadow ='0px 0px 2px 2px #ffd507';
                            s--;
                            s <=0?clearInterval(time):clearInterval(time);}, ls[index]);let time2 =setInterval(function(){
                            _this.game.lianz[value[0]][value[1]].transform ='scale(1)';
                            _this.game.lianz[value[0]][value[1]].boxShadow ='0px 0px 2px 2px #ffd507';
                            s++;
                            s >=5?clearInterval(time2):clearInterval(time2);}, ls1[index]);});for(var i =0; i <this.game.chess_Board.length; i++){for(var j =0; j <this.game.chess_Board.length; j++){if(this.game.chess_Board[i][j]===0){this.game.chess_Board[i][j]='null';}}}this.game.h.forEach(function(value, index){
                        value.text = value.list;});
            
                    uni.showModal({content: c +'赢了'});}},regret(){if(this.game.chessOff){if(this.game.h.length >0){let s = uni.upx2px(730);let dis = Math.floor(s /15);let obj =this.game.h.pop();this.cName =this.game.e %2==0?this.game.chess_Name[1]+'走':this.game.chess_Name[0]+'走';this.sChesee =this.game.e %2==1?'Bchess':'Wchess';this.game.e -=1;this.game.um -=1;this.game.chess_Board[parseInt(obj.ox / dis)][parseInt(obj.oy / dis)]=0;}else{return;}}else{return;}},anewClick(){this.game.h =[];this.game.um =0;this.game.chessOff =true;for(let i =0; i <=13; i++){this.game.chess_Board[i]=[];this.game.lianz[i]=[];for(let j =0; j <=13; j++){this.game.chess_Board[i][j]=0;this.game.lianz[i][j]=0;}}}}}</script><style>page{height: 100%;;}uni-page-body{height: 100%;;}.chat-room{display: flex;flex-direction: column;height: 100%;}.online-avatar-container{position: fixed;right: 0;width: 100%;height: 80rpx;display: flex;justify-content: flex-end;padding: 28rpx;box-shadow: 10rpx 30rpx 50rpx #fff;z-index: 40;background: #ffffff;}.online-avatar-item{width: 80rpx;height: 80rpx;border-radius: 40rpx;text-align: center;line-height: 80rpx;background:rgba(51, 51, 51, 0.3);color: #fff;font-size: 18rpx 28rpx;}.online-count{width: 80rpx;height: 80rpx;border-radius: 40rpx;text-align: center;line-height: 80rpx;background:rgba(51, 51, 51, 0.3);color: #fff;font-size: 28rpx;}.online-avatar-item image{width: 80rpx;height: 80rpx;}.chat-room-container{/* padding-top: 100rpx; */}.scroll-view{overflow-y: auto;padding: 20rpx 38rpx 130rpx 38rpx;box-sizing: border-box;-webkit-overflow-scrolling: touch;}.message-box{margin-top: 16rpx;}.message-item{box-sizing: border-box;height: 72rpx;background-color:rgba(196, 196, 196, 0.2);display: inline-block;font-size: 28rpx;border-radius: 100rpx;padding: 18rpx 30rpx;font-family: Microsoft YaHei UI;}.user-name{color: #D02129;font-family: Microsoft YaHei UI;}.user-message{color: #333;font-family: Microsoft YaHei UI;}.chat-room-input{position: fixed;bottom: 0;height: 92rpx;line-height: 92rpx;padding: 10rpx 28rpx 20rpx 28rpx;display: flex;background: #ffffff;}.uni-input{width: 528rpx;background-color:rgba(51, 51, 51, 0.1);height: 92rpx;border-radius: 100rpx;box-sizing: border-box;padding: 26rpx 40rpx;font-size: 28rpx;}.uni-btn{position: absolute;z-index: 1000;width: 72rpx;height: 72rpx;background: #D02129;right: 10rpx;top: 10rpx;border-radius: 72rpx;text-align: center;line-height: 72rpx;color: #fff;font-weight: bold;font-size: 32rpx;}.heart{width: 80rpx;height: 92rpx;padding: 0 15rpx;}.rocket{width: 40rpx;height: 92rpx;}.self{color: #D02129;}.show-animation{width: 80rpx;height: 320rpx;position: fixed;z-index: 44;left: 50%;bottom: 80rpx;margin: 0 -40rpx;justify-content: flex-end;animation: myanimation 2s linear;}.prop-heart{height: 80rpx;width: 80rpx;}.prop-rocket{height: 160rpx;width: 80rpx;}@keyframes myanimation{from{bottom: 80rpx;}to{bottom: 600rpx;}}.box{position: relative;margin: 50rpx auto;width: 750rpx;height: 810rpx;background: #e6e7ec;}.centent{position: absolute;width: 730rpx;height: 730rpx;border: 1px solid #9e9e9e;overflow: hidden;border-radius: 8rpx;box-shadow: 0rpx 0rpx 5rpx 0rpx #9e9e9e;left: 10rpx;top: 20rpx;}.canvas{background: #f7e6b7;}.button,
.anew,
.state,
.winner{position: absolute;display: block;width: 100rpx;height: 55rpx;border-radius: 10rpx;outline: none;font-size: 22rpx;box-sizing: border-box;color: #00bcd4;background: #fff;border: none;box-shadow: 1rpx 1rpx 3rpx 1rpx #9e9e9e;top: 760rpx;left: 270rpx;user-select: none;}.anew{left: 150rpx;}.state{left: 400rpx;width: 140rpx;}.state .state-chess,
.winner .state-chess{position: absolute;width: 30rpx;height: 30rpx;top: 11rpx;left: 10rpx;}.state .chessName,
.winner .chessName{position: absolute;width: 80rpx;height: 30rpx;top: 12rpx;left: 45rpx;text-align: center;line-height: 30rpx;font-size: 15rpx;}.button:active,
.anew:active{transition-property: all;transition-duration: 1s;transition-timing-function: ease;transition-delay: 0s;transform:scale(0.8);}.Bchess{position: absolute;width: 40rpx;height: 40rpx;border-radius: 40rpx;background:radial-gradient(#9e9e9e -100%, #000000 100%);box-shadow: 1rpx 1rpx 2rpx 0rpx #000000;font-size: 10rpx;line-height: 50rpx;text-align: center;color: #fff;}.Wchess{position: absolute;width: 40rpx;height: 40rpx;border-radius: 40rpx;background:radial-gradient(#e4e4e4 10%, #b7aaaa);box-shadow: 1rpx 1rpx 2rpx 0rpx #0000006e;font-size: 10rpx;line-height: 50rpx;text-align: center;color: #000000;}.winner{width: 120rpx;left: 12rpx;display: none;}</style>

3.3 下棋的实时同步功能实现

**为了实现将

ChatGPT

的下棋操作实时同步到前端小程序界面,我们这里使用了

WebSocket

长连接技术。**

**使用Flask框架与前端建立WebSocket连接,可以采用

flask-socketio库

实现。下面是详细步骤:**

  1. 安装flask-socketio库,可以使用pip命令进行安装:pip install flask-socketio
  2. 在Flask应用中导入库并创建socketio实例
Copy code
from flask import Flask
from flask_socketio import SocketIO

app = Flask(__name__)
socketio = SocketIO(app)
编写路由函数,实现WebSocket连接建立和数据传输
python
Copy code
@socketio.on('connect')defon_connect():print('WebSocket连接已建立')@socketio.on('disconnect')defon_disconnect():print('WebSocket连接已断开')@socketio.on('message')defhandle_message(message):print('收到消息:', message)
    socketio.send('已收到消息:'+ message)

以上代码中,on_connect函数是当WebSocket连接建立时会被调用,on_disconnect函数是当WebSocket连接断开时会被调用,handle_message函数是当接收到消息时会被调用。


  • 获取下棋的实现代码如下:
from flask import Flask, request, jsonify
from flask_socketio import SocketIO, emit
import openai
import os

# 设置OpenAI API密钥
openai.api_key = os.getenv("OPENAI_API_KEY")# 初始化Flask应用和SocketIO
app = Flask(__name__)
socketio = SocketIO(app)# 处理WebSocket连接事件@socketio.on('connect')defhandle_connect():print('Client connected')# 处理WebSocket断开连接事件@socketio.on('disconnect')defhandle_disconnect():print('Client disconnected')# 处理发送请求事件@socketio.on('send_request')defhandle_request(request_text):# 调用OpenAI API获取回复
    response = openai.Completion.create(
        engine="davinci",
        prompt=request_text,
        max_tokens=50,
        n=1,
        stop=None,
        temperature=0.7)# 从API响应中提取回复文本
    response_text = response.choices[0].text.strip()# 将回复发送给前端
    emit('response',{'text': response_text})if __name__ =='__main__':
    socketio.run(app, host='0.0.0.0', port=5000)

四、推荐阅读

🥇入门和进阶小程序开发,不可错误的精彩内容🥇 :

  • 《小程序开发必备功能的吐血整理【个人中心界面样式大全】》
  • 《微信小程序 | 借ChatGPT之手重构社交聊天小程序》
  • 《微信小程序 | 人脸识别的最终解决方案》
  • 《微信小程序 |基于百度AI从零实现人脸识别小程序》
  • 《吐血整理的几十款小程序登陆界面【附完整代码】》

本文转载自: https://blog.csdn.net/weixin_37797592/article/details/129707566
版权归原作者 陶人超有料 所有, 如有侵权,请联系我们删除。

“微信小程序 |做一款跟ChatGPT下五指棋的小程序”的评论:

还没有评论