C语言实现双人贪吃蛇项目(基于控制台界面)

一.贪吃蛇

贪吃蛇是一款简单而富有乐趣的游戏,它的规则易于理解,但挑战性也很高。它已经成为经典的游戏之一,并且在不同的平台上一直受到人们的喜爱和回忆。

二.贪吃蛇的功能

  1. 游戏控制:玩家可以使用键盘输入设备来控制蛇的移动方向。

  2. 蛇的移动:蛇头会根据玩家的输入方向进行移动,而蛇身会随着蛇头的移动而延长,形成一条越来越长的蛇。

  3. 食物生成:游戏界面会随机生成食物,玩家控制的蛇头需要吃掉这些食物,每吃到一块食物,蛇的身体就会增长一节。

  4. 碰撞检测:游戏会检测蛇头是否与自身的身体或者墙壁碰撞,如果碰撞则游戏结束。

  5. 分数计算:游戏会记录玩家吃到的食物数量,并根据数量进行得分计算,通常吃到的食物越多,得分越高。

  6. 难度递增:随着蛇身越来越长,游戏的难度也会逐渐增加,因为玩家需要更小心地避免碰撞

  7. 双人游戏:贪吃蛇支持双人游玩,两位玩家可以相互竞争。

三.贪吃蛇项目的实现

1.游戏前的准备

1.1游戏的状态

  • enum state 枚举类型定义了游戏的状态,包括以下常量:
    • ok:正常状态,表示游戏进行中。
    • by_wall:撞墙状态,表示蛇撞到了地图的边界。
    • by_body:撞到蛇的身体状态,表示蛇头撞到了蛇身。
    • by_self:蛇咬到自己状态,表示蛇头咬到了自己的身体。
    • by_end:游戏结束状态。
    • by_headpush:蛇头相互碰撞状态,表示两个玩家的蛇头相互碰撞。
enum state
{ok = 1,         // 游戏状态:正常状态by_wall,        // 游戏状态:撞墙by_body,        // 游戏状态:撞到蛇的身体by_self,        // 游戏状态:蛇咬到自己by_end,         // 游戏状态:游戏结束by_headpush     // 游戏状态:蛇头相互碰撞
};

1.2蛇的移动方向

  • enum direction 枚举类型定义了蛇的移动方向,包括以下常量:
    • up:表示向上移动。
    • down:表示向下移动。
    • left:表示向左移动。
    • right:表示向右移动。
enum direction
{up = 1,         // 方向:上down,           // 方向:下left,           // 方向:左right           // 方向:右
};

1.3蛇的节点

  • struct SnakeNode 结构体用于表示蛇的一个节点,包括以下成员:
    • x:节点的横坐标。
    • y:节点的纵坐标。
    • next:指向下一个节点的指针。
typedef struct SnakeNode
{int x;                  // 蛇节点的横坐标int y;                  // 蛇节点的纵坐标struct SnakeNode* next; // 指向下一个蛇节点的指针
} SnakeNode, * pSnakeNode;

1.4食物的位置

  • struct Food 结构体用于表示食物的位置,包括以下成员:
    • x:食物的横坐标。
    • y:食物的纵坐标。
typedef struct Food
{int x;                  // 食物的横坐标int y;                  // 食物的纵坐标
} Food, * pFood;

1.5整个贪吃蛇游戏

  • struct Snake 结构体用于表示蛇,包括以下成员:
    • _snake:蛇的头节点指针。
    • _food:食物指针。
    • _score:蛇的得分。
    • dir:蛇的移动方向。
    • sta:当前游戏状态。
    • _weight:奖励。
    • _sleeptime:游戏循环每次暂停的时间间隔。
typedef struct Snake
{pSnakeNode _snake;      // 蛇的头节点指针pFood _food;            // 食物指针int _score;             // 蛇的得分enum direction dir;     // 蛇的移动方向enum state sta;         // 当前游戏状态int _weight;            // 奖励int _sleeptime;         // 游戏循环每次暂停的时间间隔
} Snake, * pSnake;

2.游戏开始

2.1本地化设置

使用setlocale函数设置本地化环境为当前系统默认的环境。因为环境的差异,导致我们的中文的宽字符无法被识别,所以要本地化设置。

int main()
{setlocale(LC_ALL, "");  // 设置本地化环境为当前系统默认的环境test();  // 调用test函数进行测试return 0;  // 返回0表示程序正常结束
}

2.2 实现贪吃蛇的基本流程

test函数中,通过srand函数将当前时间作为随机数种子。然后使用do-while循环进行游戏的测试和循环控制。在循环内部,首先使用malloc动态分配了两个Snake结构体的内存,并将其指针赋值给snake1snake2。接着调用gamestart函数开始游戏,传入snake1snake2作为参数;然后调用gamerun函数进行游戏运行,同样传入snake1snake2作为参数;最后调用gameend函数结束游戏并释放内存,同样传入snake1snake2作为参数。之后,使用system("cls")清空控制台屏幕,然后在指定位置打印提示信息。接下来,使用getchar函数获取一个字符并赋值给变量ch,再使用getchar读取多余的换行符。最后,判断ch是否为字符'y''Y',如果是则继续进行下一轮游戏。

#include "snake.h"  // 引入自定义的头文件snake.hvoid test()
{srand((unsigned int)time(NULL));  // 使用当前时间作为随机数种子int ch;do {pSnake snake1 = (pSnake)malloc(sizeof(Snake));  // 动态分配一个Snake结构体的内存,并将其指针赋给snake1pSnake snake2 = (pSnake)malloc(sizeof(Snake));  // 动态分配一个Snake结构体的内存,并将其指针赋给snake2gamestart(snake1, snake2);  // 调用gamestart函数开始游戏,传入snake1和snake2作为参数gamerun(snake1, snake2);    // 调用gamerun函数进行游戏运行,传入snake1和snake2作为参数gameend(snake1, snake2);    // 调用gameend函数结束游戏,释放内存,传入snake1和snake2作为参数system("cls");  // 清空控制台屏幕setpos(46, 15);  // 设置光标位置为(46, 15)printf("选择Y/N");setpos(50, 16);  // 设置光标位置为(50, 16)ch = getchar();  // 从标准输入中获取一个字符,赋值给chgetchar();       // 读取多余的换行符} while (ch == 'y' || ch == 'Y');  // 如果输入的字符是'y'或'Y',则继续进行下一轮游戏}

2.3设置光标

该函数接受两个整型参数xy,分别表示光标的横坐标和纵坐标。在函数内部,首先调用GetStdHandle函数获取标准输出句柄,该句柄用于操作控制台窗口。然后创建一个COORD结构体变量coord,并将x赋值给coord.X,将y赋值给coord.Y,即设置光标的位置。最后,调用SetConsoleCursorPosition函数将控制台光标位置设置为指定的坐标。这样,在调用setpos函数时,控制台光标会移动到指定的位置。

void setpos(int x, int y)
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);  // 获取标准输出句柄COORD coord;coord.X = x;  // 设置光标的横坐标为xcoord.Y = y;  // 设置光标的纵坐标为ySetConsoleCursorPosition(handle, coord);  // 设置控制台光标位置为指定的坐标
}

 2.4游戏的初始化

