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

童年回忆--扫雷(包括标记功能和递归展开)--万字讲解让你学会扫雷制作

在这里插入图片描述

  • 魔王的介绍:😶‍🌫️一名双非本科大一小白。
  • 魔王的目标:🤯努力赶上周围卷王的脚步。
  • 魔王的主页:🔥🔥🔥大魔王.🔥🔥🔥
    在这里插入图片描述
    ❤️‍🔥大魔王与你分享:人生人山人海人来人往,自己自尊自爱自由自在。

在这里插入图片描述


文章目录

  • 一、前言
  • 二、文件介绍
  • 三、代码实现
    • 1.创建基本的框架
    • 2.#define定义常量
    • 3.创建和初始化二维数组
    • 4.埋雷
    • 5.打印雷盘
    • 6.玩家标记
    • 7.玩家下棋
  • 四、总代码如下
    • `game.h`
    • `game.c`
    • `test.c`
    • 效果展示图
  • 五、总结

一、前言

小时候我们在家里刚买电脑的时候,网络还不是很发达(两三年纪吧),每次断网我们都除了电脑自带的那一点单机游戏外没什么玩的,其中最好玩的便是扫雷,那么你可以用代码实现扫雷吗?这里我们添加了两个功能:第一个是标记功能,如果确定为雷我们可以标记为!,如果不确定,我们可以标记为?,第二个功能是递归展开:我们知道如果我们我们所点的那个位置一周都不是雷,那么它会自动扩开,如果我们点的地方有雷,那么会显示出周围雷的个数,如果想尝试玩一下,点击扫雷可以跳转过去,那么接下来就学习以下如何代码实现吧!

二、文件介绍

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

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

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

三、代码实现

1.创建基本的框架

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;case 0:printf("退出游戏\n");break;default:printf("输入错误,请重新输入\n");}} while (input);}int main()
{test();return 0;
}

2.#define定义常量

因为我们在点击一个位置后如果附近有雷,那么就需要显示周围有几个雷,所以我们需要访问这个位置一周的内容,所以如果我们创建的表格大小和玩的时候打印出来的一样大,那么当访问边上那些位置周围雷的个数时,就会数组越界,所以我们如果要下99雷盘,我们需要让行和列都宽一个位置,也就是创建1111的雷盘,不过打印的话只打印中间的9*9格。所以为了方便我们先定义常量。

#define ROW 9#define COL 9#define ROWS ROW+2#define COLS COL+2#define mine_num 10

3.创建和初始化二维数组

和三子棋一样,我们要实现选中那个位置出现什么效果,只能是通过二维数组,让二位数组里的元素发生变化,在玩家视角就是自己操作了这个地方,我们需要创建两个二维数组,一个是布置雷区的二维数组,只在后台存在,并不显示出来,另一个则是给玩家展示的二维数组,至于为什么是两个,有很多原因,最容易说的就是:总不能把布置的雷展示给玩家吧,这样还怎么玩,不就开挂了。所以规定:让埋雷区初始化为字符0,展示区初始化为字符*,字符0是因为我们想用一个函数来初始化这两个雷盘,传的参数只需要最后传的字符不一样(一个是字符0,一个是字符*),其他都是一样的,所以为了方便之后的操作(两个雷盘间的联系),我们把两个数组都定义为char类型。


//初始化
void init_board(char board[ROWS][ROWS], int rows, int cols, char a)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = a;}}
}
char mine[ROWS][COLS];
char show[ROWS][COLS];
//初始化雷区
init_board(mine, ROWS,COLS,'0');
//初始化展示区
init_board(show,ROWS,COLS, '*');

4.埋雷

在上篇智能三子棋博客中已经用到了随机数生成函数,点击智能三子棋可以跳转到该博客,里面有随机数的讲解。雷盘里我们初始化的是字符0,我们把埋雷的地方初始化为字符1,到计算的时候只需要让某个位置一周(8个)的数字字符相加减去7个字符0即可得到表示该位置有多少个雷的数字字符。

