智能三子棋(人机大战)—— 你会是最终赢家吗?万字讲解让你实现与自己对弈

2024-02-16 08:40

本文主要是介绍智能三子棋(人机大战)—— 你会是最终赢家吗?万字讲解让你实现与自己对弈,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在这里插入图片描述

  • 魔王的介绍:😶‍🌫️一名双非本科大一小白。
  • 魔王的目标:🤯努力赶上周围卷王的脚步。
  • 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥
    在这里插入图片描述
    ❤️‍🔥大魔王与你分享:罗曼罗兰说过:这个世上只有一种真正的英雄主义,那就是认清生活的真相并且任然热爱他。

文章目录

  • 一、前言
  • 二、文件介绍
  • 三、代码实现
    • 1.完成test.c文件模板
    • 2.创建棋盘并进行初始化
    • 3.打印棋盘
    • 4.玩家下棋
    • 5.电脑下棋
    • 6.判断输赢
    • 7.判断是否满了
    • 8.电脑智能下棋
  • 四、对于初学者较陌生的知识
    • 1.休眠函数
    • 2.清屏函数
    • 3.随机数函数
  • 五、总代码
    • game.h
    • game.c
    • test.c
    • 效果展示图
  • 六、总结

一、前言

相信大家都玩过三子棋或者五子棋游戏,但你会通过编程完美实现吗,本篇将带领你真正学会三子棋,并与你自己编译出来的程序分出胜负。


二、文件介绍

test.c:测试文件
game.c:源文件,进行函数的定义
game.h:头文件(只进行声明)

我们用测试文件调用game.h声明、game.c文件中实现的函数,这就是三个文件的关系。

为了使三者联系起来,我们需要让两个源文件(.c)文件都包含头文件,这样他们中的函数就可以一起使用了。


三、代码实现

1.完成test.c文件模板

模板介绍:我们在玩游戏时,首先肯定需要看到菜单,然后菜单中有选线供玩家选择,等玩家选择完成后,就要根据玩家的选择展开不同的路线来执行程序。为了使游戏可以重复完,我们还需要让程序能够玩完一次继续玩,直到玩家不想玩选择退出程序,程序再结束。

#include "game.h"void menu()
{printf("********************\n");printf("****** 1.play ******\n");printf("****** 0.exit ******\n");printf("********************\n");
}
void test()
{int input = 0;do{menu();printf("请选择:> ");scanf("%d", &input);switch (input){case 1:printf("开始游戏\n");game();break;default:printf("输入错误,请重新输入\n");break;case 0:printf("退出游戏\n");}} while (input);
}
int main()
{test();return 0;
}

2.创建棋盘并进行初始化

因为我们是要把符号输入到二维数组中,结合我们构造出来的图案形成三子棋的模样,所以我们需要创建一个二维数组并进行初始化(因为棋盘最开始为空白的,所以二维数组初始化的内容为空格)。

我们先在test.c文件中创建一个棋盘然后再调用game.c文件中初始化棋盘的代码。

  • 初始化棋盘代码如下:
void InitBoard(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){board[i][j] = ' ';}}
}

3.打印棋盘

我们创建并初始化棋盘后,需要打印出三子棋图供玩家进行观察和下棋,如果玩家想玩不只3*3格的三子棋,或者想把三子棋改为五子棋,也就是说当规模较大时,为了方便玩家,我们给每行每列开头都给定标号,便利玩家。

//打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col)
{int k = 0;printf(" ");printf(" ");for (k = 0; k < col; k++){printf(" ");printf("%d", k + 1);printf(" ");printf(" ");}printf("\n");int i = 0;for (i = 0; i < row; i++)//打印row行{int j = 0;printf("%-2d", i + 1);//打印每行开头的行数for (j = 0; j < col; j++)//第一种行中的那一小段(空格、数组、空格){printf(" ");printf("%c", board[i][j]);printf(" ");if (j < col - 1)printf("|");//打印一个|}printf("\n");if (i < row - 1)//第二种行中的那一小段(-、-、-){printf(" ");printf(" ");//对应补齐每行开头的行数(不然棋盘会错一位)for (j = 0; j < col; j++){printf("-");printf("-");printf("-");if (j < col - 1)printf("|");//打印一个|}printf("\n");}}
}

