C++学习路线(数据库学习)十

项目实战 - 推箱子优化

数据库表设计

  1. 用户表

表名

Users

字段名

类型

是否为空

默认值

主、外键

备注

id

int(11)

NOT

1,自增长

PK

用户id

username

varchar(64)

NOT

用户名:英文字符、数字和特殊符号的组合

password

varchar(32)

NOT

密码:英文字符、数字和特殊符号的组合,8-16位

level_id

int

1

当前关卡,关联Levels表中的id

  1. 关卡表

表名

Levels

字段名

类型

是否为空

默认值

主、外键

备注

id

int

NOT

1

PK

游戏关卡序号,从1开始

name

varchar(64)

NOT

地图名称

map_row

int

NOT

地图二位组的总行数

map_column

int

NOT

地图二维组的总列数

map_data

varchar(4096)

NOT

地图数据,二维数组对应的行列式,多行以|分开,列以逗号分隔,最大接近支持45x45的地图

next_level_id

int

0

下一关的关卡id,0代表通关

mysql>  create database box_man;   #创建数据库box_man                                                                                                                        

mysql>                                                                                     

mysql>  create table users(          #创建用户表                                                              

             id int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,                              

             username varchar(64) NOT NULL UNIQUE,                                                

             password varchar(32) NOT NULL ,                                                  

             level_id int  default 1                                                              

         );                                                                                  

mysql>  create table levels(         #创建关卡表                                                         

             id int NOT NULL PRIMARY KEY default 1,                                                 

             name varchar(64) NOT NULL UNIQUE,                                                    

             map_row int  NOT NULL,                                                               

             map_column   int NOT NULL,                                                           

             map_data     varchar(4096) NOT NULL,                                        

             next_level_id  int default 0                                                     

         );                                                                                  

mysql>   insert into users values(1000, 'martin', md5('123456qweQWE'), 1);                    

mysql>   insert into levels values(1, '牛刀小试', 9, 12,                                            

 '0,0,0,0,0,0,0,0,0,0,0,0|0,1,0,1,1,1,1,1,1,1,0,0|0,1,4,1,0,2,1,0,2,1,0,0|0,1,0,1,0,1,0,0,1,1,1,0|0,1,0,2,    

0,1,1,4,1,1,1,0|0,1,1,1,0,3,1,1,1,4,1,0|0,1,2,1,1,4,1,1,1,1,1,0|0,1,0,0,1,0,1,1,0,0,1,0|0,0,0,0,0,0,0,0,0,0,  

0,0',0);                                                                                      

                                                                                                                  

代码优化

  1. 登陆认证

database.cpp

#include "database.h"

#include <mysql.h>

#include <stdio.h>

#define DB_NAME  "box_man"

#define DB_HOST  "127.0.0.1"

#define DB_PORT  3306

#define DB_USER  "root"

#define DB_USER_PASSWD  "123456qweQWE"

static bool connect_db(MYSQL& mysql);

/***************************************************

 *功能:通过用户名和密码从数据库获取用户信息

 *输入:

 *      user - 用户信息结构体

 *

 *返回值:

 *       获取成功返回true, 失败false

 ***************************************************/

bool fetch_user_info(userinfo& user) {

    MYSQL mysql;

    MYSQL_RES* res; //查询结果集

    MYSQL_ROW row;  //记录结构体

    char sql[256];

    bool ret = false;

    //1.连接到数据库

    if (connect_db(mysql) == false) {

        return false;

    }

    //2.根据用户名和密码获取用户信息(id, level_id)

    snprintf(sql, 256, "select id, level_id from users where username='%s' and password=md5('%s');", user.username.c_str(), user.passwd.c_str());

    ret = mysql_query(&mysql, sql); //成功返回0

    if (ret) {

        printf("数据库查询出错,%s 错误原因: %s\n", sql, mysql_error(&mysql));

        mysql_close(&mysql);

        return false;

    }

    //3.获取结果

    res = mysql_store_result(&mysql);

    row = mysql_fetch_row(res);

    if (row == NULL) {//没有查找到记录

        mysql_free_result(res);

        mysql_close(&mysql);

        return false;

    }

    user.id = atoi(row[0]);

    user.level_id = atoi(row[1]);

    printf("userid: %d  level_id: %d\n", user.id, user.level_id);  //打印ID

    //4.返回结果

    //释放结果集

    mysql_free_result(res);

    //关闭数据库

    mysql_close(&mysql);

    return true;

}

bool connect_db(MYSQL& mysql) {

    //1.初始化数据库句柄

    mysql_init(&mysql);

    //2.设置字符编码

    mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "gbk");

    //3.连接数据库

    if (mysql_real_connect(&mysql, DB_HOST, DB_USER, DB_USER_PASSWD, DB_NAME, DB_PORT, NULL, 0) == NULL) {

        printf("数据库连接出错, 错误原因: %s\n", mysql_error(&mysql));

        return false;

    }

    return true;

}