该函数接受两个参数,snake1snake2,分别表示两条蛇的指针。函数开始使用断言assert,确保snake1snake2不为NULL,以保证后续操作的正确性。然后依次调用以下函数:

  • welcome:显示游戏欢迎信息,可能是在控制台输出一些欢迎文本。
  • creatmap:创建游戏地图,可能是在控制台上绘制一个游戏地图的界面。
  • initsnake:初始化蛇的身体,可能是将蛇的初始位置和长度设置为默认值。
  • creatsnake:生成两条蛇的初始位置,可能是将两条蛇放置在地图的指定位置。
  • creatfood:生成食物的位置,以供两条蛇争夺,可能是将食物随机放置在地图的空闲位置。
  • gameinfo:显示游戏信息,可能是在控制台上显示当前游戏的状态、得分等信息。
void gamestart(pSnake snake1, pSnake snake2)
{assert(snake1 && snake2);  // 使用断言确保snake1和snake2不为NULLwelcome();                // 调用welcome函数,显示游戏欢迎信息creatmap();               // 调用creatmap函数,创建游戏地图initsnake(snake1);        // 调用initsnake函数,初始化snake1蛇身initsnake(snake2);        // 调用initsnake函数,初始化snake2蛇身creatsnake(snake1, snake2);// 调用creatsnake函数,生成snake1和snake2的初始位置creatfood(snake1, snake2);// 调用creatfood函数,生成食物的位置,以供snake1和snake2争夺creatfood(snake2, snake1);// 调用creatfood函数,生成食物的位置,以供snake2和snake1争夺gameinfo(snake1, snake2); // 调用gameinfo函数,显示游戏信息
}
2.3.1欢迎信息

该函数没有参数。在函数内部,首先调用system函数设置控制台窗口的大小为100列,30行,使用命令mode con cols=100 lines=30实现。然后调用system函数设置控制台窗口的标题为"贪吃蛇",使用命令title 贪吃蛇实现。接下来,获取标准输出句柄,并获取控制台光标信息。将光标的可见性设置为false,即不可见,然后再将修改后的光标信息设置回控制台。然后使用setpos函数设置光标位置为(40, 10),在该位置打印欢迎信息。接着,使用setpos函数设置光标位置为(40, 20),调用system("pause")暂停程序的执行,等待用户按下任意键。然后使用system("cls")清空控制台屏幕。接下来,使用setpos函数设置光标位置为(38, 10),然后依次打印游戏规则的内容。再次使用setpos函数设置光标位置为(40, 20),使用system("pause")暂停程序的执行,等待用户按下任意键。最后,使用system("cls")清空控制台屏幕。

void welcome()
{system("mode con cols=100 lines=30");  // 设置控制台窗口的大小为100列,30行system("title 贪吃蛇");                // 设置控制台窗口的标题为"贪吃蛇"HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);  // 获取标准输出句柄CONSOLE_CURSOR_INFO cursor;GetConsoleCursorInfo(handle, &cursor);  // 获取控制台光标信息cursor.bVisible = false;                // 将光标设置为不可见SetConsoleCursorInfo(handle, &cursor);  // 设置控制台光标信息setpos(40, 10);                          // 设置光标位置为(40, 10)printf("欢迎来到贪吃蛇游戏!");setpos(40, 20);                          // 设置光标位置为(40, 20)system("pause");                         // 暂停程序的执行,等待用户按下任意键system("cls");                           // 清空控制台屏幕setpos(38, 10);                          // 设置光标位置为(38, 10)printf("游戏规则如下:\n");setpos(38, 11);                          // 设置光标位置为(38, 11)printf("1.用← → ↑ ↓或a  d  w  s进行操作");setpos(38, 12);                          // 设置光标位置为(38, 12)printf("2.用f1进行加速,用进行f2减速");setpos(38, 13);                          // 设置光标位置为(38, 13)printf("3.空格键暂停游戏");setpos(38, 14);                          // 设置光标位置为(38, 14)printf("4.esc退出游戏");setpos(40, 20);                          // 设置光标位置为(40, 20)system("pause");                         // 暂停程序的执行,等待用户按下任意键system("cls");                           // 清空控制台屏幕
}
2.3.2创建地图

该函数没有参数。在函数内部,首先使用setpos函数将光标位置设置为(0, 0)。然后使用循环,每次递增2,打印墙的字符。接着,使用setpos函数将光标位置设置为(0, 25),再次使用循环,每次递增2,打印墙的字符。然后使用循环,从1到24,每次递增1,使用setpos函数将光标位置设置为(0, i),打印墙的字符。最后,使用循环,从1到24,每次递增1,使用setpos函数将光标位置设置为(56, i),打印墙的字符。这样,通过在控制台上打印一系列墙的字符,创建了游戏地图的界面。

void creatmap()
{setpos(0, 0);for (int i = 0; i < 58; i += 2){wprintf(L"%c", Wall);}setpos(0, 25);for (int i = 0; i < 58; i += 2){wprintf(L"%c", Wall);}for (int i = 1; i < 25; i++){setpos(0, i);wprintf(L"%c", Wall);}for (int i = 1; i < 25; i++){setpos(56, i);wprintf(L"%c", Wall);}
}
2.3.3初始化整个贪吃蛇游戏

该函数接受一个指向Snake结构体的指针snake作为参数。在函数内部,将蛇的链表指针_snake和食物的指针_food都设置为NULL,表示蛇链表和食物尚未创建。将分数_score初始化为0,表示初始分数为0。将蛇的初始移动方向dir设置为left,表示初始方向为向左移动。将蛇的状态sta设置为ok,表示蛇的初始状态为正常状态。将蛇的初始长度_weight设置为10,表示蛇的初始长度为10。将蛇的初始移动速度_sleeptime设置为200毫秒,表示蛇的初始移动速度为每200毫秒移动一次。通过这些初始化操作,为蛇游戏的相关数据设置了初始值,以便游戏开始时使用。

void initsnake(pSnake snake)
{snake->_snake = NULL;    // 将蛇的链表指针设置为NULLsnake->_food = NULL;     // 将食物的指针设置为NULLsnake->_score = 0;       // 将分数初始化为0snake->dir = left;       // 将蛇的初始移动方向设置为左侧snake->sta = ok;         // 将蛇的初始状态设置为正常状态snake->_weight = 10;     // 将蛇的初始长度设置为10snake->_sleeptime = 200; // 将蛇的初始移动速度设置为200毫秒
}
2.3.4创建蛇的初始状态