//放雷
void put_mine(char mine[ROWS][COLS], int rows, int cols)
{int num = 0;for (num = 0; num < mine_num; num++){while (1){int i = rand() % ROW + 1;int j = rand() % COL + 1;if (mine[i][j] == '0'){mine[i][j] = '1';break;}}}
}
//埋雷
put_mine(mine,ROWS, COLS);

5.打印雷盘

做完这些操作,我们就需要让玩家看到雷盘了,打印的时候因为行与列比较多,所以我们进行了排序,让玩家一看就知道自己要选择的地方的坐标。

//打印
void print_board(char board[ROWS][COLS], int rows, int cols)
{int i = 0;printf("   ");//为了对其每行,因为每行的开头加了下标,所以要先空出来下标所占的位置for (i = 1; i < cols-1; i++)//打印每列的下标{printf("%d ", i);}printf("\n");printf("   ");//为了对其每行,因为每行的开头加了下标,所以要先空出来下标所占的位置for (i = 1; i < cols-1; i++)//让每列的下标和其下面的元素隔开{printf("- ");}printf("\n");for (i = 1; i < rows-1; i++){printf("%d| ", i);//标记每行int j = 0;for (j = 1; j < cols-1; j++){printf("%c ", board[i][j]);}printf("\n");}
}
//打印雷盘
//print_board(mine, ROWS, COLS);//上帝视角,打印雷区
//printf("\n");
print_board(show, ROWS, COLS);

6.玩家标记