database.h

#pragma once

#include <string>

using namespace std;

//用户信息

typedef struct _userinfo{

int id;            //用户id

string username;   //用户名

string passwd;     //密码

int level_id;      //关卡id

}userinfo;

bool fetch_user_info(userinfo &user);

boxman.cpp

bool login(userinfo& user) {

int times = 0;

bool ret = false;

do{

cout << "请输入用户名: ";

cin >> user.username;

cout << "请输入密码: ";

cin >> user.passwd;

//返回 bool ,成功返回true ,失败返回false .

ret = fetch_user_info(user);

times++;

if (times >= MAX_RETRY_TIMES) {

break;

}

if (ret == false) {

cout << "登陆失败,请重新输入!" << endl;

}

} while (!ret);

return ret;

}

  1. 获取关卡

//database.h

typedef struct _levelinfo {

int id;            //关卡的id

string name;       //关卡的名字

int map_row;       //地图总行数

int map_column;    //地图总列数

string  map_data;  //二维地图数据

int next_level;    //下一关卡的id

}levelinfo;

bool fetch_level_info(levelinfo &level, int level_id);

//database.cpp

/***************************************************

 *功能:根据关卡id 获取完整的关卡信息(如: 地图,下一关等)

 *输入:

 *      level - 保存关卡信息的结构体变量

 *      level_id - 要获取详细关卡信息的关卡id

 *返回值:

 *       获取成功返回true, 失败false

 ***************************************************/

bool fetch_level_info(levelinfo& level, int level_id) {

    MYSQL mysql;

    MYSQL_RES* res; //查询结果集

    MYSQL_ROW row;  //记录结构体

    char sql[256];

    bool ret = false;

    //1.连接到数据库

    if (connect_db(mysql) == false) {

        return false;

    }

    //2.根据关卡id查询数据库获取关卡地图信息

    snprintf(sql, 256, "select  name, map_row, map_column, map_data, next_level_id from levels where id=%d;", level_id);

    ret = mysql_query(&mysql, sql); //成功返回0

    if (ret) {

        printf("数据库查询出错,%s 错误原因: %s\n", sql, mysql_error(&mysql));

        mysql_close(&mysql);

        return false;

    }

    //3.获取结果

    res = mysql_store_result(&mysql);

    row = mysql_fetch_row(res);

    if (row == NULL) {//没有查找到记录

        mysql_free_result(res);

        mysql_close(&mysql);

        return false;

    }

    level.id = level_id;

    level.name = row[0];

    level.map_row = atoi(row[1]);

    level.map_column = atoi(row[2]);

    level.map_data = row[3];

    level.next_level = atoi(row[5]);

    if(debug) printf("level id: %d  name: %s map row: %d  map column: %d map data: %s next level: %d\n", level.id, level.name.c_str(), level.map_row, level.map_column, level.map_data.c_str(), level.next_level);

    

    //释放结果集

    mysql_free_result(res);

    //关闭数据库

    mysql_close(&mysql);

    return  true;

}

  1. 地图适配

//database.h

bool transform_map_db2array(levelinfo &level, int map[LINE][COLUMN]);

//database.cpp

