在windows的控制台实现贪吃蛇小游戏

news2024/11/15 4:29:57

欢迎来到博主的文章
博主id:代码小豪

前言:看懂这篇文章需要具有C语言基础,还要对单链表具有一定的理解。如果你只是想要试玩这个游戏,可以直接在文章末尾找到源码

由于实现贪吃蛇需要调用Win32 API函数,这些函数我会简单介绍,不涉及底层(主要是博主能力不够哈哈)。这篇文章的注意讲解在于贪吃蛇的算法

文章目录

    • 贪吃蛇的算法
      • 坐标
      • “蛇”的节点
      • 蛇的移动
      • 蛇的速度
      • 游戏呈现
    • 控制台指令
    • Win32api
      • 控制台光标
      • 键盘读取
    • 贪吃蛇源码
      • 头文件
      • 定义文件
      • 执行文件

贪吃蛇的算法

坐标

这是一个windows控制台,其中白色的点叫做光标。
在这里插入图片描述
如过想要控制台输出字符,字符就会出现在光标的位置。这些光标是可以通过坐标控制的,左上角的第一个坐标为(0,0),x轴向右,y轴向下。坐标点随轴依次递增。
如下:
在这里插入图片描述
假设现在有个光标在点(x,0)处,让光标的y值依次递增并输出字符’1’。呈现的效果是这样的
在这里插入图片描述
这个’1’像不像一个向下移动的贪吃蛇呢?

“蛇”的节点

我们将蛇身的坐标(x和y)作为数据项。通过链表的形式将蛇连接起来。

typedef int _pos;
typedef struct SnakeNode//蛇身的数据类型
{
	_pos x;//横坐标
	_pos y;//纵坐标
	struct SnakeNode* next;
}SnakeNode, * PSnakeNode;

贪吃蛇中的食物也要有相应的坐标,因此食物的数据类型也可以用上述的结构体类型。
在这里插入图片描述
每个节点(不论是蛇身还是食物)都有其对应的坐标,通过遍历整个链表,每访问一个节点,就在该节点对应的坐标(存储的x值,y值)打印相应的物体。

蛇的移动

蛇头作为参考点,根据玩家的方向控制,在相应的坐标处生成一个新的节点,使用头插法将新生成的节点插入蛇头的位置,并将末尾的节点释放掉。

以向下移动为例,在蛇头(x,y)向下的位置(x,y+1)的位置生成新的节点,并将末尾节点释放掉。
在这里插入图片描述

在这里插入图片描述

这样子就能做到蛇的“移动”。
在这里插入图片描述

蛇的速度

在移动的程序当中添加一个“时停”的函数,比如Sleep函数,当程序执行Sleep函数时会暂停指定的时间,然后继续执行其他操作

while (1)
	{
		phead=SnakeMove(phead);
		Sleep(1000);
	}

这里的Sleep函数是库函数,定义在头文件<windows.h>

游戏呈现

这里给大家看看博主贪吃蛇实现如何

QQ录屏20240208220229

控制台指令

通过指令可以对控制台进行操作,比如输入指令“cls”可以清除当前控制台屏幕。

	system("cls");

执行这段代码时会清理控制台屏幕的当前信息

	system("pause");

暂停操作

	system("mode con cols=120 lines=30");

对控制台的窗口大小进行修改

	system("title 贪吃蛇");

修改标题

Win32api

贪吃蛇的算法已经讲解完,现在来介绍一下使用到的其他函数

控制台光标

我将操作控制台光标的程序封装成了一个函数,只需要输入坐标,控制台光标就会移动到该坐标上

void SetPos(int x, int y)//设置光标位置
{
	HANDLE cursorhandle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(cursorhandle, pos);
}

GetStdHanDle函数用来获取控制台的句柄
COORD:是WindowsAPI中定义的⼀个结构体,表⽰⼀个字符在控制台屏幕上的坐标
SetConsoleCursorPosition:设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD类型的pos中,调⽤SetConsoleCursorPosition函数将光标位置设置到指定的位置

这段代码的原理如下:
先获得控制台的句柄,在创建一个“坐标”的变量,然后使用函数将光标移动到指定坐标的位置

键盘读取

程序需要接收玩家的按键操作,此时需要用到一个读取虚拟键码的函数——GetAysncKeyState
在这里插入图片描述
将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态

