自制贪吃蛇小游戏

        此片文章涉及到到控制台设置的相关操作,虚拟键码,宽字符输出等,有些地方大家可能会看不懂,可以阅读以下文章来进一步了解:

控制台程序设置-CSDN博客

效果展示:

QQ2024428-181932

源码已放在文章结尾

目录

一.功能实现

二.头文件的声明

三.游戏开始 -- GameStart

1.窗口设置

2.光标设置

2.1光标的隐藏

2.2光标坐标设置--SetPos

3.欢迎界面打印--WelcomeToGame

4.地图绘制--CreateMap

5.蛇身初始化--InitSnake

6.食物坐标设定--CreateFood

四.游戏运行-- GameRun

1.打印玩法说明

2.打印当前得分和食物分数

3.获取按键状态--Key

4.蛇的移动-Snakemove

4.1.计算新节点的坐标

4.2.是否撞墙--KillByWall

4.3.是否撞到自身--KillByself

5.循环进行

五.游戏结束 -- GameEnd

1.打印游戏结束的原因

2.释放空间

 六.游戏的优化

七.优化后源码


 首先我们需要对默认窗口做一下更改,如下:

一.功能实现

  •         地图绘制
  •         蛇撞墙死亡
  •         蛇撞自身死亡
  •         用↓ → ← ↑来操作蛇的方向
  •         蛇吃食物加分并记录总得分
  •         蛇的加减功能
  •         蛇的速度越快每个食物分数越高
  •         蛇每吃一个食物身体加长
  •         空格键暂停游戏,再次点击开始游戏

二.头文件的声明

我们把该项目分为三部分,分别是头文件Snake.h,源文件Snake.c,源文件test.c

以下是头文件上的声明:

#pragma
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<locale.h>
#include<windows.h>
#include<stdbool.h>
#include<time.h>
#define pos_x 24//蛇的初始横坐标
#define pos_y 5 //蛇的初始纵坐标
#define WALL L'□' //墙的形状
#define BODY L'●' //蛇身的形状
#define FOOD L'★'//食物的形状
#define Key(x) (GetAsyncKeyState(x)&1)//判断按键是否被按过
enum DIRECTION//蛇的方向
{UP = 1,DOWN,LEFT,RIGHT
};
enum GAME_STATUS//蛇的状态
{OK,//正常KILL_BY_WALL,//撞墙KILL_BY_SELF,//撞到自己END_NORMAL//正常退出
};
typedef struct SnakeNode//储存坐标
{int x;int y;struct SnakeNode* next;
}SnakeNode, *pSnakeNode;
typedef struct Snake//蛇的维护
{pSnakeNode _pSnake;//蛇的坐标pSnakeNode _pFood;//食物的坐标enum DIRECTION _dir;//蛇的移动方向enum GAME_STATUS _status;//蛇的状态int _food_weight;//一个食物的分数int _score;//总分数int _sleep_time;//蛇的速度
}Snake,*pSnake;

三.游戏开始 -- GameStart

        在做准备工作中需要在主函数中进行本地化,以方便后面输出宽字符。如下:

setlocale(LC_ALL, "");

1.窗口设置

        在游戏开始之前我们需要对运行窗口进行设定,首先我们对它的标题进行设置,如下:

system("title 贪吃蛇");

         其次是窗口大小的设定,比如设置一个100行,30列的窗口,如下:

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

2.光标设置

2.1光标的隐藏

        为了方便玩家的体验,我们把光标隐藏,也就是把它的透明度该为fales,如下:

    HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);//获取柄CONSOLE_CURSOR_INFO Info;//申请CONSOLE_CURSOR_INFO类型的变量,用于储存坐标信息GetConsoleCursorInfo(houtput, &Info);//获取坐标信息Info.bVisible = false;//改变坐标透明度SetConsoleCursorInfo(houtput, &Info);//设置坐标

2.2光标坐标设置--SetPos

        在做打印时候需要将光标移动到合适的坐标位置,而这个操作到后面是会频繁操作的,所以我们把它封装成一个函数,如下:

void SetPos(int x, int y)//设置光标的坐标
{HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle获取柄,HANDLE接收柄COORD pos = { x,y };//坐标SetConsoleCursorPosition(houtput, pos);
}

3.欢迎界面打印--WelcomeToGame

        欢迎界面我们可以玩家打印一些欢迎界面和玩法说明,在此之前我们需要把光标调到适应的位置,使其把信息打印到中间位置效果更佳。如下:

        上图的窗口右下角的 请按任意键继续...是代码system("pause"); 带来的效果,它作用是暂停程序的运行,按任意键可以使程序继续运行。

4.地图绘制--CreateMap

        在地图创建中我们是用宽字符 '□'去构造的,而宽字符占两个字节。蛇身我们用宽字符'●'去构造,而后面的设计中是要判断蛇是否撞墙的,所以在打印 '□' 和 '●' 之前光标要移动到横坐标为偶数的坐标位置,或要移动到横坐标为奇数的坐标位置,这样可以保证不会出现蛇头的一半在墙里面,一半在墙外面的情况,如这样:2d0aed15edda4741ba12f6e238a5c9b1.png

        其次要保证食物的横坐标奇偶性和蛇横坐标保持一致,也是为了避免这种情况的发生。(这里我们选择让蛇,墙体,食物的横坐标都为偶数)

那么接下来打印地图就比较简单了,如下:

void CreateMap()//地图绘制
{for (int i = 0; i <= 56; i += 2)wprintf(L"%lc", WALL);SetPos(0, 26);for (int i = 0; i <= 56; i+=2)wprintf(L"%lc", WALL);for (int i = 1; i <= 26; i++){SetPos(0, i);wprintf(L"%lc", WALL);}for (int i = 1; i < 26; i++){SetPos(56, i);wprintf(L"%lc", WALL);}
}

效果如下:(当然此图并不是该代码的输出结果) 

dbe4215c39e3473b998a222966a6338a.png

5.蛇身初始化--InitSnake

        蛇在初始化状态,我们可以用5个节点来给蛇初始化并打印,当然还需要初始化蛇的移动方向,蛇的状态,食物的分数,总分数,速度(休眠时间)