bool transform_map_db2array(levelinfo& level, int map[LINE][COLUMN]) {

    if (level.map_row > LINE || level.map_column > COLUMN) {

        printf("地图超大,请重新设置!\n");

        return false;

    }

    if (level.map_data.length() < 1) {

        printf("地图数据有误,请重新设置!\n");

        return false;

    }

    int start = 0, end = 0;

    int row = 0, column = 0;

    do {

        end = level.map_data.find('|', start);

        if (end < 0) {

            end = level.map_data.length();

        }

        if (start >= end) break;

        string line = level.map_data.substr(start, end - start);

        printf("get line: %s\n", line.c_str());

        //对行地图数据进行解析

        char *next_token = NULL;

        char* item = strtok_s((char*)line.c_str(), ",", &next_token);

        column = 0;

        while (item && column < level.map_column) {

            printf("%s ", item);

            map[row][column] = atoi(item);

            column++;

            item = strtok_s(NULL, ",", &next_token);

        }

        if (column < level.map_column) {

            printf("地图数据解析出错,终止!\n");

            return false;

        }

        printf("\n");

        row++;

        if (row >= level.map_row) {

            break;

        }

        start = end + 1;

    } while (1 == 1);

    if (row < level.map_row) {

        printf("地图行数少于设定, %d(need: %d),终止!\n", row, level.map_row);

        return false;

    }

    return true;

}

//boxman.cpp

//把数据库中的地图数据转换到map 中

ret = transform_map_db2array(level, map);

  1. 下一关跳转

//database.h

bool update_user_level(userinfo& user, int next_level_id);

//database.cpp

bool update_user_level(userinfo& user, int next_level_id) {

    MYSQL mysql;

    MYSQL_RES* res; //查询结果集

    MYSQL_ROW row;  //记录结构体

    char sql[256];

    bool ret = false;

    //1.连接到数据库

    if (connect_db(mysql) == false) {

        return false;

    }

    //2.根据用户id 更新下一关的level_id

    snprintf(sql, 256, "update users set level_id = %d where id=%d;", next_level_id, user.id);

    ret = mysql_query(&mysql, sql);

    if (ret) {

        printf("数据库更新出错,%s 错误原因: %s\n", sql, mysql_error(&mysql));

        mysql_close(&mysql);

        return false;

    }

    //关闭数据库

    mysql_close(&mysql);

    return true;

}

//boxman.cpp

//...............前面省略N行代码....................

void gameNextScene(IMAGE* bg) {

putimage(0, 0, bg);

settextcolor(WHITE);

RECT rec = { 0, 0, SCREEN_WIDTH, SCREEN_HEIGHT };

settextstyle(20, 0, _T("宋体"));

drawtext(_T("恭喜您~ \n此关挑战成功,任意键跳转到下一关!"), &rec, DT_CENTER | DT_VCENTER | DT_SINGLELINE);

::system("pause");

cleardevice();

}

//...............中间省略N行代码....................

if (isGameOver()) {

if (level.next_level < 1) {

gameOverScene(&bg_img);

quit = true;

break;

}

gameNextScene(&bg_img);

//更新用户下一关的关卡信息

if (update_user_level(user, level.next_level)) {

user.level_id = level.next_level;

}

break;

//quit = true;

}

  1. 实战 棋牌游戏数据库开发
  2. 用户表

表名

UserInfo

字段名

类型

是否为空

默认值

主、外键

备注

id

int(11)

NOT

1,自增长

PK,FK

用户id

userName

varchar(64)

NOT

用户名:英文字符、数字和特殊符号的组合

nickName

varchar(64)

NOT

昵称

passWord

varchar(32)

NOT

密码:英文字符、数字和特殊符号的组合,8-16位

gender

enum

(,)

性别,男/女

userRight

bit(64)

NOT

基本权限

玩家权限标志,每一位代表一种权限, 比如旁观权限,大厅公聊权限,私聊权限等。

faceID

int(11)

默认头像

玩家头像索引号码

registerDate

datetime

NOT

玩家注册日期

LastLogonDate

datetime

NOT

玩家最后登陆日期

lastLogonIp

varchar(32)

NOT

玩家最后登陆IP

logonTimes

int(11)

NOT

玩家登陆总次数

mobile

char(11)

NOT

玩家注册手机

age

tinyint(3)

玩家年龄

  1. 游戏信息表

表名

GameInfo

字段名

类型

是否为空

默认值

主、外键

备注

userId

int(11)

NOT

FK

玩家标识ID,是用户ID 表的外键

score

int

NOT

0

玩家分数(金币数)

winCount

int

NOT

0

游戏胜利局数

LostCount

int

NOT

0

游戏输局局数