如果返回的16位的short数据中,最⾼位是1,说明按键的状态是按下,如果最⾼是0,说明按键的状态是抬起;
如果最低位被置为1则说明,该按键被按过,否则为0。
如果我们要判断⼀个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1

可以将这个函数做成一个宏,少些点代码

#define KEY_PRESS(vk) (GetAsyncKeyState(vk)&0x1?1:0)

比如判断是否按下s键,可以找到s键对应的虚拟键码
在这里插入图片描述

	if (KEY_PRESS(0x53))
	{
		printf("press s");
	}

这样子就会执行按下这个键后对应的操作

所有的键位对应的虚拟键码可以在这个网站上找到
虚拟键码

贪吃蛇源码

这里附上贪吃蛇的源代码,大家可以根据自己的思路设计自己的贪吃蛇游戏

贪吃蛇代码被博主用一个头文件,和两个源文件进行封装。其中头文件用来声明函数和数据类型,一个源文件用来定义函数类型,还有一个源文件用来测试案例。

头文件

#define _CRT_SECURE_NO_WARNINGS 1
#pragma once

#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<locale.h>
#include<stdbool.h>
#include<assert.h>
#include<time.h>

#define WALL L'□'//墙体模型
#define BODY L'●'//蛇身模型
#define FOOD L'★'//食物模型

#define COLS 56 //地图长度
#define ROWS 25 //地图宽度

#define ORIGIN_POS_X 24//初始x坐标
#define ORIGIN_POS_Y 5//初始y坐标
#define ORIGIN_NODE 5//初始蛇长

#define KEY_PRESS(vk) (GetAsyncKeyState(vk)&0x1?1:0)
enum GAME_STATUS//游戏运行状态
{
	PLAY = 1,
	ESC,
	KILL_BY_WALL,
	KILL_BY_SELF
};

enum DIRECTION//蛇的移动方向 
{
	UP = 1,
	DOWN,
	LEFT,
	RIGHT
};

typedef int _pos;
typedef struct SnakeNode//蛇身的数据类型
{
	_pos x;//横坐标
	_pos y;//纵坐标
	struct SnakeNode* next;
}SnakeNode, * PSnakeNode;

typedef struct Snake//记录游戏数据
{
	PSnakeNode snake;//蛇的当前位置
	PSnakeNode food;//食物的当前位置
	int score;//总分
	int foodwight;//单个食物得分
	int speed;//蛇的速度,由于Sleep函数的特性,这个值越大,蛇的速度越慢
	enum GAME_STATUS status;
	enum DIRECTION dir;
}snake, * psnake;

void GameStart(psnake snake);//开始流程

void CreateMap(void);//生成地图

void GameMenu(void);//游戏菜单

void CreateSnake(psnake psnake);//生成贪吃蛇

void CreateFood(psnake psnake);//生成食物

void GameRun(psnake psnake);//游戏流程

void SnakeMove(psnake psnake);//移动操作

bool NextIsFood(psnake psnake, PSnakeNode pnext);//得分判定

void EatFoodSuccess(psnake psnake,PSnakeNode pnext);//成功吃到食物

void EatFoodFail(psnake psnake, PSnakeNode pnext);//未成功吃到食物

void KillBySelf(psnake psnake);//碰撞检测

void KillByWall(psnake psnake);//检测是否撞墙

void GameOver(psnake psnake);

void SetPos(int x, int y);

定义文件

#include"snake.h"
void SetPos(int x, int y)//设置光标位置
{
	HANDLE cursorhandle = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD pos = { x,y };
	SetConsoleCursorPosition(cursorhandle, pos);
}

void GameMenu(void)
{
	setlocale(LC_ALL, "");//将语言环境设置为中文语言,方便宽字体打印
	SetPos(40, 15);
	printf("欢迎来到贪吃蛇小游戏");
	SetPos(40, 20);
	system("pause");
	system("cls");

	/*介绍游戏规则*/
	SetPos(20, 10);
	printf("用↑ ↓ ← →控制蛇吞掉食物,F3加速,F4减速");
	SetPos(20, 11);
	printf("速度越快,得分越高,不要碰到墙壁,也不要吃掉自己哦\n");
	SetPos(20, 12);
	system("pause");
	system("cls");
}

