当前位置: 首页 > article >正文

forms实现连连看

说明:
forms实现连连看
效果图:
在这里插入图片描述

step1:C:\Users\wangrusheng\RiderProjects\WinFormsApp2\WinFormsApp2\Form1.cs

  using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;namespace WinFormsApp2
{public partial class Form1 : Form{private const int ROWS = 12;private const int COLS = 12;private const int CELL_SIZE = 40;private const int BORDER = 1;private readonly string[] EMOJI_LIST = {"🐶", "🐱", "🐭", "🐹", "🐰", "🦊", "🐻", "🐼","🐨", "🐯", "🦁", "🐮", "🐷", "🐸", "🐵", "🐧"};private Button[,] grid = new Button[ROWS, COLS];private int[,] board = new int[ROWS, COLS];private Point? firstSelection = null;private List<Point> currentPath = null;private System.Windows.Forms.Timer pathTimer = new System.Windows.Forms.Timer();private int score = 0;private List<Point> hintPair = new List<Point>();private System.Windows.Forms.Timer hintTimer = new System.Windows.Forms.Timer();public Form1(){InitializeComponent();InitializeGameBoard();SetupControls();pathTimer.Interval = 500;pathTimer.Tick += (s, e) => ClearPath();hintTimer.Interval = 2000;hintTimer.Tick += (s, e) => ClearHint();this.DoubleBuffered = true;this.ClientSize = new Size(COLS * CELL_SIZE, ROWS * CELL_SIZE + 60);}private void SetupControls(){// Score Labelvar lblScore = new Label{Name = "lblScore",Location = new Point(10, ROWS * CELL_SIZE + 10),AutoSize = true,Text = "得分: 0"};// Restart Buttonvar btnRestart = new Button{Text = "重新开始",Location = new Point(100, ROWS * CELL_SIZE + 10),Size = new Size(80, 30)};btnRestart.Click += (s, e) => RestartGame();// Hint Buttonvar btnHint = new Button{Text = "提示",Location = new Point(200, ROWS * CELL_SIZE + 10),Size = new Size(80, 30)};btnHint.Click += (s, e) => ShowHint();Controls.AddRange(new Control[] { lblScore, btnRestart, btnHint });}private void InitializeGameBoard(){int innerRows = ROWS - 2 * BORDER;int innerCols = COLS - 2 * BORDER;int totalInner = innerRows * innerCols;List<int> tileList = new List<int>();for (int i = 0; i < totalInner / 2; i++){int index = i % EMOJI_LIST.Length;tileList.Add(index);tileList.Add(index);}var rand = new Random();tileList = tileList.OrderBy(x => rand.Next()).ToList();int tileIndex = 0;for (int i = 0; i < ROWS; i++){for (int j = 0; j < COLS; j++){var btn = new Button{Size = new Size(CELL_SIZE, CELL_SIZE),Location = new Point(j * CELL_SIZE, i * CELL_SIZE),Tag = new Point(i, j),Font = new Font("Segoe UI Emoji", 12),FlatStyle = FlatStyle.Flat};btn.Click += Button_Click;if (IsBorder(i, j)){board[i, j] = -1;btn.Enabled = false;btn.BackColor = Color.Gray;}else{board[i, j] = tileList[tileIndex++];btn.Text = EMOJI_LIST[board[i, j]];}grid[i, j] = btn;Controls.Add(btn);}}}private void Button_Click(object sender, EventArgs e){var btn = (Button)sender;var pos = (Point)btn.Tag;if (board[pos.X, pos.Y] == -1) return;if (firstSelection == null){firstSelection = pos;btn.BackColor = Color.LightBlue;}else{var second = pos;if (firstSelection == second){ClearSelection();return;}var p1 = firstSelection.Value;var p2 = second;if (board[p1.X, p1.Y] == board[p2.X, p2.Y] && CheckConnection(p1, p2)){currentPath = GetConnectionPath(p1, p2);pathTimer.Start();Invalidate();board[p1.X, p1.Y] = -1;board[p2.X, p2.Y] = -1;grid[p1.X, p1.Y].Text = "";grid[p2.X, p2.Y].Text = "";score += 10;UpdateScore();}ClearSelection();}}private bool CheckConnection(Point p1, Point p2){if (DirectConnection(p1, p2)) return true;if (OneTurnConnection(p1, p2)) return true;return TwoTurnConnection(p1, p2);}private bool DirectConnection(Point a, Point b){if (a.X == b.X){int minY = Math.Min(a.Y, b.Y);int maxY = Math.Max(a.Y, b.Y);for (int y = minY + 1; y < maxY; y++){if (board[a.X, y] != -1) return false;}return true;}if (a.Y == b.Y){int minX = Math.Min(a.X, b.X);int maxX = Math.Max(a.X, b.X);for (int x = minX + 1; x < maxX; x++){if (board[x, a.Y] != -1) return false;}return true;}return false;}private bool OneTurnConnection(Point a, Point b){var corner1 = new Point(a.X, b.Y);if (board[corner1.X, corner1.Y] == -1){if (DirectConnection(a, corner1) && DirectConnection(corner1, b)) return true;}var corner2 = new Point(b.X, a.Y);if (board[corner2.X, corner2.Y] == -1){if (DirectConnection(a, corner2) && DirectConnection(corner2, b)) return true;}return false;}private bool TwoTurnConnection(Point a, Point b){// Horizontal scanfor (int x = 0; x < ROWS; x++){var p1 = new Point(x, a.Y);var p2 = new Point(x, b.Y);if (board[p1.X, p1.Y] == -1 && board[p2.X, p2.Y] == -1){if (DirectConnection(a, p1) && DirectConnection(p1, p2) && DirectConnection(p2, b))return true;}}// Vertical scanfor (int y = 0; y < COLS; y++){var p1 = new Point(a.X, y);var p2 = new Point(b.X, y);if (board[p1.X, p1.Y] == -1 && board[p2.X, p2.Y] == -1){if (DirectConnection(a, p1) && DirectConnection(p1, p2) && DirectConnection(p2, b))return true;}}return false;}private List<Point> GetConnectionPath(Point a, Point b){var path = new List<Point> { a };if (DirectConnection(a, b)){path.Add(b);return path;}if (OneTurnConnection(a, b)){if (board[a.X, b.Y] == -1){path.Add(new Point(a.X, b.Y));}else{path.Add(new Point(b.X, a.Y));}path.Add(b);return path;}// For two-turn connection (simplified path)path.Add(a);path.Add(b);return path;}protected override void OnPaint(PaintEventArgs e){base.OnPaint(e);if (currentPath != null && currentPath.Count >= 2){using (var pen = new Pen(Color.Blue, 4)){var points = currentPath.Select(p => new Point(p.Y * CELL_SIZE + CELL_SIZE/2, p.X * CELL_SIZE + CELL_SIZE/2)).ToArray();e.Graphics.DrawLines(pen, points);}}// Draw hintif (hintPair.Count == 2){using (var pen = new Pen(Color.Gold, 4)){var points = hintPair.Select(p => new Point(p.Y * CELL_SIZE + CELL_SIZE/2, p.X * CELL_SIZE + CELL_SIZE/2)).ToArray();e.Graphics.DrawLines(pen, points);}}}private void ShowHint(){for (int i = BORDER; i < ROWS - BORDER; i++){for (int j = BORDER; j < COLS - BORDER; j++){if (board[i, j] == -1) continue;for (int x = i; x < ROWS - BORDER; x++){for (int y = (x == i ? j + 1 : BORDER); y < COLS - BORDER; y++){if (board[x, y] == board[i, j] && CheckConnection(new Point(i, j), new Point(x, y))){hintPair = new List<Point> { new Point(i, j), new Point(x, y) };hintTimer.Start();Invalidate();return;}}}}}}private void ClearPath() => currentPath = null;private void ClearHint() => hintPair.Clear();private void UpdateScore() => Controls["lblScore"].Text = $"得分: {score}";private bool IsBorder(int x, int y) => x < BORDER || y < BORDER || x >= ROWS - BORDER || y >= COLS - BORDER;private void ClearSelection(){if (firstSelection != null)grid[firstSelection.Value.X, firstSelection.Value.Y].BackColor = DefaultBackColor;firstSelection = null;}private void RestartGame(){Controls.OfType<Button>().Where(b => b.Tag != null).ToList().ForEach(b => Controls.Remove(b));board = new int[ROWS, COLS];grid = new Button[ROWS, COLS];score = 0;UpdateScore();InitializeGameBoard();ClearPath();ClearHint();}}
}

备选方案: 纯数字版

 namespace WinFormsApp2
{
public partial class Form1 : Form
{
// Board dimensions (include a border to simplify connection checking)
private int rows = 12; // for example, 12 rows (including border)
private int cols = 12; // 12 columns (including border)
private int cellSize = 40; // pixel size for each button// Game grid of buttons and underlying board values.private Button[,] grid;private int[,] board;// To store the first and second selected positionsprivate Point? firstSelection = null;public Form1(){InitializeComponent();InitializeGameBoard();}// Initializes the game board with a border and fills the inner cells with matching pairs.private void InitializeGameBoard(){grid = new Button[rows, cols];board = new int[rows, cols];// Calculate total inner cells (excluding borders) and make sure they form pairs.int innerRows = rows - 2;int innerCols = cols - 2;int totalInner = innerRows * innerCols;if(totalInner % 2 != 0){MessageBox.Show("Total number of inner cells must be even.");return;}// Prepare list of pairs (here we simply use numbers to represent different tiles)List<int> tileList = new List<int>();for (int i = 0; i < totalInner / 2; i++){tileList.Add(i);tileList.Add(i);}// Shuffle the tile list randomlyRandom rand = new Random();tileList = tileList.OrderBy(x => rand.Next()).ToList();// Create buttons and assign valuesint index = 0;for (int i = 0; i < rows; i++){for (int j = 0; j < cols; j++){Button btn = new Button();btn.Width = cellSize;btn.Height = cellSize;btn.Location = new Point(j * cellSize, i * cellSize);btn.Tag = new Point(i, j);btn.Click += Button_Click;grid[i, j] = btn;this.Controls.Add(btn);// Create a border: outside the inner grid, set value to -1 (indicating an always-empty cell)if (i == 0 || j == 0 || i == rows - 1 || j == cols - 1){board[i, j] = -1;btn.Enabled = false; // disable border buttonsbtn.BackColor = Color.Gray;}else{board[i, j] = tileList[index];index++;// Display the tile value (in a final game you would show an image/icon)btn.Text = board[i, j].ToString();}}}}// Handles button click events for selecting tiles.private void Button_Click(object sender, EventArgs e){Button btn = sender as Button;Point pos = (Point)btn.Tag;int x = pos.X;int y = pos.Y;// Ignore clicks on empty cells (or border cells)if (board[x, y] == -1 || string.IsNullOrEmpty(btn.Text))return;if (firstSelection == null){// First tile selectedfirstSelection = pos;btn.BackColor = Color.Yellow;}else{// Second tile selectedPoint secondSelection = pos;// If user clicked the same tile, just ignoreif (firstSelection.Value == secondSelection)return;// Check if the two tiles have the same value.Point p1 = firstSelection.Value;Point p2 = secondSelection;if (board[p1.X, p1.Y] != board[p2.X, p2.Y]){// Not a matching pair. Reset first tile's highlight and choose the new one.grid[p1.X, p1.Y].BackColor = default(Color);firstSelection = secondSelection;btn.BackColor = Color.Yellow;}else{// Same value: check if they can be connectedif (CheckConnectivity(p1, p2)){// Connection is valid: remove the tiles.board[p1.X, p1.Y] = -1;board[p2.X, p2.Y] = -1;grid[p1.X, p1.Y].Text = "";grid[p2.X, p2.Y].Text = "";grid[p1.X, p1.Y].BackColor = default(Color);grid[p2.X, p2.Y].BackColor = default(Color);}else{// Cannot connect: reset the highlight.grid[p1.X, p1.Y].BackColor = default(Color);}// Reset selection for next pair.firstSelection = null;}}}// Checks whether two positions can be connected using at most two turns.private bool CheckConnectivity(Point p1, Point p2){// 1. Direct connection check: same row or same column.if (DirectConnection(p1, p2))return true;// 2. Check connection with one turn.if (OneTurnConnection(p1, p2))return true;// 3. Check connection with two turns.if (TwoTurnConnection(p1, p2))return true;return false;}// Direct connection: both positions on the same row or column and the cells between them are empty.private bool DirectConnection(Point p1, Point p2){if (p1.X == p2.X){int minY = Math.Min(p1.Y, p2.Y);int maxY = Math.Max(p1.Y, p2.Y);for (int j = minY + 1; j < maxY; j++){if (board[p1.X, j] != -1)return false;}return true;}if (p1.Y == p2.Y){int minX = Math.Min(p1.X, p2.X);int maxX = Math.Max(p1.X, p2.X);for (int i = minX + 1; i < maxX; i++){if (board[i, p1.Y] != -1)return false;}return true;}return false;}// One-turn connection: Try turning at (p1.X, p2.Y) and (p2.X, p1.Y)private bool OneTurnConnection(Point p1, Point p2){// First turning point: (p1.X, p2.Y)Point p3 = new Point(p1.X, p2.Y);if (board[p3.X, p3.Y] == -1){if (DirectConnection(p1, p3) && DirectConnection(p3, p2))return true;}// Second turning point: (p2.X, p1.Y)Point p4 = new Point(p2.X, p1.Y);if (board[p4.X, p4.Y] == -1){if (DirectConnection(p1, p4) && DirectConnection(p4, p2))return true;}return false;}// Two-turn connection: try connecting by scanning through possible rows and columns.private bool TwoTurnConnection(Point p1, Point p2){// Try vertical scan: for each row, check if we can connect via two turns.for (int i = 0; i < rows; i++){Point p3 = new Point(i, p1.Y);Point p4 = new Point(i, p2.Y);if (board[p3.X, p3.Y] == -1 && board[p4.X, p4.Y] == -1){if (DirectConnection(p1, p3) && OneTurnConnection(p3, p2))return true;}}// Try horizontal scan: for each column, check similarly.for (int j = 0; j < cols; j++){Point p3 = new Point(p1.X, j);Point p4 = new Point(p2.X, j);if (board[p3.X, p3.Y] == -1 && board[p4.X, p4.Y] == -1){if (DirectConnection(p1, p3) && OneTurnConnection(p3, p2))return true;}}return false;}
}}

end

相关文章:

forms实现连连看

说明&#xff1a; forms实现连连看 效果图&#xff1a; step1:C:\Users\wangrusheng\RiderProjects\WinFormsApp2\WinFormsApp2\Form1.cs using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Windows.Forms;namespace …...

多视图几何--立体校正--Fusiello方法

1. 坐标系对齐与正交基构造 目标&#xff1a;构建新坐标系基向量 { e 1 , e 2 , e 3 } \{ \mathbf{e}_1, \mathbf{e}_2, \mathbf{e}_3 \} {e1​,e2​,e3​}&#xff0c;使成像平面共面且极线水平对齐。 (1) 基线方向 e 1 \mathbf{e}_1 e1​ 基线向量由左右相机光心平移向量…...

鸿蒙开发踩坑记录 - 2024S2

wrapBuilder如果想View和ObservedV2做绑定 必须要用 ComponentV2 Param 和 区别 退出两层循环 Builder的传入的参数及时是Trace修饰的也无法刷新组件 折叠屏展开后键盘无法点击 vm是公用的&#xff0c;组件生命周期问题导致 监听键盘高度变化失效 原因&#xff1a;分享面…...

【学Rust写CAD】21 2D 点(point.rs)

源码 //matrix/point.rs use std::ops::Mul; use super::algebraic_units::{Zero, One}; use super::generic::Matrix;/// 点坐标结构体 #[derive(Debug, Clone, Copy, PartialEq)] pub struct Point<X, Y>(Matrix<X, Y, One, Zero, Zero, One>);impl<X, Y>…...

0基础入门scrapy 框架,获取豆瓣top250存入mysql

一、基础教程 创建项目命令 scrapy startproject mySpider --项目名称 创建爬虫文件 scrapy genspider itcast "itcast.cn" --自动生成 itcast.py 文件 爬虫名称 爬虫网址 运行爬虫 scrapy crawl baidu(爬虫名&#xff09; 使用终端运行太麻烦了&#xff0c;而且…...

鸿蒙NEXT小游戏开发:井字棋

1. 引言 井字棋是一款经典的两人对战游戏&#xff0c;简单易懂&#xff0c;适合各个年龄段的玩家。本文将介绍如何使用鸿蒙NEXT框架开发一个井字棋游戏&#xff0c;涵盖游戏逻辑、界面设计及AI对战功能。 2. 开发环境准备 电脑系统&#xff1a;windows 10 开发工具&#xff1a;…...

deep-sync开源程序插件导出您的 DeepSeek 与 public 聊天

一、软件介绍 文末提供下载 deep-sync开源程序插件导出您的 DeepSeek 与 public 聊天&#xff0c;这是一个浏览器扩展&#xff0c;它允许用户公开、私下分享他们的聊天对话&#xff0c;并使用密码或过期链接来增强 Deepseek Web UI。该扩展程序在 Deepseek 界面中添加了一个 “…...

4. 理解Prompt Engineering:如何让模型听懂你的需求

引言:当模型变成“实习生” 想象一下,你新招的实习生总把“帮我写份报告”理解为“做PPT”或“整理数据表”——这正是开发者与大模型对话的日常困境。某金融公司优化提示词后,合同审查准确率从72%飙升至94%。本文将用3个核心法则+5个行业案例,教你用Prompt Engineering让…...

网络编程—网络概念

目录 1 网络分类 1.1 局域网 1.2 广域网 2 常见网络概念 2.1 交换机 2.2 路由器 2.3 集线器 2.4 IP地址 2.5 端口号 2.6 协议 3 网络协议模型 3.1 OSI七层模型 3.2 TCP/IP五层模型 3.3 每层中常见的协议和作用 3.3.1 应用层 3.3.2 传输层 3.3.3 网络层 3.3.4…...

基于Rust与WebAssembly实现高性能前端计算

引言 随着Web应用的复杂性增加&#xff0c;前端开发者经常面临性能瓶颈。传统JavaScript在处理密集型计算任务&#xff08;如大数据处理或实时图像渲染&#xff09;时&#xff0c;往往显得力不从心。而Rust语言凭借其高性能和内存安全特性&#xff0c;结合WebAssembly的接近原生…...

MATLAB 代码学习

1. Cell数组 Cell数组用于存储异构数据&#xff0c;每个元素&#xff08;称为cell&#xff09;可以包含不同类型的数据&#xff08;如数值、字符串、矩阵等&#xff09;。 1.1 创建Cell数组 直接赋值&#xff1a;使用花括号{}定义内容。 students {Alice, 20, [85, 90, 78…...

SELinux

一、selinux技术详解 SELinux 概述 SELinux&#xff0c;即 Security-Enhanced Linux&#xff0c;意为安全强化的 Linux&#xff0c;由美国国家安全局&#xff08;NSA&#xff09;主导开发。开发初衷是防止系统资源被误用。在 Linux 系统中&#xff0c;系统资源的访问均通过程…...

Axios 相关的面试题

在跟着视频教程学习项目的时候使用了axios发送请求&#xff0c;但是只是跟着把代码粘贴上去&#xff0c;一些语法规则根本不太清楚&#xff0c;但是根据之前的博客学习了fetch了之后&#xff0c;一看axios的介绍就明白了。所以就直接展示axios的面试题吧 本文主要内容&#xff…...

Spring Cloud 跨云灾备:如何实现5分钟级区域切换?

引言&#xff1a;云原生时代&#xff0c;区域级故障的致命性与应对 在混合云与多云架构中&#xff0c;单个区域的宕机可能导致全局服务瘫痪&#xff08;如2023年AWS美东区域故障影响超200家金融系统&#xff09;。传统灾备方案依赖手动切换DNS或冷备集群&#xff0c;恢复时间长…...

ES6对函数参数的新设计

ES6 对函数参数进行了新的设计&#xff0c;主要添加了默认参数、不定参数和扩展参数&#xff1a; 不定参数和扩展参数可以认为恰好是相反的两个模式&#xff0c;不定参数是使用数组来表示多个参数&#xff0c;扩展参数则是将多个参数映射到一个数组。 需要注意&#xff1a;不定…...

爬虫【feapder框架】

feapder框架 1、简单介绍 简介 feapder上手简单、功能强大的Python爬虫框架&#xff0c;内置AirSpider、Spider、Task、Spider、BatchSpider四种爬虫解决不同场景的需求支持断点续爬、监控报警、浏览器渲染、海量数据去重等功能更有功能强大的爬虫管理系统feaplat为其提供方…...

python如何提取html中所有的图片链接

在Python中&#xff0c;你可以使用BeautifulSoup库来解析HTML内容&#xff0c;并提取其中所有的图片链接&#xff08;即<img>标签的src属性&#xff09;。以下是一个示例代码&#xff0c;展示了如何做到这一点&#xff1a; 首先&#xff0c;确保你已经安装了BeautifulSo…...

网络协议之系列

网络协议之基础介绍 。 网络协议之清空购物车时都发生了啥&#xff1f; 。...

LLaMA Factory微调后的大模型在vLLM框架中对齐对话模版

LLaMA Factory微调后的大模型Chat对话效果&#xff0c;与该模型使用vLLM推理架构中的对话效果&#xff0c;可能会出现不一致的情况。 下图是LLaMA Factory中的Chat的对话 下图是vLLM中的对话效果。 模型回答不稳定&#xff1a;有一半是对的&#xff0c;有一半是无关的。 1、未…...

群体智能优化算法-鹈鹕优化算法(Pelican Optimization Algorithm, POA,含Matlab源代码)

摘要 鹈鹕优化算法&#xff08;Pelican Optimization Algorithm, POA&#xff09;是一种灵感来自自然界鹈鹕觅食行为的元启发式优化算法。POA 模拟鹈鹕捕食的两个主要阶段&#xff1a;探索阶段和开发阶段。通过模拟鹈鹕追捕猎物的动态行为&#xff0c;该算法在全局探索和局部开…...

代理模式-spring关键设计模式,bean的增强,AOP的实现

以下是一个结合代理模式解决实际问题的Java实现案例&#xff0c;涵盖远程调用、缓存优化、访问控制等场景&#xff0c;包含逐行中文注释&#xff1a; 场景描述 开发一个跨网络的文件查看器&#xff0c;需实现&#xff1a; 远程文件访问&#xff1a;通过代理访问网络文件 缓存…...

前端实现单点登录(SSO)的方案

概念&#xff1a;单点登录&#xff08;Single Sign-On, SSO&#xff09;主要是在多个系统、多个浏览器或多个标签页之间共享登录状态&#xff0c;保证用户只需登录一次&#xff0c;就能访问多个关联应用&#xff0c;而不需要重复登录。 &#x1f4a1; 方案分类 1. 前端级别 SS…...

在 Blazor 中使用 Chart.js 快速创建数据可视化图表

前言 BlazorChartjs 是一个在 Blazor 中使用 Chart.js 的库&#xff08;支持Blazor WebAssembly和Blazor Server两种模式&#xff09;&#xff0c;它提供了简单易用的组件来帮助开发者快速集成数据可视化图表到他们的 Blazor 应用程序中。本文我们将一起来学习一下在 Blazor 中…...

SQL server 2022和SSMS的使用案例1

一&#xff0c;案例讲解 二&#xff0c;实战讲解 实战环境 你需要确保你已经安装完成SQL Server 2022 和SSMS 20.2 管理面板。点此跳转至安装教程 SQL Server2022Windows11 专业工作站SSMS20.2 1&#xff0c;连接数据库 打开SSMS&#xff0c;连接数据库。 正常连接示意图&…...

【每日算法】Day 16-1:跳表(Skip List)——Redis有序集合的核心实现原理(C++手写实现)

解锁O(log n)高效查询的链表奇迹&#xff01;今日深入解析跳表的数据结构设计与实现细节&#xff0c;从基础概念到Redis级优化策略&#xff0c;彻底掌握这一平衡树的优雅替代方案。 一、跳表核心思想 跳表&#xff08;Skip List&#xff09; 是一种基于多层有序链表的概率型数…...

前沿科技:3D生成领域技术与应用分析

以下是关于3D生成领域的详细分析,涵盖技术发展、应用场景、挑战与未来趋势、市场动态及典型案例: 一、技术发展与核心方法 3D表示方法 显式表示:包括点云、网格(三角形或四边形)和分层深度图像(LDI),适合直接操作和渲染,但细节复杂度高。 隐式表示:如神经辐射场(NeR…...

Spring Boot 3.4.3 基于 JSqlParser 和 MyBatis 实现自定义数据权限

前言 在企业级应用中,数据权限控制是保证数据安全的重要环节。本文将详细介绍如何在 Spring Boot 3.4.3 项目中结合 JSqlParser 和 MyBatis 实现灵活的数据权限控制,通过动态 SQL 改写实现多租户、部门隔离等常见数据权限需求。 一、环境准备 确保开发环境满足以下要求: …...

GO语言学习(14)GO并发编程

目录 &#x1f308;前言 1.goroutine&#x1f31f; 2.GMP模型&#x1f31f; 2.1 GMP的由来☀️ 2.2 什么是GMP☀️ 3.channel &#x1f31f; 3.1 通道声明与数据传输&#x1f4a5; 3.2 通道关闭 &#x1f4a5; 3.3 通道遍历 &#x1f4a5; 3.4 Select语句 &#x1f4…...

【Audio开发二】Android原生音量曲线调整说明

一&#xff0c;客制化需求 客户方对于音量加减键从静音到最大音量十五个档位区域的音量变化趋势有定制化需求。 二&#xff0c;音量曲线调试流程 Android根据不同的音频流类型定义不同的曲线&#xff0c;曲线文件存放在/vendor/etc/audio_policy_volumes.xml或者default_volu…...

sass报错,忽略 Sass 弃用警告,降级版本

最有效的方法是创建一个 .sassrc.json 文件来配置 Sass 编译器。告诉 Sass 编译器忽略来自依赖项的警告消息。 解决方案&#xff1a; 1. 在项目根目录创建 .sassrc.json 文件&#xff1a; {"quietDeps": true }这个配置会让 Sass 编译器忽略所有来自依赖项&#x…...