void InitSnake(pSnake ps)//蛇身的初始化
{ps->_pSnake = NULL;//重点!!pSnakeNode pnew = NULL;for (int i = 0; i < 5; i++){pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);pnew->x = pos_x + i * 2;pnew->y = pos_y;pnew->next = NULL;if ((ps->_pSnake) == NULL){ps->_pSnake = pnew;}else{pnew->next = ps->_pSnake;ps->_pSnake = pnew;}}pnew = ps->_pSnake;while (pnew){SetPos(pnew->x, pnew->y);wprintf(L"%lc", BODY);pnew = pnew->next;}ps->_status = OK;ps->_food_weight = 10;ps->_score = 0;ps->_sleep_time = 200;ps->_dir = RIGHT;
}

6.食物坐标设定--CreateFood

        食物的坐标是随机的,需要一个随机数生成函数,虽然说是随机但也有前提条件

        1.食物不能在墙上和墙以外

        2.食物的横坐标必须是偶数(地图绘制那里讲过原因,这里不在赘述)

        3.食物不能在蛇的身上

        反过来说如果产生的随机数是这两个条件中的任意一个都不能要需要重新生成。这里用 go to语句更为方便。

代码实现:

void CreateFood(pSnake ps)
{int x, y;pSnakeNode cur = NULL;again:cur = ps->_pSnake;do{x = rand() % 53 + 2;y = rand() % 25 + 1;} while (x % 2 != 0);while (cur){if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}pSnakeNode Food = (pSnakeNode)malloc(sizeof(SnakeNode));assert(Food);Food->x = x;Food->y = y;Food->next = NULL;ps->_pFood = Food;SetPos(x, y);wprintf(L"%lc", FOOD);
}

这里已把srand((unsigned int)time(NULL));放在了主函数main中 

四.游戏运行-- GameRun

1.打印玩法说明

        在游戏运行过程中我们可以把玩法说明打印到右侧空白的地方,注意打印前需要调整光标的坐标位置,包括后面涉及到的所有打印

2.打印当前总得分和食物分数

        在打印食物分数和总分数过程中要注意这两项是跟着蛇的运动而改变的,需要和蛇的移动一起放在一个循环中。

3.获取按键状态--Key

        我们通过获取键盘按键状态,来相应的改变蛇的运动方向和速度

要注意几个点:

        1.蛇不能向反方向走,比如蛇的方向原本是向右的但玩家按取一个 ← 按键应该示为无效。

        2.玩家按空格键后如何让游戏暂停是个问题,我们可以用一个死循环的睡眠来实现,并且如果再次按空格键退出循环。其次如果需要把 "游戏已暂停,点击空格键继续" 打印到屏幕上的话,当游戏再次开始后此字符串的位置应用空格字符来填充,否则就会一直停留在屏幕上。

        3.蛇的速度不能无限的小或无限的大要不然玩家无法玩,应该设置一个上下限。

代码如下:

		if (Key(VK_UP) && ps->_dir != DOWN)ps->_dir = UP;else if (Key(VK_DOWN) && ps->_dir != UP)ps->_dir = DOWN;else if (Key(VK_LEFT) && ps->_dir != RIGHT)ps->_dir = LEFT;else if (Key(VK_RIGHT) && ps->_dir != LEFT)ps->_dir = RIGHT;if (Key(VK_SPACE)){while (1){SetPos(29,13);printf("游戏已暂停,点击空格键继续");if (Key(VK_SPACE))break;Sleep(300);}SetPos(29, 13);int x = 26;while (x--)printf(" ");}if (Key(VK_ESCAPE))ps->_status = END_NORMAL;if (Key(VK_SHIFT)){if (ps->_sleep_time >= 80){ps->_sleep_time -=30 ;ps->_food_weight += 2;}}if (Key(VK_CONTROL)){if (ps->_sleep_time <= 320){ps->_sleep_time += 30;ps->_food_weight -= 2;}}

4.蛇的移动-Snakemove

        在写此函数的时候我们先想一个问题如何实现动态呢?有人可能会想每输出一次做一次清屏处理

        这确实是行得通的。但在此我们用另一种方法,当下一个节点无食物的时候,将下一个节点头插到原头节点上并删除尾节点然后打印出整个蛇,并且将原来的尾用空格覆盖,否则它会一直停留在屏幕上当下一个节点有食物的时候,将下一个节点头插到原头节点上但尾节点不用删不能用空格覆盖,并重新构造新的食物。效果如下:

当下一个节点无食物的时候:

3d081aee73184f0e849f78987aee6ccc.png

当下一个节点有食物的时候: 

8d76a9cd6009460db037a36d7d451e2c.png

        所以在打印之前我们需要判断下一个节点是否为食物,然后以不同的方式打印

4.1.计算新节点的坐标

        在蛇的移动过程中我们需要不断的插入头节点并删除尾节点,插入什么样的头节点是根据从玩家获取到的按键状态来决定的,比如一个正在向右移动的蛇,玩家按了 ↑ 按键,那么我们创造的下一个节点内储存的横坐标就应是原头节点的横坐标,纵坐标应是原头节点纵坐标减1。以此类推。

代码如下:

void SnakeMove(pSnake ps)
{pSnakeNode pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);switch (ps->_dir){case UP:pnew->y = ps->_pSnake->y - 1;pnew->x = ps->_pSnake->x;break;case DOWN:pnew->y = ps->_pSnake->y + 1;pnew->x = ps->_pSnake->x;break;case LEFT:pnew->x = ps->_pSnake->x - 2;pnew->y = ps->_pSnake->y;break;case RIGHT:pnew->x = ps->_pSnake->x + 2;pnew->y = ps->_pSnake->y;break;}pnew->next = ps->_pSnake;ps->_pSnake = pnew;if ((pnew->x == ps->_pFood->x )&& (pnew->y == ps->_pFood->y))//是食物{int i = 112;while (pnew){SetPos(pnew->x, pnew->y);color(i++);wprintf(L"%lc", BODY);pnew = pnew->next;if (i == 126)i = 112;if (i == 119||i==112)i++;}color(112);ps->_score += ps->_food_weight;free(ps->_pFood);printf("\a");CreateFood(ps);}else//不是食物{while (pnew->next->next){SetPos(pnew->x, pnew->y);color(120);wprintf(L"%lc", BODY);pnew = pnew->next;}color(112);SetPos(pnew->next->x, pnew->next->y);printf("  ");free(pnew->next);pnew->next = NULL;}
}

4.2.是否撞墙--KillByWall

        在判断是否撞到墙,我们只需要判断头节点坐标是否和墙体坐标相同,如果相同就把蛇的状态对应改变就可以。代码如下:

void KillByWall(pSnake ps)//判断是否撞墙
{if ((ps->_pSnake->y == 0) || (ps->_pSnake->y == 26)|| (ps->_pSnake->x == 0) || (ps->_pSnake->x == 56))ps->_status = KILL_BY_WALL;
}