void GameStart(psnake psnake)
{
	srand((unsigned int)time(NULL));
	system("mode con cols=120 lines=30");//如果地图扩大了,那么请将这里的指令也修改一下
	system("title 贪吃蛇");

	/*隐藏光标*/
	HANDLE cmd_handle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO info = { 0 };
	GetConsoleCursorInfo(cmd_handle, &info);
	info.bVisible = false;
	SetConsoleCursorInfo(cmd_handle, &info);

	/*游戏主菜单*/
	GameMenu();

	/*生成地图*/
	CreateMap();

	/*生成贪吃蛇*/
	CreateSnake(psnake);

	/*创建食物*/
	CreateFood(psnake);
	/*函数结束*/
}

void CreateMap(void)
{
	_pos i = 0;
	//生成地图上层
	SetPos(0, 0);
	for (i = 0; i <= COLS; i += 2)
		wprintf(L"%lc", WALL);
	//生成地图下层
	SetPos(0, ROWS);
	for (i = 0; i <= COLS; i += 2)
		wprintf(L"%lc", WALL);
	//生成地图左侧
	for (i = 1; i < ROWS; i++)
	{
		SetPos(0, i);
		wprintf(L"%lc", WALL);
	}
	//生成地图右侧
	for (i = 1; i < ROWS; i++)
	{
		SetPos(COLS, i);
		wprintf(L"%lc", WALL);
	}
}

void CreateSnake(psnake psnake)
{
	int i = 0;
	PSnakeNode cur = NULL;//蛇头
	PSnakeNode snakehead = NULL;
	for (i = 0; i < ORIGIN_NODE; i++)
	{
		cur = (PSnakeNode)malloc(sizeof(SnakeNode));
		assert(cur);
		cur->x = ORIGIN_POS_X + 2 * i;
		cur->y = ORIGIN_POS_Y;
		cur->next = NULL;
		//由于蛇身的数据结构是链表,因此用头插法将蛇的节点连接起来
		if (!snakehead) {
			snakehead = cur;
		}
		else {
			cur->next = snakehead;
			snakehead = cur;
		}
	}
	psnake->snake = snakehead;//将初始化好的数据记录在主游戏数据中
	/*根据数据在游戏中生成贪吃蛇*/
	cur = psnake->snake;
	while (cur)
	{
		SetPos(cur->x, cur->y);
		wprintf(L"%lc", BODY);
		cur = cur->next;
	}
	/*初始化游戏中的所有数值*/
	psnake->dir = RIGHT;
	psnake->score = 0;
	psnake->speed = 200;
	psnake->foodwight = 10;
	psnake->status = PLAY;
}

void CreateFood(psnake psnake)
{
	_pos x;
	_pos y;

again:
	do {
		x = rand() % (COLS - 3) + 2;
		y = rand() % (ROWS - 1) + 1;
	} while (x % 2 != 0);
	/*检查生成食物的坐标是否合理*/
	PSnakeNode cur = psnake->snake;
	while (cur)
	{
		if (cur->x == x && cur->y == y)
			goto again;
		cur = cur->next;
	}
	/*生成食物*/
	PSnakeNode pfood = (PSnakeNode)malloc(sizeof(SnakeNode));
	assert(pfood);
	pfood->x = x;
	pfood->y = y;
	SetPos(pfood->x, pfood->y);
	wprintf(L"%lc", FOOD);
	psnake->food = pfood;
}

void Printmsg(void)
{
	SetPos(COLS + 10, 15);
	printf("不能撞墙,不能咬到自己");
	SetPos(COLS + 10, 16);
	printf("用↑ ↓ ← →控制蛇吞掉食物,F3加速,F4减速");
	SetPos(COLS + 10, 20);
	printf("关注代码小豪谢谢喵");
}