fleeCount

int

NOT

0

游戏逃跑局数

playTimeCount

int

NOT

0

玩家游戏的总时长

allPlayTimes

int

NOT

0

玩家游戏的总次数

  1. 游戏日志表

表名

GameLog

字段名

类型

是否为空

默认值

主、外键

备注

userId

int(11)

NOT

FK

玩家标识ID,是用户ID 表的外键

roomId

int

NOT

房间号

kindId

int

NOT

玩家进入的房间类型标识号码

InScore

int

NOT

玩家进入房间开始游戏时的分值(金币数)

goal

int

NOT

游戏得分,+表示赢钱,-表示输钱

WinCount

int

NOT

0

在房间中游戏胜利局数

LostCount

int

NOT

0

在房间中游戏失败局数

clientIP

varchar(32)

NOT

0

玩家登入房间的IP地址

logonTime

datetime

NOT

玩家进入房间的时间

leftTime

datetime

NOT

玩家离开房间的时间

  1. 游戏列表信息

表名

GameList

字段名

类型

是否为空

默认值

主、外键

备注

typeId

int

NOT

PK

类型标识ID,是用户ID 表的外键

typeName

varchar(64)

NOT

类型名字,例如扑克类,麻将类等

enable

int

NOT

1

控制游戏大厅是否显示该类型,默认为 1,即为默认显示

  1. 游戏种类信息

表名

GameLog

字段名

类型

是否为空

默认值

主、外键

备注

kindID

int

NOT

PK

游戏的唯一标识

kindName

varchar(64)

NOT

游戏名称, 比如德州扑克,斗地主等

typeID

int

NOT

外键(GameTypeInfo的主键),该游戏所属类型

processName

int

NOT

客户端进程名称

minVersion

decimal(8,2)

NOT

客户端进程的最低版本,若是登录时发现客户端版本低于这个值,要求其更新

enable

int

NOT

1

控制游戏大厅是否显示该游戏,默认为1。

  1. 附件一 作业答案

7.6 设计游戏用户信息表

回顾下Jack 要实现的用户登陆模块,具体需求如下:

  • 游戏玩家访问游戏客户端,通过客户端界面输入用户名和密码
  • 在游戏玩家点击确认后,客户端连接至数据库服务器对用户名和密码进行确认,

如果验证成功,则 玩家可以进入大厅,如果失败,则不允许进入!

俗话说得好,要开车,先修路!

请帮Jack 设计好相应的数据库表,并插入少量样例数据!

mysql> create database game_db;   #创建游戏数据库game_db

mysql> use game_db;   #选择数据库game_db

mysql> create table users (

 id int(11) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',

 username   varchar(64)  NOT NULL UNIQUE COMMENT '用户名',

 password   varchar(32)  NOT NULL COMMENT '密码',

 nickname   varchar(64)  DEFAULT NULL COMMENT '昵称',

 mobile      char(11)     DEFAULT NULL COMMENT '手机号码',

 age         tinyint(3)    unsigned DEFAULT 18 COMMENT '年龄',

 idno        char(18)     DEFAULT NULL COMMENT '身份证号码'

);

作用1:  验证用户的身份

作用2:  用来保存用户的基本信息

更高逼格的设计: 分成两个表,用户信息表和用户验证表

基于以下三方面的原因:

面向对象方面考虑  - 用户信息和用户验证是两种对象

性能方面考虑      - 登陆验证的时候列较少,查询速度快。

安全方面考虑      - 防止在查询用户信息时,把密码也直接查询出来,会容易被攻击和进行恶       意操作。

mysql> create database game_db;   #创建游戏数据库game_db

mysql> use game_db;   #选择数据库game_db

mysql> create table users (

 id int(11) unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT COMMENT '主键',

 username   varchar(64)  NOT NULL UNIQUE COMMENT '用户名',

 nickname   varchar(64) DEFAULT NULL COMMENT '昵称',

 mobile      char(11)  DEFAULT NULL COMMENT '手机号码',

 age         tinyint(3) unsigned DEFAULT 18 COMMENT '年龄',

 idno        char(18) DEFAULT NULL COMMENT '身份证号码'

);