4.3.是否撞到自身--KillByself

        判断是否撞到自身只需要判断头节点的坐标是否和蛇身体坐标相同,如果相同的话同样是把蛇的状态对应改变。代码如下:

void KillByself(pSnake ps)//判断是否撞到自己
{pSnakeNode pr = ps->_pSnake;pSnakeNode pu = ps->_pSnake->next;while (pu){if (pu->x == pr->x && pu->y == pr->y){ps->_status = KILL_BY_SELF;return;}pu = pu->next;}
}

5.循环进行

        以上的操作只是完成了蛇的一次移动,我们需要一个do while语句使它循环起来,不过为了控制蛇的速度在此之前我们需要加上一个Sleep睡眠,如下:

Sleep(ps->_sleep_time);

然后就是在考虑一下循环条件,即

                 ps->_status == OK

如下:

do
{......Sleep(ps->_sleep_time);} while (ps->_status == OK);

五.游戏结束 -- GameEnd

1.打印游戏结束的原因

        这个操作也是很简单我们只需要检查一下蛇的状态然后用 if 语句进行条件输出就可以。

        到这里我们可能就会发现设置蛇的状态的必要性,和用枚举类型来做该设置的优势,其次上面的循环也用到了蛇的状态。

2.释放空间

        注意我们在写程序的过程中使用的蛇身和食物都是用malloc动态申请的空间,最好呢是我们手动把它们释放掉。

void GameEnd(pSnake ps)//游戏结束善后处理
{SetPos(29, 13);if (ps->_status == KILL_BY_SELF){color(116);printf("你撞到了自己,游戏结束");}if (ps->_status == KILL_BY_WALL){color(116);printf("你撞到了墙,游戏结束");}free(ps->_pFood);while (ps->_pSnake){pSnakeNode cur = ps->_pSnake->next;free(ps->_pSnake);ps->_pSnake = cur;}
}

 六.游戏的优化

        当我们学会了以上这些操作以后,我们就可以根据自己的需要来提升游戏的效果

例如:

1.给蛇,食物,墙体设置颜色。

2.把蛇的身体设置成不同的形状。

2.添加双人模式,添加食物个数。

 ... ...

        这里我来提一下双人模式的设计,比如我们想要实现的功能是:

  • 玩家1控制的蛇撞到玩家2控制蛇的身体,那么玩家1就死亡。
  • 玩家撞到自己的身体并不会死亡。
  • 任意玩家按空格键使该游戏暂停。
  • 食物的数量为10个。
  • 两玩家可以分别控制自己的蛇的速度,让博弈更激烈。

        第1,2点呢比较简单,第3点的实现我们可以把食物做成10个节点的链表,当一个食物被吃掉的时候就更新该食物对应的节点所储存的坐标并再次打印出食物

        而然难点是在于如何让蛇的速度不能互相干扰,为了解决这个问题我们可以用一个双线程来同时处理两个玩家控制的蛇相当于把它们分别放在不同时空分别运行,这样它们的时间就可以互不干扰,但它们又共用一些资源比如SetPos函数,也就是它们同时控制光标的位置,这就会导致光标的位置随着时间随意乱窜打印的并不是我们想要的结果,这样我们考虑用一个时间来处理这个问题。

七.优化后源码

Snake.h

#pragma
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<locale.h>
#include<windows.h>
#include<stdbool.h>
#include<time.h>
//蛇的初始坐标
#define pos_x 24
#define pos_y 5//单人模式 地图坐标
#define X 58
#define Y 26//双人模式 地图坐标
#define X2 98
#define Y2 38#define WALL L'□'//地图边界
#define BODY L'●'//蛇身
#define FOOD L'★'//食物
#define Key(x) (GetAsyncKeyState(x)&1)//键盘敲击信息读取CRITICAL_SECTION cs;enum DIRECTION//蛇的方向
{UP = 1,DOWN,LEFT,RIGHT
};
enum GAME_STATUS
{OK,//正常KILL_BY_WALL,//撞墙KILL_BY_SELF,//撞到自己END_NORMAL//正常退出
};
typedef struct SnakeNode
{//坐标int x;int y;struct SnakeNode* next;
}SnakeNode, * pSnakeNode;
typedef struct Snake
{pSnakeNode _pSnake;//蛇的坐标pSnakeNode _pFood;//食物的坐标enum DIRECTION _dir;//蛇的移动方向enum GAME_STATUS _status;//蛇的状态int _food_weight;//一个食物的分数int _score;//分数int _sleep_time;//蛇的速度
}Snake, * pSnake;
typedef struct LSnake
{pSnake p1;pSnake p2;int x;
}LSnake,*pLSnake;int menu();//菜单打印void color(int x);//颜色设置void SetPos(int x, int y);//光标位置设定int GameStart(pSnake ps1,pSnake ps2); //游戏开始
int WelcomeToGame();//欢迎界面void PrintHelpInfo1();//单人模式 玩法说明
void PrintHelpInfo2();//双人模式 玩法说明void CreateMap1();//单人模式 地图绘制
void CreateMap2();//双人模式 地图绘制void InitSnake1(pSnake ps);//单人模式 蛇身的初始化
void InitSnake2(pSnake ps);//双人模式 蛇身的初始化void CreateFood1(pSnake ps);//单人模式 食物坐标的设定
void CreateFood2(pSnake ps1, pSnake ps2);//双人模式 食物坐标的设定
void PrintFood(pSnakeNode hfood);//打印食物DWORD WINAPI th1(LPVOID ps);//玩家1的线程
DWORD WINAPI th2(LPVOID ps);//玩家2的线程void GameRun1(pSnake ps);//单人模式 游戏运行主逻辑
void GameRun2(pSnake ps1, pSnake ps2);//双人模式 游戏运行主逻辑void KillByWallp(pSnake ps1);
void KillByWall(pSnake ps);//判断是否撞墙
void KillByself(pSnake ps);//判断是否撞到自己
void KillByselfp(pSnakeNode pnew, pSnake ps);//是否撞到对方玩家身体pSnakeNode OpFood(pSnakeNode ps, pSnakeNode hfood);//判断是否吃到食物void SnakeMove1(pSnake ps);//单人模式 蛇的移动
void SnakeMove2(pSnake ps1, pSnake ps2);//双人模式 蛇的移动void GameEnd(pSnake ps);//单人模式 游戏结束善后
void GameEndp(pSnake ps1, pSnake ps2);//双人模式 游戏结束善后