void pause()
{
	SetPos(COLS + 10, ROWS - 1);
	printf("按空格继续");
	do
	{
		Sleep(100);
		if (KEY_PRESS(VK_SPACE))
			break;
	} while (1);
	SetPos(COLS + 10, ROWS - 1);
	printf("          ");
}
void GameRun(psnake psnake)
{
	/*游戏内信息*/
	Printmsg();
	//游戏运行逻辑
	do
	{
		//分数
		SetPos(COLS + 10, 10);
		printf("总分:%d", psnake->score);
		SetPos(COLS + 10, 11);
		printf("单个食物得分:%2d",psnake->foodwight);

		//检测按键
		if (KEY_PRESS(VK_UP) && psnake->dir != DOWN)
			psnake->dir = UP;
		if (KEY_PRESS(VK_DOWN) && psnake->dir != UP)
			psnake->dir = DOWN;
		if (KEY_PRESS(VK_LEFT) && psnake->dir != RIGHT)
			psnake->dir = LEFT;
		if (KEY_PRESS(VK_RIGHT) && psnake->dir != LEFT)
			psnake->dir = RIGHT;
		if (KEY_PRESS(VK_ESCAPE))
			psnake->status = ESC;//退出游戏
		if (KEY_PRESS(VK_SPACE)) //暂停游戏
			pause();
		if (KEY_PRESS(VK_F3))//加速
		{
			if (psnake->speed > 50)
			{
				psnake->speed -= 30;
				psnake->foodwight += 2;
			}
		}
		if (KEY_PRESS(VK_F4))//减速
		{
			if (psnake->foodwight > 2)
			{
				psnake->speed += 30;
				psnake->foodwight -= 2;
			}
		}
		Sleep(psnake->speed);
		//蛇的移动
		SnakeMove(psnake);
	} while (psnake->status == PLAY);
}

void SnakeMove(psnake psnake)
{
	PSnakeNode pnext = (PSnakeNode)malloc(sizeof(SnakeNode));
	assert(pnext);
	pnext->next = NULL;
	switch (psnake->dir)
	{
	case UP:
		pnext->x = psnake->snake->x;
		pnext->y = psnake->snake->y - 1;
		break;
	case DOWN:
		pnext->x = psnake->snake->x;
		pnext->y = psnake->snake->y + 1;
		break;
	case LEFT:
		pnext->x = psnake->snake->x-2;
		pnext->y = psnake->snake->y ;
		break;
	case RIGHT:
		pnext->x = psnake->snake->x+2;
		pnext->y = psnake->snake->y ;
		break;
	}
	/*判断该方向的坐标上是不是食物*/
	if (NextIsFood(psnake, pnext))//是食物就吃掉,并增加体型
	{
		EatFoodSuccess(psnake,pnext);//成功吃到食物
	}
	else
	{
		EatFoodFail(psnake,pnext);//未成功吃到食物
	}
	KillBySelf(psnake);
	KillByWall(psnake);
}

bool NextIsFood(psnake psnake, PSnakeNode pnext)
{
	if (psnake->food->x == pnext->x && psnake->food->y == pnext->y)//判定成功
		return true;
	return false;//判定失败
}

void EatFoodSuccess(psnake psnake, PSnakeNode pnext)
{
	/*增加体型*/
	pnext->next = psnake->snake;
	psnake->snake = pnext;
	/*在屏幕上生成蛇的新节点*/
	SetPos(pnext->x, pnext->y);

	psnake->score += psnake->foodwight;//加分
	free(psnake->food);
	CreateFood(psnake);
}

void EatFoodFail(psnake psnake, PSnakeNode pnext)
{
	pnext->next = psnake->snake;
	psnake->snake = pnext;

	PSnakeNode cur = psnake->snake;
	while (cur->next->next)//找到尾结点
	{
		SetPos(cur->x, cur->y);
		cur = cur->next;
		wprintf(L"%lc", BODY);
	}

	SetPos(cur->next->x, cur->next->y);
	wprintf(" ");
	free(cur->next);
	cur->next = NULL;
}

void KillBySelf(psnake psnake)//碰撞判定
{
	_pos x = psnake->snake->x;
	_pos y = psnake->snake->y;

	PSnakeNode cur = psnake->snake->next;
	while (cur)
	{
		if (cur->x == x && cur->y == y)//如果蛇头碰到身体就算死亡
		{
			psnake->status = KILL_BY_SELF;
			return;
		}
		cur = cur->next;
	}
}

void KillByWall(psnake psnake)
{
	_pos x = psnake->snake->x;
	_pos y = psnake->snake->y;

	if (x == 0 ||//判断贪吃蛇是否撞到墙
		x >= COLS ||
		y == 0 ||
		y >= ROWS)
		psnake->status = KILL_BY_WALL;
}

void GameOver(psnake psnake)
{
	SetPos(30, 15);
	switch (psnake->status)
	{
	case ESC:
		system("cls");
		printf("退出成功,感谢您的游玩");
		SetPos(0, ROWS+2);
		exit(EXIT_SUCCESS);
		break;
	case KILL_BY_SELF:
		printf("很抱歉,您被自己吃了");
		break;
	case KILL_BY_WALL:
		printf("很抱歉,您撞到墙了");
		break;
	}
	/*清空动态内存*/
	PSnakeNode cur = psnake->snake;
	PSnakeNode del = NULL;

	while (cur)
	{
		del = cur;
		cur = cur->next;
		free(del);
	}

	free(psnake->food);
	psnake = NULL;
}

