express+vue 在线五子棋(一)

示例

在这里插入图片描述

在线体验地址五子棋,记得一定要再拉个人才能对战

本期难点

1、完成了五子棋的布局,判断游戏结束
2、基本的在线对战
3、游戏配套im(这个im的实现,请移步在线im)

下期安排

1、每步的倒计时设置
2、黑白棋分配由玩家自定义
3、新增旁观者
4、悔棋
5、自行创建一盘棋局

感兴趣的,还请点个免费的收藏与关注,后续会一直跟进这个系列

前端部分五子棋布局与游戏输赢判断

<template><div class="flex-wrap flex-justify-between"><div class="gobang-main"><!-- {{ userdata._id }}{{ gameBase }} -->步数: {{ currentStep }} 我方:{{ getQi }}<el-button v-if="isAdmin" @click="clearGame"> 清空游戏 </el-button><!-- 下棋区 --><game :list="gobangList" :config="config" @clickHandle="clickHandle"></game><!-- <el-button v-if="isGameOver && isAdmin" @click="reloadGame"> 重新开始 </el-button> --></div><!-- im区 --><Imref="imRef"v-if="game_im_id":style="{ width: '440px' }":isShowLeft="false":gobang_id="gobang_id":game_im_id="game_im_id"@room_baseinfo="room_baseinfo"@get_game_content="get_game_content"@get_gb_info="get_gb_info"@del_gobang="del_gobang"></Im></div>
</template><script>
import Im from '@/views/blog/im/index.vue'
import { baseURL } from '@/plugins/config.js'
import { get_gobang_list, post_gobang, get_gobang, del_gobang } from '@/api/data.js'
import game from './game.vue'
export default {components: {Im,game,},data() {return {isGameOver: false,page: 'list',gameBase: {_id:'',status: '',max: 10,max_move_time: 0,all_time: 0,hei_user_id: '',bai_user_id: '',im_romm_id:''},gobangMembers: [], // 五子棋游戏成员列表room_id: '',gobangList: [],config: {type: 1, // 1为白棋 2为黑棋line: 15, // 棋盘线条数width: 36,},first: true,}},computed: {...Vuex.mapState(['userdata']),...Vuex.mapGetters(['isAdmin']),gobang_id() {return this.gameBase._id},game_im_id() {return this.gameBase.im_romm_id},// 当前步数currentStep() {let result = 0this.gobangList.forEach((item) => {item.forEach((itey) => {if (itey.step_number > 0) {result += 1}})})return result},getQi() {// 自己是黑棋还是白棋let { _id } = this.userdataif (_id == this.gameBase.bai_user_id) {return '白棋'}if (_id == this.gameBase.hei_user_id) {return '黑棋'}return '观众'},step_content() {// 具体下的内容 1白字 2黑子const obj = {白棋: 1,黑棋: 2,}return obj[this.getQi] || 0},},created() {this.init()},methods: {del_gobang() {// 清空数据// this.gobangList = []// this.isGameOver = false// this.gameBase = {//     status: '',//     max: 10,//     max_move_time: 0,//     all_time: 0,//     hei_user_id: '',//     bai_user_id: '',// }location.reload()},clearGame() {this.$confirm('确定要清空游戏吗?').then((res) => {this.$refs.imRef.send_msg({room_id: this.room_id,specialType: 3,gobang_id: this.gobang_id,})}).catch(() => {})},// 黑棋先行,一人一只下isShould() {let { currentStep, gobangList, step_content } = this// 黑棋个数let heiNumber = 0// 白棋个数let baiNumber = 0// 遍历棋盘gobangList.forEach((aaa) => {aaa.forEach((item) => {if (item.step_content == 1) {baiNumber += 1}if (item.step_content == 2) {heiNumber += 1}})})// 判断现在下的步数的奇数还是偶数let isOdd = currentStep % 2if (step_content === 1) {// 白棋return isOdd === 1}if (step_content === 2) {// 黑棋return isOdd === 0}},clickHandle({ x, y }) {let {step_content,room_id,gobang_id,userdata: { _id: author_id },currentStep,isGameOver,} = thisif (isGameOver) {return this.$message.warning('游戏已结束')}// 只有棋手才能下棋if (![1, 2].includes(+step_content)) return// 判断是否该下子if (!this.isShould()) {return this.$message.warning('请等待对方落子')}let obj = {room_id,specialType: 2,gobang_id,gobang_member_id: author_id,step_number: currentStep + 1,step_content,x,y,author_id,}this.$refs.imRef.send_msg(obj, () => {})},room_baseinfo({ gobangMembers, room_id }) {this.gobangMembers = Array.isArray(gobangMembers) ? gobangMembers : []this.room_id = room_id || ''},initConfigList() {// 生成一个二维数组let { line } = this.configfor (let i = 0; i < line; i++) {this.gobangList.push([])for (let j = 0; j < line; j++) {this.gobangList[i].push({x: i,y: j,step_content: 0, // 0: 空 1: 白 2: 黑})}}},async init() {this.initConfigList()let res = nulltry {res = await get_gobang_list()} catch (err) {return}if (res.data || this.isArray(res.data.data)) {if (res.data.data.length === 0) {let res = await post_gobang({game_name: '五子棋',}).catch(() => {return {}})if (!res.data || !this.isObject(res.data.data)) returnObject.assign(this.gameBase,res.data.data)}if (res.data.data.length) {Object.assign(this.gameBase,res.data.data[0])}}// 获取现有的对局信息get_gobang({ gobang_id: this.gobang_id }).then((res) => {if (res.data && this.isArrayLength(res.data.data)) {let arr = res.data.datathis.gobangList = this.gobangList.map((aaa) => {aaa = aaa.map((item) => {let { x, y } = itemarr.find((itey) => {let { step_content, step_number, gobang_member_id } = iteyif (itey.x == x + 1 && itey.y == y + 1 && step_content) {Object.assign(item, {step_content,step_number,gobang_member_id,})return true}})return item})return aaa})console.log(this.gobangList)}}).catch(() => {})},get_game_content(row) {this.gobangList = this.gobangList.map((aaa) => {aaa = aaa.map((item) => {let { x, y } = itemlet { step_content, step_number, gobang_member_id } = rowif (row.x == x + 1 && row.y == y + 1 && step_content) {Object.assign(item, {step_content,step_number,gobang_member_id,})}return item})return aaa})this.checkWin()},get_gb_info(row) {this.gameBase = Object.assign(this.gameBase, row)console.log('get_gb_info',this.gameBase)},// 判断是否胜利 需要知道哪种棋子胜利checkWin() {// if(this.first) returnthis.first = false// 判断当前棋盘是否有五子连珠let { line } = this.configlet { gobangList: list } = thislet type = 0 // 0: 没有胜利 1: 白棋胜利 2: 黑棋胜利 3: 平局// 判断横向for (let i = 0; i < line; i++) {for (let j = 0; j < line - 4; j++) {if (list[i][j].step_content !== 0 &&list[i][j].step_content === list[i][j + 1].step_content &&list[i][j].step_content === list[i][j + 2].step_content &&list[i][j].step_content === list[i][j + 3].step_content &&list[i][j].step_content === list[i][j + 4].step_content) {type = list[i][j].step_contentbreak}}}// 判断纵向for (let i = 0; i < line; i++) {for (let j = 0; j < line - 4; j++) {if (list[j][i].step_content !== 0 &&list[j][i].step_content === list[j + 1][i].step_content &&list[j][i].step_content === list[j + 2][i].step_content &&list[j][i].step_content === list[j + 3][i].step_content &&list[j][i].step_content === list[j + 4][i].step_content) {type = list[j][i].step_contentbreak}}}// 判断左斜for (let i = 0; i < line - 4; i++) {for (let j = 0; j < line - 4; j++) {if (list[i][j].step_content !== 0 &&list[i][j].step_content === list[i + 1][j + 1].step_content &&list[i][j].step_content === list[i + 2][j + 2].step_content &&list[i][j].step_content === list[i + 3][j + 3].step_content &&list[i][j].step_content === list[i + 4][j + 4].step_content) {type = list[i][j].step_contentbreak}}}// 判断右斜for (let i = 0; i < line - 4; i++) {for (let j = 4; j < line; j++) {if (list[i][j].step_content !== 0 &&list[i][j].step_content === list[i + 1][j - 1].step_content &&list[i][j].step_content === list[i + 2][j - 2].step_content &&list[i][j].step_content === list[i + 3][j - 3].step_content &&list[i][j].step_content === list[i + 4][j - 4].step_content) {type = list[i][j].step_contentbreak}}}// 判断是否平局let flag = truefor (let i = 0; i < line; i++) {for (let j = 0; j < line; j++) {if (list[i][j].step_content == 0) {flag = falsebreak}}}// 如果是平局if (flag) {type = 3}const obj = {1: '白棋胜利',2: '黑棋胜利',3: '平局',}if (obj[type]) {this.$message.success(obj[type])this.isGameOver = true}},},
}
</script><style lang="scss" scoped></style>

express代码

Gobang 为五子棋基本设置表
GobangMember 五子棋对战与观战人表
GobangItem 每一步的对战信息表

const { io } = require("../../tool/socket.js");
const { AuthorInfo } = require("../../mod/author/author_info");
const { ImRoom } = require("../../mod/game/im_room.js");
const { ImRoomSys } = require("../../mod/game/im_room_sys.js");
const { ImRoomMember } = require("../../mod/game/im_room_member.js");
const { Game } = require("../../mod/game/game.js");
const { GameList } = require("../../mod/game/game_list.js");
const { Gobang } = require("../../mod/game/gobang.js");
const { GobangMember } = require("../../mod/game/gobang_member.js");
const { GobangItem } = require("../../mod/game/gobang_item.js");let allSocket = {};// 监听客户端的连接
io.on("connection", function (socket) {allSocket[socket.id] = socket;// 监听用户掉线socket.on("disconnect", async () => {// 更新用户状态let user = await ImRoomMember.findOneAndUpdate({ socket_id: socket.id },{ status: "2" });if (user) {delete allSocket[user.im_room_id];// 这是触发的方法数组,默认只有im的人员信息变化const funStatus = ["members_change"];// 对于五子棋游戏相关退出房间操作try {let res = await GobangMember.findOneAndUpdate({ socket_id: socket.id },{ status: "2" });// TODO: 这儿存在性能问题if (res.n == 1) {funStatus.push("gobang_members_change");}} catch (err) {console.log(err);}// 向房间的用户同步信息sendMsgToRoom(user.im_room_id, null, funStatus);}});// 监听加入房间socket.on("join_room", async (data) => {if (!global.isObject(data)) {resMsg("加入房间参数错误", 400);return;}// game_id 是游戏id,只有游戏才需要传入let { user_id, room_id, gobang_id } = data;if (!user_id) {resMsg("用户id不能为空", 400);return;}let user = await AuthorInfo.findOne({ _id: user_id });if (!user) {resMsg("用户不存在", 400);return;}if (!room_id) {resMsg("房间id不能为空", 400);return;}let room = await ImRoom.findOne({ _id: room_id, status: "1" });if (!room) {resMsg("房间不存在", 400);return;}let { max, status } = room;if (+status !== 1) {resMsg("房间未开放", 300);return;}// 查找所有加入该房间,并且状态为在线的用户let members = await ImRoomMember.find({im_room_id: room_id,status: 1,}).countDocuments();if (members >= max) {resMsg("房间已满", 300);return;}// 查找用户是否已经加入过该房间let oldUser = await ImRoomMember.findOne({im_room_id: room_id,author_id: user_id,});if (!oldUser) {let res = await new ImRoomMember({im_room_id: room_id,author_id: user_id,author_type: 2,created_time: getCurrentTimer(),updated_time: getCurrentTimer(),status: 1,socket_id: socket.id,}).save();if (!res) {resMsg("加入房间失败", 400);return;}} else {await ImRoomMember.updateOne({ im_room_id: room_id, author_id: user_id },{ socket_id: socket.id, status: 1 });}// 这是触发的方法数组,默认只有im的人员信息变化const funStatus = ["members_change"];// 对于五子棋游戏相关加入房间操作if (gobang_id) {let game = await Gobang.findOne({ _id: gobang_id });if (!game) {resMsg("游戏不存在", 400);return;}// 查找用户是否已经加入过该游戏let oldUser = await GobangMember.findOne({gobang_id,author_id: user_id,});if (!oldUser) {let res = await new GobangMember({gobang_id,author_id: user_id,created_time: getCurrentTimer(),updated_time: getCurrentTimer(),status: 1,socket_id: socket.id,user_type: "3",}).save();if (!res) {resMsg("加入游戏失败", 400);return;}} else {try {await GobangMember.updateOne({ gobang_id, author_id: user_id },{ socket_id: socket.id, status: 1 });} catch (error) {console.log("err", err);}}// 查看是否需要更新游戏基本信息-黑棋与白棋let gameInfo = await Gobang.findOne({ _id: gobang_id });if (gameInfo) {let { bai_user_id, hei_user_id } = gameInfo;// 查看用户是否在线let baiUser = await GobangMember.findOne({author_id: bai_user_id,gobang_id,});let heiUser = await GobangMember.findOne({author_id: hei_user_id,gobang_id,});console.log(111,heiUser,baiUser)if (!heiUser) {await Gobang.updateOne({ _id: gobang_id }, { hei_user_id: user_id });} else if (!baiUser) {await Gobang.updateOne({ _id: gobang_id }, { bai_user_id: user_id });}}funStatus.push("get_gb");funStatus.push("gobang_members_change");}// 房间信息改变,向房间内所有在线用户推送房间信息sendMsgToRoom(room_id, null, funStatus, gobang_id);});// 主动推出登录socket.on("live_room", async (data) => {let { room_id, user_id, gobang_id } = data;// 更新用户状态let user = await ImRoomMember.findOneAndUpdate({ im_room_id: room_id, author_id: user_id },{ status: "2" });if (user) {delete allSocket[user.socket_id];// 这是触发的方法数组,默认只有im的人员信息变化const funStatus = ["members_change"];if (gobang_id) {// 对于五子棋游戏相关退出房间操作try {await GobangMember.findOneAndUpdate({ gobang_id, author_id: user_id },{ status: "2" });} catch (err) {console.log(err);}funStatus.push("gobang_members_change");}// 向房间的用户同步信息sendMsgToRoom(room_id, null, funStatus, gobang_id);}});// 发送消息socket.on("send_msg", async (data) => {if (!global.isObject(data)) return;// time是时长// specialType 默认1 im的发送消息;2 五子棋的发送下棋消息 3 五子棋发送清空数据消息let {room_id,author_id,content,msg_type = "1",time = 0,poster = "",video_width = "",video_height = "",specialType = 1,gobang_id,gobang_member_id,step_number,step_content = 0,x,y,} = data;if (specialType == 3) {// 有关五子棋的消息if (!gobang_id || !room_id) {resMsg("清空数据消息有字段缺失", 400, "err", socket);return;}let gobang = await Gobang.findOneAndDelete({ _id: gobang_id });if (!gobang) {resMsg("删除失败", 400, "err", socket);return;}let { im_romm_id } = gobang;// 删除人员await ImRoomMember.deleteMany({ gobang_id: gobang_id });// 删除对局信息await GobangItem.deleteMany({ gobang_id: gobang_id });// 删除聊天室await ImRoom.deleteOne({ _id: im_romm_id });// 删除聊天记录await ImRoomSys.deleteMany({ im_romm_id });// 删除聊天成员信息await ImRoomMember.deleteMany({ im_romm_id });console.log(111)sendMsgToRoom(room_id, null, ["del_gobang"], gobang_id);return}if (specialType == 2) {// 有关五子棋的消息console.log(data);if (!room_id ||!gobang_id ||!gobang_member_id ||!gobang_member_id ||!step_number ||!x ||!y ||!author_id) {resMsg("下棋消息有字段缺失", 400, "err", socket);return;}if (![1, 2].includes(+step_content)) {resMsg("观众不能下棋", 400, "err", socket);return;}let oldGb = await GobangItem.findOne({gobang_id,step_number,});if (oldGb) {resMsg("您已经下过棋了", 400);return;}try {let newGb = await new GobangItem({gobang_id,gobang_member_id: author_id,step_number,created_time: getCurrentTimer(),updated_time: getCurrentTimer(),step_content,x,y,}).save();sendMsgToRoom(room_id, newGb, [], gobang_id);} catch (err) {console.log(err);resMsg("保存步数失败", 400);return;}return;}if (!content) {resMsg("请输入内容", 400);return;}// 判断用户是否存在if (!author_id) {resMsg("用户id不能为空", 400);return;}let user = await AuthorInfo.findOne({ _id: author_id });if (!user) {resMsg("用户id不能为空", 400);return;}// 判断房间是否存在if (!room_id) {resMsg("房间id不能为空", 400);return;}let room = await ImRoom({ _id: room_id, status: "1" });if (!room) {resMsg("房间未开放", 400);return;}if (!content) {resMsg("消息内容不能为空", 400);return;}// 保存消息let params = {im_room_id: room_id,author_id: author_id,content: content,msg_type,created_time: getCurrentTimer(),updated_time: getCurrentTimer(),};if (time) {params.time = time;}if (msg_type == 4) {if (poster) {params.poster = poster;}if (video_width) {params.video_width = video_width;}if (video_height) {params.video_height = video_height;}}let room_sys = await new ImRoomSys(params).save();if (!room_sys) {resMsg("保存消息失败", 400);return;}// 找出对应的成员信息let userinfo = await AuthorInfo.findOne({ _id: author_id },{username: 1,header_img: 1,});if (!userinfo) {resMsg("用户信息不存在", 400);return;}room_sys.author_id = userinfo;sendMsgToRoom(room_id, room_sys);});/*** 向一个房间内的所有在线用户推送房间的基本信息* row 本次聊天信息* name 触发事件的小别名* **/async function sendMsgToRoom(room_id, row = null, names = [], game_id = "") {if (!room_id) return;// 找出全部在线的成员let members = await ImRoomMember.find({im_room_id: room_id,status: 1,},{ socket_id: 1 });if (!members || members.length === 0) return;let sockets = members.map((item) => item.socket_id);// 找出房间信息let room = (await ImRoom.findOne({ _id: room_id, status: "1" })) || {};// 查找出当前房间的总消息数let roomSysCount = await ImRoomSys.find({im_room_id: room_id,}).countDocuments();let res = {data: room,roomSysCount,msg: "房间信息已更新",};if (names.length > 0) {// 去重names = [...new Set(names)];for (let i = 0; i < names.length; i++) {const item = names[i];switch (item) {case "members_change":// 人员状态有变化let roomMembers = await ImRoomMember.find({ im_room_id: room_id },{ author_id: 1, status: 1, room_username: 1 }).populate("author_id", "username header_img").exec();res.roomMembers = roomMembers;break;case "gobang_members_change":// 五子棋人员状态有变化let gobangMembers = await GobangMember.find({ gobang_id: game_id }).populate("author_id", "username header_img").exec();Object.assign(res, {gobangMembers,});break;case "get_gb":// 获取游戏的基本信息let gameInfo = await Gobang.findOne({ _id: game_id });if (gameInfo) {res.gb_info = gameInfo;}break;case "del_gobang":res.is_del_gobang = true;break;}}}if (global.isObject(row)) {if (game_id) {// 五子棋消息res.game_content = row;} else {// im有新消息res.content = row;}}sockets.forEach((item) => {let socket = allSocket[item];if (socket) {resMsg(res, 200, "room_baseinfo", socket);}});}// 获取当前时间戳function getCurrentTimer() {return Date.now();}// 统一返回消息function resMsg(msg, code = 400, name = "err", _socket) {let obj = {code,};if (code === 200) {obj.msg = "操作成功";obj.data = msg;} else {obj.msg = msg;}socket = _socket ? _socket : socket;socket.emit(name, obj);}
});

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

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

相关文章

# Kafka_深入探秘者(3):kafka 消费者

Kafka_深入探秘者&#xff08;3&#xff09;&#xff1a;kafka 消费者 一、kafka 消费者、消费组 1、Kafka 消费者是消费组的一部分&#xff0c;当多个消费者形成一个消费组来消费主题时&#xff0c;每个消费者会收到不同分区的消息。假设有一个 T1 主题&#xff0c;该主题有…

Web应用防火墙(WAF)(上:基础概念篇)

运维专题 Web应用防火墙&#xff08;WAF&#xff09;&#xff08;上&#xff1a;基础概念篇&#xff09; - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. She…

pgAdmin后台命令执行漏洞(CVE-2023-5002)

​ 我们可以看到针对于漏洞 CVE-2022-4223&#xff0c;官方做了一定的修复措施。 web\pgadmin\misc_init_.py#validate_binary_path ​ 首先是添加了 login_required​ 进行权限校验。在 Flask 框架中&#xff0c;login_required​ 装饰器通常与 Flask-Login 扩展一起使用。…

LED恒流调光电路

LED等在工作的时候发热较大&#xff0c;所以通常选用铝基板作为底板&#xff1b;常用白色油墨。 LED必须在恒流源电路下工作&#xff0c;下图为最简单的恒流源&#xff1a;B极电压3.3V不变左下侧蓝色的为稳压二极管&#xff0c;由于BE极可以看做二极管&#xff0c;压降为0.7V&…

OpenCV颜色检测

OpenCV颜色检测 前言策略分析根据颜色检测目标对象相关链接 前言 绿幕技术是一种经典的视频编辑技术&#xff0c;可以用于将人物置于不同的背景中。例如在电影制作中&#xff0c;技术的关键在于演员不能身着特定颜色的衣服(比如绿色)&#xff0c;站在只有绿色的背景前。然后&a…

异地组网如何OEM?

在现代信息社会中&#xff0c;企业越来越需要跨地域进行数据传输与共享。面临的挑战却是如何在不暴露在公网的情况下&#xff0c;实现异地组网并保障数据的安全性。本文将介绍一种名为“异地组网OEM”的解决方案&#xff0c;该方案能够通过私有通道传输数据并对数据进行安全加密…

我的大学生活-人面不知何处去(大三篇)

我的大学生活&#xff08;大三篇&#xff09; 前言推荐大三&#xff08;人面不知何处去&#xff09;2022年8月2022年9月2022年10月2022年11月2022年12月 寒假2023年1月 大三&#xff08;人面不知何处去&#xff09;2023年2月2023年3月2023年4月2023年5月2023年6月 暑假2023年7月…

【LeedCode】二分查找算法(一)

二分查找算法的时间复杂度是O(logN) &#xff0c;更优于传统的遍历数组算法值得我们学习。 注意二分查找一般使用的前提是&#xff1a;待操作的数组的元素有某种规律也就是要有二阶性&#xff0c;二段性就是在数组中选取一点根据该数组元素某种规律可以把数组分为两部分&#x…

国企:2024年6月中国移动相关招聘信息 三

中国移动卓望公司-卓望信息 卓望公司成立于2000年6月,是中国移动的控股子公司,积极拓展互联网、IT、ICT领域,提供平台及应用开发、运营运维等服务。  成立二十余年来,卓望公司逐渐形成包括业务合作管理、内容渠道运营、网络集中运维、企业服务、安全服务、行业DICT服务等…

LDR6500U,让设备爱上“被骗”的充电速度!

在数字设备日新月异的今天&#xff0c;兼容性和充电效率已成为用户关注的核心焦点。尤其是随着电子设备市场的全球化发展&#xff0c;标准化的需求日益凸显。近期&#xff0c;欧洲联盟&#xff08;简称“欧盟”&#xff09;就电子设备充电接口问题做出了重要决策&#xff0c;要…

高校新生如何选择最优手机流量卡?

一年一度的高考已经结束了&#xff0c;愿广大学子金榜题名&#xff0c;家长们都给孩子准备好了手机&#xff0c;那么手机流量卡应该如何选择呢&#xff1f; 高校新生在选择手机流量卡时&#xff0c;需要综合考量流量套餐、费用、网络覆盖、售后服务等多方面因素&#xff0c;以下…

Java开发-实际工作经验和技巧-0001-PostgreSQL数据库存储磁盘满了重启以及应急措施

Java开发-实际工作经验和技巧-0001-PostgreSQL数据库存储磁盘满了重启以及应急措施 更多内容欢迎关注我&#xff08;持续更新中&#xff0c;欢迎Star✨&#xff09; Github&#xff1a;CodeZeng1998/Java-Developer-Work-Note 技术公众号&#xff1a;CodeZeng1998&#xff0…

用于射频功率应用的氮化铝电阻元件

EAK推出了新的厚膜氮化铝 &#xff08;AlN&#xff09; 电阻器和端接系列&#xff0c;以补充公司现有的产品。传统上&#xff0c;射频功率电阻元件采用氧化铍&#xff08;BeO&#xff09;陶瓷材料作为陶瓷基板;然而&#xff0c;由于国际上要求从产品中去除BeO的压力&#xff0c…

[HBM] HBM 国产进程, 国产HBM首次研发成功 (202406)

依公知及经验整理&#xff0c;原创保护&#xff0c;禁止转载。 专栏 《深入理解DDR》 AI 的火热浪潮带火了高带宽内存的需求&#xff0c;HBM已是存储市场耀眼的明星。目前市场上还没有国产HBM, 什么时候可以看到国产希望呢&#xff1f; 或许现在可以看到曙光了。 1. 设计端 1…

免费内网穿透工具 ,快解析内网穿透解决方案

在IPv4公网IP严重不足的环境下&#xff0c;内网穿透技术越来越多的被人们所使用&#xff0c;使用内网穿透技术的好处有很多。 1&#xff1a;无需公网ip 物以稀为贵&#xff0c;由于可用的公网IP地址越来越少&#xff0c;价格也是水涨船高&#xff0c;一个固定公网IP一年的成本…

全面讲解数字化采购:整体技术架构与最佳实践

在全球化和数字化浪潮的推动下&#xff0c;企业的采购流程正经历深刻变革。数字化采购通过引入先进的信息技术&#xff0c;优化供应链管理&#xff0c;提高采购效率&#xff0c;降低成本。本文将详细介绍数字化采购的整体技术架构&#xff0c;并分享最佳实践经验&#xff0c;帮…

Jenkins nginx自动化构建前端vue项目

在现代的Web开发中&#xff0c;Vue.js已经成为一种非常流行的JavaScript框架。为了更高效地管理和部署Vue.js项目&#xff0c;使用自动化构建工具是至关重要的。Jenkins作为一款强大的持续集成和持续部署&#xff08;CI/CD&#xff09;工具&#xff0c;为我们提供了一种便捷的方…

海洋生物识别系统+图像识别+Python+人工智能课设+深度学习+卷积神经网络算法+TensorFlow

一、介绍 海洋生物识别系统。以Python作为主要编程语言&#xff0c;通过TensorFlow搭建ResNet50卷积神经网络算法&#xff0c;通过对22种常见的海洋生物&#xff08;‘蛤蜊’, ‘珊瑚’, ‘螃蟹’, ‘海豚’, ‘鳗鱼’, ‘水母’, ‘龙虾’, ‘海蛞蝓’, ‘章鱼’, ‘水獭’, …

Apple - Media Playback Programming Guide

本文翻译整理自&#xff1a;Media Playback Programming Guide&#xff08;Updated: 2018-01-16 https://developer.apple.com/library/archive/documentation/AudioVideo/Conceptual/MediaPlaybackGuide/Contents/Resources/en.lproj/Introduction/Introduction.html#//apple_…