该函数接受两个指向Snake结构体的指针snake1snake2作为参数。在函数内部,首先创建蛇1的头结点p1,并将其位置设置为(24, 5)。然后将蛇1的链表指针_snake指向头结点p1,表示蛇1的链表的起始节点为头结点。然后在控制台上打印头结点的字符表示。接着使用循环,从1到4,每次递增1,创建蛇1的身体节点j,并将其位置设置为(24 + i * 2, 5)。然后在控制台上打印身体节点的字符表示。将头结点的next指针指向身体节点j,表示蛇1的头结点连接到身体节点。然后更新头结点为身体节点,为下一个身体节点的创建做准备。接下来,按照类似的方式,创建蛇2的头结点和身体节点。蛇2的头结点位置为(24, 22),蛇2的身体节点位置从(26, 22)开始递增。在控制台上打印蛇2的头结点和身体节点的字符表示。通过这些操作,创建了两条蛇的初始状态,每条蛇由一个头结点和四个身体节点组成。

void creatsnake(pSnake snake1, pSnake snake2)
{pSnakeNode p1 = (pSnakeNode)malloc(sizeof(SnakeNode)); // 创建蛇1的头结点assert(p1);p1->next = NULL;p1->x = 24;p1->y = 5;snake1->_snake = p1;setpos(p1->x, p1->y);wprintf(L"%c", Body);for (int i = 1; i < 5; i++){pSnakeNode j = (pSnakeNode)malloc(sizeof(SnakeNode)); // 创建蛇1的身体节点assert(j);j->x = 24 + i * 2;j->y = 5;j->next = NULL;setpos(j->x, j->y);wprintf(L"%c", Body);p1->next = j;p1 = p1->next;}pSnakeNode p2 = (pSnakeNode)malloc(sizeof(SnakeNode)); // 创建蛇2的头结点assert(p2);p2->next = NULL;p2->x = 24;p2->y = 22;snake2->_snake = p2;setpos(p2->x, p2->y);wprintf(L"%c", Body);for (int i = 1; i < 5; i++){pSnakeNode j = (pSnakeNode)malloc(sizeof(SnakeNode)); // 创建蛇2的身体节点assert(j);j->x = 24 + i * 2;j->y = 22;j->next = NULL;setpos(j->x, j->y);wprintf(L"%c", Body);p2->next = j;p2 = p2->next;}
}
2.3.5创建食物

该函数接受两个指向Snake结构体的指针snake1snake2作为参数。在函数内部,首先定义变量cout用于控制是否需要重新生成食物位置。然后定义变量xy用于存储食物的坐标。通过循环和条件判断,生成在游戏区域内的随机坐标(x, y),其中x是2到53之间的偶数,y是1到24之间的任意数。这样可以保证食物落在游戏区域内的空闲位置。接着,遍历蛇1和蛇2的身体节点,以及蛇2的食物位置(如果存在),检查食物位置是否与这些节点重叠。如果有重叠,则重新生成食物位置,通过goto语句返回到again标签处重新生成。如果食物位置与蛇的身体节点和食物位置都不重叠,将变量cout设置为1,表示食物位置已经确定。然后,将食物的坐标存储到蛇1的数据结构中,将食物指针指向食物结构体。在控制台上打印食物的字符表示,以显示食物的位置。通过这些操作,生成并放置了食物,并确保食物不与蛇的身体节点和其他食物重叠。