执行文件

#include"snake.h"

void Test1(void)
{
	char ch = 0;
	do
	{
		snake snake = { 0 };
		GameStart(&snake);//初始化游戏
		GameRun(&snake);//游戏运行
		GameOver(&snake);//游戏结束
		SetPos(30, 15);
		printf("重新游玩?(输入Y):");
		ch = getchar();
		getchar();
	} while (ch == 'Y' || ch == 'y');
	system("cls");
	SetPos(30, 15);
	printf("退出成功,感谢您的游玩");
	SetPos(0, ROWS + 2);
}
int main()
{
	Test1();
	return 0;
}

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

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

相关文章

vue3项目中的404页面

vue3项目中的404页面 春节前的最后一篇技术博客了 写了不少vue项目&#xff0c;发现一直没有正确处理404页面。404页面的出现有这么几种可能&#xff1a; 错误输入了页面地址路由连接跳转时&#xff0c;某些路由已经不存在了&#xff0c;而程序员并没有正确处理 也就是说40…

jvm问题自查思路

本文聊一下最近处理了一些jvm的问题上&#xff0c;将这个排查和学习过程分享一下&#xff0c;看了很多资料&#xff0c;最终都会落地到几个工具的使用&#xff0c;本文主要是从文档学习、工具学习和第三方技术验证来打开认知和实践&#xff0c;希望有用。 一、文档 不仅知道了…

假期刷题打卡--Day26

1、MT1212乘法表 请编写一个简单程序&#xff0c;输出九九乘法表。输入n&#xff0c;就输出乘法表到n的地方。 格式 输入格式&#xff1a; 输入整型 输出格式&#xff1a; 输出整型。形式如&#xff1a;1*11 样例 1 输入&#xff1a; 5输出&#xff1a; 1*11 2*12 …

编曲入门软件哪个好 编曲入门教程 Studio One哪个版本好 Studio One6.5正版多少钱 FL Studio下载

新手编曲软件推荐&#xff1f;新手学编曲要先熟悉编曲逻辑&#xff0c;因此需要选择编曲逻辑简明易懂的宿主软件。编曲新手应该做哪些准备&#xff1f;准备好编曲设备、宿主软件、基础乐理学习资料。 一、编曲入门软件哪个好 新手入门阶段还没有形成系统的编曲思维&#xff0…

整合 Axios

大家好我是苏麟 , 今天聊一下Axios . Axios Axios 是一个基于 promise 网络请求库&#xff0c;作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpReques…

七、Nacos源码系列:Nacos服务发现

目录 一、服务发现 二、getServices()&#xff1a;获取服务列表 2.1、获取服务列表 2.2、总结图 三、getInstances(serviceId)&#xff1a;获取服务实例列表 3.1、从缓存中获取服务信息 3.2、缓存为空&#xff0c;执行订阅服务 3.2.1、调度更新&#xff0c;往线程池中…

【算法】{画决策树 + dfs + 递归 + 回溯 + 剪枝} 解决排列、子集问题(C++)

文章目录 1. 前言2. 算法例题 理解思路、代码46.全排列78.子集 3. 算法题练习1863.找出所有子集的异或总和再求和47.全排列II17.电话号码的字母组合 1. 前言 dfs问题 我们已经学过&#xff0c;对于排列、子集类的问题&#xff0c;一般可以想到暴力枚举&#xff0c;但此类问题用…

基于Chrome插件的Chatgpt对话无损导出markdown格式(Typora完美显示)

刚刚提交插件到Chrome插件商店正在审核&#xff0c;想尝试的可以先使用&#xff1a; https://github.com/thisisbaiy/ChatGPT-To-Markdown-google-plugin/tree/main 我将源代码上传至了GitHub&#xff0c;欢迎star, IssueGoogle插件名称为&#xff1a;ChatGPT to MarkDown plus…

海外云手机——平台引流的重要媒介

随着互联网的飞速发展&#xff0c;跨境电商、短视频引流以及游戏行业等领域正经历着迅猛的更新换代。在这个信息爆炸的时代&#xff0c;流量成为至关重要的资源&#xff0c;而其中引流环节更是关乎业务成功的关键。海外云手机崭露头角&#xff0c;成为这一传播过程中的重要媒介…