显示出展示区后玩家就开始下棋了,每次玩家在下棋前,我们都要问是否进行标记,然后标记一次后继续问是要标记还是要退出标记进行扫雷。标记的时候我们需要先判断玩家选择的位置是否在范围内(1~9),然后还要判断是否该位置已经被扫过了(如果没被扫过,该位置坐标只能是’*‘,’!‘,’?')

//玩家标记
void mark_board(char show[ROWS][COLS], int rows, int cols)
{int flag = 0;while (1){printf("选择标记方式:按1标记为雷(!),按2标记为不确定(?),按3取消标记(*),选择4进入排雷环节\n");printf("请玩家选择标记方式:> ");scanf("%d", &flag);if (flag == 1){int i = 0;int j = 0;printf("玩家选择标记位置:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (show[i][j] != '*'&&show[i][j]!='?'){printf("该位置已经扫过或者已经被标记了该种符号,请重新选择\n");continue;}show[i][j] = '!';}}else if (flag == 2){int i = 0;int j = 0;printf("玩家选择:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (show[i][j] != '*' && show[i][j] != '!'){printf("该位置已经扫过或者已经被标记了该种符号,请重新选择\n");continue;}show[i][j] = '?';}}else if (flag == 3)//取消标记,变为原来的*{int i = 0;int j = 0;printf("玩家选择:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (show[i][j] == '?' || show[i][j] == '!'){show[i][j] = '*';}else{printf("该位置已经扫过或者已经被标记了该种符号,请重新选择\n");continue;}}}else if (flag == 4)return;elseprintf("选择错误,请重新选择\n");system("cls");print_board(show, ROWS, COLS);}
}
mark_board(show, ROWS, COLS);//每次输入前的标记环节

7.玩家下棋

因为玩家下棋和递归展开、判断周围雷个数以及输赢是连起来的,所以这个部分比较多。

  • 当扫的雷的个数等于(玩家看到的整个雷盘的个数减去雷的个数)的时候,如果程序还没有结束(也就是这期间没被炸死),那么就说明玩家扫雷成功,游戏胜利。
  • 玩家在进行选择排雷位置时,选择的位置需要合理(1~9),然后还需要没被扫过。
  • 当玩家选择的位置一周都没有雷时,该位置由*变为空格(也就是说只有这个位置一周都没有雷,才变为空格,并且展开一周,否则变为周围雷的个数),并且周围全部展开(每展开一个都要让扫雷的个数+1,否则就不能胜利了),然后继续判断,直到附近有雷时,显示出雷的个数。
  • 当玩家选择的坐标正好是雷时,游戏结束,扫雷失败。
  • 我们第三个所提到的展开一片所用到的就是递归:当我们输入的坐标周围不是雷时,展开周围的全部然后再在周围的这八个里面依次判断是否符合,如果符合就变为空格并且继续展开一篇,如果周围有雷,就不再展开,该位置变为周围雷的个数。
  • 上面的这个如果不经处理就会导致死循环,因为我们选的这个如果周围没雷,就会展开一片,那么这一片又与我们选的这个相邻,那么又会回去判断我们选择的这个位置,然后就这样重复,最终会导致内存崩了。所以我们在进行递归时加一个限制条件,它必须是!、?或*才可以,因为如果是数字字符或空格,说明这个地方已经判断过了,那么就不能再判断这个位置。
    判断周围雷的个数时,因为我们最终想要的是一个数字字符形式,所以我们在让要判断的这个位置周围雷的个数时,我们需要让周围相加减去7个字符0,而不是8个。
  • 我们在表达某个位置一周的坐标的时候,采取的是遍历法,用两个for循环找到这个位置一周的坐标并判断他们是显示数字还是再展开一片。
  • 递归展开是根据安 度 因的扫雷博客自己写出来的,点击安度因可以跳转过去。

//周围雷个数
char around_mine(char mine[ROWS][COLS], int i, int j)
{return mine[i][j - 1] + mine[i][j + 1] + mine[i + 1][j] + mine[i - 1][j] + mine[i - 1][j - 1] + mine[i + 1][j + 1] + mine[i - 1][j + 1] + mine[i + 1][j - 1] - 7 * '0';//一共是8个字符0,但因为我们要用到一个,所以减掉7个,用的那一个是因为我们想以字符数字的形式赋过去,因为数组是字符类型的
}//递归展开
void recursion(char mine[ROWS][COLS], char show[ROWS][COLS], int i, int j, int* p)
{int x = 0;int y = 0;for (x = -1; x <= 1; x++){for (y = -1; y <= 1; y++){if (x + i > 0 && x + i <= ROW && y + j > 0 && y + j <= COL)//防止越界{if (mine[i + x][j + y] == '0' && (show[i + x][j + y] == '*' || show[i + x][j + y] == '?' || show[i + x][j + y] == '!')){(*p)++;if (around_mine(mine, i + x, j + y) == '0'){show[i + x][j + y] = ' ';recursion(mine, show, i + x, j + y, p);}else{show[i + x][j + y] = around_mine(mine, i + x, j + y);//recursion(mine, show, i + x, j + y, p);}}elsecontinue;}}}
}//玩家选择坐标
int player_option(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols,int* p)
{int i = 0;int j = 0;printf("玩家选择:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (mine[i][j] == '1'){return 0;}if (show[i][j] == '*'||show[i][j]=='!'||show[i][j]=='?'){(*p)++; show[i][j] = around_mine(mine, i, j);if (show[i][j] == '0'){show[i][j] = ' ';recursion(mine, show, i, j, p);//递归展开}/*elserecursion(mine, show, i, j, p);*/return 1;}else{printf("该位置已经排过,请重新选择位置\n");Sleep(1500);return 1;}}
}//玩家进行标记和排雷
int num = 0;
int ret = 0;
while (num<ROW*COL-mine_num)//当重复的次数为所有非雷个数后跳出循环,胜利
{mark_board(show, ROWS, COLS);//每次输入前的标记环节ret = player_option(mine, show, ROWS, COLS, &num);system("cls");print_board(show, ROWS, COLS);if (ret == 0){printf("很遗憾,你被炸死了,雷区如下:\n");print_board(mine, ROWS, COLS);//让玩家死后看到这盘扫雷游戏中雷都在哪里break;}//print_board(show, ROWS, COLS);
}
if (num == ROW * COL - mine_num)printf("恭喜你扫除了全部的雷!!!\n");

四、总代码如下

game.h

#pragma once#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <windows.h>#define ROW 9#define COL 9#define ROWS ROW+2#define COLS COL+2#define mine_num 10//初始化
void init_board(char board[ROWS][ROWS], int rows, int cols, char a);//埋雷
void put_mine(char mine[ROWS][COLS],int rows, int cols);//打印
void print_board(char board[ROWS][COLS], int rows, int cols);//玩家选择坐标
int player_option(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols);//玩家标记
void mark_board(char show[ROWS][COLS], int rows, int cols);

game.c

#define _CRT_SECURE_NO_WARNINGS 1#include "game.h"//初始化
void init_board(char board[ROWS][ROWS], int rows, int cols, char a)
{int i = 0;for (i = 0; i < rows; i++){int j = 0;for (j = 0; j < cols; j++){board[i][j] = a;}}
}//放雷
void put_mine(char mine[ROWS][COLS], int rows, int cols)
{int num = 0;for (num = 0; num < mine_num; num++){while (1){int i = rand() % ROW + 1;int j = rand() % COL + 1;if (mine[i][j] == '0'){mine[i][j] = '1';break;}}}
}//打印
void print_board(char board[ROWS][COLS], int rows, int cols)
{int i = 0;printf("   ");//为了对其每行,因为每行的开头加了下标,所以要先空出来下标所占的位置for (i = 1; i < cols-1; i++)//打印每列的下标{printf("%d ", i);}printf("\n");printf("   ");//为了对其每行,因为每行的开头加了下标,所以要先空出来下标所占的位置for (i = 1; i < cols-1; i++)//让每列的下标和其下面的符号隔开{printf("- ");}printf("\n");for (i = 1; i < rows-1; i++){printf("%d| ", i);//标记每行int j = 0;for (j = 1; j < cols-1; j++){printf("%c ", board[i][j]);}printf("\n");}
}//周围雷个数
char around_mine(char mine[ROWS][COLS], int i, int j)
{return mine[i][j - 1] + mine[i][j + 1] + mine[i + 1][j] + mine[i - 1][j] + mine[i - 1][j - 1] + mine[i + 1][j + 1] + mine[i - 1][j + 1] + mine[i + 1][j - 1] - 7 * '0';//一共是8个字符0,但因为我们要用到一个,所以减掉7个,用的那一个是因为我们想以字符数字的形式赋过去,因为数组是字符类型的
}//递归展开
void recursion(char mine[ROWS][COLS], char show[ROWS][COLS], int i, int j, int* p)
{int x = 0;int y = 0;for (x = -1; x <= 1; x++){for (y = -1; y <= 1; y++){if (x + i > 0 && x + i <= ROW && y + j > 0 && y + j <= COL)//防止越界{if (mine[i + x][j + y] == '0' && (show[i + x][j + y] == '*' || show[i + x][j + y] == '?' || show[i + x][j + y] == '!')){(*p)++;if (around_mine(mine, i + x, j + y) == '0'){show[i + x][j + y] = ' ';recursion(mine, show, i + x, j + y, p);}else{show[i + x][j + y] = around_mine(mine, i + x, j + y);//recursion(mine, show, i + x, j + y, p);}}elsecontinue;}}}
}//玩家选择坐标
int player_option(char mine[ROWS][COLS], char show[ROWS][COLS], int rows, int cols,int* p)
{int i = 0;int j = 0;printf("玩家选择:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (mine[i][j] == '1'){return 0;}if (show[i][j] == '*'||show[i][j]=='!'||show[i][j]=='?'){(*p)++; show[i][j] = around_mine(mine, i, j);if (show[i][j] == '0'){show[i][j] = ' ';recursion(mine, show, i, j, p);//递归展开}/*elserecursion(mine, show, i, j, p);*/return 1;}else{printf("该位置已经排过,请重新选择位置\n");Sleep(1500);return 1;}}
}//玩家标记
void mark_board(char show[ROWS][COLS], int rows, int cols)
{int flag = 0;while (1){printf("选择标记方式:按1标记为雷(!),按2标记为不确定(?),按3取消标记(*),选择4进入排雷环节\n");printf("请玩家选择标记方式:> ");scanf("%d", &flag);if (flag == 1){int i = 0;int j = 0;printf("玩家选择标记位置:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (show[i][j] != '*'&&show[i][j]!='?'){printf("该位置已经扫过或者已经被标记了该种符号,请重新选择\n");continue;}show[i][j] = '!';}}else if (flag == 2){int i = 0;int j = 0;printf("玩家选择:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (show[i][j] != '*' && show[i][j] != '!'){printf("该位置已经扫过或者已经被标记了该种符号,请重新选择\n");continue;}show[i][j] = '?';}}else if (flag == 3){int i = 0;int j = 0;printf("玩家选择:> ");scanf("%d %d", &i, &j);if (i > 0 && i <= ROW && j > 0 && j <= COL){if (show[i][j] == '?' || show[i][j] == '!'){show[i][j] = '*';}else{printf("该位置已经扫过或者已经被标记了该种符号,请重新选择\n");continue;}}}else if (flag == 4)return;elseprintf("选择错误,请重新选择\n");system("cls");print_board(show, ROWS, COLS);}
}

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 mine[ROWS][COLS];char show[ROWS][COLS];//初始化雷区init_board(mine, ROWS,COLS,'0');//初始化展示区init_board(show,ROWS,COLS, '*');//埋雷put_mine(mine,ROWS, COLS);//打印雷盘//print_board(mine, ROWS, COLS);//上帝视角,打印雷区//printf("\n");print_board(show, ROWS, COLS);//玩家进行标记和排雷int num = 0;int ret = 0;while (num<ROW*COL-mine_num)//当重复的次数为所有非雷个数后跳出循环,胜利{mark_board(show, ROWS, COLS);//每次输入前的标记环节ret = player_option(mine, show, ROWS, COLS, &num);system("cls");print_board(show, ROWS, COLS);if (ret == 0){printf("很遗憾,你被炸死了,雷区如下:\n");print_board(mine, ROWS, COLS);//让玩家死后看到这盘扫雷游戏中雷都在哪里break;}//print_board(show, ROWS, COLS);}if (num == ROW * COL - mine_num)printf("恭喜你扫除了全部的雷!!!\n");
}void test()
{int input = 0;do{menu();printf("请选择:> ");scanf("%d", &input);switch (input){case 1:printf("开始游戏\n");game();break;case 0:printf("退出游戏\n");break;default:printf("输入错误,请重新输入\n");}} while (input);}int main()
{srand((unsigned int)time(NULL));test();return 0;
}

效果展示图

请添加图片描述

五、总结

在这里插入图片描述

💘原创不易,还希望各位佬佬支持一下\textcolor{colourful}{💘原创不易,还希望各位佬佬支持一下}💘原创不易,还希望各位佬佬支持一下

💓点赞,你的认可是我创作的动力!\textcolor{red}{💓点赞,你的认可是我创作的动力!}💓点赞,你的认可是我创作的动力!

💕收藏,你的青睐是我努力的方向!\textcolor{orange}{💕收藏,你的青睐是我努力的方向!}💕收藏,你的青睐是我努力的方向!

💞评论,你的意见是我进步的财富!\textcolor{aqua}{💞评论,你的意见是我进步的财富!}💞评论,你的意见是我进步的财富!

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

相关文章:

童年回忆--扫雷(包括标记功能和递归展开)--万字讲解让你学会扫雷制作

魔王的介绍&#xff1a;&#x1f636;‍&#x1f32b;️一名双非本科大一小白。魔王的目标&#xff1a;&#x1f92f;努力赶上周围卷王的脚步。魔王的主页&#xff1a;&#x1f525;&#x1f525;&#x1f525;大魔王.&#x1f525;&#x1f525;&#x1f525; ❤️‍&#x1…...

【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理

【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 【重器】GPS北斗卫星时钟基准与卫星授时服务技术原理 1.前言 由计算机网络系统组成的分布式系统&#xff0c;若想协调一致进行&#xff1a;IT行业的“整点开拍”、“秒杀”、“Leader选举”&#xff0c;通信行业的“同步组网…...

软件测试未来发展趋势怎么样

未来&#xff0c;互联网技术是很多企业能够活下去的关键点。互联网技术成为新的基建&#xff0c;互联网“基建”化就决定了软件测试行业的缺口会一直扩大。 并且&#xff0c;软件测试岗位&#xff0c;已不仅局限于互联网企业&#xff0c;现已逐步深入到实体产业&#xff0c;金…...

aws Distro for OpenTelemetry 可观测性workshop记录

参考资料 https://aws-otel.github.io/docs/introductionhttps://aws-otel.github.io/docs/introduction aws distro for opentelemetry 官方提供了不同语言不同使用场景下完善的使用实例和相关配置。 AWS Distro for OpenTelemetrics 由以下部分组成&#xff0c;用于向后端…...

Leetcode力扣秋招刷题路-0068

从0开始的秋招刷题路&#xff0c;记录下所刷每道题的题解&#xff0c;帮助自己回顾总结 68. 文本左右对齐 给定一个单词数组 words 和一个长度 maxWidth &#xff0c;重新排版单词&#xff0c;使其成为每行恰好有 maxWidth 个字符&#xff0c;且左右两端对齐的文本。 你应该…...

Nginx介绍及安装(windows版,Linux版)

目录 一、Nginx介绍 1、Nginx优势 2、Nginx作用 3、部署静态资源 4、代理 5、负载均衡 二、Nginx安装步骤&#xff08;windows版&#xff09; 三、Nginx安装步骤&#xff08;Linux版&#xff09; 1、官网下载安装包&#xff0c;下载完之后上传到Linux系统上 2、在Lin…...

Camera | 4.瑞芯微平台MIPI摄像头应用程序编写

前面3篇我们讲解了camera的基础概念&#xff0c;MIPI协议&#xff0c;CSI2&#xff0c;常用命令等&#xff0c;本文带领大家入门&#xff0c;如何用c语言编写应用程序来操作摄像头。 Linux下摄像头驱动都是基于v4l2架构&#xff0c;要基于该架构编写摄像头的应用程序&#xff…...

【1250. 检查「好数组」】

来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 描述&#xff1a; 给你一个正整数数组 nums&#xff0c;你需要从中任选一些子集&#xff0c;然后将子集中每一个数乘以一个 任意整数&#xff0c;并求出他们的和。 假如该和结果为 1&#xff0c;那么原数组就是一个「…...

Spring 如何解决循环依赖?

什么是循环依赖 &#xff1f; 一个或多个对象之间存在直接或间接的依赖关系&#xff0c;这种依赖关系构成一个环形调用&#xff0c;有下面 3 种方式。 我们看一个简单的 Demo&#xff0c;对标“情况 2”。 Service public class Louzai1 {Autowiredprivate Louzai2 louzai2;…...

CocoaPods使用指南

前言 对于大多数软件开发团队来说&#xff0c;依赖管理工具必不可少&#xff0c;它能针对开源和私有依赖进行安装与管理&#xff0c;从而提升开发效率&#xff0c;降低维护成本。针对不同的语言与平台&#xff0c;其依赖管理工具也各有不同&#xff0c;例如 npm 管理 Javascri…...

Kafka 消息队列

目录主流的消息队列消息队列的应用场景缓存/肖锋解耦异步处理KafkaKafka的定义Kafka的底层基础架构Kafka分区如何保证Leader选举Kafka分区如何保证Leader和Follower数据的一致性Kafka 中消费者的消费方式Kafka 高效读写数据的原因&#xff08;高性能吞吐的原因&#xff09;&…...

华为OD机试 - 挑选字符串(Python)| 真题+思路+考点+代码+岗位

挑选字符串 题目 给定a-z,26 个英文字母小写字符串组成的字符串A和B, 其中A可能存在重复字母,B不会存在重复字母, 现从字符串A中按规则挑选一些字母可以组成字符串B 挑选规则如下: 同一个位置的字母只能挑选一次, 被挑选字母的相对先后顺序不能被改变, 求最多可以同时…...

对比Hashtable、HashMap、TreeMap有什么不同?

第9讲 | 对比Hashtable、HashMap、TreeMap有什么不同&#xff1f; Map 是广义 Java 集合框架中的另外一部分&#xff0c;HashMap 作为框架中使用频率最高的类型之一&#xff0c;它本身以及相关类型自然也是面试考察的热点。 今天我要问你的问题是&#xff0c;对比 Hashtable、…...

测试新版Android Studio的手机镜像效果

学更好的别人&#xff0c; 做更好的自己。 ——《微卡智享》 本文长度为669字&#xff0c;预计阅读2分钟 前言 春节刚上班&#xff0c;就开始了疯狂出差的节奏&#xff0c;期间发现Android Studio发布新的版本2022.1.1(Electric Eel)&#xff0c;里面两个更新的内容蓝牙模拟器和…...

女生可以参加IT培训吗?

2023年了&#xff0c;就不要把性别当作选择专业的前提条件了。虽然这句话说过很多次了&#xff0c;作为IT行业来说&#xff0c;是非常欢迎女生的加入&#xff1b;尤其是整天都是面对一大堆男攻城狮&#xff0c;工作氛围一点都不活跃&#xff0c;反而显得压抑和杂乱&#xff0c;…...

刷题25-重排链表

重排链表 解题思路&#xff1a;通过观察链表可以发现&#xff0c;把链表一分为二&#xff0c;后半段链表反转&#xff0c;然后两个链表穿插连接&#xff0c;当链表的节点总数是奇数时&#xff0c;要保证链表的前半段比后半段多一个节点。 关于把链表一分为二&#xff0c;可以…...

VHDL-延迟模型-惯性延迟与传输延迟

目录 1&#xff0c;惯性延时 2&#xff0c;传输延时 信号通过元件都会有延迟&#xff0c;延迟时间的计算是逻辑仿真的重要功能。考虑延迟信息得到的仿真输出波形可以更精确地反映实际电路的情况。针对元件的延时&#xff0c;人们根据需要建立了一些用的延时模型&#xff0c;这…...

2023年美赛(MCM/ICM)简介

2023年美赛将要如期开赛,这里为了 让大家对今年的美赛有一个直接 客观的了解。对2023年美赛&#xff08;MCM/ICM&#xff09;进行一下简要的介绍。相关资料大家可以查看另一篇文章一、竞赛时间February 16-20, 2023开赛时间 北京时间 17号(本周五) 6:00结束时间 北京时间 21号(…...

5min完成linux环境Jenkins的安装

5min搞定linux环境Jenkins的安装安装Jenkinsstep1: 使用wget 命令下载Jenkinsstep2、创建Jenkins日志目录并运行jekinsstep3、访问jenkins并解锁jenkins&#xff0c;安装插件以及创建管理员用户step4、到此&#xff0c;就完成了Finish、以上步骤中遇到的问题1、 jenkins启动不了…...

华为OD机试 - 字母计数(Python)| 真题+思路+考点+代码+岗位

字母计数 题目 给出一个只包含字母的字符串, 不包含空格,统计字符串中各个子字母(区分大小写)出现的次数, 并按照字母出现次数从大到小的顺序输出各个字母及其出现次数 如果次数相同,按照自然顺序排序,且小写字母在大写字母之前 输入 输入一行仅包含字母的字符串 输出 按…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

ETLCloud可能遇到的问题有哪些?常见坑位解析

数据集成平台ETLCloud&#xff0c;主要用于支持数据的抽取&#xff08;Extract&#xff09;、转换&#xff08;Transform&#xff09;和加载&#xff08;Load&#xff09;过程。提供了一个简洁直观的界面&#xff0c;以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()

操作系统&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 编程语言&#xff1a;C11 算法描述 在 GPU 上对图像执行 均值漂移滤波&#xff08;Mean Shift Filtering&#xff09;&#xff0c;用于图像分割或平滑处理。 该函数将输入图像中的…...

Web 架构之 CDN 加速原理与落地实践

文章目录 一、思维导图二、正文内容&#xff08;一&#xff09;CDN 基础概念1. 定义2. 组成部分 &#xff08;二&#xff09;CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 &#xff08;三&#xff09;CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 &#xf…...

【Android】Android 开发 ADB 常用指令

查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...