create  table user_auths(

userid int(11) unsigned NOT NULL COMMENT '外键,对应users表中的id',

username   varchar(64)  NOT NULL UNIQUE COMMENT '用户名',

password varchar(32) NOT NULL COMMENT '密码',

FOREIGN KEY(userid) REFERENCES users(id)

);

mysql> insert into users (username, nickname, mobile, age, idno) values('martin', '程咬金', '18684518289', 39, '430623871234567898');

mysql> insert into user_auths values(1, 'martin', '123456qweQWE');  #密码明文,不安全  

mysql> insert into user_auths values(1, 'martin', md5('123456qweQWE')); #使用内部函数md5 加密,一亿年马老师都无法破解

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

Vue3集成搜索引擎智能提示API

需求&#xff1a; 如何在项目中实现像百度搜索框一样的智能提示效果&#xff0c;如下图所示&#xff1a; 相关知识&#xff1a; 下面是各厂商提供的免费API 厂商请求百度http://suggestion.baidu.com/su?wd中国&cbwindow.baidu.sug必应http://api.bing.com/qsonhs.as…

python3的基本数据类型:可变集合的用法

一. 简介 前面学习了 python3中的一种基本数据类型-集合&#xff0c;文章如下&#xff1a; python3的基本数据类型&#xff1a;集合的创建与分类-CSDN博客 本文继续学习 Python3中的集合&#xff0c;主要学习 可变集合的用法。 二. python3的基本类型&#xff1a;可变集合的…

从零开始:我的鸿蒙学习之旅(二)

前言 记录我在学习鸿蒙操作系统过程中的成长&#xff0c;旨在激励我自己&#xff0c;也希望能激发读者们的学习热情&#xff0c;一起愉快地探索鸿蒙开发的世界&#xff01; 我说说这几天的学习成果吧&#xff0c;将开发入门的第一部分的剩下小节以及第二部分的第一小结写完了…

SSM学习记录(一)之SSM整合

SSM学习记录&#xff08;一&#xff09;之SSM整合 一、SSM整合二、SSM整合的核心问题1、SSM需要几个IoC容器2、每个IoC容器对应哪些类型组件3、IoC容器之间的关系和调用方向4、具体有多少配置以及对应的容器的关系5、IoC初始化方式和配置位置 一、SSM整合 微观&#xff1a;将学…

【从理论到应用】HTTP请求响应详解 (请求数据格式,请求方式,Web开发中的体现)

目录 一.HTTP协议 二.HTTP请求数据格式 请求方式 三.Web开发中的HTTP请求与响应 接收HTTP请求 同一响应格式 四.使用第三方工具发送HTTP请求&#xff08;Apifox、postman、Yapi&#xff09; 一.HTTP协议 HTTP&#xff08;Hypertext Transfer Protocol&#xff0c;超…

猎板PCB罗杰斯板材的应用案例

以下是几个猎板 PCB 与罗杰斯板材结合的具体案例&#xff1a; 案例一&#xff1a;5G 通信基站天线 PCB 在 5G 通信基站的天线系统中&#xff0c;对高频信号的传输和处理要求极高。猎板 PCB 采用罗杰斯板材&#xff0c;凭借其稳定的低介电常数&#xff08;如 RO4003C 板材&…

基于Java Springboot快递物流管理系统

一、作品包含 源码数据库全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js、Layui 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA 数据库&#xff1a;MySQL8.0 数据库管…

力扣662:二叉树的最大宽度

给你一棵二叉树的根节点 root &#xff0c;返回树的 最大宽度 。 树的 最大宽度 是所有层中最大的 宽度 。 每一层的 宽度 被定义为该层最左和最右的非空节点&#xff08;即&#xff0c;两个端点&#xff09;之间的长度。将这个二叉树视作与满二叉树结构相同&#xff0c;两端…

Servlet的使用

一.Servelt简介 1.为什么需要servlet:因为前端三件套无法操控数据库,即与用户进行交互操作 2.servlet由服务器端调用和执行的(由tomcat解析和调用的),由java语言编写,本质就是java类 3.功能强大,可以完成几乎所有的网站功能,按照Servlet规范开发 二.手动开发Servelt 1.Servl…

【嵌入式C语言】GCC概述+C语言编译过程