【保姆级教程|YOLOv8改进】【7】多尺度空洞注意力(MSDA),DilateFormer实现暴力涨点

《博主简介》 小伙伴们好&#xff0c;我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源&#xff0c;可关注公-仲-hao:【阿旭算法与机器学习】&#xff0c;共同学习交流~ &#x1f44d;感谢小伙伴们点赞、关注&#xff01; 《------往期经典推…

Ribbon全方位解析:构建弹性的Java微服务

第1章 引言 大家好,我是小黑,咱们今天聊聊Ribbon,这货是个客户端负载均衡工具,用在Spring Cloud里面能让咱们的服务调用更加灵活和健壮。负载均衡,听起来挺高大上的,其实就是把外界的请求平摊到多个服务器上,避免某个服务器压力太大,其他的却在那儿闲着。 Ribbon的牛…

Springboot整合JUnit5框架

目录 第一章、在pom文件中导入依赖第二章、新建测试类第三章、新建测试方法 友情提醒: 先看文章目录&#xff0c;大致了解文章知识点结构&#xff0c;点击文章目录可直接跳转到文章指定位置。 第一章、在pom文件中导入依赖 SpringBoot2.2x之后的版本中spring-boot-starter-te…

Python(21)正则表达式中的“元字符”

大家好&#xff01;我是码银&#x1f970; 欢迎关注&#x1f970;&#xff1a; CSDN&#xff1a;码银 公众号&#xff1a;码银学编程 获取资源&#xff1a;公众号回复“python资料” 在本篇文章中介绍的是正则表达式中一部分具有特殊意义的专用字符&#xff0c;也叫做“元…

基于51 单片机的交通灯系统 源码+仿真+ppt

主要内容&#xff1a; 1&#xff09;南北方向的绿灯、东西方向的红灯同时亮40秒。 2&#xff09;南北方向的绿灯灭、黄灯亮5秒&#xff0c;同时东西方向的红灯继续亮。 3&#xff09;南北方向的黄灯灭、左转绿灯亮&#xff0c;持续20秒&#xff0c;同时东西方向的红灯继续…

rust语言tokio库底层原理解析

目录 1 rust版本及tokio版本说明1 tokio简介2 tokio::main2.1 tokio::main使用多线程模式2.2 tokio::main使用单线程模式 3 builder.build()函数3.1 build_threaded_runtime()函数新的改变功能快捷键合理的创建标题&#xff0c;有助于目录的生成如何改变文本的样式插入链接与图…

前端JavaScript篇之对执行上下文的理解

目录 对执行上下文的理解创建执行上下文 对执行上下文的理解 当我们在执行JavaScript代码时&#xff0c;JavaScript引擎会创建并维护一个执行上下文栈来管理执行上下文。执行上下文有三种类型&#xff1a;全局执行上下文、函数执行上下文和eval函数执行上下文。 在写代码的时…

第十三、十四个知识点:用javascript获取表单的内容并加密

我们先来写一段代码&#xff1a; <body><form action"#" method"post">//写一个表单<span>用户名&#xff1a;</span><input type"text" id"username" name"username"><span>密码&a…

BGP 双归不同运营商并且客户之间互为主备的部署实验

一、拓朴&#xff1a; 要求&#xff1a; 1、双方 ISP 均不得将客户 AS 做为穿越 AS 2、对于客户业务的出流量&#xff1a;客户 AS100 和 200 访问 ISP 时&#xff0c;AS100优选从 Line-1 线路&#xff0c;AS200 优选从 Line-2 访问&#xff0c;但当 Line-1 和 …

Springboot+vue的社区智慧养老监护管理平台设计与实现(有报告),Javaee项目,springboot vue前后端分离项目

演示视频&#xff1a; Springbootvue的社区智慧养老监护管理平台设计与实现&#xff08;有报告&#xff09;&#xff0c;Javaee项目&#xff0c;springboot vue前后端分离项目 项目介绍&#xff1a; 本文设计了一个基于Springbootvue的前后端分离的社区智慧养老监护管理平台设…

springboot项目启动报错:dynamic-datasource can not find primary datasource

项目启动报错信息 Caused by: com.baomidou.dynamic.datasource.exception.CannotFindDataSourceException: dynamic-datasource can not find primary datasourceat com.baomidou.dynamic.datasource.DynamicRoutingDataSource.determinePrimaryDataSource(DynamicRoutingDat…