4.玩家下棋

游戏是由程序员编译的,但是玩家可能是个小白,玩家并不知道数组下标是从0开始的,所以我们需要让玩家输入的两个值都减去1才是玩家真实想填入的地方。但是我们在填入时,首先需要判断输入的坐标是否合法,也就是说是否为坐标范围之外的值,如果是,需要重新输入,判断完这个,我们还需要判断这个坐标是否已经被使用,只有这两个条件都满足,我们才可以将棋子落入玩家想下的地方。

//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;while (1){printf("玩家下棋,请输入坐标:> ");scanf("%d %d", &i, &j);if ((i > 0 && i <= row) && (j > 0 && j <= col)){if (board[i - 1][j - 1] == ' '){board[i - 1][j - 1] = '*';break;}elseprintf("输入坐标已经使用,请重新输入\n");}elseprintf("输入坐标不在范围内,请重新输入\n");}
}

5.电脑下棋

电脑下棋需要用到随机数rand(),最后会统一讲对初学者比较陌生的库函数。和玩家下棋很相似,不过不用减一了,因为这是电脑操作的。但是还需要判断是否已被占用,若已被占用,就重新给定一组值,直到电脑成功下一个棋。

//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{while (1){int i = rand() % row;int j = rand() % col;if (board[i][j] == ' '){board[i][j] = '#';break;}}
}

6.判断输赢

三子棋的胜利分为四种形式,一种是横向三个,一种是纵向三个,一种是右下倾斜(\),一种是左下倾斜(/),这四种方式我们都会采用遍历法实现。

//判断输赢
char JudgeGame(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;//横for (i = 0; i < row; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')return board[i][j];}}//竖for (j = 0; j < col; j++){for (i = 0; i < row - 2; i++){if (board[i][j] == board[i+1][j] && board[i][j] == board[i+2][j] && board[i][j] != ' ')return board[i][j];}}//右下方向(\)for (i = 0; i < row - 2; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i+1][j + 1] && board[i][j] == board[i+2][j + 2] && board[i][j] != ' '){return board[i][j];}}}//左下方向(/)for (i = 0; i <row-2; i++){for (j = col - 1; j > 1; j--){if (board[i][j] == board[i+1][j - 1] && board[i][j] == board[i+2][j - 2] && board[i][j] != ' ')return board[i][j];}}return 0;
}

7.判断是否满了

每次判断完是否胜利后,如果没有胜利,我们不能直接让另一个下棋,我们还要判断是否已经满了,如果满了还没分出胜负(因为是先判断输赢,再判断是否满的,所以这一点不用用管就是这样),那就是平局。

//判断是否棋盘已经下满
int is_full(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1;
}

8.电脑智能下棋

我们如果不给电脑赋一点智商,他真的好笨,让他赢都赢不了,难受啊,但又没办法给他说话,那么就让我们的思想赋给电脑,这样就是两个你在对比输赢了,哈哈哈哈。

说实话让电脑智能一点其实自己想的时候没有思路,于是看了安 度 因(点击安度因可以跳转到他的文章)大佬的智能三子棋,但是真的,就瞄一眼思路瞬间就出来了,我们只要想到从获胜那里提取思路,真的一下就出来了,无非就是:那四种情况下有两个棋子,所谓的两个棋子又分为三种情况:比如说###获胜,那么情况就有三个,##空、#空#、空##,都是这三种情况,代码如下:

//电脑智能下棋
int intelligent_move(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;//横行拦截/下棋for (i = 0; i < row; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i][j + 1] && board[i][j] != ' ' && board[i][j + 2] == ' '){board[i][j+2] = '#';return 1;}if (board[i][j] == board[i][j + 2] && board[i][j] != ' ' && board[i][j + 1] == ' '){board[i][j+1] = '#';return 1;}if (board[i][j + 1] == board[i][j + 2] && board[i][j + 1] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}//纵行拦截/下棋for (j = 0; j < col; j++){for (i = 0; i < row - 2; i++){if (board[i][j] == board[i+1][j] && board[i][j] != ' ' && board[i+2][j] == ' '){board[i+2][j] = '#';return 1;}if (board[i][j] == board[i+2][j] && board[i][j] != ' ' && board[i+1][j] == ' '){board[i+1][j] = '#';return 1;}if (board[i+1][j] == board[i+2][j] && board[i+1][j] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}//右下方向拦截/下棋for (i = 0; i < row - 2; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ' && board[i + 2][j + 2] == ' '){board[i + 2][j + 2] = '#';return 1;}if (board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ' && board[i + 1][j + 1] == ' '){board[i + 1][j + 1] = '#';return 1;}if (board[i+2][j+2] == board[i + 1][j + 1] && board[i+2][j+2] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}//左下方向拦截/下棋for (i = 0; i < row - 2; i++){for (j = col-1; j > 1; j--){if (board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ' && board[i + 2][j - 2] == ' '){board[i + 2][j - 2] = '#';return 1;}if (board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ' && board[i + 1][j - 1] == ' '){board[i + 1][j - 1] = '#';return 1;}if (board[i+2][j-2] == board[i + 1][j - 1] && board[i+2][j-2] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}return 0;
}

四、对于初学者较陌生的知识

1.休眠函数

睡眠函数:我们在玩时是不是觉得电脑反应好快,我们明明已经给他赋上智慧了,他却还那么快,这不就比我们都聪明了,为了让他笨一点,我们让他下的时候反应一秒,这就引入了睡眠函数,C语言库里是小写sleep,但是VS必须开头大写,也就是Sleep,我们按小写说,那就是sleep(unsigned int),里面的无符号整型单位是ms毫秒,所以我们写1000,实际就是每次走到这个程序停顿1秒。对应的头文件是<windows.h>

2.清屏函数

清屏函数:每次棋盘被修改,我们都要打印一次,但是这次打印出来上次的不就没用了吗,让他们一直留着好麻烦,所以我们引入一个清屏函数,system(“cls”);对应的头文件是<windows.h>

3.随机数函数

  • 随机数函数rand:
  1. rand函数原型:
    一、#include <stdlib.h>;
    二、int rand(void);

  2. rand函数调用:
    一、rand()函数每次调用前会查询是否调用过srand(seed),是否给seed设定了一个值,如果有那么它会自动调用srand(seed)一次来初始化它的起始值。
    二、若之前没有调用srand(seed),那么系统会自动给seed赋初始值,即srand(1)自动调用它一次。

  • srand函数:
  1. 一、srand函数是随机数发生器的初始化函数,原型:
    void srand(unsigned int seed);
    二、这个函数需要提供一个种子,如srand(1),用1来初始化种子。
    三、rand函数产生随机数时,如果srand(seed)播下种子之后,一旦种子相同,产生的随机数将是相同的。但是我们很多时候都是要让rand()产生一个随机数,那么这就意味着我们需要让种子值时刻发生变化,所以就可以这样赋值:srand(time(NULL)),那么我们就又引入了时间函数,详细如下

  • time函数:
  1. 我们常常使用系统时间来初始化,使用time函数来获取系统时间,得到的值是一个时间戳,即从1970年1月1日到现在时间的秒数,然后将得到的time_t类型数据转化为(unsigned int)的数,然后再传给srand函数,用法如下:
    一、srand(unsigned int)time(NULL);对应的头文件:<time.h>,我们在使用rand和srand时,主要使用的就是这一种初始化方法。
    二、如果感觉时间间隔太小,可以让这个整体乘上一个数:srand((unsigned int)time(NULL)*10)
    三、time的参数传NULL表示不需要经过参数获得的time_t数据。
    四、time函数原型如下:
    time_t time(time_t * tloc); time_t类型被定义为一个长整型
    五、详细的rand讲解可以点击这里进入该文章

