【C语言】简易版扫雷+进阶版扫雷

目录

前言

一、分模块化

二、准备雷盘

2.1 游戏菜单

2.2 创建雷盘思路

2.3 构建雷盘

2.4 雷盘展示

2.4.1 初始化雷盘

2.4.2 打印雷盘

三、排雷

3.1 布置雷

3.2 排查雷

四、进阶版扫雷

总结


前言

C语言实现扫雷小游戏,帮我们更进一步的掌握数组、模块化思想等知识。


一、分模块化

对于扫雷小游戏,相信老铁们应该不陌生,根据信息进行排雷,大家可以参考网页版的扫雷游戏:扫雷小游戏

对于扫雷小游戏,虽然是一个小项目,代码量不多,但对于初学者来说,重要的是学习如何分模块开发项目。

本文将该游戏分成三个文件:

  • test.c游戏测试文件
  • game.c游戏执行逻辑(函数实现)
  • game.h游戏声明(函数声明,头文件)

二、准备雷盘

扫雷游戏,首先需要一个雷盘,本文讲解的雷盘为9×9规格。

2.1 游戏菜单

一个游戏,最先呈现给用户看的是游戏菜单,对于游戏菜单,可以用do...while循环 + switch选择语句完成,因为无论用户是否开始还是退出游戏,程序都会运行一次。