void creatfood(pSnake snake1, pSnake snake2)
{int cout = 0;int x, y;pFood food1 = (pFood)malloc(sizeof(Food)); // 创建食物结构体assert(food1);
again:if (cout == 0){do {x = rand() % 52 + 2; // 生成一个2到53之间的随机数作为x坐标y = rand() % 23 + 1; // 生成一个1到24之间的随机数作为y坐标} while (x % 2 != 0); // 保证x坐标是偶数,以确保食物落在游戏区域内的空闲位置pSnakeNode p1 = snake1->_snake;pSnakeNode p2 = snake1->_snake;while (p1 && p2){if (snake2->_food == NULL){if (p1->x == x && p1->y == y && p2->x == x && p2->y == y)goto again; // 如果食物位置与蛇1和蛇2的身体节点位置重叠,则重新生成食物位置}else if (p1->x == x && p1->y == y && p2->x == x && p2->y == y && snake2->_food->x == x && snake2->_food->y == y)goto again; // 如果食物位置与蛇1、蛇2的身体节点位置以及蛇2的食物位置重叠,则重新生成食物位置p1 = p1->next;p2 = p2->next;}cout = 1;}food1->x = x;food1->y = y;snake1->_food = food1; // 将食物指针存储到蛇1的数据结构中setpos(food1->x, food1->y);wprintf(L"%c", FOOD); // 在控制台上打印食物的字符表示
}
2.3.6显示游戏的规则

该函数接受两个指向Snake结构体的指针snake1snake2作为参数。在函数内部,使用setpos函数将光标定位到相应的位置,然后使用printf函数将相关信息打印在控制台上。首先打印蛇1的分数和奖励信息,分别位于(70, 6)和(70, 7)的位置。接着打印蛇2的分数和奖励信息,分别位于(70, 10)和(70, 11)的位置。然后打印游戏规则,分别位于(62, 15)到(62, 20)的位置。通过这些操作,在控制台上显示了游戏的相关信息和规则。

void gameinfo(pSnake snake1, pSnake snake2)
{setpos(70, 6);printf("分数:%d", snake1->_score); // 打印蛇1的分数setpos(70, 7);printf("奖励:%d", snake1->_weight); // 打印蛇1的奖励setpos(70, 10);printf("分数:%d", snake2->_score); // 打印蛇2的分数setpos(70, 11);printf("奖励:%d", snake2->_weight); // 打印蛇2的奖励setpos(62, 15);printf("游戏规则如下:");setpos(62, 16);printf("1.用← → ↑ ↓或a  d  w  s进行操作");setpos(62, 17);printf("2.用f1进行加速,用进行f2减速");setpos(62, 18);printf("3.空格键暂停游戏");setpos(62, 19);printf("4.esc退出游戏");setpos(62, 20);printf("5.咬到蛇身或撞墙都会死");
}

3.游戏进行中

3.1控制游戏的运行逻辑

该函数接受两个指向Snake结构体的指针snake1snake2作为参数。在函数内部,使用do-while循环来控制游戏的逻辑。在循环内部,根据按键的状态来判断玩家的操作,例如W、S、A、D键用于控制蛇1的移动方向,空格键用于暂停游戏,ESC键用于结束游戏。同时,F1和F2键用于加速和减速蛇的移动速度,上下左右箭头键用于控制蛇2的移动方向。接着调用snakemove函数来移动蛇1和蛇2的位置。然后更新显示蛇1和蛇2的分数和奖励信息。最后根据蛇1的睡眠时间进行延时,然后继续下一轮循环,直到蛇1或蛇2的状态不再为正常(游戏结束)。

void gamerun(pSnake snake1, pSnake snake2)
{do {if (Key_state(0x57) && snake1->dir != down){snake1->dir = up; // 如果按下W键且蛇1不朝下移动,则将蛇1的方向设置为上}else if (Key_state(0x53) && snake1->dir != up){snake1->dir = down; // 如果按下S键且蛇1不朝上移动,则将蛇1的方向设置为下}else if (Key_state(0x41) && snake1->dir != right){snake1->dir = left; // 如果按下A键且蛇1不朝右移动,则将蛇1的方向设置为左}else if (Key_state(0x44) && snake1->dir != left){snake1->dir = right; // 如果按下D键且蛇1不朝左移动,则将蛇1的方向设置为右}else if (Key_state(VK_SPACE)){pause(); // 如果按下空格键,则暂停游戏}else if (Key_state(VK_ESCAPE)){snake1->sta = by_end; // 如果按下ESC键,则将蛇1的状态设置为结束snake2->sta = by_end; // 将蛇2的状态设置为结束}else if (Key_state(VK_F1)){if (snake1->_sleeptime >= 80){(snake1->_sleeptime) -= 20; // 如果按下F1键且蛇1的睡眠时间大于等于80,则减少蛇1的睡眠时间(snake1->_weight) += 2; // 增加蛇1的奖励}setpos(70, 7);printf("奖励:%d", snake1->_weight); // 更新蛇1的奖励显示if (snake2->_sleeptime >= 80){(snake2->_sleeptime) -= 20; // 如果按下F1键且蛇2的睡眠时间大于等于80,则减少蛇2的睡眠时间(snake2->_weight) += 2; // 增加蛇2的奖励}setpos(70, 11);printf("奖励:%d", snake2->_weight); // 更新蛇2的奖励显示}else if (Key_state(VK_F2)){if (snake1->_sleeptime <= 280){(snake1->_sleeptime) += 20; // 如果按下F2键且蛇1的睡眠时间小于等于280,则增加蛇1的睡眠时间(snake1->_weight) -= 2; // 减少蛇1的奖励}setpos(70, 7);printf("奖励:%d", snake1->_weight); // 更新蛇1的奖励显示if (snake2->_sleeptime <= 280){(snake2->_sleeptime) += 20; // 如果按下F2键且蛇2的睡眠时间小于等于280,则增加蛇2的睡眠时间(snake2->_weight) -= 2; // 减少蛇2的奖励}setpos(70, 11);printf("奖励:%d", snake2->_weight); // 更新蛇2的奖励显示}else if (Key_state(VK_UP) && snake2->dir != down){snake2->dir = up; // 如果按下上箭头键且蛇2不朝下移动,则将蛇2的方向设置为上}else if (Key_state(VK_DOWN) && snake2续:.dir != up){snake2->dir = down; // 如果按下下箭头键且蛇2不朝上移动,则将蛇2的方向设置为下}else if (Key_state(VK_LEFT) && snake2->dir != right){snake2->dir = left; // 如果按下左箭头键且蛇2不朝右移动,则将蛇2的方向设置为左}else if (Key_state(VK_RIGHT) && snake2->dir != left){snake2->dir = right; // 如果按下右箭头键且蛇2不朝左移动,则将蛇2的方向设置为右}snakemove(snake1, snake2); // 移动蛇1snakemove(snake2, snake1); // 移动蛇2setpos(70, 6);printf("分数:%d", snake1->_score); // 更新蛇1的分数显示setpos(70, 7);printf("奖励:%d", snake1->_weight); // 更新蛇1的奖励显示setpos(70, 10);printf("分数:%d", snake2->_score); // 更新蛇2的分数显示setpos(70, 11);printf("奖励:%d", snake2->_weight); // 更新蛇2的奖励显示Sleep(snake1->_sleeptime); // 根据蛇1的睡眠时间进行延时} while (snake1->sta == ok && snake2->sta == ok); // 当蛇1和蛇2的状态都为正常时继续循环
}

3.2 游戏的暂停

在函数内部,使用一个无限循环while (1)来检测空格键的状态。如果空格键被按下(Key_state(VK_SPACE)返回true),则函数使用return语句立即返回,从而退出循环并继续游戏的执行。如果空格键未被按下,函数会通过Sleep(1000)函数让程序休眠1秒钟,然后再次检测空格键的状态。这样循环会一直执行,直到空格键被按下并函数返回。这样就实现了游戏的暂停功能。

void pause()
{while (1){if (Key_state(VK_SPACE))return;Sleep(1000);}
}

3.3 蛇的移动及一系列的判断

该函数包含了以下功能:

  • 创建一个新的蛇头节点 i,并将其插入到蛇身链表的头部。
  • 根据贪吃蛇的方向更新蛇头的位置。
  • 如果贪吃蛇吃到了食物,增加贪吃蛇的得分并生成新的食物。
  • 如果贪吃蛇没有吃到食物,移动蛇尾,即删除蛇身链表的最后一个节点,并在屏幕上擦除该节点的位置。
  • 检查贪吃蛇是否撞墙,如果是则设置状态为 by_wall 并返回。
  • 检查贪吃蛇是否自噬,即蛇头是否碰到了蛇身的其他部分。
  • 绘制贪吃蛇的身体,即在屏幕上打印出每个节点的位置。
void snakemove(pSnake snake1, pSnake snake2)
{pSnakeNode i = (pSnakeNode)malloc(sizeof(SnakeNode));assert(i);i->next = snake1->_snake;// 根据贪吃蛇的方向更新蛇头的位置if (snake1->dir == up){i->x = snake1->_snake->x;i->y = snake1->_snake->y - 1;}else if (snake1->dir == down){i->x = snake1->_snake->x;i->y = snake1->_snake->y + 1;}else if (snake1->dir == left){i->x = snake1->_snake->x - 2;i->y = snake1->_snake->y;}else if (snake1->dir == right){i->x = snake1->_snake->x + 2;i->y = snake1->_snake->y;}else if (snake1->sta == by_end){return;}// 更新蛇头的位置snake1->_snake = i;pSnakeNode p = snake1->_snake;// 判断是否吃到了食物if ((i->x == snake1->_food->x && i->y == snake1->_food->y) || (i->x == snake2->_food->x && i->y == snake2->_food->y)){(snake1->_score) += snake1->_weight;creatfood(snake1, snake2);}else{// 如果没有吃到食物,则移动蛇尾pSnakeNode pre = NULL;while (p->next != NULL){pre = p;p = p->next;}pre->next = NULL;setpos(p->x, p->y);printf("  ");free(p);}// 判断是否撞墙if (snake1->_snake->x == 0 || snake1->_snake->x == 56 || snake1->_snake->y == 0 || snake1->_snake->y == 25){snake1->sta = by_wall;return;}// 判断是否自噬kill_self(snake1, snake2);// 绘制蛇的身体p = i;while (p){setpos(p->x, p->y);wprintf(L"%c", Body);p = p->next;}
}
3.3.1 判断贪吃蛇是否自噬或者与另一个贪吃相撞

该函数包含了以下功能:

  • 初始化两个指针 p1 和 p2 分别指向贪吃蛇1和贪吃蛇2的蛇身链表的第二个节点(跳过蛇头)。
  • 检测贪吃蛇1的蛇头是否与贪吃蛇2的蛇头位置重叠,如果是,则将两个贪吃蛇的状态都设置为 by_headpush 表示头部碰撞,并立即返回。
  • 遍历贪吃蛇1和贪吃蛇2的蛇身链表,检测贪吃蛇1的蛇头是否与贪吃蛇2的蛇身节点或贪吃蛇1自身的蛇身节点位置重叠,如果是,则将贪吃蛇1的状态设置为相应的自噬状态(by_body 或 by_self),并立即返回。

这个函数的作用是在每次贪吃蛇移动后检测是否发生自噬或者与其他贪吃蛇相撞的情况,以便在后续的游戏逻辑中处理相应的情况。

void kill_self(pSnake snake1, pSnake snake2)
{pSnakeNode p1 = snake1->_snake->next;pSnakeNode p2 = snake2->_snake->next;// 检测蛇头是否碰撞if (snake1->_snake->x == snake2->_snake->x && snake1->_snake->y == snake2->_snake->y){snake1->sta = by_headpush;snake2->sta = by_headpush;return;}// 检测蛇头是否与蛇身碰撞while (p1 && p2){if (snake1->_snake->x == p2->x && snake1->_snake->y == p2->y){snake1->sta = by_body;return;}if (snake1->_snake->x == p1->x && snake1->_snake->y == p1->y){snake1->sta = by_self;return;}p1 = p1->next;p2 = p2->next;}
}

4.游戏结束

该函数包含以下功能:

  • 检查贪吃蛇的状态,根据不同的情况显示相应的游戏结束提示信息。
  • 释放贪吃蛇1和贪吃蛇2所占用的内存。

具体逻辑如下:

首先,函数检查两条蛇的状态是否相同。如果状态不同,根据不同的状态显示相应的游戏结束提示信息。

  • 如果蛇1的状态是by_body,表示蛇1咬到了蛇2的身体,显示"玩家1咬到对方蛇身了,游戏结束!"的提示信息。
  • 如果蛇1的状态是by_wall,表示蛇1撞到了墙壁,显示"玩家1撞到墙了,游戏结束!"的提示信息。
  • 如果蛇2的状态是by_body,表示蛇2咬到了蛇1的身体,显示"玩家2咬到对方蛇身了,游戏结束!"的提示信息。
  • 如果蛇2的状态是by_wall,表示蛇2撞到了墙壁,显示"玩家2撞到墙了,游戏结束!"的提示信息。
  • 如果蛇1的状态是by_self,表示蛇1咬到了自己的身体,显示"玩家1咬到自己蛇身了,游戏结束!"的提示信息。
  • 如果蛇2的状态是by_self,表示蛇2咬到了自己的身体,显示"玩家2咬到自己蛇身了,游戏结束!"的提示信息。

如果两条蛇的状态相同,继续检查状态。

  • 如果蛇1的状态是by_end,表示蛇1到达了游戏结束状态,显示"游戏结束!"的提示信息。
  • 如果蛇1的状态是by_body,表示蛇1和蛇2都咬到了对方的身体,显示"玩家1和玩家2都咬到对方蛇身了,游戏结束!"的提示信息。
  • 如果蛇1的状态是by_wall,表示蛇1和蛇2都撞到了墙壁,显示"玩家1和玩家2撞到墙了,游戏结束!"的提示信息。
  • 如果蛇1的状态是by_headpush,表示蛇1和蛇2相互碰撞,显示"两位玩家相撞了,游戏结束!"的提示信息。
  • 如果蛇1的状态是by_self,表示蛇1和蛇2都咬到了自己的身体,显示"玩家1和玩家2都咬到自己蛇身了,游戏结束!"的提示信息。

接下来,函数释放贪吃蛇1所占用的内存。首先释放蛇1的食物(_food),然后依次释放蛇1的节点(_snake)所占用的内存。最后,函数释放贪吃蛇2所占用的内存。首先释放蛇2的食物(_food),然后依次释放蛇2的节点(_snake)所占用的内存。

void gameend(pSnake snake1, pSnake snake2)
{// 检查贪吃蛇状态,显示相应的游戏结束提示信息并释放内存if (snake1->sta != snake2->sta){if (snake1->sta == by_body){system("cls");setpos(42, 15);printf("玩家1咬到对方蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_wall){system("cls");setpos(38, 15);printf("玩家1撞到墙了,游戏结束!");setpos(40, 22);system("pause");}else if (snake2->sta == by_body){system("cls");setpos(34, 15);printf("玩家2咬到对方蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake2->sta == by_wall){system("cls");setpos(34, 15);printf("玩家2撞到墙了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_self){system("cls");setpos(34, 15);printf("玩家1咬到自己蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake2->sta == by_self){system("cls");setpos(34, 15);printf("玩家2咬到自己蛇身了,游戏结束!");setpos(40, 22);system("pause");}}else{if (snake1->sta == by_end){system("cls");setpos(48, 15);printf("游戏结束!");setpos(42, 22);system("pause");}else if (snake1->sta == by_body){system("cls");setpos(34, 15);printf("玩家1和玩家2都咬到对方蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_wall){system("cls");setpos(34, 15);printf("玩家1和玩家2撞到墙了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_headpush){system("cls");setpos(34, 15);printf("两位玩家相撞了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_self){system("cls");setpos(34, 15);printf("玩家1和玩家2都咬到自己蛇身了,游戏结束!");setpos(40, 22);system("pause");}}// 释放贪吃蛇1的内存free(snake1->_food);pSnakeNode p = snake1->_snake;pSnakeNode pre = NULL;while (p){pre = p;p = p->next;pre->next = NULL;free(pre);}free(snake1);// 释放贪吃蛇2的内存free(snake2->_food);p = snake2->_snake;pre = NULL;while (p){pre = p;p = p->next;pre->next = NULL;free(pre);}free(snake2);
}

四.贪吃蛇的测试

五.贪吃蛇的源码呈现

1.snake.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<windows.h>
#include<locale.h>
#include<stdbool.h>
#include<assert.h>
#include<time.h>
#define Wall L'□'
#define Body L'●'
#define FOOD L'★'
#define Key_state(KEY) ((GetAsyncKeyState(KEY)&(0x1))?1:0)
enum state
{ok = 1,by_wall,by_body,by_self,by_end,by_headpush
};
enum direction
{up = 1,down,left,right
};
typedef struct SnakeNode
{int x;int y;struct SnakeNode* next;
}SnakeNode, * pSnakeNode;
typedef struct Food
{int x;int y;
}Food, * pFood;
typedef struct Snake
{pSnakeNode _snake;pFood _food;int _score;enum direction dir;enum state sta;int _weight;int _sleeptime;
}Snake, * pSnake;
void gamestart(pSnake snake1,pSnake snake2);
void setpos(int x, int y);
void welcome();
void creatmap();
void creatfood(pSnake snake1,pSnake snake2);
void initsnake(pSnake snake1);
void creatsnake(pSnake snake1, pSnake snake2);
void gameinfo(pSnake snake1, pSnake snake2);
void gamerun(pSnake snake1, pSnake snake2);
void pause();
void snakemove(pSnake snake1,pSnake snake2);
void kill_self(pSnake snake);
void gameend(pSnake snake);

2.test.c

#include"snake.h"
void test()
{srand((unsigned int)time(NULL));int ch;do {pSnake snake1 = (pSnake)malloc(sizeof(Snake));pSnake snake2 = (pSnake)malloc(sizeof(Snake));gamestart(snake1,snake2);gamerun(snake1,snake2);gameend(snake1,snake2);system("cls");setpos(46, 15);printf("选择Y/N");setpos(50, 16);ch = getchar();getchar();} while (ch == 'y' || ch == 'Y');
}
int main()
{setlocale(LC_ALL, "");test();return 0;
}

3.snake.c

#include"snake.h"
void setpos(int x, int y)
{HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);COORD coord;coord.X = x;coord.Y = y;SetConsoleCursorPosition(handle, coord);
}
void welcome()
{system("mode con cols=100 lines=30");system("title 贪吃蛇");HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO cursor;GetConsoleCursorInfo(handle, &cursor);cursor.bVisible = false;SetConsoleCursorInfo(handle, &cursor);setpos(40, 10);printf("欢迎来到贪吃蛇游戏!");setpos(40, 20);system("pause");system("cls");setpos(38, 10);printf("游戏规则如下:\n");setpos(38, 11);printf("1.用← → ↑ ↓或a  d  w  s进行操作");setpos(38, 12);printf("2.用f1进行加速,用进行f2减速");setpos(38, 13);printf("3.空格键暂停游戏");setpos(38, 14);printf("4.esc退出游戏");setpos(40, 20);system("pause");system("cls");
}
void creatmap()
{setpos(0, 0);for (int i = 0; i < 58; i += 2){wprintf(L"%c", Wall);}setpos(0, 25);for (int i = 0; i < 58; i += 2){wprintf(L"%c", Wall);}for (int i = 1; i < 25; i++){setpos(0, i);wprintf(L"%c", Wall);}for (int i = 1; i < 25; i++){setpos(56, i);wprintf(L"%c", Wall);}
}
void initsnake(pSnake snake)
{snake->_snake = NULL;snake->_food = NULL;snake->_score = 0;snake->dir = left;snake->sta = ok;snake->_weight = 10;snake->_sleeptime = 200;
}
void creatsnake(pSnake snake1,pSnake snake2)
{pSnakeNode p1 = (pSnakeNode)malloc(sizeof(SnakeNode));assert(p1);p1->next = NULL;p1->x = 24;p1->y = 5;snake1->_snake = p1;setpos(p1->x, p1->y);wprintf(L"%c", Body);for (int i = 1; i < 5; i++){pSnakeNode j = (pSnakeNode)malloc(sizeof(SnakeNode));assert(j);j->x = 24 + i * 2;j->y = 5;j->next = NULL;setpos(j->x, j->y);wprintf(L"%c", Body);p1->next = j;p1 = p1->next;}pSnakeNode p2 = (pSnakeNode)malloc(sizeof(SnakeNode));assert(p2);p2->next = NULL;p2->x = 24;p2->y = 22;snake2->_snake = p2;setpos(p2->x, p2->y);wprintf(L"%c", Body);for (int i = 1; i < 5; i++){pSnakeNode j = (pSnakeNode)malloc(sizeof(SnakeNode));assert(j);j->x = 24 + i * 2;j->y = 22;j->next = NULL;setpos(j->x, j->y);wprintf(L"%c", Body);p2->next = j;p2 = p2->next;}
}
void creatfood(pSnake snake1,pSnake snake2)
{int cout = 0;int x, y;pFood food1 = (pFood)malloc(sizeof(Food));assert(food1);
again:if (cout == 0){do {x = rand() % 52 + 2;y = rand() % 23 + 1;} while (x % 2 != 0);pSnakeNode p1 = snake1->_snake;pSnakeNode p2 = snake1->_snake;while (p1&&p2){if (snake2->_food == NULL){if (p1->x == x && p1->y == y && p2->x == x && p2->y == y)goto again;}else if (p1->x == x && p1->y == y && p2->x == x && p2->y == y&&snake2->_food->x==x&&snake2->_food->y==y)goto again;p1 = p1->next;p2 = p2->next;}cout = 1;}food1->x = x;food1->y = y;snake1->_food = food1;setpos(food1->x, food1->y);wprintf(L"%c", FOOD);
}
void gameinfo(pSnake snake1,pSnake snake2)
{setpos(70, 6);printf("分数:%d", snake1->_score);setpos(70, 7);printf("奖励:%d", snake1->_weight);setpos(70, 10);printf("分数:%d", snake2->_score);setpos(70, 11);printf("奖励:%d", snake2->_weight);setpos(62, 15);printf("游戏规则如下:");setpos(62, 16);printf("1.用← → ↑ ↓或a  d  w  s进行操作");setpos(62, 17);printf("2.用f1进行加速,用进行f2减速");setpos(62, 18);printf("3.空格键暂停游戏");setpos(62, 19);printf("4.esc退出游戏");setpos(62, 20);printf("5.咬到蛇身或撞墙都会死");
}
void pause()
{while (1){if (Key_state(VK_SPACE))return;Sleep(1000);}
}
void kill_self(pSnake snake1,pSnake snake2)
{pSnakeNode p1 = snake1->_snake->next;pSnakeNode p2 = snake2->_snake->next;if (snake1->_snake->x == snake2->_snake->x && snake1->_snake->y == snake2->_snake->y){snake1->sta = by_headpush;snake2->sta = by_headpush;return;}while (p1&&p2){if (snake1->_snake->x == p2->x && snake1->_snake->y == p2->y){snake1->sta = by_body;return;}if (snake1->_snake->x == p1->x && snake1->_snake->y == p1->y){snake1->sta = by_self;return;}p1 = p1->next;p2 = p2->next;}
}
void snakemove(pSnake snake1,pSnake snake2)
{pSnakeNode i = (pSnakeNode)malloc(sizeof(SnakeNode));assert(i);i->next = snake1->_snake;if (snake1->dir == up){i->x = snake1->_snake->x;i->y = snake1->_snake->y - 1;}else if (snake1->dir == down){i->x = snake1->_snake->x;i->y = snake1->_snake->y + 1;}else if (snake1->dir == left){i->x = snake1->_snake->x - 2;i->y = snake1->_snake->y;}else if (snake1->dir == right){i->x = snake1->_snake->x + 2;i->y = snake1->_snake->y;}else if (snake1->sta == by_end){return;}snake1->_snake = i;pSnakeNode p = snake1->_snake;if ((i->x == snake1->_food->x && i->y == snake1->_food->y)|| (i->x == snake2->_food->x && i->y == snake2->_food->y)){(snake1->_score) += snake1->_weight;creatfood(snake1,snake2);}else{pSnakeNode pre = NULL;while (p->next != NULL){pre = p;p = p->next;}pre->next = NULL;setpos(p->x, p->y);printf("  ");free(p);}if (snake1->_snake->x == 0 || snake1->_snake->x == 56 || snake1->_snake->y == 0 || snake1->_snake->y == 25){snake1->sta = by_wall;return;}kill_self(snake1,snake2);p = i;while (p){setpos(p->x, p->y);wprintf(L"%c", Body);p = p->next;}
}
void gamestart(pSnake snake1,pSnake snake2)
{assert(snake1&&snake2);welcome();creatmap();initsnake(snake1);initsnake(snake2);creatsnake(snake1,snake2);creatfood(snake1,snake2);creatfood(snake2, snake1);gameinfo(snake1,snake2);
}
void gamerun(pSnake snake1,pSnake snake2)
{do {if (Key_state(0x57) && snake1->dir != down){snake1->dir = up;}else if (Key_state(0x53) && snake1->dir != up){snake1->dir = down;}else if (Key_state(0x41) && snake1->dir != right){snake1->dir = left;}else if (Key_state(0x44) && snake1->dir != left){snake1->dir = right;}else if (Key_state(VK_SPACE)){pause();}else if (Key_state(VK_ESCAPE)){snake1->sta = by_end;snake2->sta = by_end;}else if (Key_state(VK_F1)){if (snake1->_sleeptime >= 80){(snake1->_sleeptime) -= 20;(snake1->_weight) += 2;}setpos(70, 7);printf("奖励:%d", snake1->_weight);if (snake2->_sleeptime >= 80){(snake2->_sleeptime) -= 20;(snake2->_weight) += 2;}setpos(70, 11);printf("奖励:%d", snake2->_weight);}else if (Key_state(VK_F2)){if (snake1->_sleeptime <= 280){(snake1->_sleeptime) += 20;(snake1->_weight) -= 2;}setpos(70, 7);printf("奖励:%d", snake1->_weight);if (snake2->_sleeptime <= 280){(snake2->_sleeptime) += 20;(snake2->_weight) -= 2;}setpos(70, 11);printf("奖励:%d", snake2->_weight);}else if (Key_state(VK_UP) && snake2->dir != down){snake2->dir = up;}else if (Key_state(VK_DOWN) && snake2->dir != up){snake2->dir = down;}else if (Key_state(VK_LEFT) && snake2->dir != right){snake2->dir = left;}else if (Key_state(VK_RIGHT) && snake2->dir != left){snake2->dir = right;}snakemove(snake1,snake2);snakemove(snake2, snake1);setpos(70, 6);printf("分数:%d", snake1->_score);setpos(70, 7);printf("奖励:%d", snake1->_weight);setpos(70, 10);printf("分数:%d", snake2->_score);setpos(70, 11);printf("奖励:%d", snake2->_weight);Sleep(snake1->_sleeptime);} while (snake1->sta == ok&&snake2->sta==ok);
}
void gameend(pSnake snake1,pSnake snake2)
{/*if (snake1->sta == by_end){system("cls");setpos(48, 15);printf("游戏结束!");setpos(42, 22);system("pause");}else*/if (snake1->sta != snake2->sta){if (snake1->sta == by_body){system("cls");setpos(42, 15);printf("玩家1咬到对方蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_wall){system("cls");setpos(38, 15);printf("玩家1撞到墙了,游戏结束!");setpos(40, 22);system("pause");}/*else if (snake2->sta == by_end){system("cls");setpos(48, 15);printf("游戏结束!");setpos(42, 22);system("pause");}*/else if (snake2->sta == by_body){system("cls");setpos(34, 15);printf("玩家2咬到对方蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake2->sta == by_wall){system("cls");setpos(34, 15);printf("玩家2撞到墙了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_self){system("cls");setpos(34, 15);printf("玩家1咬到自己蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake2->sta == by_self){system("cls");setpos(34, 15);printf("玩家2咬到自己蛇身了,游戏结束!");setpos(40, 22);system("pause");}}else{if (snake1->sta == by_end){system("cls");setpos(48, 15);printf("游戏结束!");setpos(42, 22);system("pause");}else if (snake1->sta == by_body){system("cls");setpos(34, 15);printf("玩家1和玩家2都咬到对方蛇身了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_wall){system("cls");setpos(34, 15);printf("玩家1和玩家2撞到墙了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_headpush){system("cls");setpos(34, 15);printf("两位玩家相撞了,游戏结束!");setpos(40, 22);system("pause");}else if (snake1->sta == by_self){system("cls");setpos(34, 15);printf("玩家1和玩家2都咬到自己蛇身了,游戏结束!");setpos(40, 22);system("pause");}}free(snake1->_food);pSnakeNode p = snake1->_snake;pSnakeNode pre = NULL;while (p){pre = p;p = p->next;pre->next = NULL;free(pre);}free(snake1);free(snake2->_food);p = snake2->_snake;pre = NULL;while (p){pre = p;p = p->next;pre->next = NULL;free(pre);}free(snake2);
}

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

139GB,台北倾斜摄影OSGB数据V0.1版

本月初发布了谷歌倾斜摄影数据OSGB转换工具V0.2版(更新&#xff01;谷歌倾斜摄影转换生成OSGB瓦片V0.2版),并免费分享了基于V0.2版转换工具生产的澳门地区OSGB数据(首发&#xff01;澳门地区OSGB数据V0.2版免费分享),V0.2版本在生产速度、显示效率和OSGB数据轻量化方面进行了优…

NVIDIA Jetson jtop查看资源信息

sudo -H pip install -U jetson-stats 安装好之后可能需要reboot 执行jtop&#xff1a; 时间久了可能会退出&#xff0c;可参考如下再次启动。 nvidiategra-ubuntu:~$ jtop The jtop.service is not active. Please run: sudo systemctl restart jtop.service nvidiategra-ub…

修改docker镜像版本,容器大小缩小10%!

shigen坚持更新文章的博客写手&#xff0c;擅长Java、python、vue、shell等编程语言和各种应用程序、脚本的开发。记录成长&#xff0c;分享认知&#xff0c;留住感动。 个人IP&#xff1a;shigen 是的&#xff0c;你看的没错&#xff1a;修改docker镜像的版本&#xff0c;我的…

最新知识付费小程序源码独立版 支持多终端合一+源码开源可二开+含完整代码包和安装教程

在当今信息爆炸的时代&#xff0c;知识付费逐渐成为了一种新型的商业模式。为了满足广大开发者和运营者的需求&#xff0c;分享一个最新版的知识付费小程序源码独立版。该版本不仅支持多终端合一&#xff0c;还具备源码开源可二开的特性&#xff0c;同时提供了完整的代码包和安…

【性能测试】ChaosTesting(混沌测试)ChaosBlade(混沌实验工具)(六)-servelt

7. servelt接口规范 7.0 创建servelt blade create servlet 7.0.1 介绍 Servlet 是 Java 的 web 的接口规范&#xff0c;Java web 服务器都遵循此规范实现。本场景主要模拟 Java Web 请求延迟、异常场景。 [blade create servlet delay](blade create servlet delay.md) 请…

网页自动跳转到其他页面,点击浏览器返回箭头,回不到原来页面的问题

背景&#xff1a;今天产品提个需求&#xff0c;需要从index页面自动触发跳转到下一页面的事件&#xff0c;从而不做任何操作&#xff0c;直接跳转到test页面。 代码是这样的&#xff1a; index.vue: <template><div style"width:500px;height:600px;background-…

WIFISKY 7层流控路由器 confirm.php RCE漏洞复现

0x01 产品简介 WIFISKY-7层流控路由器是一款可用于家庭或办公环境的无线路由器,具备流控功能以优化网络流量和提供更稳定的网络连接。该路由器采用了7层流控技术,能够依据网络数据包的内容进行智能管理,从而实现对网络流量的精细化控制和优化。这种技术可以提升网络的整体性…

Science Robotics 美国斯坦福大学研制了外行星洞穴探测机器人

月球和火星上的悬崖、洞穴和熔岩管已被确定为具有地质和天体生物学研究理想地点。由于其隔绝特性&#xff0c;这些洞穴提供了相对稳定的条件&#xff0c;可以促进矿物质沉淀和微生物生长。在火星上&#xff0c;这些古老的地下环境与火星表面可能适合居住时几乎没有变化&#xf…

孙中亮:北斗三十周年,看北斗芯片高质量发展历程和方向

1994年1月10日&#xff0c;北斗一号建设正式启动&#xff0c;党中央决策建设独立自主的北斗卫星导航系统。2020年7月31日&#xff0c;北斗三号全球卫星导航系统正式开通&#xff0c;标志着北斗系统进入全球化发展新阶段。随着2024年的到来&#xff0c;北斗系统建设已走过栉风沐…

上位机图像处理和嵌入式模块部署(树莓派4b与视觉slam十四讲)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 实际使用中&#xff0c;树莓派4b是非常好的一个基础平台。本身板子价格也不是很贵&#xff0c;建议大家多多使用。之前关于vslam&#xff0c;也就是…

ChatGPT实战100例 - (18) 用事件风暴玩转DDD

文章目录 ChatGPT实战100例 - (18) 用事件风暴玩转DDD一、标准流程二、定义目标和范围三、准备工具和环境四、列举业务事件五、 组织和排序事件六、确定聚合并引入命令七、明确界限上下文八、识别领域事件和领域服务九、验证和修正模型十、生成并验证软件设计十一、总结 ChatGP…

力扣HOT100 - 108. 将有序数组转换为二叉搜索树

解题思路&#xff1a; 二叉搜索树一般使用中序遍历 class Solution {public TreeNode sortedArrayToBST(int[] nums) {return helper(nums,0,nums.length-1);}public TreeNode helper(int[] nums,int left,int right){if(left>right) return null;//确定根节点//总是选择中…

2024年阿里云域名注册活动,com域名1元起,cn域名33元起

随着互联网的飞速发展&#xff0c;一个好的域名已经成为了企业或个人在线身份的重要标志。注册域名是很多用户开启互联网业务的第一步&#xff0c;2024年很多注册商现在com域名注册都快逼近80元了。作为国内最大的域名注册商与云服务商&#xff0c;近日&#xff0c;阿里云推出了…

提升你的C编程技能:使用cURL下载Kwai视频

概述 本文将介绍如何利用C语言以及cURL库来实现Kwai视频的下载。cURL作为一个功能强大的网络传输工具&#xff0c;能够在C语言环境下轻松地实现数据的传输。我们还将探讨如何运用代理IP技术&#xff0c;提升爬虫的匿名性和效率&#xff0c;以适应Kwai视频平台的发展趋势。 正…

Java web应用性能分析之【Linux服务器性能监控分析概叙】

大多数场景&#xff0c;我们的Java web应用都是部署在linux环境&#xff0c;所以对linux服务器的性能指标需要有一个比较清晰的认识。Linux服务器的性能指标无非就5个方面&#xff1a;CPU、内存、磁盘、网络、文件系统。不同的性能指标都有对应的命令进行监控和查看&#xff08…

【前端面试常问】什么是前端工程化

&#x1f31f;【前端面试常问】前端工程化&#x1f31f; &#x1f4da; 什么是前端工程化&#xff1f; &#x1f389; 前端工程化&#xff0c;简而言之&#xff0c;是通过整合先进的工具链和最佳实践&#xff0c;将前端开发过程实现标准化、自动化和高效化的过程&#xff0c;…

美森快船和以星快船有什么区别?美线海运都有哪些快船?

在繁忙的国际海运市场中&#xff0c;快船服务以其高效、快捷的特点受到广大货主的青睐。其中&#xff0c;美森快船和以星快船作为知名的海运服务提供商&#xff0c;凭借着卓越的服务品质&#xff0c;在航运界树立了良好的口碑。那么&#xff0c;美森快船和以星快船究竟有何不同…

探讨自回归模型和扩散模型的发展应用

在当前大模型驱动的内容创新浪潮中&#xff0c;人工智能产业正以前所未有的力度拥抱一场由大模型技术策动的科技革新运动。这场革命不仅重塑了人机交互的边界&#xff0c;使其跃升至更高层次的认知协作&#xff0c;而且正在颠覆传统的计算思维与执行模式&#xff0c;催生出全新…

SpringCloud引入SpringBoot Admin

Spring Boot Admin可以监控和管理Spring Boot&#xff0c;能够将 Actuator 中的信息进行界面化的展示&#xff0c;也可以监控所有 Spring Boot 应用的健康状况&#xff0c;提供警报功能。 1. 创建SpringBoot工程 2. 引入相关依赖 <dependency><groupId>com.alib…

安全小课堂丨什么是暴力破解?如何防止暴力破解

什么是暴力破解&#xff1f; 暴力破解也可称为穷举法、枚举法&#xff0c;是一种比较流行的密码破译方法&#xff0c;也就是将密码进行一一推算直到找出正确的密码为止。比如一个6位并且全部由数字组成的密码&#xff0c;可能有100万种组合&#xff0c;也就是说最多需要尝试10…