五、总代码

game.h

#pragma once#include <stdio.h>
#include <windows.h>
#include <time.h>
#include <stdlib.h>#define ROW 3
#define COL 3//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col);//打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col);//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col);//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col);//判断输赢
char JudgeGame(char board[ROW][COL], int row, int col);//判断是否棋盘已经下满
int is_full(char board[ROW][COL], int row, int col);//电脑智能下棋
int intelligent_move(char board[ROW][COL], int row, int col);

game.c

#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"//初始化棋盘
void InitBoard(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){board[i][j] = ' ';}}
}//打印棋盘
void PrintBoard(char board[ROW][COL], int row, int col)
{int k = 0;printf(" ");printf(" ");for (k = 0; k < col; k++){printf(" ");printf("%d", k + 1);printf(" ");printf(" ");}printf("\n");int i = 0;for (i = 0; i < row; i++)//打印row行{int j = 0;printf("%-2d", i + 1);//打印每行开头的行数for (j = 0; j < col; j++)//第一种行中的那一小段(空格、数组、空格){printf(" ");printf("%c", board[i][j]);printf(" ");if (j < col - 1)printf("|");//打印一个|}printf("\n");if (i < row - 1)//第二种行中的那一小段(-、-、-){printf(" ");printf(" ");//对应补齐每行开头的行数(不然棋盘会错一位)for (j = 0; j < col; j++){printf("-");printf("-");printf("-");if (j < col - 1)printf("|");//打印一个|}printf("\n");}}
}//玩家下棋
void PlayerMove(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;while (1){printf("玩家下棋,请输入坐标:> ");scanf("%d %d", &i, &j);if ((i > 0 && i <= row) && (j > 0 && j <= col)){if (board[i - 1][j - 1] == ' '){board[i - 1][j - 1] = '*';break;}elseprintf("输入坐标已经使用,请重新输入\n");}elseprintf("输入坐标不在范围内,请重新输入\n");}
}//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col)
{while (1){int i = rand() % row;int j = rand() % col;if (board[i][j] == ' '){board[i][j] = '#';break;}}
}//判断输赢
char JudgeGame(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;//横for (i = 0; i < row; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i][j + 1] && board[i][j] == board[i][j + 2] && board[i][j] != ' ')return board[i][j];}}//竖for (j = 0; j < col; j++){for (i = 0; i < row - 2; i++){if (board[i][j] == board[i+1][j] && board[i][j] == board[i+2][j] && board[i][j] != ' ')return board[i][j];}}//右下方向(\)for (i = 0; i < row - 2; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i+1][j + 1] && board[i][j] == board[i+2][j + 2] && board[i][j] != ' '){return board[i][j];}}}//左下方向(/)for (i = 0; i <row; i++){for (j = col - 1; j > 1; j--){if (board[i][j] == board[i+1][j - 1] && board[i][j] == board[i+2][j - 2] && board[i][j] != ' ')return board[i][j];}}return 0;
}//判断是否棋盘已经下满
int is_full(char board[ROW][COL], int row, int col)
{int i = 0;for (i = 0; i < row; i++){int j = 0;for (j = 0; j < col; j++){if (board[i][j] == ' ')return 0;}}return 1;
}//电脑智能下棋
int intelligent_move(char board[ROW][COL], int row, int col)
{int i = 0;int j = 0;//横行拦截/下棋for (i = 0; i < row; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i][j + 1] && board[i][j] != ' ' && board[i][j + 2] == ' '){board[i][j+2] = '#';return 1;}if (board[i][j] == board[i][j + 2] && board[i][j] != ' ' && board[i][j + 1] == ' '){board[i][j+1] = '#';return 1;}if (board[i][j + 1] == board[i][j + 2] && board[i][j + 1] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}//纵行拦截/下棋for (j = 0; j < col; j++){for (i = 0; i < row - 2; i++){if (board[i][j] == board[i+1][j] && board[i][j] != ' ' && board[i+2][j] == ' '){board[i+2][j] = '#';return 1;}if (board[i][j] == board[i+2][j] && board[i][j] != ' ' && board[i+1][j] == ' '){board[i+1][j] = '#';return 1;}if (board[i+1][j] == board[i+2][j] && board[i+1][j] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}//右下方向拦截\下棋for (i = 0; i < row - 2; i++){for (j = 0; j < col - 2; j++){if (board[i][j] == board[i + 1][j + 1] && board[i][j] != ' ' && board[i + 2][j + 2] == ' '){board[i + 2][j + 2] = '#';return 1;}if (board[i][j] == board[i + 2][j + 2] && board[i][j] != ' ' && board[i + 1][j + 1] == ' '){board[i + 1][j + 1] = '#';return 1;}if (board[i+2][j+2] == board[i + 1][j + 1] && board[i+2][j+2] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}//左下方向拦截/下棋for (i = 0; i < row - 2; i++){for (j = col-1; j > 1; j--){if (board[i][j] == board[i + 1][j - 1] && board[i][j] != ' ' && board[i + 2][j - 2] == ' '){board[i + 2][j - 2] = '#';return 1;}if (board[i][j] == board[i + 2][j - 2] && board[i][j] != ' ' && board[i + 1][j - 1] == ' '){board[i + 1][j - 1] = '#';return 1;}if (board[i+2][j-2] == board[i + 1][j - 1] && board[i+2][j-2] != ' ' && board[i][j] == ' '){board[i][j] = '#';return 1;}}}return 0;
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"void menu()
{printf("********************\n");printf("****** 1.play ******\n");printf("****** 0.exit ******\n");printf("********************\n");
}void game()
{char board[ROW][COL];//创建棋盘InitBoard(board, ROW, COL);//初始化棋盘PrintBoard(board, ROW, COL);//打印棋盘char ret = 0;while (1){PlayerMove(board, ROW, COL);//玩家下棋,玩家为*system("cls");//清屏PrintBoard(board, ROW, COL);//打印棋盘ret = JudgeGame(board, ROW, COL);//判断输赢if (ret != 0)break;if (ret = is_full(board, ROW, COL) == 1)break;int flag = intelligent_move(board, ROW, COL);//如果这一步电脑智能下棋确实下了,那么flag为1,否则为0if(flag==0)//flag为0,说明没有智能下棋,那么就进行随机下棋ComputerMove(board, ROW, COL);//电脑下棋,电脑为#Sleep(1000);//休眠一秒(让电脑思考一会,哈哈哈哈哈)system("cls");//清屏PrintBoard(board, ROW, COL);//打印棋盘ret = JudgeGame(board, ROW, COL);//判断输赢if (ret != 0)break;if (ret = is_full(board, ROW, COL) == 1)break;}if (ret == '*')printf("恭喜你赢啦!!!\n");else if (ret == '#')printf("好遗憾,你连自己设置的电脑都玩不赢!!!\n");elseprintf("棋盘下满了,未分出胜负,电脑表示不服!!!\n");
}
void test()
{int input = 0;do{menu();printf("请选择:> ");scanf("%d", &input);switch (input){case 1:printf("开始游戏\n");game();break;default:printf("输入错误,请重新输入\n");break;case 0:printf("退出游戏\n");}} while (input);
}int main()
{srand((unsigned int)time(NULL));test();return 0;
}

效果展示图

请添加图片描述

六、总结

在这里插入图片描述

✨请点击下面进入主页关注大魔王
如果感觉对你有用的话,就点我进入主页关注我吧!

这篇关于智能三子棋(人机大战)—— 你会是最终赢家吗?万字讲解让你实现与自己对弈的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/714049

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

通过SSH隧道实现通过远程服务器上外网

搭建隧道 autossh -M 0 -f -D 1080 -C -N user1@remotehost##验证隧道是否生效,查看1080端口是否启动netstat -tuln | grep 1080## 测试ssh 隧道是否生效curl -x socks5h://127.0.0.1:1080 -I http://www.github.com 将autossh 设置为服务,隧道开机启动

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测

时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测 目录 时序预测 | MATLAB实现LSTM时间序列未来多步预测-递归预测基本介绍程序设计参考资料 基本介绍 MATLAB实现LSTM时间序列未来多步预测-递归预测。LSTM是一种含有LSTM区块(blocks)或其他的一种类神经网络,文献或其他资料中LSTM区块可能被描述成智能网络单元,因为

vue项目集成CanvasEditor实现Word在线编辑器

CanvasEditor实现Word在线编辑器 官网文档:https://hufe.club/canvas-editor-docs/guide/schema.html 源码地址:https://github.com/Hufe921/canvas-editor 前提声明: 由于CanvasEditor目前不支持vue、react 等框架开箱即用版,所以需要我们去Git下载源码,拿到其中两个主

android一键分享功能部分实现

为什么叫做部分实现呢,其实是我只实现一部分的分享。如新浪微博,那还有没去实现的是微信分享。还有一部分奇怪的问题:我QQ分享跟QQ空间的分享功能,我都没配置key那些都是原本集成就有的key也可以实现分享,谁清楚的麻烦详解下。 实现分享功能我们可以去www.mob.com这个网站集成。免费的,而且还有短信验证功能。等这分享研究完后就研究下短信验证功能。 开始实现步骤(新浪分享,以下是本人自己实现

springboot家政服务管理平台 LW +PPT+源码+讲解

3系统的可行性研究及需求分析 3.1可行性研究 3.1.1技术可行性分析 经过大学四年的学习,已经掌握了JAVA、Mysql数据库等方面的编程技巧和方法,对于这些技术该有的软硬件配置也是齐全的,能够满足开发的需要。 本家政服务管理平台采用的是Mysql作为数据库,可以绝对地保证用户数据的安全;可以与Mysql数据库进行无缝连接。 所以,家政服务管理平台在技术上是可以实施的。 3.1

基于Springboot + vue 的抗疫物质管理系统的设计与实现

目录 📚 前言 📑摘要 📑系统流程 📚 系统架构设计 📚 数据库设计 📚 系统功能的具体实现    💬 系统登录注册 系统登录 登录界面   用户添加  💬 抗疫列表展示模块     区域信息管理 添加物资详情 抗疫物资列表展示 抗疫物资申请 抗疫物资审核 ✒️ 源码实现 💖 源码获取 😁 联系方式 📚 前言 📑博客主页:

探索蓝牙协议的奥秘:用ESP32实现高质量蓝牙音频传输

蓝牙(Bluetooth)是一种短距离无线通信技术,广泛应用于各种电子设备之间的数据传输。自1994年由爱立信公司首次提出以来,蓝牙技术已经经历了多个版本的更新和改进。本文将详细介绍蓝牙协议,并通过一个具体的项目——使用ESP32实现蓝牙音频传输,来展示蓝牙协议的实际应用及其优点。 蓝牙协议概述 蓝牙协议栈 蓝牙协议栈是蓝牙技术的核心,定义了蓝牙设备之间如何进行通信。蓝牙协议

智能客服到个人助理,国内AI大模型如何改变我们的生活?

引言 随着人工智能(AI)技术的高速发展,AI大模型越来越多地出现在我们的日常生活和工作中。国内的AI大模型在过去几年里取得了显著的进展,不少独创的技术点和实际应用令人瞩目。 那么,国内的AI大模型有哪些独创的技术点?它们在实际应用中又有哪些出色表现呢?此外,普通人又该如何利用这些大模型提升工作和生活的质量和效率呢?本文将为你一一解析。 一、国内AI大模型的独创技术点 多模态学习 多

python实现最简单循环神经网络(RNNs)

Recurrent Neural Networks(RNNs) 的模型: 上图中红色部分是输入向量。文本、单词、数据都是输入,在网络里都以向量的形式进行表示。 绿色部分是隐藏向量。是加工处理过程。 蓝色部分是输出向量。 python代码表示如下: rnn = RNN()y = rnn.step(x) # x为输入向量,y为输出向量 RNNs神经网络由神经元组成, python