【C语言】贪吃蛇【附源码】
欢迎来到英杰社区https://bbs.csdn.net/topics/617804998
一、游戏说明:
一个基于C语言链表开发的贪吃蛇游戏:
1. 按方向键上下左右,可以实现蛇移动方向的改变。
2. 短时间长按方向键上下左右其中之一,可实现蛇向该方向的短时间加速移动。
3. 按空格键可实现暂停,暂停后按任意键继续游戏。
4. 按Esc键可直接退出游戏。
5. 按R键可重新开始游戏。
代码中运用到了键盘虚拟键判断、终端窗口大小的改变、光标的定位以及输出字体的颜色
二、效果展示:
三、代码讲解:
首先导入必要模块:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>#define ROW 22 //游戏区行数
#define COL 42 //游戏区列数#define KONG 0 //标记空(什么也没有)
#define WALL 1 //标记墙
#define FOOD 2 //标记食物
#define HEAD 3 //标记蛇头
#define BODY 4 //标记蛇身#define UP 72 //方向键:上
#define DOWN 80 //方向键:下
#define LEFT 75 //方向键:左
#define RIGHT 77 //方向键:右
#define SPACE 32 //暂停
#define ESC 27 //退出
初始化函数 InitSnake()
:
它主要完成以下几个任务:
- 将蛇的长度初始化为2,初始位置设定在游戏界面的中央。
- 初始化蛇身体的位置,将蛇身体的坐标保存在数组
body[]
中。- 将蛇头和蛇身体的位置在游戏界面上标记出来,使用
face[][]
数组来表示游戏界面,其中HEAD
表示蛇头,BODY
表示蛇身。
//初始化蛇
void InitSnake()
{snake.len = 2; //蛇的身体长度初始化为2snake.x = COL / 2; //蛇头位置的横坐标snake.y = ROW / 2; //蛇头位置的纵坐标//蛇身坐标的初始化body[0].x = COL / 2 - 1;body[0].y = ROW / 2;body[1].x = COL / 2 - 2;body[1].y = ROW / 2;//将蛇头和蛇身位置进行标记face[snake.y][snake.x] = HEAD;face[body[0].y][body[0].x] = BODY;face[body[1].y][body[1].x] = BODY;
}
随机生成食物的函数 RandFood()
:
- 使用
rand()
函数生成一个随机的横纵坐标(i
和j
)作为食物的位置。- 使用
do-while
循环来确保生成的食物位置为空(即face[i][j]
等于KONG
,表示该位置为空)。- 在游戏界面的相应位置标记食物,使用
FOOD
来表示食物。- 将终端颜色设置为红色,使用
color(12)
函数。- 将光标跳转到生成的随机位置处,使用
CursorJump(2 * j, i)
函数。- 在食物位置打印食物图标,这里使用了
"●"
表示食物。
//随机生成食物
void RandFood()
{int i, j;do{//随机生成食物的横纵坐标i = rand() % ROW;j = rand() % COL;} while (face[i][j] != KONG); //确保生成食物的位置为空,若不为空则重新生成face[i][j] = FOOD; //将食物位置进行标记color(12); //颜色设置为红色CursorJump(2 * j, i); //光标跳转到生成的随机位置处printf("●"); //打印食物
}
打印蛇部分:
- 如果
flag
的值为1,表示需要打印蛇。- 将终端颜色设置为绿色,使用
color(10)
函数。- 将光标跳转到蛇头的位置,使用
CursorJump(2 * snake.x, snake.y)
函数。- 在蛇头的位置打印蛇头图标,这里使用了
"■"
表示蛇头。- 使用
for
循环遍历蛇的身体,将光标跳转到每个蛇身体部分的位置,并打印蛇身体的图标,这里使用了"□"
表示蛇身体。
覆盖蛇部分:
- 如果
flag
的值不为1,表示需要覆盖蛇。- 首先检查蛇尾的位置是否为
(0, 0)
,这是为了避免在蛇的长度增加时将墙壁位置覆盖。- 如果蛇尾的位置不是
(0, 0)
,则将光标跳转到蛇尾的位置,并将该位置打印为空格,即将蛇尾覆盖掉。
void DrawSnake(int flag)
{if (flag == 1) //打印蛇{color(10); //颜色设置为绿色CursorJump(2 * snake.x, snake.y);printf("■"); //打印蛇头for (int i = 0; i < snake.len; i++){CursorJump(2 * body[i].x, body[i].y);printf("□"); //打印蛇身}}else //覆盖蛇{if (body[snake.len - 1].x != 0) //防止len++后将(0, 0)位置的墙覆盖{//将蛇尾覆盖为空格即可CursorJump(2 * body[snake.len - 1].x, body[snake.len - 1].y);printf(" ");}}
}
移动蛇的函数:
DrawSnake(0);
:调用DrawSnake
函数,将当前显示的蛇覆盖掉,参数0
表示覆盖蛇。
face[body[snake.len - 1].y][body[snake.len - 1].x] = KONG;
:将蛇移动后原来的蛇尾位置标记为空。
face[snake.y][snake.x] = BODY;
:将蛇头移动后的新位置标记为蛇身。更新蛇身体的位置:
- 使用
for
循环从蛇尾开始,依次将每个蛇身体部分的位置更新为上一个蛇身体的位置,实现蛇身体的移动。更新蛇头的位置:
- 将蛇头的位置信息更新为移动后的新位置。
DrawSnake(1);
:调用DrawSnake
函数,打印移动后的蛇,参数1
表示打印蛇。
void MoveSnake(int x, int y)
{DrawSnake(0); //先覆盖当前所显示的蛇face[body[snake.len - 1].y][body[snake.len - 1].x] = KONG; //蛇移动后蛇尾重新标记为空face[snake.y][snake.x] = BODY; //蛇移动后蛇头的位置变为蛇身//蛇移动后各个蛇身位置坐标需要更新for (int i = snake.len - 1; i > 0; i--){body[i].x = body[i - 1].x;body[i].y = body[i - 1].y;}//蛇移动后蛇头位置信息变为第0个蛇身的位置信息body[0].x = snake.x;body[0].y = snake.y;//蛇头的位置更改snake.x = snake.x + x;snake.y = snake.y + y;DrawSnake(1); //打印移动后的蛇
}
初始化设置:
int n = RIGHT;
:开始游戏时,默认向右移动。int tmp = 0;
:记录蛇的移动方向。
游戏循环:
- 使用
while(1)
构建游戏主循环,表示游戏一直进行。n = getch();
:获取键盘输入的方向控制。
方向控制调整:
- 通过
switch
语句,根据用户输入的方向键来调整蛇的移动方向。- 如果用户按下的方向键与当前蛇的移动方向相反,则忽略该输入,保持蛇的当前移动方向不变。
蛇的移动:
- 使用
switch
语句,根据当前的移动方向来调用run
函数,实现蛇的移动,并更新tmp
记录的当前移动方向。
游戏控制:
- 如果用户按下空格键,则游戏暂停。
- 如果用户按下 ESC 键,则清空屏幕并退出游戏。
- 如果用户按下 'r' 或 'R' 键,则重新开始游戏,清空屏幕并调用
main
函数重新执行游戏。
void Game()
{int n = RIGHT; int tmp = 0; goto first; while (1){n = getch(); switch (n){case UP:case DOWN: if (tmp != LEFT&&tmp != RIGHT) {n = tmp; }break;case LEFT:case RIGHT: if (tmp != UP&&tmp != DOWN) {n = tmp; }case SPACE:case ESC:case 'r':case 'R':break; //这四个无需调整default:n = tmp;break;}first:switch (n){case UP: run(0, -1); tmp = UP;break;case DOWN: run(0, 1); tmp = DOWN; break;case LEFT: run(-1, 0); tmp = LEFT; break;case RIGHT:run(1, 0); tmp = RIGHT;break;case SPACE: system("pause>nul"); break;case ESC:system("cls"); color(7);CursorJump(COL - 8, ROW / 2);printf(" 游戏结束 ");CursorJump(COL - 8, ROW / 2 + 2);exit(0);case 'r':case 'R': system("cls"); main();}}
}
移动控制:
int x, int y
:参数x
和y
表示蛇每次移动的横向和纵向偏移量。int t = 0;
:初始化一个计时器t
,用来控制蛇移动的速度。
移动循环:
- 使用
while(1)
构建移动主循环,表示蛇一直在移动。t
控制了蛇的移动速度。在每次移动前,程序会等待一段时间,然后才执行移动操作。
等待时间控制:
if (t == 0) t = 3000;
:如果t
的值为0,则将其设置为3000,控制蛇的移动速度。t
越小,蛇移动速度越快,可以根据需要调整这个值来设置游戏的难度。- 使用
while(--t)
循环来实现等待,即等待一段时间后再执行移动操作。
键盘检测:
if (kbhit() != 0)
:检测键盘是否有输入,如果有输入,则退出当前循环,返回到Game
函数读取键值。
移动和判断:
- 如果没有键盘输入,即
t == 0
,则执行移动蛇的操作,包括判断是否得分以及游戏是否结束。- 如果有键盘输入,就退出移动循环,返回到
Game
函数,等待下一次键盘输入。
void run(int x, int y)
{int t = 0;while (1){if (t == 0)t = 3000; while (--t){if (kbhit() != 0) break;}if (t == 0) {JudgeFunc(x, y); MoveSnake(x, y); }else {break;}}
}
判断食物:
- 首先检查蛇头即将到达的位置是否是食物 (
FOOD
),如果是,则表示蛇吃到了食物。- 如果蛇吃到了食物,则执行以下操作:
- 蛇的长度增加
snake.len++
,即蛇身加长。- 更新得分
grade += 10
。- 打印当前得分,并重新随机生成食物。
判断墙或蛇身碰撞:
- 如果蛇头即将到达的位置是墙 (
WALL
) 或者蛇身 (BODY
),则表示游戏结束。- 在游戏结束时,执行以下操作:
- 暂停一段时间留给玩家反应时间
Sleep(1000)
。- 清空屏幕
system("cls")
。- 根据当前得分与最高记录的比较,打印相应的提示信息,包括是否打破最高记录以及游戏是否再来一局的询问。
- 根据玩家的选择,决定是重新开始游戏还是退出程序。
void JudgeFunc(int x, int y)
{//若蛇头即将到达的位置是食物,则得分if (face[snake.y + y][snake.x + x] == FOOD){snake.len++; //蛇身加长grade += 10; //更新当前得分color(7); //颜色设置为白色CursorJump(0, ROW);printf("当前得分:%d", grade); //重新打印当前得分RandFood(); //重新随机生成食物}//若蛇头即将到达的位置是墙或者蛇身,则游戏结束else if (face[snake.y + y][snake.x + x] == WALL || face[snake.y + y][snake.x + x] == BODY){Sleep(1000); //留给玩家反应时间system("cls"); //清空屏幕color(7); //颜色设置为白色CursorJump(2 * (COL / 3), ROW / 2 - 3);if (grade > max){printf("恭喜你打破最高记录,最高记录更新为%d", grade);WriteGrade();}else if (grade == max){printf("与最高记录持平,加油再创佳绩", grade);}else{printf("请继续加油,当前与最高记录相差%d", max - grade);}CursorJump(2 * (COL / 3), ROW / 2);printf("GAME OVER");while (1) //询问玩家是否再来一局{char ch;CursorJump(2 * (COL / 3), ROW / 2 + 3);printf("再来一局?(y/n):");scanf("%c", &ch);if (ch == 'y' || ch == 'Y'){system("cls");main();}else if (ch == 'n' || ch == 'N'){CursorJump(2 * (COL / 3), ROW / 2 + 5);exit(0);}else{CursorJump(2 * (COL / 3), ROW / 2 + 5);printf("选择错误,请再次选择");}}}
}
函数 ReadGrade()
:
- 首先,它尝试以只读的方式打开文件 "贪吃蛇最高得分记录.txt"。
- 如果文件打开失败(即文件不存在),则会以只写的方式打开文件,并将当前最高得分
max
写入文件中(初始时max
可能为0)。- 然后,将文件指针移到文件开头。
- 接着,从文件中读取一个整数,即最高得分记录,将其存储到变量
max
中。- 最后,关闭文件,并将文件指针置空。
void ReadGrade()
{FILE* pf = fopen("贪吃蛇最高得分记录.txt", "r"); //以只读的方式打开文件if (pf == NULL) //打开文件失败{pf = fopen("贪吃蛇最高得分记录.txt", "w"); //以只写的方式打开文件fwrite(&max, sizeof(int), 1, pf); //将max写入文件(此时max为0),即将最高得分初始化为0}fseek(pf, 0, SEEK_SET); //使文件指针pf指向文件开头fread(&max, sizeof(int), 1, pf); //读取文件当中的最高得分到max当中fclose(pf); //关闭文件pf = NULL; //文件指针及时置空
}
函数 WriteGrade()
:
- 首先,它以只写的方式打开文件 "贪吃蛇最高得分记录.txt"。
- 如果文件打开失败,即
pf
为空,那么程序会打印出一条错误信息,并退出程序。- 如果文件打开成功,那么函数会将本局游戏的得分
grade
写入文件中。- 最后,函数关闭文件,并将文件指针
pf
置空。
void WriteGrade()
{FILE* pf = fopen("贪吃蛇最高得分记录.txt", "w");if (pf == NULL){printf("保存最高得分记录失败\n");exit(0);}fwrite(&grade, sizeof(int), 1, pf);fclose(pf);pf = NULL;
}
主函数 main()
:
- 首先,它声明了两个全局变量
max
和grade
,分别用来存储最高得分和本局游戏得分。- 然后,在
main()
函数内部,通过#pragma warning (disable:4996)
关闭了编译器的警告提示,可能是因为某些函数被认为是不安全的。- 接着,初始化了两个全局变量
max
和grade
,将它们都设置为0。- 使用
system()
函数设置了命令提示符窗口的标题为 "贪吃蛇",并设置了窗口大小为84列 * 23行。- 调用
HideCursor()
函数隐藏了命令提示符窗口中的光标。- 调用
ReadGrade()
函数从文件中读取最高分到全局变量max
中。- 调用
InitInterface()
函数初始化游戏界面。- 调用
InitSnake()
函数初始化贪吃蛇。- 使用
srand((unsigned int)time(NULL))
函数根据当前时间设置随机数种子。- 调用
RandFood()
函数随机生成食物。- 调用
DrawSnake(1)
函数在界面上绘制贪吃蛇。- 最后,调用
Game()
函数开始游戏。
完整代码:
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <Windows.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>#define ROW 22 //游戏区行数
#define COL 42 //游戏区列数#define KONG 0 //标记空(什么也没有)
#define WALL 1 //标记墙
#define FOOD 2 //标记食物
#define HEAD 3 //标记蛇头
#define BODY 4 //标记蛇身#define UP 72 //方向键:上
#define DOWN 80 //方向键:下
#define LEFT 75 //方向键:左
#define RIGHT 77 //方向键:右
#define SPACE 32 //暂停
#define ESC 27 //退出//蛇头
struct Snake
{int len; //记录蛇身长度int x; //蛇头横坐标int y; //蛇头纵坐标
}snake;//蛇身
struct Body
{int x; //蛇身横坐标int y; //蛇身纵坐标
}body[ROW * COL]; //开辟足以存储蛇身的结构体数组int face[ROW][COL]; //标记游戏区各个位置的状态//隐藏光标
void HideCursor();
//光标跳转
void CursorJump(int x, int y);
//初始化界面
void InitInterface();
//颜色设置
void color(int c);
//从文件读取最高分
void ReadGrade();
//更新最高分到文件
void WriteGrade();
//初始化蛇
void InitSnake();
//随机生成食物
void RandFood();
//判断得分与结束
void JudgeFunc(int x, int y);
//打印蛇与覆盖蛇
void DrawSnake(int flag);
//移动蛇
void MoveSnake(int x, int y);
//执行按键
void run(int x, int y);
//游戏主体逻辑函数
void Game();int max, grade; //全局变量
int main()
{
#pragma warning (disable:4996) max = 0, grade = 0; system("title 贪吃蛇");system("mode con cols=84 lines=23");HideCursor(); //隐藏光标ReadGrade(); //从文件读取最高分到max变量InitInterface(); //初始化界面InitSnake(); //初始化蛇srand((unsigned int)time(NULL));RandFood(); DrawSnake(1); //打印蛇Game(); //开始游戏return 0;
}//隐藏光标
void HideCursor()
{CONSOLE_CURSOR_INFO curInfo; //定义光标信息的结构体变量curInfo.dwSize = 1; //如果没赋值的话,光标隐藏无效curInfo.bVisible = FALSE; //将光标设置为不可见HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄SetConsoleCursorInfo(handle, &curInfo); //设置光标信息
}
//光标跳转
void CursorJump(int x, int y)
{COORD pos; //定义光标位置的结构体变量pos.X = x; //横坐标pos.Y = y; //纵坐标HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); //获取控制台句柄SetConsoleCursorPosition(handle, pos); //设置光标位置
}
void InitInterface()
{color(6); for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){if (j == 0 || j == COL - 1){face[i][j] = WALL; //标记该位置为墙CursorJump(2 * j, i);printf("■");}else if (i == 0 || i == ROW - 1){face[i][j] = WALL; //标记该位置为墙printf("■");}else{face[i][j] = KONG; }}}color(7);CursorJump(0, ROW);printf("当前得分:%d", grade);CursorJump(COL, ROW);printf("历史最高得分:%d", max);
}
void color(int c)
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), c); }
void ReadGrade()
{FILE* pf = fopen("贪吃蛇最高得分记录.txt", "r"); if (pf == NULL) //打开文件失败{pf = fopen("贪吃蛇最高得分记录.txt", "w"); fwrite(&max, sizeof(int), 1, pf);}fseek(pf, 0, SEEK_SET);fread(&max, sizeof(int), 1, pf);fclose(pf); //关闭文件pf = NULL; //文件指针及时置空
}
//更新最高分到文件
void WriteGrade()
{FILE* pf = fopen("贪吃蛇最高得分记录.txt", "w"); //以只写的方式打开文件if (pf == NULL) //打开文件失败{printf("保存最高得分记录失败\n");exit(0);}fwrite(&grade, sizeof(int), 1, pf); //将本局游戏得分写入文件当中fclose(pf); //关闭文件pf = NULL; //文件指针及时置空
}
void InitSnake()
{snake.len = 2; snake.x = COL / 2; snake.y = ROW / 2; body[0].x = COL / 2 - 1;body[0].y = ROW / 2;body[1].x = COL / 2 - 2;body[1].y = ROW / 2;face[snake.y][snake.x] = HEAD;face[body[0].y][body[0].x] = BODY;face[body[1].y][body[1].x] = BODY;
}
void RandFood()
{int i, j;do{i = rand() % ROW;j = rand() % COL;} while (face[i][j] != KONG);face[i][j] = FOOD; color(12); CursorJump(2 * j, i); printf("●");
}
void JudgeFunc(int x, int y)
{if (face[snake.y + y][snake.x + x] == FOOD){snake.len++; grade += 10; color(7); CursorJump(0, ROW);printf("当前得分:%d", grade);RandFood(); }else if (face[snake.y + y][snake.x + x] == WALL || face[snake.y + y][snake.x + x] == BODY){Sleep(1000);system("cls"); color(7);CursorJump(2 * (COL / 3), ROW / 2 - 3);if (grade > max){printf("恭喜你打破最高记录,最高记录更新为%d", grade);WriteGrade();}else if (grade == max){printf("与最高记录持平,加油再创佳绩", grade);}else{printf("请继续加油,当前与最高记录相差%d", max - grade);}CursorJump(2 * (COL / 3), ROW / 2);printf("GAME OVER");while (1) {char ch;CursorJump(2 * (COL / 3), ROW / 2 + 3);printf("再来一局?(y/n):");scanf("%c", &ch);if (ch == 'y' || ch == 'Y'){system("cls");main();}else if (ch == 'n' || ch == 'N'){CursorJump(2 * (COL / 3), ROW / 2 + 5);exit(0);}else{CursorJump(2 * (COL / 3), ROW / 2 + 5);printf("选择错误,请再次选择");}}}
}void DrawSnake(int flag)
{if (flag == 1) {color(10); CursorJump(2 * snake.x, snake.y);printf("■"); for (int i = 0; i < snake.len; i++){CursorJump(2 * body[i].x, body[i].y);printf("□"); }}else{if (body[snake.len - 1].x != 0) {CursorJump(2 * body[snake.len - 1].x, body[snake.len - 1].y);printf(" ");}}
}
void MoveSnake(int x, int y)
{DrawSnake(0); face[body[snake.len - 1].y][body[snake.len - 1].x] = KONG; face[snake.y][snake.x] = BODY;for (int i = snake.len - 1; i > 0; i--){body[i].x = body[i - 1].x;body[i].y = body[i - 1].y;}body[0].x = snake.x;body[0].y = snake.y;snake.x = snake.x + x;snake.y = snake.y + y;DrawSnake(1);
}
void run(int x, int y)
{int t = 0;while (1){if (t == 0)t = 3000;while (--t){if (kbhit() != 0)break;}if (t == 0) //键盘未被敲击{JudgeFunc(x, y); //判断到达该位置后,是否得分与游戏结束MoveSnake(x, y); //移动蛇}else //键盘被敲击{break; }}
}
void Game()
{int n = RIGHT; int tmp = 0; goto first; while (1){n = getch(); //读取键值switch (n){case UP:case DOWN: if (tmp != LEFT && tmp != RIGHT) {n = tmp; //那么下一次蛇的移动方向设置为上一次蛇的移动方向}break;case LEFT:case RIGHT: if (tmp != UP && tmp != DOWN) {n = tmp; }case SPACE:case ESC:case 'r':case 'R':break; //这四个无需调整default:n = tmp; break;}first:switch (n){case UP: run(0, -1); tmp = UP;break;case DOWN: //方向键:下run(0, 1); tmp = DOWN; //记录当前蛇的移动方向break;case LEFT: //方向键:左run(-1, 0); tmp = LEFT; //记录当前蛇的移动方向break;case RIGHT: run(1, 0); tmp = RIGHT; break;case SPACE: //暂停system("pause>nul"); break;case ESC: system("cls");color(7); CursorJump(COL - 8, ROW / 2);printf(" 游戏结束 ");CursorJump(COL - 8, ROW / 2 + 2);exit(0);case 'r':case 'R': system("cls"); main();}}
}
相关文章:

【C语言】贪吃蛇【附源码】
欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 一、游戏说明: 一个基于C语言链表开发的贪吃蛇游戏: 1. 按方向键上下左右,可以实现蛇移动方向的改变。 2. 短时间长按方向键上下左右其中之一,可实现蛇向该方向的短时间…...

【技巧】压缩文件如何设置“自动加密”?
很多人会在压缩文件的时候,同时设置密码,以此保护私密文件。如果经常需要压缩文件并设置密码,不妨使用解压缩软件的“自动加密”功能,更省时省力。 下面介绍WinRAR解压缩软件的两种“自动加密”的方法,一起来看看吧&a…...

内网穿透时报错【Bad Request This combination of host and port requires TLS.】的原因
目录 前言:介绍一下内网穿透 1.内网直接https访问(可以正常访问) 程序配置的证书 2.内网穿透后,通过外网访问 3.原因 4.内网非https的Web应用,使用https后,也变成了https访问 5.题外话 感觉自己的web应用配置了…...

计算机网络:物理层 - 信道复用
计算机网络:物理层 - 信道复用 频分复用时分复用统计时分复用波分复用码分复用 计算机网络中,用户之间通过信道进行通信,但是信道是有限的,想要提高网络的效率,就需要提高信道的利用效率。因此计算机网络中普遍采用信道…...

【算法集训】基础算法:滑动窗口
定义一个快慢指针,用于截取数组中某一段信息。同时可以改变快慢指针的值来获取结果,这个过程比较像滑动。 1493. 删掉一个元素以后全为 1 的最长子数组 定义快慢指针快指针先走,如果到了第二个0上的时候。前面1的个数就是fast - slow - 1&a…...

QT 二维坐标系显示坐标点及点与点的连线-通过定时器自动添加随机数据点
QT 二维坐标系显示坐标点及点与点的连线-通过定时器自动添加随机数据点 功能介绍头文件C文件运行过程 功能介绍 上面的代码实现了一个简单的 Qt 应用程序,其功能包括: 创建一个 MainWindow 类,继承自 QMainWindow,作为应用程序的…...

C语言TCP服务器模型 : select + 多线程与双循环单线程阻塞服务器的比较
观察到的实验现象: 启动三个客户端: 使用双循环阻塞服务器:只能accept后等待收发,同时只能与一个客户端建立连接,必须等已连接的客户端多次收发 明确断开后才能与下个客户端连接 使用IO多路复用select:可以同时接收所有的连接请求,并且连接状态一直是存活的,直到客户端关闭连…...

【数字IC/FPGA】手撕代码:模3检测器(判断输入序列能否被3整除)
今天我们来手撕一个常见的笔试题,使用的方法是三段式Moore状态机。 题目描述: 输入端口是串行的1bit数据,每个时钟周期进来一位新数据后,实时检查当前序列是否能整除3,若能则输出1,否则输出0。 例如&#…...

最小可行产品需要最小可行架构——可持续架构(三)
前言 最小可行产品(MVP)的概念可以帮助团队专注于尽快交付他们认为对客户最有价值的东西,以便在投入大量时间和资源之前迅速、廉价地评估产品的市场规模。MVP不仅需要考虑产品的市场可行性,还需要考虑其技术可行性,以…...

笔记: 数据结构与算法--时间复杂度二分查找数组
算法复杂度 不依赖于环境因素事前分析法 计算最坏情况的时间复杂度每一条语句的执行时间都按照t来计算 时间复杂度 大O表示法 n 数据量 ; f(n) 实际的执行条数当存在一个n0 , 使得 n > n0,并且 c * g(n) 恒> f(n) : 渐进上界(算法最坏的情况)那么f(n)的时间复杂度 …...

AI绘画教程:Midjourney使用方法与技巧从入门到精通
文章目录 一、《AI绘画教程:Midjourney使用方法与技巧从入门到精通》二、内容介绍三、作者介绍🌤️粉丝福利 一、《AI绘画教程:Midjourney使用方法与技巧从入门到精通》 一本书读懂Midjourney绘画,让创意更简单,让设计…...

Spring-事务管理
1、事务管理 1.1、回滚方式 默认回滚方式:发生运行异常时异常和error时回滚,发生受查(编译)异常时提交。不过,对于受查异常,程序员也可以手工设置其回滚方式 1.2、事务定义接口 1.2.1、事务隔离级别常量 这些常量…...

MySql实战--为什么我的MySQL会“抖”一下
时的工作中,不知道你有没有遇到过这样的场景,一条SQL语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢,并且这样的场景很难复现,它不只随机,而且持续时间还很短…...

【蓝桥杯第十三届省赛B】(部分详解)
九进制转十进制 #include <iostream> #include<math.h> using namespace std; int main() {cout << 2*pow(9,3)0*pow(9,2)2*pow(9,1)2*pow(9,0) << endl;return 0; }顺子日期 #include <iostream> using namespace std; int main() {// 请在此…...

[linux初阶][vim-gcc-gdb] OneCharter: vim编辑器
一.vim编辑器基础 目录 一.vim编辑器基础 ①.vim的语法 ②vim的三种模式 ③三种模式的基本切换 ④各个模式下的一些操作 二.配置vim环境 ①手动配置(不推荐) ②自动配置(推荐) vim是vi的升级版,包含了更加丰富的功能. ①.vim的语法 vim [文件名] ②vim的三种模式 命令…...

【Lazy ORM 框架学习】
Gitee 点赞关注不迷路 项目地址 快速入门 模块所属层级描述快照版本正式版本wu-database-lazy-lambdalambda针对不同数据源wu-database-lazy-orm-coreorm 核心orm核心处理wu-database-lazy-sqlsql核心处理成处理sql解析、sql执行、sql映射wu-elasticsearch-starterESESwu-hb…...

安科瑞路灯安全用电云平台解决方案【电不起火、电不伤人】
背景介绍 近年来 ,随着城市规模的不断扩大 ,路灯事业蓬勃发展。但有的地方因为观念、技术、管理等方面不完善 ,由此引发了一系列安全问题。路灯点多面广 ,一旦漏电就极容易造成严重的人身安全事故。不仅给受害者家庭带来痛苦 &am…...

MYSQL——索引概念索引结构
索引 索引是帮助数据库高效获取数据的排好序的数据结构。 有无索引时,查询的区别 主要区别在于查询速度和系统资源的消耗。 查询速度: 在没有索引的情况下,数据库需要对表中的所有记录进行扫描,以找到符合查询条件的记录&#…...

Linux(CentOS7)配置系统服务以及开机自启动
目录 前言 两种方式 /etc/systemd/system/ 进入 /etc/systemd/system/ 文件夹 创建 nginx.service 文件 重新加载 systemd 配置文件 编辑 配置开机自启 /etc/init.d/ 进入 /etc/init.d/ 文件夹 创建 mysql 文件 编写脚本内容 添加/删除系统服务 配置开机自启 …...

0 决策树基础
目录 1 绪论 2 模型 3 决策树面试总结 1 绪论 决策树算法包括ID3、C4.5以及C5.0等,这些算法容易理解,适用各种数据,在解决各种问题时都有良好表现,尤其是以树模型为核心的各种集成算法,在各个行业和领域都有广泛的…...

Linux速览(2)——环境基础开发工具篇(其一)
本章我们来介绍一些linux的常用工具 目录 一. Linux 软件包管理器 yum 1.什么是软件包? 2. 查看软件包 3. 如何安装软件 4. 如何卸载软件 5.yum补充 6. 关于 rzsz 二. Linux编辑器-vim使用 1. vim的基本概念 2. vim的基本操作 3. vim正常模式命令集 4. vim末行模式…...

AWS SES发送邮件时常见的错误及解决方法?
AWS SES发送邮件如何做配置?使用AWS SES发信的限制? 在使用AWS SES发送邮件时,可能会遇到一些常见的错误。AokSend将介绍一些常见的AWS SES发送邮件错误及其相应的解决方法,帮助用户更好地利用AWS SES进行邮件发送。 AWS SES发送…...

视频基础学习三——视频帧率、码率与分辨率
文章目录 前言一、介绍1.定义2.三者之间的关系 总结 前言 在之前的文章中详细介绍了一些关于图像的色彩与格式,而视频其实就是由一张张图片进行展示呈现出来的。 我们会经常说一段视频的质量好不好,而什么是视频的质量呢?博主的个人理解就是…...

Spring(详细介绍)
目录 一、简介 1、什么是Spring? 2、Spring框架的核心特性 3、优点 二、IOC容器 介绍 1、获取资源的传统方式 2、控制反转方式获取资源 3、DI 4、IOC容器在Spring中的实现 入门案例 1、创建Maven Module 2、引入依赖 3、创建HelloWorld类 4、在Spring的配…...

Kettle使用
1.准备工作 KETTLE-5.4.zip HANA环境192.168.xx.xx 用户名:system 密码:****** 端口号:30015 Oracle环境 192.168.xx.xx 用户名 HANA_TEST 密码 ****** 端口号:31001 配置java环境变量 因为本次数据转换测试为将HANA数据转换到Or…...

互联网摸鱼日报(2024-04-01)
互联网摸鱼日报(2024-04-01) 36氪新闻 「矽迪半导体」获数千万天使轮融资,提供高效功率半导体方案|硬氪首发 本周双碳大事:国资委即将发布央企ESG指导意见;上海发文推动建立产品碳足迹管理体系;隆基新硅片面世 数字…...

pnpm比npm、yarn好在哪里?
前言 pnpm对比npm/yarn的优点: 更快速的依赖下载更高效的利用磁盘空间更优秀的依赖管理 我们按照包管理工具的发展历史,从 npm2 开始讲起: npm2 使用早期的npm1/2安装依赖,node_modules文件会以递归的形式呈现,严格…...

大前端-postcss安装使用指南
PostCSS 是一款强大的 CSS 处理工具,可以用来自动添加浏览器前缀、代码合并、代码压缩等,提升代码的可读性,并支持使用最新的 CSS 语法。以下是一份简化的 PostCSS 安装使用指南: 一、安装 PostCSS 在你的项目目录中,…...

全局UI方法-弹窗三-文本滑动选择器弹窗(TextPickDialog)
1、描述 根据指定的选择范围创建文本选择器,展示在弹窗上。 2、接口 TextPickDialog(options?: TextPickDialogOptions) 3、TextPickDialogOptions 参数名称 参数类型 必填 参数描述 rang string[] | Resource 是 设置文本选择器的选择范围。 selected nu…...

LibreOffice 将word,excel,PowerPoint文件转换PDF
安装LibreOffice并将Word和Excel文件转换为PDF文件,并设置文件存放路径的步骤如下: 1. 安装LibreOffice 如果尚未安装LibreOffice,可以通过以下命令在Ubuntu上安装: sudo apt update sudo apt install libreoffice 2. 使用Li…...