用ChatGPT通过WebSocket开发一个交互性的五子棋微信小程序(二)

文章目录

    • 1 前言
      • 1.1 实现的原理
      • 1.2 如何与微信小程序联系
    • 2 五子棋项目
      • 2.1 申请OpenAI的API
      • 2.2 调用API代码
      • 2.3 界面代码
    • 3 同步五子棋到前端小程序
      • 3.1 WebSocket长连接
      • 3.2 获取实时下棋
    • 4 讨论

1 前言

1.1 实现的原理

大体方向是将ChatGPT作为后端语言模型,然后将其与前端的图形用户界面(GUI)集成起来。以下是三大关键要素:

  • 游戏逻辑

首先在游戏逻辑方面,我们需要检测玩家点击的位置,并在棋盘上放置相应的棋子。在每次玩家下棋后,我们需要检查游戏是否结束,以及胜利方是哪一方。这可以通过遍历棋盘上的棋子来实现。我们可以检查每个棋子的周围8个方向是否有五个相同的棋子,如果有,则游戏结束,并宣布胜利方是哪一方。

  • 与ChatGPT集成

为了让玩家与ChatGPT进行交互,我们可以在每次玩家下棋后,将棋盘上的状态作为输入传递给ChatGPT模型。ChatGPT将输出一个字符串,表示ChatGPT认为下一步应该下哪个位置。然后,我们将该位置用一个不同的颜色显示在棋盘上,作为ChatGPT下的棋子。

  • 界面

首先是要创建一个游戏界面,将一个窗口将其分成15x15的网格,并在其中绘制棋盘线。

最后,我们需要创建一个用户界面,允许玩家与游戏进行交互。我们可以在窗口底部添加一个文本框,用于输入ChatGPT的文本提示,并添加一个按钮,用于让ChatGPT下棋。玩家可以在棋盘上点击一个位置,然后按下按钮,将其作为ChatGPT的输入。在接收到ChatGPT的下棋提示后,程序会自动在棋盘上下一个棋子。

1.2 如何与微信小程序联系

以下一个基本流程:

  1. 用户进入微信小程序并打开五子棋游戏页面。
  2. 游戏页面显示游戏界面,包括棋盘、棋子和提示信息。
  3. 用户点击棋盘上的一个位置,将其作为下一步的落子位置。
  4. 用户点击下棋按钮,触发下棋事件。
  5. 小程序将用户落子位置和当前棋盘状态作为输入传递给ChatGPT模型。
  6. ChatGPT模型计算出下一步最佳落子位置,并将该位置返回给小程序。
  7. 小程序在棋盘上显示ChatGPT的落子位置。
  8. 小程序检查游戏是否结束,并宣布胜利方是哪一方。
  9. 用户可以选择再次玩游戏或者退出游戏。

用字符画了个简陋的流程图,我奶奶都会看:

+---------+       +--------+      +--------+
|         |       |        |      |        |
|进入小程序 | -->   |游戏界面 | -->  |  下棋   |
|         |       |        |      |        |
+---------+       +--------+      +--------+||v+-------------+| ChatGPT 模型 |+-------------+||v+------------+| 在棋盘上下棋 |   +------------+||v+--------------+| 游戏结束或退出 |+--------------+

2 五子棋项目

2.1 申请OpenAI的API

还是老样子,OpenAI的API网址:https://platform.openai.com/account/api-keys

2.2 调用API代码

用Python的request库:

import os
import requests
import jsonAPI_KEY = os.environ.get("OPENAI_API_KEY")def generate_text(prompt: str, max_tokens: int) -> str:headers = {"Content-Type": "application/json","Authorization": f"Bearer {API_KEY}"}data = {"prompt": prompt,"max_tokens": max_tokens}response = requests.post(url="https://api.openai.com/v1/engines/davinci-codex/completions",headers=headers,data=json.dumps(data))response.raise_for_status()response_data = json.loads(response.text)generated_text = response_data["choices"][0]["text"]return generated_text.strip()if __name__ == "__main__":prompt = "Hello, my name is"max_tokens = 5try:generated_text = generate_text(prompt, max_tokens)print(f"Generated text: {generated_text}")except requests.exceptions.RequestException as e:print(f"Error: {e}")