test.c文件
#include "game.h"
void menu()
{printf("********************\n");printf("***** 1、play ******\n");printf("***** 0、exit ******\n");printf("********************\n");
}
int main()
{int input = 0;do{//游戏菜单menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}game.h文件
#pragma once
#include <stdio.h>

2.2 创建雷盘思路

对于雷盘,使用二维数组存储数据是最合适的,符合行列。那一个雷盘就可以了吗?

我们规定:雷用字符1表示,非雷用字符0表示。

因此冲突点就出现了,如果对某个位置进行排雷,统计雷数时,正好也为1,那究竟是雷还是雷数呢?

为此,这里用了一个很巧妙的方法,我们定义两个大小一致的二维数组,也就是两个雷盘,一个雷盘用于布置雷,一个雷盘用于存放统计后雷的个数。

因此,我们有以下规定:

  • 布置雷的二维数组叫mine。
  • 存放雷数的二维数组叫show。因为要展示给用户看选择的位置周围的雷数,因此叫show。
  • mine雷盘中字符0为非雷,字符1为雷。
  • show雷盘中字符*表示未排查,字符数字表示该位置已被排查。

前面说过,我们的雷盘是一个9×9的规格,那相对于的两个数组的大小也是9×9吗?

其实不是,应该为11×11,因为当我们对最上、最下、最左、最右中的位置进行排雷时,统计周围有几颗雷时,会造成数组越界的情况,因此我们定义多2行2列的数据,这部分位置不存放雷,将雷存放在9×9的雷盘中,多定义的2行2列只是为了防止数组越界。


2.3 构建雷盘

对于数组的大小,我们不能写死,应该用#define标识符常量来表示,方便以后想扩大雷盘。并且我们需要分别定义9×9和11×11的标识符,因为在布置雷、打印雷盘、排雷的功能中只需要用到9×9的区域,而在初始化雷盘时,需要用到11×11区域。

test.c文件
#include "game.h"
void menu()
{printf("********************\n");printf("***** 1、play ******\n");printf("***** 0、exit ******\n");printf("********************\n");
}
void game()
{//定义两个大小相同的二维数组//这里的数组大小最好用#define标识符表示,后续想改变就该#define就好了//用于布置雷,用字符数组的原因是规定字符0为非雷,字符1为雷char mine[ROWS][COLS] = { 0 };//用于存放排查雷的信息(主要给用户看的页面//用字符数组的原因是规定雷数用字符数字表示,其它位置用字符*表示char show[ROWS][COLS] = { 0 };}
int main()
{int input = 0;do{//游戏菜单menu();printf("请选择:>");scanf("%d", &input);switch (input){case 1:game();break;case 0:printf("退出游戏\n");break;default:printf("选择错误\n");break;}} while (input);return 0;
}game.h文件
#include <stdio.h>
/*解释一下这里定义的标识符:该游戏的排雷范围为9×9。点击一处位置,那周围的8处位置就要判断有几个雷。当位置位于上下一行时或者左右一行时,那访问周围8处位置时,就会造成越界访问了,因此这里可以加多两行两列,目的是为了不越界访问这两行两列不放置雷,雷的范围只在9×9中
*/
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2

2.4 雷盘展示

2.4.1 初始化雷盘

首先,我们要对六个雷盘进行初始化操作,mine雷盘一开始全为字符0,因为还没布置雷;show雷盘一开始全为字符*,因为还没开始排雷。

test.c文件
#include "game.h"
void game()
{//初始化两个棋盘//mine雷盘一开始全是字符0,因为还没布置雷InitializeMinefield(mine, ROWS, COLS, '0');//show雷盘一开始全是字符*,因为还没统计周围雷数InitializeMinefield(show, ROWS, COLS, '*');
}game.h文件
#pragma once
#include <stdio.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//初始化雷盘
//这里的参数写什么?
//既然是初始化雷盘,那要有个数组来接收传来的mine数组和show数组
//初始化9×9还是11×11?11×11,这样方便后续计算雷的个数
//还有一个参数很重要,那就是set,既然用一个函数就初始化两个雷盘
//那就要将标识字符传过来,进行设置
void InitializeMinefield(char init[ROWS][COLS],int rows,int cols,char set);game.c文件
#include "game.h"
//初始化雷盘
void InitializeMinefield(char init[ROWS][COLS], int rows, int cols, char set)
{for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){init[i][j] = set; //set为标识符号,mine雷盘传'0',show雷盘传'*'}}
}

初始化两个雷盘,要为每个雷盘分别写一个函数吗?

不需要,mine雷盘初始化时将字符0当成参数;show雷盘初始化时将字符*当成参数即可。


2.4.2 打印雷盘

打印雷盘的注意点在于打印多大的雷盘:是9×9,还是11×11?

前面说过,其实我们真正的雷盘大小为9×9的,11×11是为了让数组不越界。

test.c文件
#include "game.h"
void game()
{//打印雷盘,给用户展示的是show雷盘//打印多大?9×9,因为这是真正排雷区域PrintMindefield(show, ROW, COL);
}game.h文件
#pragma once
#include <stdio.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2//打印雷盘
//这里需要注意,接收数组的大小需要写11×11,因为定义数组的时候就是11×11
//打印时只打印9×9,但在语法上来说,数组的大小为11×11。
void PrintMindefield(char print[ROWS][COLS],int row,int col);game.c文件
#include "game.h"
//打印雷盘
void PrintMindefield(char print[ROWS][COLS], int row, int col)
{printf("-------扫雷--------\n");//给雷盘编号,这样用户更快找到坐标进行排雷//上边编号for (int i = 0; i <= col; i++){printf("%d ", i);}printf("\n");//初始值从下标1开始,最后下标row/col//因为数组的大小为11×11,只打印9×9时,就不能从0开始了,结尾也同理for (int i = 1; i <= row; i++){printf("%d ", i); //左边编号for (int j = 1; j <= col; j++){printf("%c ", print[i][j]);}//每打印一行就\nprintf("\n");}
}

虽然我们只打印9×9的雷盘,但是定义数组时的大小为11×11,在函数形参接收时,数组中的[][]应为11×11,但传过去的行和列为9、9。


雷盘准备完毕,我们看看效果:


三、排雷

3.1 布置雷

布置雷的思路很简单,我们在mine数组上,生成随机坐标,需要注意的如下:

  • 该坐标位置没布置过雷(坐标内容为字符0)。
  • 生成随机数的函数,srand随机数生成器和rand函数搭配使用。
  • #define标识符定义雷的个数。
test.c文件
#include "game.h"
void game()
{//布置雷//在mine数组中布置//#define标识符定义雷数//同样,只需要在row × col中布置Place_mine(mine, ROW, COL);
}game.h文件
#pragma once
#include <stdio.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//雷的总个数
#define Mine_Sum 10
//布置雷
void Place_mine(char mine[ROWS][COLS], int row, int col);game.c文件
#include "game.h"
//布置雷
//随机布置,随机生成坐标,使用rand函数前要设置随机生成器srand
/*条件:坐标不是雷,即不是'1'
*/
void Place_mine(char mine[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;int count = Mine_Sum;//总雷数,当count为0时,表示已布置好雷while (count){x = rand() % row + 1; y = rand() % col + 1; if (mine[x][y] == '0'){mine[x][y] = '1';count--;}}}

3.2 排查雷

对于用户操作方面:

  • 用户通过坐标进行排雷。
  • 输入的坐标有边界条件:x>=1 && x<=row && y>=1 && y<=col
  • 输入的坐标不能重复

什么时候结束呢?两种情况:

  • 被炸死
  • 排雷成功:排雷次数<row*col - 雷数

如何统计周围雷数:

  • 周围坐标之和 - 8*字符0。
  • 因为是mine数组中只有字符0或字符1.
  • 字符数字转为数字:字符数字-字符0 = 数字。因为字符进行加减操作时,是以ascll码进行。
  • 数字转为字符数字:数字+字符0 = 数字。
  • 因此周围坐标之和再给每个坐标依次减字符0,那最终的结果就为周围雷的个数(数字)。
  • 统计完成后,将个数转为字符个数,存储到对应位置的show雷盘中。
test.c文件
#include "game.h"
void game()
{//排雷(用户输入坐标排雷)/*排雷功能需要两个雷盘,mine雷盘用来检查周围雷的个数show雷盘用于存放统计好周围雷的个数,并展示*/Examine(mine, show, ROW, COL);
}game.h文件
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdlib.h>
#include <time.h>
#include <Windows.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
//雷的总个数
#define Mine_Sum 10
//排雷
void Examine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);game.c文件
#include "game.h"
//排雷
/*两个核心:1、通过用户坐标排雷2、检查周围坐标有几个雷后,放置到show雷盘中显示
*/
//统计该坐标周围的雷数
//此时的查找的雷盘范围为:11×11,防止越界
int StatisNumberMines(char mine[ROWS][COLS], int x, int y)
{/*mine雷盘中放的都是:字符0 或 字符1前备知识:字符数字转为数字: 字符数字 - 字符0 = 数字数字转字符数字:数字 + 字符0 = 字符数字原因:因为在进行字符间的加减操作时,是以ascll码进行的。现在mine雷盘中放的都是字符数字,那将8个位置的字符数字相加后: (8个位置之和) - 8*字符0再依次减字符0,那就能统计处周围有几个雷*/return (mine[x + 1][y] + mine[x + 1][y - 1] +mine[x][y - 1] + mine[x - 1][y - 1] + mine[x - 1][y] +mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1]) - 8 * '0';
}
void Examine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;/*坐标限制:1、不能重复2、不能超出有效范围:x>=1 && x<=row && y>=1 && y<=col*//*什么时候结束呢?两种情况:1、被炸死。2、排雷成功:排雷次数<row*col - 雷数*/int num = 0;while (num< row * col-Mine_Sum){printf("请玩家输入排雷坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){//输入坐标不能重复/*检查show雷盘,未排雷过的坐标为字符*,排查过的坐标字符0或字符数字*/if (show[x][y] == '*'){//判断是否是雷if (mine[x][y] == '0'){/*输入的坐标不是雷统计周围8个坐标有几颗雷*///在mine雷盘中统计int count = StatisNumberMines(mine, x, y);//统计好后放到show雷盘中//当然,要将数字转为字符数字,因为数组时char类型show[x][y] = count + '0';PrintMindefield(show, ROW, COL);num++;}//是雷就结束else{printf("您被炸死了\n");PrintMindefield(mine, ROW, COL);break;}}else{printf("该坐标已被排查\n");}}else{printf("输入的坐标超出范围\n");}}if (num == row*col - Mine_Sum){printf("恭喜你,排雷成功!\n");}
}

四、进阶版扫雷

简易版的扫雷有什么缺陷呢?

其实有很多功能都没有实现,比如即时、标记、剩余雷数等等,但最重要的是展开一片的功能没有实现,因此进阶版扫雷,将修改排雷函数,让用户输入坐标后,将不是周围一大片不是雷的地方展开,并提供更多雷数信息。

此时的扫雷,只能一个一个坐标的排查,并不会展开一片。

展开一大片的关键点:

  • 该坐标不是雷
  • 该坐标周围坐标没有雷
  • 排查坐标没有被排查过。(为什么?因为当有一个坐标满足三个条件后,然后该坐标周围又有坐标满足条件,进行展开,那原先满足条件的坐标也算是它周围8个坐标,那还要判断它吗?它已经不是雷了,因此这个条件很重要,容易造成死递归)
//统计该坐标周围的雷数
//此时的查找的雷盘范围为:11×11,防止越界
int StatisNumberMines(char mine[ROWS][COLS], int x, int y)
{/*mine雷盘中放的都是:字符0 或 字符1前备知识:字符数字转为数字: 字符数字 - 字符0 = 数字数字转字符数字:数字 + 字符0 = 字符数字原因:因为在进行字符间的加减操作时,是以ascll码进行的。现在mine雷盘中放的都是字符数字,那将8个位置的字符数字相加后: (8个位置之和) - 8*字符0再依次减字符0,那就能统计处周围有几个雷*/return (mine[x + 1][y] + mine[x + 1][y - 1] +mine[x][y - 1] + mine[x - 1][y - 1] + mine[x - 1][y] +mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1]) - 8 * '0';
}
//排雷,展开一片
/*基本思路:1、递归,终止条件为周围坐标之和不为0,说明周围有雷2、如果为0,那将该坐标设为空字符,然后依次查看周围坐标的周围坐标是否为0,如果是那就设置为空但前提是查看的坐标没有被排查过,就是坐标里的值是'*',并且该坐标没超出范围
*/
void Unfold(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)
{int count = StatisNumberMines(mine, x, y);if (count == 0){show[x][y] = ' ';int i = 0;int j = 0;for (i = x - 1; i <= x + 1; i++){for (j = y - 1; j <= y + 1; j++){if (show[i][j] == '*' && i > 0 && i < 10 && j>0 && j < 10){Unfold(mine, show, i, j);}}}}else{show[x][y] = count + '0';}
}
//查看show雷盘中还剩多少个位置没排查,当只剩Mine_Sum个时,排雷成功
int Win(char show[ROWS][COLS],int row,int col)
{int count = 0;for (int i = 0; i < row; i++){for (int j = 0; j < col; j++){if (show[i][j] == '*'){count++;}}}return count;}
void Examine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{int x = 0;int y = 0;/*坐标限制:1、不能重复2、不能超出有效范围:x>=1 && x<=row && y>=1 && y<=col*//*什么时候结束呢?两种情况:1、被炸死。2、排雷成功:排雷次数<row*col - 雷数*/int num = 0;while (num< row * col-Mine_Sum){printf("请玩家输入排雷坐标:>");scanf("%d %d", &x, &y);if (x >= 1 && x <= row && y >= 1 && y <= col){//输入坐标不能重复/*检查show雷盘,未排雷过的坐标为字符*,排查过的坐标字符0或字符数字*/if (show[x][y] == '*'){//判断是否是雷if (mine[x][y] == '0'){//进阶版----展开一片Unfold(mine, show, x, y);PrintMindefield(show, ROW, COL);}//是雷就结束else{printf("您被炸死了\n");PrintMindefield(mine, ROW, COL);break;}}else{printf("该坐标已被排查\n");}}else{printf("输入的坐标超出范围\n");}if (Win(show, row, col) == Mine_Sum){printf("恭喜你,排雷成功!\n");PrintMindefield(mine, ROW, COL);break;}}
}

使用递归实现,当周围坐标没有雷时,将该坐标设置为空字符,然后再依次对周围坐标判断是否被排查过并且不超过有效范围,如果满足,则递归,看该坐标的周围坐标是否符合没有雷条件。直到周围坐标有雷,递归就结束,开始返回。


总结

这就是扫雷小游戏,希望对您有所帮助,后续会出更多干货,多多支持,关注我❤❤❤!源代码自取。

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

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

相关文章

Windows Server 2016虚拟机安装教程

一、VMware Workstation虚拟机软件的下载 官网下载入口&#xff1a;​​​​​​Download VMware Workstation Pro - VMware Customer Connect​​​​​ 下载好之后自己看着提示安装软件就好. 二、镜像文件的下载 下载网站入口&#xff1a;MSDN, 我告诉你 - 做一个安静…

【Java EE】Spring核心思想(一)——IOC

文章目录 &#x1f38d;Spring 是什么&#xff1f;&#x1f384;什么是IoC呢&#xff1f;&#x1f338;传统程序开发&#x1f338;传统程序开发的缺陷&#x1f338;如何解决传统程序的缺陷&#xff1f;&#x1f338;控制反转式程序开发&#x1f338;对比总结 &#x1f332;理解…

汇编语言知识点整理(应付考试专用,想学习找其他的)

1 基础知识 1.1 信息在计算机内部的表示和存储 1.1.1 信息存储的基本概念 信息在计算机内部是以二进制数据的形式在存储器中存取的。介绍两个基本概念&#xff1a; 位&#xff08;Bit&#xff09; 计算机中最小的数据单位&#xff0c;一位有0、1两状态。Bit是计算机中最小…

MySQL优化表,表的碎片整理和空间回收,清理空间

1.sql -- 查看表占用空间大小。简单查询可以用show table status like blog_visit; select data_length, index_length, data_free, o.* from information_schema.tables o where table_schema in (lishuoboy-navigation) and table_nameblog_visit order by data_length des…

计算机服务器中了rmallox勒索病毒怎么办,rmallox勒索病毒解密流程步骤

在企业的生产运营过程中网络发挥着巨大作用&#xff0c;利用网络可以拓宽市场&#xff0c;提高办公效率&#xff0c;网络为企业的生产运营提供了极大便利&#xff0c;但也为企业的数据安全带来隐患。近日&#xff0c;云天数据恢复中心接到多家企业的求助&#xff0c;企业的计算…

使用 Verdaccio 私有化 npm 源指南

使用 Verdaccio 私有化 npm 源指南 使用 Verdaccio 私有化 npm 源指南 介绍什么是 Verdaccio为什么选择 Verdaccio部署 Verdaccio Nodejs 部署 全局局部 Docker 部署云服务商一键部署 注册用户发布私有 npm 包管理 npm 包项目使用私有源 全量切换部分切换 结尾源代码链接 介…

网络篇10 | 网络层 IP

网络篇10 | 网络层 IP 01 简介02 名称解释03 IP报文格式(IPv4)1&#xff09;4位版本协议(version)2&#xff09;4位首部长度(header length)3&#xff09;8位服务类型(Type Of Service, TOS)4&#xff09;16位总长度5&#xff09;16位(分片)标识6&#xff09;3位(分片)标志7&am…

Spring Cloud 集成 RabbitMQ

目录 前言步骤引入相关maven依赖添加相关配置 使用方法配置消息序列化创建第一个消息队列和交换机使用方法 总结 前言 在当今的微服务架构盛行的时代&#xff0c;消息队列作为一种重要的通信机制&#xff0c;在分布式系统中扮演着不可或缺的角色。RabbitMQ&#xff0c;作为一款…

ASP.NET公交车管理系统的实现与设计

摘 要 随着经济的日益增长&#xff0c;信息化时代已经到来&#xff0c;生活中各种信息趋向数字化、清晰化。公交车作为现代城市生活中一种重要的交通工具&#xff0c;其数量增多&#xff0c;车型也不再单一&#xff0c;雇用的司机增多&#xff0c;这样使得公交车公司的车辆信…

XTTS数据迁移方案

前置条件检查 XTTS使用限制较多&#xff0c;V3版本按照本节逐项检查 目标库操作系统不能是windows 源库&#xff1a;redhut 7.9 目标库&#xff1a;redhut 7.9 检查数据库时区&#xff08;两边都需要&#xff09; SQL> select dbtimezone from dual; 检查结果两边都一致…

机器学习和深度学习--李宏毅 (笔记与个人理解)Day 16

Day 16 deep Learning – 鱼与熊掌兼得 最近在减重&#xff0c; 昨天跑了个一公里&#xff0c;然后今天上午又打了个篮球&#xff0c;真是老胳膊老腿了&#xff0c;运动完给我困得不行 Review 见前面的笔记 这里说dl 会提供一个足够大的模型&#xff0c; 来使得Dall loss 足够小…

Unity类银河恶魔城学习记录12-14 p136 Merge Skill Tree with Sword skill源代码

Alex教程每一P的教程原代码加上我自己的理解初步理解写的注释&#xff0c;可供学习Alex教程的人参考 此代码仅为较上一P有所改变的代码 【Unity教程】从0编程制作类银河恶魔城游戏_哔哩哔哩_bilibili CharacterStats.cs using System.Collections; using System.Collections.…

【氮化镓】GaN HEMTs结温和热阻测试方法

文章《Temperature rise detection in GaN high-electron-mobility transistors via gate-drain Schottky junction forward-conduction voltages》&#xff0c;由Xiujuan Huang, Chunsheng Guo, Qian Wen, Shiwei Feng, 和 Yamin Zhang撰写&#xff0c;发表在《Microelectroni…

绿联HDMI延长器40265使用AG7120芯片放大器方案

HDMI延长器和放大器 延长器&#xff1a;主要用于HDMI线的延长&#xff0c;有HDMI对接头方式延长&#xff0c;或HDMI公头加HDMI母头的HDMI线进行延长&#xff0c;或通过网线方式延长&#xff0c;早期为双网线&#xff0c;目前已发展为单网线&#xff0c;需要注意的是&#xff0…

NLP_知识图谱_图谱问答实战

文章目录 图谱问答NERac自动机实体链接实体消歧 多跳问答neo4j_graph执行流程结构图![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/1577c1d9c9e342b3acbf79824aae980f.png)company_data![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/20f567d877c743b…

【core analyzer】core analyzer的介绍和安装详情

目录 &#x1f31e;1. core和core analyzer的基本概念 &#x1f33c;1.1 coredump文件 &#x1f33c;1.2 core analyzer &#x1f31e;2. core analyzer的安装详细过程 &#x1f33c;2.1 方式一 简单但不推荐 &#x1f33c;2.2 方式二 推荐 &#x1f33b;2.2.1 安装遇到…

TCP/IP 协议栈在 Linux 内核中的 运行时序分析

1、Linux内核概述 1.1 Linux内核结构 一个完整的Linux内核一般由5部分组成&#xff0c;它们分别是内存管理、进程管理、进程间通信、bai虚拟文件系统和网络接口。 1、内存管理 内存管理主要完成的是如何合理有效地管理整个系统的物理内存&#xff0c;同时快速响应内核各个子…

数据可视化基础与应用-04-seaborn库人口普查分析--如何做人口年龄层结构金字塔

总结 本系列是数据可视化基础与应用的第04篇seaborn&#xff0c;是seaborn从入门到精通系列第3篇。本系列主要介绍基于seaborn实现数据可视化。 参考 参考:我分享了一个项目给你《seaborn篇人口普查分析–如何做人口年龄层结构金字塔》&#xff0c;快来看看吧 数据集地址 h…

7 种实现 CSS 三角形的原理与方法 以及 三角形在网页设计中的作用

三角形在网页设计中不仅是图形设计的基本元素&#xff0c;更是实现视觉引导、空间构建、情绪传达、品牌塑造、性能优化以及创新表达的重要工具。其广泛应用和多功能性使其成为设计师手中不可或缺的设计语言组成部分。本文介绍了7种CSS实现三角形的方法。 CSS实现三角形主要有以…

MYSQL执行过程和顺序详解

一、前言 1.1、说明 就MySQL在执行过程、sql执行顺序&#xff0c;以及一些相关关键字的注意点方面的学习分享内容。 在参考文章的基础上&#xff0c;会增加自己的理解、看法&#xff0c;希望本文章能够在您的学习中提供帮助。 如有错误的地方&#xff0c;欢迎指出纠错&…