Snake .c

#define _CRT_SECURE_NO_WARNINGS 1
#include"snake.h"
#define Key(x) (GetAsyncKeyState(x)&1)
void color(int x)
{SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), x);
}
void SetPos(int x, int y)//设置光标的坐标
{HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);//GetStdHandle获取柄,HANDLE接收柄COORD pos = { x,y };//坐标SetConsoleCursorPosition(houtput, pos);
}
int menu()
{SetPos(36, 10);printf("******** "); color(121); printf("1.单人模式 "); color(112); printf("*********");SetPos(36, 11);printf("******** "); color(124); printf("2.双人博弈 "); color(112); printf("*********");SetPos(38, 12);printf("请选择>>");char c, k;int x = 0,i=0;while (scanf("%c%c", &c, &k),c != '1' && c!= '2'){SetPos(36, 13+i++);color(116);printf("输入错误,请输入1或2");color(112);}x = c - '0';return x;
}
int WelcomeToGame()//欢迎界面打印
{SetPos(40, 10);printf("欢迎来到贪吃蛇游戏!");SetPos(80, 28);system("pause");int x = menu();system("cls");if (x == 1){SetPos(5, 10);printf("请用键盘按键↑← → ↓来控制蛇的移动方向,空格键暂停,Ese键退出游戏,");printf("蛇吃到食物会增加长度和分数,蛇撞到自身或墙壁游戏失败,");printf("Tab键加速,Q键减速");}else{SetPos(5, 10);printf("玩家一:请用键盘按键↑← → ↓来控制蓝蛇的移动方向,Alt右键加速, Ctrl右键减速");SetPos(5, 12);printf("玩家二:请用键盘按键 W A S D 来控制绿蛇的移动方向,Alt左键加速,C键减速");SetPos(16, 14);printf("空格键暂停游戏");}SetPos(80, 28);system("pause");system("cls");return x;
}
void CreateMap1()//地图绘制
{for (int i = 0; i < X; i += 2){wprintf(L"%lc", WALL);}SetPos(0, Y);for (int i = 0; i < X; i += 2){wprintf(L"%lc", WALL);}for (int i = 1; i <= Y; i++){SetPos(0, i);wprintf(L"%lc", WALL);}for (int i = 1; i < Y; i++){SetPos(X-2, i);wprintf(L"%lc", WALL);}
}
void CreateMap2()//地图绘制
{for (int i = 0; i < X2; i += 2){wprintf(L"%lc", WALL);}SetPos(0, Y2);for (int i = 0; i < X2; i += 2){wprintf(L"%lc", WALL);}for (int i = 1; i <= Y2; i++){SetPos(0, i);wprintf(L"%lc", WALL);}for (int i = 1; i < Y2; i++){SetPos(X2-2, i);wprintf(L"%lc", WALL);}
}
void InitSnake1(pSnake ps)//玩家一蛇身的初始化
{ps->_pSnake = NULL;//重点!!pSnakeNode pnew = NULL;for (int i = 0; i < 5; i++){pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);pnew->x = pos_x + i * 2;pnew->y = pos_y;pnew->next = NULL;if ((ps->_pSnake) == NULL){ps->_pSnake = pnew;}else{pnew->next = ps->_pSnake;ps->_pSnake = pnew;}}pnew = ps->_pSnake;while (pnew){SetPos(pnew->x, pnew->y);wprintf(L"%lc", BODY);pnew = pnew->next;}ps->_status = OK;ps->_food_weight = 10;ps->_score = 0;ps->_sleep_time = 200;ps->_dir = RIGHT;
}
void InitSnake2(pSnake ps)//蛇身的初始化
{ps->_pSnake = NULL;//重点!!pSnakeNode pnew = NULL;for (int i = 0; i < 5; i++){pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);pnew->x = 24 + i * 2;pnew->y = 10;pnew->next = NULL;if ((ps->_pSnake) == NULL){ps->_pSnake = pnew;}else{pnew->next = ps->_pSnake;ps->_pSnake = pnew;}}pnew = ps->_pSnake;while (pnew){SetPos(pnew->x, pnew->y);wprintf(L"%lc", BODY);pnew = pnew->next;}ps->_status = OK;ps->_food_weight = 10;ps->_score = 0;ps->_sleep_time = 200;ps->_dir = RIGHT;
}
void PrintFood(pSnakeNode hfood)//打印食物
{pSnakeNode ps = hfood;int i = 112;while (ps){color(i++);SetPos(ps->x, ps->y);wprintf(L"%lc", FOOD);ps = ps->next;if(i==119)i++;}color(112);
}
void CreateFood2(pSnake ps1,pSnake ps2)
{int x=0, y=0,n=10;pSnakeNode cur1 = NULL,cur2=NULL,Food1=NULL,hFood1=NULL;pSnakeNode Food2 = NULL, hFood2 = NULL;pSnakeNode hfood = NULL;while (n--){again:cur1 = ps1->_pSnake;cur2 = ps2->_pSnake;do{x = rand() % (X2 - 4) + 2;y = rand() % (Y2 - 1) + 1;} while (x % 2 != 0);while (cur1){if (x == cur1->x && y == cur1->y){goto again;}cur1 = cur1->next;}while (cur2){if (x == cur2->x && y == cur2->y){goto again;}cur2 = cur2->next;}while (hfood){if (x == hfood->x && y == hfood->y){goto again;}hfood = hfood->next;}pSnakeNode pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);pnew->x = x;pnew->y = y;pnew->next = NULL;if (!hFood1){Food1 = pnew;hFood1 = Food1;hfood = Food1;}else{Food1->next = pnew;Food1 = Food1->next;}}ps1->_pFood = hFood1;ps2->_pFood = hFood1;PrintFood(hFood1);
}
void CreateFood1(pSnake ps)
{int x, y;pSnakeNode cur = NULL;
again:cur = ps->_pSnake;do{x = rand() % 53 + 2;y = rand() % 25 + 1;} while (x % 2 != 0);while (cur){if (x == cur->x && y == cur->y){goto again;}cur = cur->next;}pSnakeNode Food = (pSnakeNode)malloc(sizeof(SnakeNode));assert(Food);Food->x = x;Food->y = y;Food->next = NULL;ps->_pFood = Food;SetPos(x, y);wprintf(L"%lc", FOOD);
}
int GameStart(pSnake ps1, pSnake ps2)//开始游戏
{system("mode con cols=100 lines=35 ");system("title 贪吃蛇");HANDLE houtput = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO Info;GetConsoleCursorInfo(houtput, &Info);Info.bVisible = false;SetConsoleCursorInfo(houtput, &Info);int x=WelcomeToGame();//欢迎界面if (x == 2){system("mode con cols=150 lines=42 ");}color(116);if (x == 1)CreateMap1();//地图绘制elseCreateMap2();color(112);if (x == 1){InitSnake1(ps1);//蛇身的初始化CreateFood1(ps1);}else{InitSnake1(ps1);InitSnake2(ps2);CreateFood2(ps1,ps2);//食物坐标的设定}return x;
}
void PrintHelpInfo1()//打印玩法
{SetPos(60, 15);printf("请用键盘按键↑← → ↓来控制蛇的移动方向");SetPos(60, 16);printf("蛇吃到食物会增加长度和分数");SetPos(60, 17);printf("蛇撞到自身或墙壁游戏失败");SetPos(60, 18);printf("Tab键加速,Q键减速");SetPos(60, 19);printf("空格键表示暂停,Ese键退出游戏");SetPos(60, 1);
}
void PrintHelpInfo2()//打印玩法
{SetPos(X2+6, 15);printf("玩家1请用键盘按键↑← → ↓来控制蛇的移动方向");SetPos(X2 + 6, 16);printf("玩家2请用键盘按键 W A S D  来控制蛇的移动方向");SetPos(X2 + 6, 18);printf("蛇吃到食物会增加长度和分数");SetPos(X2 + 6, 19);printf("蛇撞到自己或另一玩家不会死亡,蛇撞墙壁游戏失败");SetPos(X2 + 6, 20);printf("Shift加速,Ctrl减速");SetPos(X2 + 6, 21);printf("空格键表示暂停,Ese键退出游戏");SetPos(X2 + 6, 1);
}
void SnakeMove1(pSnake ps)单人模式
{pSnakeNode pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);switch (ps->_dir){case UP:pnew->y = ps->_pSnake->y - 1;pnew->x = ps->_pSnake->x;break;case DOWN:pnew->y = ps->_pSnake->y + 1;pnew->x = ps->_pSnake->x;break;case LEFT:pnew->x = ps->_pSnake->x - 2;pnew->y = ps->_pSnake->y;break;case RIGHT:pnew->x = ps->_pSnake->x + 2;pnew->y = ps->_pSnake->y;break;}pnew->next = ps->_pSnake;ps->_pSnake = pnew;if ((pnew->x == ps->_pFood->x) && (pnew->y == ps->_pFood->y)){while (pnew){SetPos(pnew->x, pnew->y);color(116);wprintf(L"%lc", BODY);pnew = pnew->next;}color(112);ps->_score += ps->_food_weight;free(ps->_pFood);printf("\a");CreateFood1(ps);}else{while (pnew->next->next){SetPos(pnew->x, pnew->y);color(120);wprintf(L"%lc", BODY);pnew = pnew->next;}color(112);SetPos(pnew->next->x, pnew->next->y);printf("  ");free(pnew->next);pnew->next = NULL;}Sleep(ps->_sleep_time);
}
void ChangeFood(pSnake ps1,pSnake ps2,pSnakeNode ps)//改变食物位置
{pSnakeNode cur1 = NULL, cur2 = NULL,hfood=ps2->_pFood;int x = 0, y = 0;Again:cur1 = ps1->_pSnake;cur2 = ps2->_pSnake;do{x = rand() % (X2 - 4) + 2;y = rand() % (Y2 - 1) + 1;} while (x % 2 != 0);while (cur1){if (x == cur1->x && y == cur1->y){goto Again;}cur1 = cur1->next;}while (cur2){if (x == cur2->x && y == cur2->y){goto Again;}cur2 = cur2->next;}while (hfood){if (x == hfood->x && y == hfood->y){goto Again;}hfood = hfood->next;}ps->x = x, ps->y = y;
}
pSnakeNode OpFood(pSnakeNode ps, pSnakeNode hfood)
{pSnakeNode hf = hfood;while (hf){if (ps->x == hf->x && ps->y == hf->y)return hf;hf = hf->next;}return NULL;
}//玩家1///
DWORD WINAPI th1(LPVOID ps)
{pLSnake psk = (pLSnake)ps;pSnake pw1 = NULL, pw2 = NULL;pw1 = psk->p1;pw2 = psk->p2;int fup = 0;do{EnterCriticalSection(&cs);color(112);SetPos(X2 + 6, 8);printf("玩家1 绿蛇");LeaveCriticalSection(&cs);EnterCriticalSection(&cs);SetPos(X2 + 6, 9);if (fup == 1){printf("食物分数:"); color(116); printf("%2d", pw1->_food_weight); color(112);}else if (fup == -1){printf("食物分数:"); color(114); printf("%2d", pw1->_food_weight); color(112);}else{printf("食物分数:%2d", pw1->_food_weight); }LeaveCriticalSection(&cs);EnterCriticalSection(&cs);color(112);SetPos(X2 + 6, 10);printf("总得分:%d", pw1->_score);LeaveCriticalSection(&cs);if (Key(VK_UP) && pw1->_dir != DOWN)pw1->_dir = UP;else if (Key(VK_DOWN) && pw1->_dir != UP)pw1->_dir = DOWN;else if (Key(VK_LEFT) && pw1->_dir != RIGHT)pw1->_dir = LEFT;else if (Key(VK_RIGHT) && pw1->_dir != LEFT)pw1->_dir = RIGHT;if (Key(VK_SPACE)){EnterCriticalSection(&cs);SetPos(29, 13);printf("游戏已暂停,点击空格键继续");while (1){Sleep(200);if (Key(VK_SPACE))break;}int x = 26;SetPos(29, 13);while (x--)printf(" ");LeaveCriticalSection(&cs);}if (Key(0XA5)){if (pw1->_sleep_time >= 80){pw1->_sleep_time -= 30;pw1->_food_weight += 2;fup = 1;}}if (Key(0XA3)){if (pw1->_sleep_time <= 320){pw1->_sleep_time += 30;pw1->_food_weight -= 2;fup = -1;}}///pSnakeNode pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);switch (pw1->_dir){case UP:pnew->y = pw1->_pSnake->y - 1;pnew->x = pw1->_pSnake->x;break;case DOWN:pnew->y = pw1->_pSnake->y + 1;pnew->x = pw1->_pSnake->x;break;case LEFT:pnew->x = pw1->_pSnake->x - 2;pnew->y = pw1->_pSnake->y;break;case RIGHT:pnew->x = pw1->_pSnake->x + 2;pnew->y = pw1->_pSnake->y;break;}pnew->next = pw1->_pSnake;pw1->_pSnake = pnew;KillByselfp(pnew, pw2);KillByWallp(pw1);pSnakeNode k = OpFood(pnew, pw1->_pFood);int x1 = X2, y1 = Y2;if (k){x1 = pnew->x + 2;y1 = pnew->y + 2;EnterCriticalSection(&cs);SetPos(x1, y1);color(116);printf("+%d", pw1->_food_weight);LeaveCriticalSection(&cs);int i = 112;while (pnew){EnterCriticalSection(&cs);SetPos(pnew->x, pnew->y);wprintf(L"%lc", BODY);LeaveCriticalSection(&cs);color(i++);pnew = pnew->next;if (i == 126)i = 112;if (i == 119 || i == 112)i++;}color(112);printf("\a");ChangeFood(pw1, pw2, k);PrintFood(pw1->_pFood);pw1->_score += pw1->_food_weight;}else{while (pnew->next->next){EnterCriticalSection(&cs);SetPos(pnew->x, pnew->y);color(114);wprintf(L"%lc", BODY);LeaveCriticalSection(&cs);pnew = pnew->next;}color(112);EnterCriticalSection(&cs);SetPos(pnew->next->x, pnew->next->y);printf("  ");LeaveCriticalSection(&cs);free(pnew->next);pnew->next = NULL;}Sleep(pw1->_sleep_time);EnterCriticalSection(&cs);SetPos(x1, y1);printf("   ");LeaveCriticalSection(&cs);} while (pw2->_status == OK && pw1->_status == OK);return 0;
}//玩家2///
DWORD WINAPI th2(LPVOID ps)
{pLSnake psk = (pLSnake)ps;pSnake pw1 = NULL, pw2 = NULL;pw1 = psk->p1;pw2 = psk->p2;int fp = 0;do {EnterCriticalSection(&cs);color(112);SetPos(X2 + 6, 12);printf("玩家2 蓝蛇");LeaveCriticalSection(&cs);EnterCriticalSection(&cs);SetPos(X2 + 6, 13);if (fp == 1){printf("食物分数:"); color(116); printf("%2d", pw2->_food_weight); color(112);}else if (fp == -1){printf("食物分数:"); color(114); printf("%2d", pw2->_food_weight); color(112);}else{printf("食物分数:%2d", pw2->_food_weight); }LeaveCriticalSection(&cs);EnterCriticalSection(&cs);color(112);SetPos(X2 + 6, 14);printf("总得分:%2d", pw2->_score);LeaveCriticalSection(&cs);if (Key(0x57) && pw2->_dir != DOWN)pw2->_dir = UP;else if (Key(0x53) && pw2->_dir != UP)pw2->_dir = DOWN;else if (Key(0x41) && pw2->_dir != RIGHT)pw2->_dir = LEFT;else if (Key(0x44) && pw2->_dir != LEFT)pw2->_dir = RIGHT;if (Key(0xA4)){if (pw2->_sleep_time >= 80){pw2->_sleep_time -= 30;pw2->_food_weight += 2;fp = 1;}}if (Key(0x43)){if (pw2->_sleep_time <= 320){pw2->_sleep_time += 30;pw2->_food_weight -= 2;fp = -1;}}pSnakeNode pnew = (pSnakeNode)malloc(sizeof(SnakeNode));assert(pnew);switch (pw2->_dir){case UP:pnew->y = pw2->_pSnake->y - 1;pnew->x = pw2->_pSnake->x;break;case DOWN:pnew->y = pw2->_pSnake->y + 1;pnew->x = pw2->_pSnake->x;break;case LEFT:pnew->x = pw2->_pSnake->x - 2;pnew->y = pw2->_pSnake->y;break;case RIGHT:pnew->x = pw2->_pSnake->x + 2;pnew->y = pw2->_pSnake->y;break;}pnew->next = pw2->_pSnake;pw2->_pSnake = pnew;KillByselfp(pnew, pw1);KillByWallp(pw2);pSnakeNode k = OpFood(pnew, pw2->_pFood);int x2 = X2, y2 = Y2;if (k){x2 = pnew->x + 2;y2 = pnew->y + 2;EnterCriticalSection(&cs);SetPos(x2, y2);color(116);printf("+%d", pw2->_food_weight);LeaveCriticalSection(&cs);int i = 112;while (pnew){EnterCriticalSection(&cs);SetPos(pnew->x, pnew->y);color(i++);wprintf(L"%lc", BODY);LeaveCriticalSection(&cs);pnew = pnew->next;if (i == 126)i = 112;if (i == 119 || i == 112)i++;}color(112);printf("\a");ChangeFood(pw1, pw2, k);PrintFood(pw2->_pFood);pw2->_score += pw2->_food_weight;}else{while (pnew->next->next){EnterCriticalSection(&cs);SetPos(pnew->x, pnew->y);color(121);wprintf(L"%lc", BODY);LeaveCriticalSection(&cs);pnew = pnew->next;}EnterCriticalSection(&cs);SetPos(pnew->next->x, pnew->next->y);printf("  ");LeaveCriticalSection(&cs);free(pnew->next);pnew->next = NULL;}Sleep(pw2->_sleep_time);EnterCriticalSection(&cs);SetPos(x2, y2);printf("   ");LeaveCriticalSection(&cs);} while (pw2->_status == OK&&pw1->_status==OK);return 0;  // 可返回任意值
}
void KillByWall(pSnake ps)//判断是否撞墙
{if ((ps->_pSnake->y == 0) || (ps->_pSnake->y == Y)|| (ps->_pSnake->x == 0) || (ps->_pSnake->x == X-2))ps->_status = KILL_BY_WALL;
}
void KillByWallp(pSnake ps)//判断是否撞墙
{if ((ps->_pSnake->y == 0) || (ps->_pSnake->y == Y2)|| (ps->_pSnake->x == 0) || (ps->_pSnake->x == X2 - 2))ps->_status = KILL_BY_WALL;
}
void KillByself(pSnake ps)//判断是否撞到自己
{pSnakeNode pr = ps->_pSnake;pSnakeNode pu = ps->_pSnake->next;while (pu){if (pu->x == pr->x && pu->y == pr->y){ps->_status = KILL_BY_SELF;return;}pu = pu->next;}
}
void KillByselfp(pSnakeNode pnew, pSnake ps)//判断是否撞到对方
{pSnakeNode pu = ps->_pSnake->next;while (pu){if (pnew->x == pu->x && pnew->y == pu->y){ps->_status = KILL_BY_SELF;return;}pu = pu->next;}
}
void GameRun1(pSnake ps)//游戏运行
{PrintHelpInfo1();int fuk = 0;do{SetPos(64, 12);printf("总得分:%d", ps->_score);SetPos(64, 13);if (fuk == 1){printf("食物分数:"); color(116); printf("%2d", ps->_food_weight); color(112);}else if (fuk == -1){printf("食物分数:"); color(114); printf("%2d", ps->_food_weight); color(112);}else{printf("食物分数:%2d", ps->_food_weight);}if (Key(VK_UP) && ps->_dir != DOWN)ps->_dir = UP;else if (Key(VK_DOWN) && ps->_dir != UP)ps->_dir = DOWN;else if (Key(VK_LEFT) && ps->_dir != RIGHT)ps->_dir = LEFT;else if (Key(VK_RIGHT) && ps->_dir != LEFT)ps->_dir = RIGHT;if (Key(VK_SPACE)){while (1){SetPos(29, 13);printf("游戏已暂停,点击空格键继续");if (Key(VK_SPACE))break;Sleep(300);}SetPos(29, 13);int x = 26;while (x--)printf(" ");}if (Key(VK_ESCAPE))ps->_status = END_NORMAL;if (Key(0x09)){if (ps->_sleep_time >= 80)//if (ps->_sleep_time >= 30){ps->_sleep_time -= 30;ps->_food_weight += 2;fuk = 1;}}if (Key(0x51)){if (ps->_sleep_time <= 320){ps->_sleep_time += 30;ps->_food_weight -= 2;fuk = -1;}}SnakeMove1(ps);KillByself(ps);KillByWall(ps);} while (ps->_status == OK);
}
void GameRun2(pSnake pu1, pSnake pu2)
{LSnake kp;pLSnake psk = &kp;psk->p1 = pu1;psk->p2 = pu2;HANDLE thp1 = NULL, thp2 = NULL;// 初始化临界区InitializeCriticalSection(&cs);// 创建线程thp1 = CreateThread(NULL, 0, th1, (LPVOID)psk, 0, NULL);thp2 = CreateThread(NULL, 0, th2, (LPVOID)psk, 0, NULL);assert(thp1);assert(thp2);// 等待线程结束WaitForSingleObject(thp1, INFINITE);WaitForSingleObject(thp2, INFINITE);// 销毁临界区DeleteCriticalSection(&cs);// 关闭线程句柄CloseHandle(thp1);CloseHandle(thp2);
}
void GameEnd(pSnake ps)//游戏结束善后处理
{SetPos(29, 13);if (ps->_status == KILL_BY_SELF){color(116);printf("你撞到了自己,游戏结束");}if (ps->_status == KILL_BY_WALL){color(116);printf("你撞到了墙,游戏结束");}free(ps->_pFood);while (ps->_pSnake){pSnakeNode cur = ps->_pSnake->next;free(ps->_pSnake);ps->_pSnake = cur;}
}
void GameEndp(pSnake ps1, pSnake ps2)
{SetPos(29, 13);if (ps1->_status == KILL_BY_WALL){color(116);printf("玩家1撞到了墙,玩家2获胜");}while (ps1->_pSnake){pSnakeNode cur = ps1->_pSnake->next;free(ps1->_pSnake);ps1->_pSnake = cur;}SetPos(29, 14);if (ps2->_status == KILL_BY_WALL){color(116);printf("玩家2撞到了墙,玩家1获胜");}SetPos(29, 15);if (ps2->_status == KILL_BY_SELF){color(116);printf("玩家2死亡,玩家1获胜");}SetPos(29, 15);if (ps1->_status == KILL_BY_SELF){color(116);printf("玩家1死亡,玩家2获胜");}free(ps2->_pFood);while (ps2->_pSnake){pSnakeNode cur = ps2->_pSnake->next;free(ps2->_pSnake);ps2->_pSnake = cur;}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#include"Snake.h"
void test()
{Snake ps1,ps2;ps1._pFood = NULL, ps2._pFood = NULL;ps1._pSnake = NULL, ps2._pSnake = NULL;setlocale(LC_ALL, "");srand((unsigned int)time(NULL));int x = 0;do{x = GameStart(&ps1,&ps2);if (x == 1){GameRun1(&ps1);GameEnd(&ps1);}else{GameRun2(&ps1, &ps2);GameEndp(&ps1,&ps2);}SetPos(27, 16);printf("M键重新开始游戏,Esc键退出");color(112);while (1){if (Key(VK_ESCAPE))return;if (Key(0x4D))break;Sleep(23);}} while (1);if (x == 1)SetPos(0, Y + 1);elseSetPos(0, Y2 + 1);
}
int main()
{test();color(127);return 0;
}

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

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

相关文章

Graph Neural Networks(GNN)学习笔记

本学习笔记的组织结构是&#xff0c;先跟李沐老师学一下&#xff0c;再去kaggle上寻摸一下有没有类似的练习&#xff0c;浅做一下&#xff0c;作为一个了解。 ———————————0428更新—————————————— 课程和博客看到后面准备主要看两个&#xff1a;GCN和…

ubuntu安装Anaconda安装及conda使用

一. 安装anaconda3详细教程 1、下载镜像 清华大学开源软件镜像站下载地址&#xff1a; https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 下拉到最低端选择Linux&#xff0c;选择最新版&#xff08;32/64位&#xff09;下载。这里我下载的是版本Anaconda3-4.3.30-Linux…

Java中的File类

File类概述和构造方法 File&#xff1a;它是文件和目录路径名的抽象表示 文件和目录是可以通过File封装成对象的 对于File而言&#xff0c;其封装的并不是一个真正存在的文件&#xff0c;仅仅是一个路径名而已&#xff0c;它可以存在&#xff0c;也可以不存在 我们对Fie的操…

大厂常见算法50题-替换空格

专栏持续更新50道算法题&#xff0c;都是大厂高频算法题&#xff0c;建议关注, 一起巧‘背’算法! 文章目录 题目解法一 String类replace方法解法二 遍历替换总结 题目 解法一 String类replace方法 String类自带的replace&#xff0c;方法传入两个char类型的参数&#xff0c;分…

【MySQL 数据宝典】【索引原理】- 004 优化示例-join in exist

一、join 优化原理 1.1 基本连接方式介绍 JOIN 是 MySQL 用来进行联表操作的&#xff0c;用来匹配两个表的数据&#xff0c;筛选并合并出符合我们要求的结果集。 1.2 驱动表的定义 1.2.1 什么是驱动表 多表关联查询时,第一个被处理的表就是驱动表,使用驱动表去关联其他表.驱…

使用 SSH 密钥配置 Git 账号需要以下步骤

1、生成 SSH 密钥&#xff1a; 如果你还没有 SSH 密钥&#xff0c;可以使用以下命令在电脑终端中生成一个新的 SSH 密钥&#xff1a; ssh-keygen -t rsa -b 4096 -f /Users/XXXX/.ssh/id_rsa_my_personal -C "your_emailexample.com" ssh-keygen 是用于生成 SSH 密…

《Fundamentals of Power Electronics》——Buck、Boost、Buck-Boost三个电路的CCM-DCM工作特性总结

Buck、Boost、Buck-Boost这三个电路的CCM-DCM工作特性总结如下表所示&#xff1a; Buck、Boost、Buck-Boost这三个电路工作在DCM模式下电压传输比的对比图如下所示&#xff1a; 由上图可知&#xff0c;Buck-Boost电路的工作特性是一条斜率为的直线&#xff0c;Buck电路和Boost电…

RK3588 - RKNN(Rockchip 神经处理单元)的逆向工程

本文翻译自https://jas-hacks.blogspot.com/2024/02/rk3588-reverse-engineering-rknn.html RK3588 NPU 的内部操作和功能主要隐藏在名为RKNPU2的闭源 SDK 中。由于对大型语言模型 (LLM) 的兴趣以及对transform模型最佳矩阵乘法的追求&#xff0c;想了解 RKNPU SDK 新引入的矩阵…

自动开箱机:提升包装物流效率的关键设备

随着电子商务的飞速发展&#xff0c;物流行业面临着重要的挑战和机遇。如何在保证服务质量的同时&#xff0c;提高物流效率&#xff0c;降低成本&#xff0c;成为摆在物流企业面前的重要课题。在这个背景下&#xff0c;自动开箱机以其高效、精准、省力的特点&#xff0c;正逐渐…

OpenMM——教程学习(1)

如何从零开始做一个蛋白小分子动力学模拟 AmberTools将被用来生成输入文件&#xff0c;OpenMM 将被用来运行模拟&#xff0c;模拟平台为在线百度AI Stuio, 并使用GPU加速。 First thing’s first, 到PDB 蛋白数据库下载一需要模拟的靶点晶体&#xff0c;备用。 1. H web server…

一文讲清:什么是供应商管理?供应商管理怎么做?

供应商管理指的是对供应商的了解、选择、开发、使用和控制等综合性管理工作的总称。其目的在于建立起一个稳定可靠的供应商队伍&#xff0c;为企业生产提供可靠的物资供应。但是企业在进行供应商管理往往面临以下问题&#xff1a; 1、招投标&#xff0c;信息不透明 这主要表…

R语言的基本图形

一&#xff0c;条形图 安装包 install.packages("vcd") 绘制简单的条形图 barplot(c(1,2,4,5,6,3)) 水平条形图 barplot(c(1,2,4,5,6,3),horiz TRUE) 堆砌条形图 > d1<-c("Placebo","Treated") > d2<-c("None",&qu…

你不需要总是在 React 中使用 useState

在我审查的一个拉取请求中&#xff0c;我注意到在许多拉取请求中看到的一种模式。React 组件具有多个 UI 状态&#xff0c;例如 loading、error 和 success。 作者使用了多个 useState 钩子来管理这些状态&#xff0c;这导致代码难以阅读且容易出错&#xff0c;例如&#xff1a…

hadoop命令

hadoop命令 目录 hadoop命令 1.查看文件下面有哪些文件和目录 2.获取文件信息 查看文件内容 3.创建一个文件夹 4.剪切 1&#xff09;从本地hadoop剪切到hdfs并上传到hdfs 2&#xff09;剪切 从hdfs剪切到本地hadoop目录上 5.删除 1&#xff09;递归删除 2&#xff0…

springboot权限验证学习-下

上篇讲了rbac对于菜单的权限&#xff0c;下面准备完成按钮权限以及行数据和列数据权限 权限控制(按钮权限) 权限控制 操作权限就是将操作视为资源&#xff0c;比如删除操作&#xff0c;有些人可以有些人不行。于后端来说&#xff0c;操作就是一个接口。于前端来说&#xff0…

秋招后端开发面试题 - JVM底层原理

目录 JVM底层原理前言面试题Java 对象的创建过程&#xff1f;什么是指针碰撞&#xff1f;什么是空闲列表&#xff1f;/ 内存分配的两种方式&#xff1f;JVM 里 new 对象时&#xff0c;堆会发生抢占吗&#xff1f;JVM 是怎么设计来保证线程安全的&#xff1f;/ 内存分配并发问题…

k8s pod使用sriov

之前的文章中讲了k8s multus的使用&#xff0c;本章节来讲述下如何使用multus来实现sriov的使用。 一、sriov 简介 SR-IOV在2010年左右由Intel提出&#xff0c;但是随着容器技术的推广&#xff0c;intel官方也给出了SR-IOV技术在容器中使用的开源组件&#xff0c;例如&#…

3MF体积设计扩展

3MF 联盟最近宣布了他们最新的体积设计扩展&#xff08;volumetric design extension&#xff09;&#xff0c;用于通过基于体积的描述来编码几何形状和空间多样性属性。 该组织致力于推进 3D 打印的通用规范&#xff0c;目前正在新扩展达到 1.0 之前征求公众反馈。 NSDT工具推…

OpenCV 实现重新映射

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇&#xff1a;OpenCV 实现霍夫圆变换 下一篇 :OpenCV实现仿射变换 目标 在本教程中&#xff0c;您将学习如何&#xff1a; 一个。使用 OpenCV 函数 cv&#xff1a;&#xff1a;remap 实现简单的重新…

20240428如何利用IDM下载磁链视频

缘起&#xff1a; https://weibo.com/tv/show/1034:4864336909500449 中国获奖独立纪录片《阿辉》揭秘红灯区“教父”的生存法则 5,751次观看 1年前 发布于 陕西 身为里中横 67.7万粉丝 互联网科技博主 微博原创视频博主 头条文章作者 https://weibo.com/tv/show/1034:4864…