用OpenAI库:

from flask import Flask, request
import openai
import osapp = Flask(__name__)openai.api_key = os.environ.get("OPENAI_API_KEY")def generate_response(prompt: str, max_tokens: int = 60) -> str:response = openai.Completion.create(engine="davinci",prompt=prompt,max_tokens=max_tokens)return response.choices[0].text.strip()@app.route("/")
def home():return "Hello, World!"@app.route("/chat", methods=["POST"])
def chat():try:data = request.jsonmessage = data["message"]if not message:return "Invalid message", 400response = generate_response(message)return responseexcept (KeyError, ValueError):return "Invalid request data", 400except Exception as e:return str(e), 500if __name__ == "__main__":port = int(os.environ.get("PORT", 5000))app.run(host="0.0.0.0", port=port, debug=True)

2.3 界面代码

 <template><view class="chat-room"><gpt-card :show="showGPT"></gpt-card><view class="box" ><view class="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><view class="winner"><view class="state-chess Bchess"></view><view class="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;export default {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.showGPTthis.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 = trueself.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 = 1self.userInfo.name = users[0].nickname}if(users.length==2){self.userInfo.chessRole = 2self.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 = contentthis.chessMassage.chessRole = this.userInfo.chessRolelet userNum=this.currentRoom.onlineUsers.users.lengthmessage = {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.1 WebSocket长连接

FlaskFlask-SocketIO 实现了一个简单的WebSocket服务,先安装库:pip install flask-socketio,创建一个socketio实例:

# app.py
from flask import Flask
from flask_socketio import SocketIOsocketio = SocketIO()def create_app(config=None):app = Flask(__name__)app.config.from_mapping(SECRET_KEY='your-secret-key',# other Flask config parameters)if config is not None:app.config.from_mapping(config)socketio.init_app(app)register_blueprints(app)return appdef register_blueprints(app):from . import chatapp.register_blueprint(chat.bp)# chat.py
from flask import Blueprint, request
from flask_socketio import emit, join_room, leave_roombp = Blueprint('chat', __name__)@bp.route('/')
def index():return "Hello, World!"@socketio.on('connect')
def on_connect():print('WebSocket连接已建立')@socketio.on('disconnect')
def on_disconnect():print('WebSocket连接已断开')@socketio.on('join')
def on_join(data):username = data['username']room = data['room']join_room(room)emit('message', f'{username} 加入了房间 {room}', room=room)@socketio.on('leave')
def on_leave(data):username = data['username']room = data['room']leave_room(room)emit('message', f'{username} 离开了房间 {room}', room=room)@socketio.on('message')
def on_message(data):username = data['username']message = data['message']room = data['room']emit('message', f'{username}: {message}', room=room)

3.2 获取实时下棋

from flask import Flask, request, jsonify
from flask_socketio import SocketIO, emit
import openai
import os# 初始化Flask应用和SocketIO
app = Flask(__name__)
socketio = SocketIO(app)# 从环境变量中读取OpenAI API密钥
openai.api_key = os.getenv("OPENAI_API_KEY")# 处理WebSocket连接事件
@socketio.on('connect')
def handle_connect():print('Client connected')# 处理WebSocket断开连接事件
@socketio.on('disconnect')
def handle_disconnect():print('Client disconnected')# 处理发送请求事件
@socketio.on('send_request')
def handle_request(request_text):try:# 调用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})except Exception as e:# 如果发生异常,将错误信息返回给前端emit('response', {'error': str(e)})if __name__ == '__main__':socketio.run(app, host='0.0.0.0', port=5000)

4 讨论

实现五子棋这个工作原理是很容易理解的,重点难点是小程序的界面代码,和同步下棋内容到小程序,这一步可以理解为是可视化,笔者是OS系统,似乎是路径或者环境问题,部分报错尚未解决,以上代码是结合windows优化过的,下篇出成品介绍!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/1969.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我用ChatGPT开发一个小程序赚到第一桶金

ChatGPT是OpenAI基于GPT-3.5架构训练出来的一个大型语言模型&#xff0c;其拥有广泛的使用者群体。随着机器学习技术的不断进步&#xff0c;ChatGPT在人工智能应用领域中的应用越来越广泛。 ChatGPT被广泛应用于智能客服领域&#xff0c;因为它可以帮助企业提高客户满意度和快…

2023全新ChatGPT3.5小程序开源源码 全新UI 全网首发

2023全新ChatGPT3.5小程序开源源码 全新UI 全网首发 这一版本ui比较好看 回复速度也快了 小程序是java的 带后台 本来准备给你们带上接口的然后么后台是和接口连接的 几十块钱&#xff01; 而且最近openkey 封号比较频繁所以大家自己弄下&#xff01; 小程序需配合java…

全网首发2023全新ChatGPT3.5小程序开源源码 全新UI

源码简介&#xff1a; 2023全新ChatGPT3.5小程序开源源码 全新UI 全网首发 这一版本ui比较好看 回复速度也快了 小程序是java的 带后台 本来准备给你们带上接口的然后么后台是和接口连接的 我改什么内容你们前段都会显示所以全开源 自己搭建下吧&#xff0c;腾讯云买个国外服…

ChatGPT之小程序开发

写一个能够使用ChatGPT的微信小程序需要什么呢&#xff1f; 列出项目目录 components dialogue 是否能完成一个微信小程序项目呢&#xff1f; 投票 说说各位的看法&#xff1a;

类chatGPT接入小程序,效果也不差

经过一周的努力&#xff0c;我们终于完成了一个免费的 类ChatGPT小程序接入的搭建。chatGPT就不用介绍了&#xff0c;他是利用大规模预训练好的神经网络模型生成自然语言的相应。类chatGPT目前有开源的模型框架&#xff0c;可以尝试自己进行训练一下。如果想让他们服务于自己的…

如何用chatgpt源码搭建小程序

在今天的互联网时代&#xff0c;小程序已经成为了一种非常流行的应用形式&#xff0c;同时也是越来越多企业和个人必不可少的一种展示和交互的工具。开发一个自己的小程序需要有对技术的一定要求&#xff0c;但是通过使用chatgpt源码&#xff0c;我们可以比较轻松地搭建一个自己…

ChatGPT引导下的编程起航:零基础学会Python编程(ChatGPT版)

&#x1f482; 个人网站:【海拥】【游戏大全】【神级源码资源网】&#x1f91f; 前端学习课程&#xff1a;&#x1f449;【28个案例趣学前端】【400个JS面试题】&#x1f485; 寻找学习交流、摸鱼划水的小伙伴&#xff0c;请点击【摸鱼学习交流群】 目录 前言如何使用 ChatGPT对…

如何实现高性能网络编程-ChatGPT怎么看

hi ,大家好&#xff0c;我是大师兄。 听说最近chatgpt特别火&#xff0c;那我们邀请一下chatgpt如何实现&#xff1a; 我们先来小试牛刀&#xff1a; 刚开始用先用英文交流一下&#xff0c;然后试一下中文&#xff1a; 元芳你怎么看&#xff1f; 下期直播主题--网络编程 (如何实…

什么是真正的ChatGPT——ChatGPT的工作原理、优点和限制分析

目录 前言 ChatGPT的优点 1. 可以识别情感并作出相应的回应 2. 可以提供实用的建议和指南 3. 可以提供个性化的服务 4. 可以提高效率和便捷性 ChatGPT的限制和挑战 1. 对于一些复杂或模糊的问题无法处理 2. 面临隐私和安全问题 3. 需要大量的数据和算法支持 总结 前言…

15个借助AI,ChatGPT自动写代码工具

整理了15个借助AI和ChatGPT辅助我们自动写代码的工具&#xff0c;整理到 15个借助AI,ChatGPT自动写代码工具https://www.webhub123.com/#/home/detail?projectHashid19072648&ownerUserid27786724 ​每个卡片为一个工具对应的网址&#xff0c;点击图片直达。可以点击右上…

用ChatGPT做嵌入式应用开发

ChatGPT是一种基于自然语言处理技术的人工智能模型&#xff0c;由OpenAI团队开发的。它基于大规模的语言数据集进行训练&#xff0c;并可以生成高质量的自然语言文本&#xff0c;包括对话、摘要、翻译等多种应用。 ChatGPT 主要应用场景包括&#xff1a; 智能客服&#xff1a…

9款工具让 ChatGPT 如虎添翼! 帮你效率翻百倍!

ChatGPT chat.openai.com ChatGPT能够在同一个会话期间内回答上下文相关的后续问题。其在短时间内引爆全球的原因在于&#xff0c;在网友们晒出的截图中&#xff0c;ChatGPT不仅能流畅地与用户对话&#xff0c;甚至能写诗、撰文、编码。 会问AI 地址&#xff1a;公众号 「…

ChatGPT万能工具箱 | ChatGPT辅助神器 提升了用户体验 提问回答更加精确。

简介 提高ChatGPT网站的用户体验&#xff0c;提供一些实用的功能&#xff0c;如自动从URL中填充提示、在回复框中提供自动提示按钮等等。通过ChatGPT万能工具箱&#xff0c;您可以获得一些额外的实用功能&#xff0c;以提高ChatGPT网站的使用体验。目前&#xff0c;我们提供了两…

4个ChatGPT拓展出来的工具

现在ChatGPT 相关 的方向非常的多&#xff0c;各个大厂一个一个推出了自己的大模型&#xff0c;从国外到国内&#xff0c;ChatGPT 相关 也有几十个&#xff0c;这是大厂的方向。 对于比较小的团队&#xff0c;很多都是在ChatGPT 的基础上进行的开发&#xff0c;下面罗列出4个在…

体验一波ChatGpt工具-cursor(自动代码生成)

最近体验了一把cursor&#xff0c;自动生成代码工具&#xff0c;集成了最近很火的ChatGpt&#xff0c;目前比较好的就是代码生成工具大概就是github copilot和cursor&#xff0c;不过github copilot需要付费使用或者漫长的waitlist&#xff0c;所以目前比较好的cursor 官网介绍…

当我问 ChatGPT 能否推荐一下好用的 API 管理工具时?

近期围绕 ChatGPT 的话题&#xff0c;真的太多了。我们就知道了 ChatGPT 简单说就是搜索引擎社交工具&#xff0c;这个解释最简单明了。出于好奇&#xff0c;我也用 ChatGPT 测试了一下&#xff1a; 我&#xff1a; 在中国&#xff0c;最好的 API 管理工具是什么&#xff1f; …

13种ChatGPT类实用工具

01 /ChatGPT for google/ 一个浏览器插件&#xff0c;可搭配现有的搜索引擎来使用 最大化搜索效率&#xff0c;对搜索体验的提升相当离谱&#xff1a; 安装完插件后&#xff0c;在搜索引擎搜索任何问题&#xff0c;都能获取两份答案 谷歌ChatGPT演示 02 /VScode 插件/ 程序员…

16款ChatGPT工具,炸裂收藏!

上一篇&#xff1a;ChatGPTXMind&#xff0c;炸裂了&#xff01; 1.ChatGPT for google 一个浏览器插件&#xff0c;可搭配现有的搜索引擎来使用。 最大化搜索效率&#xff0c;对搜索体验的提升相当离谱&#xff1a; 安装完插件后&#xff0c;在搜索引擎搜索任何问题&#xff0…

ChatGPT:这个AI工具集导航你应该收藏

AI的到来让我们的工作事半功倍&#xff0c;无论你是文员&#xff0c;财务&#xff0c;还是开发营销&#xff0c;你有了这些AI工具&#xff0c;你的工作效率将大大提升。 这个AI工具集包含了&#xff0c;AI写作&#xff0c;AI图像&#xff0c;AI聊天。。。等等机会所有的AI工具…

16款ChatGPT工具,太炸裂了,收藏!

因公众号更改推送规则&#xff0c;请点“在看”并加“星标”第一时间获取精彩技术分享 点击关注#互联网架构师公众号&#xff0c;领取架构师全套资料 都在这里 0、2T架构师学习资料干货分 上一篇&#xff1a;ChatGPT研究框架&#xff08;80页PPT&#xff0c;附下载&#xff09;…