目录 前言1 课程介绍1.1 计算机程序语言的学习思路?1.2 基本程序设计思想:1.3 C语言工具的特性:1.4 推荐教材 2 GCC的使用及其常用选项介绍2.1 GCC概述gcc -vgcc -ogcc -v -o 2.2 C语言编译过程2.2.1 预处理2.2.2 编译2.2.3 汇编2.2.4 链接2.2.5 问题 2.3 宏的使用 前言 重新学…

C语言 数组排序 – 插入法排序 - C语言零基础入门教程

目录 一.简介二.数组插入法排序原理三.数组插入法排序实战四.猜你喜欢 零基础 C/C 学习路线推荐 : C/C 学习目录 >> C 语言基础入门 一.简介 经过前面的学习&#xff0c;我们已经学会了数组遍历&#xff0c;在开发中&#xff0c;我们经常回碰到对数组进行排序&#xff0c…

vulnhub- Machine_Matrix_v3靶机的测试报告

目录 一、测试环境 1、系统环境 2、使用工具/软件 二、测试目的 三、操作过程 1、信息搜集 2、Getshell 3、提权 四、结论 一、测试环境 1、系统环境 渗透机&#xff1a;kali2021.1(192.168.200.131) 靶 机&#xff1a;Linux matrix 4.16.3-porteus(192.168.200.1…

2024-11-13 Unity Addressables1——概述与导入

文章目录 1 概述1.1 介绍1.2 主要作用1.3 Addressables 与 AssetBundle 的区别 2 导入3 配置3.1 方法一3.2 方法二 1 概述 1.1 介绍 ​ Addressables 是可寻址资源管理系统。 ​ Unity 从 2018.2 版本开始&#xff0c;建议用于替代 AssetBundle 的高阶资源管理系统。在 Unit…

操作系统lab4-页面置换算法的模拟

操作系统lab4-页面置换算法的模拟 文章目录 操作系统lab4-页面置换算法的模拟实验目的实验内容实验分析 代码测试用例运行结果 实验目的 1、掌握请求分页存储管理的常用理论&#xff1a;页面置换算法。 2、理解请求分页中的按需调页机制。 实验内容 独立地用高级语言编写和…

springboot的依赖实现原理:spring-boot-starter-parent解析

01 dependencyManagement的作用 在使用springboot时我们会在项目pom引入以下配置和依赖 <parent><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-parent</artifactId><version>2.7.18</version> &l…

基于Java Springboot图书馆管理系统

一、作品包含 源码数据库文档全套环境和工具资源部署教程 二、项目技术 前端技术&#xff1a;Html、Css、Js 数据库&#xff1a;MySQL 后端技术&#xff1a;Java、Spring Boot、MyBatis 三、运行环境 开发工具&#xff1a;IDEA/eclipse 数据库&#xff1a;MySQL8.0 数据…

MySQL联合索引(abc)命中测试

1.建表 mysql创建一张表&#xff0c;表名&#xff1a;‘test_models’ id列为 主键&#xff0c;int类型 &#xff0c;自增a,b,c,d,e 全部是int&#xff08;11&#xff09;为&#xff08;a,b,c&#xff09;添加一个联合索引 index_abc 执行语句&#xff1a;创建表 CREATE TA…

Linux信号

1. 什么是进程&#xff1f; 从内核的角度&#xff0c;进程是系统分配资源的单位。当一个程序(静态)被加载到内存&#xff0c;操作系统为程序分配一个PCB&#xff08;进程控制块&#xff09;。 PCB&#xff1a;Process Control Block。在Linux中PCB叫做task_struct的结构体&am…

07-案例-图书管理

欢迎来到“雪碧聊技术”CSDN博客&#xff01; 在这里&#xff0c;您将踏入一个专注于Java开发技术的知识殿堂。无论您是Java编程的初学者&#xff0c;还是具有一定经验的开发者&#xff0c;相信我的博客都能为您提供宝贵的学习资源和实用技巧。作为您的技术向导&#xff0c;我将…

js中typeOf无法区分数组对象

[TOC]&#xff08;js中typeOf无法区分数组对象) 前提&#xff1a;很多时候我们在JS中用typeOf来判断值类型&#xff0c;如&#xff1a;typeOf ‘abc’//string ,typeOf 123 //number; 但当判断对象为数组时返回的仍是’object’ 这时候我们可以使用Object.prototype.toString.c…