C语言贪吃蛇(可在头文件中添加食物,选择撞墙是否会死)

2024-04-19 23:52

本文主要是介绍C语言贪吃蛇(可在头文件中添加食物,选择撞墙是否会死),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 项目目标

项目为控制台程序,在控制台上实现。

1. 实现游戏开始界面,让用户选择模式(撞墙/循环)等;

2. 实现地图的绘制;

3. 实现贪吃蛇,并使其根据用户的命令移动;

4. 实现食物的随机刷新,并为每一种食物设置分值;

5. 在游戏过程中打印适当的提示信息以及实时信息的刷新;

6. 实现贪吃蛇的变长;

7. 实时检测游戏状态(正常/撞墙/撞到自己);

2. 所需知识

C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。

这些知识,想必大家在学习C语言的过程中已经熟练到出神入化了,但是对于Win32 API可能会感到有点陌生。

接下来我们重点介绍一下Win32 API。

2.1 WIn32 API

Windows 这个多作业系统除了协调应用程序的执行、分配内存、管理资源之外, 它同时也是一个很大的服务中心,调用这个服务中心的各种服务(每⼀种服务就是⼀个函数),可以帮应用程序达到开启视窗、描绘图形、使用周边设备等目的,由于这些函数服务的对象是应用程序(Application), 所以便称之为 Application Programming Interface,简称 API 函数。

Win32 API也就是Microsoft Windows 32位平台的应用程序编程接口。

利用Win32 API提供的函数,我们就可以比较方便地在控制台上进行信息的打印,地图的绘制等。

以下为这个项目需要用到的一些API函数。


2.1.1 GetStdHandle 函数 - Windows Console | Microsoft Learn

HANDLE GetStdHandle(DWORD nStdHandle);

GetStdHandle是⼀个Windows API函数。它用于从⼀个特定的标准设备(标准输入、标准输出或标准错误)中取得⼀个句柄(用来标识不同设备的数值,类型为HANDLE),使用这个句柄可以操作设备。

句柄其实就类似于FILE*指针:当你需要对某个文件进行操作时,你需要将对应的文件指针传入对应的函数;当你需要对某个设备进行操作时,你需要将对应的句柄传入对应的函数。

他的参数有以下三个:

含义
STD_INPUT_HANDLE标准输入设备
STD_OUTPUT_HANDLE标准输出设备
STD_ERROR_HANDLE标准错误设备

 

控制台的屏幕属于标准输出设备,所以在该项目中我们在使用这个函数时传入的都是STD_OUTPUT_HANDLE,然后定义一个HANDLE类型的变量来接收其返回的句柄即可。

例如:

HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);

 2.1.2 GetConsoleCursorInfo 函数 - Windows Console | Microsoft Learn

BOOL WINAPI GetConsoleCursorInfo(HANDLE hConsoleOutput,PCONSOLE_CURSOR_INFO lpConsoleCursorInfo
);

GetConsoleCursorInfo函数用于检索有关指定控制台屏幕缓冲区的光标大小和可见性的信息 。

它的第一个参数为标准输出设备的句柄,第二个参数为一个指向 CONSOLE_CURSOR_INFO(CONSOLE_CURSOR_INFO 结构 - Windows Console | Microsoft Learn) 结构的指针,该结构接收有关控制台游标的信息。

CONSOLE_CURSOR_INFO结构的定义如下

typedef struct _CONSOLE_CURSOR_INFO {DWORD dwSize;BOOL bVisible;
} CONSOLE_CURSOR_INFO, *PCONSOLE_CURSOR_INFO;

• dwSize:表示光标填充的字符单元格的百分比, 此值介于1到100之间。

                  光标外观会变化,范围从完全填充单元格到单元底部的水平线条。

• bVisible:表示光标的可见性。 如果光标可见,则此成员为 TRUE。

在使用时,我们需要先定义一个CONSOLE_CURSOR_INFO类型的变量,然后将其传入函数中。

此时,这个变量中就存储了当前光标的大小和可见性信息,我们可以通过访问这个结构体变量的成员来修改光标的参数。

例如:

HANDLE hOutput = NULL;
//获取标准输出的句柄(⽤来标识不同设备的数值)
hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息

但是,该变量只是获得了一个备份并将其储存,并没有直接与光标建立联系。

要使修改后的参数得到应用,我们还需要调用GetConsoleCursorInfo函数。


2.1.3 SetConsoleCursorInfo 函数 - Windows Console | Microsoft Learn

BOOL WINAPI SetConsoleCursorInfo(HANDLE hConsoleOutput,const CONSOLE_CURSOR_INFO *lpConsoleCursorInfo
);

SetConsoleCursorInfo函数用于设置光标的参数,本质上就是让刚才获得的CONSOLE_CURSOR_INFO类型的变量存储的信息得到应用。

它的参数与GetConsoleCursorInfo函数一模一样,只需要在设置完光标参数之后,将变量再统统扔给它即可。

例如:

HANDLE hOutput = GetStdHandle(STD_OUTPUT_HANDLE);
//影藏光标操作
CONSOLE_CURSOR_INFO CursorInfo;
GetConsoleCursorInfo(hOutput, &CursorInfo);//获取控制台光标信息
CursorInfo.bVisible = false; //隐藏控制台光标
SetConsoleCursorInfo(hOutput, &CursorInfo);//设置控制台光标状态

 2.1.4 SetConsoleCursorPosition 函数 - Windows Console | Microsoft Learn

BOOL WINAPI SetConsoleCursorPosition(HANDLE hConsoleOutput,COORD pos
);

SetConsoleCursorPosition函数用于设置指定控制台屏幕缓冲区中的光标位置,我们将想要设置的坐标信息放在COORD(COORD 结构 - Windows Console | Microsoft Learn)类型的pos中,调用SetConsoleCursorPosition函数将光标位置设置到指定的位置。

COORD结构体的定义如下:

typedef struct _COORD {SHORT X;SHORT Y;
} COORD, *PCOORD;

COORD 是Windows API中定义的一个结构体,表示一个字符在控制台屏幕幕缓冲区上的坐标,坐标系 (0,0) 的原点位于缓冲区的顶部左侧单元格。

水平向右为x轴正方向,竖直向下为y轴正方向。

y轴的单位长度(一个中文字符的高度/宽度)是x轴单位长度的两倍。

例如: 

COORD pos = { 10, 5};HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput, pos);

这段代码就是将光标的位置设置到(10,5)的位置。

由于在项目中,无论是绘制地图,打印蛇,打印食物还是在指定位置打印信息都需要设置光标位置,所以我们将设置光标位置的功能封装为了一个函数SetPos。

//设置光标的坐标
void SetPos(short x, short y)
{COORD pos = { x, y };HANDLE hOutput = NULL;//获取标准输出的句柄(⽤来标识不同设备的数值)hOutput = GetStdHandle(STD_OUTPUT_HANDLE);//设置标准输出上光标的位置为posSetConsoleCursorPosition(hOutput, pos);
}

2.1.5 getAsyncKeyState 函数 (winuser.h) - Win32 apps | Microsoft Learn

SHORT GetAsyncKeyState(int vKey
);

GetAsyncKeyState函数用于获取按键的状态。

将键盘上每个键的虚拟键值传递给函数,函数通过返回值来分辨按键的状态。

虚拟键码 (Winuser.h) - Win32 apps | Microsoft Learn 

GetAsyncKeyState 的返回值是short类型,在上一次调用 GetAsyncKeyState 函数后,如果返回的16位的short数据中:

• 最高位是1,说明按键的状态是按下,如果最高是0,说明按键的状态是抬 起。

• 如果最低位被置为1则说明,该按键被按过,否则为0。

如果我们要判断一个键是否被按过,可以检测GetAsyncKeyState返回值的最低值是否为1.

为了使用方便,我们定义了下面这个宏:

#define KEY_PRESS(VK) ( (GetAsyncKeyState(VK) & 0x1) ? 1 : 0 )

2.2 C语言的国际化特性

如果你需要用一些中文的宽字符来表示表示墙体,蛇,食物的话,就需要用到这个知识。

例如:打印墙体使用宽字符:□,打印蛇使用宽字符●,打印食物使用宽字符★

具体的细节,如果感兴趣的话可以自己去了解,在该项目中,你只需要知道setlocale函数即可。

setlocale - C++ Reference

char* setlocale (int category, const char* locale);

要使程序能够打印这些宽字符,只需要下面这个语句即可:

setlocal(LC_ALL, "");

3. 项目实现

3.1 Snake.h

这里我没有使用宽字符来表示墙,蛇,和食物,而是直接使用的汉字,目的是为了方便读者分辨定义的符号是什么意思。

要增加食物数量或种类的话,将FOOD_MAX的值修改之后,在FOOD_SHAPES和FOOD_WEIGHTS中分别添加其符号和分值即可。

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <locale.h>
#include <time.h>
#include <stdbool.h>#define WALL L'墙'
#define BODY L'蛇'#define FOOD_MAX 3//食物种数#define FOOD_SHAPES {L'史', L'蕉', L'苹'}//食物外形列表
#define FOOD_WEIGHTS {1145, 10, 20}//食物分值列表#define ORIGIN_LEN 5
#define ORIGIN_X 24
#define ORIGIN_Y 5
#define KEY_PRESS(vk) ((GetAsyncKeyState(vk) & 0x1) ? 1 : 0)//类型定义
enum DIRECTIONS//方向
{UP,//上DOWN,//下LEFT,//左RIGHT//右
};enum STATUS//游戏状态
{NORMAL,//正常END_NORMAL,//正常退出END_WALL,//撞墙结束END_SELF//撞到自己结束
};//蛇身结点
typedef struct SnakeNode
{int x;int y;struct SnakeNode* next;
}SnakeNode, *pSnakeNode;//食物结点
typedef struct Food
{int x;int y;int weight;WCHAR shape;
}Food, *pFood;//贪吃蛇游戏
typedef struct Snake
{pSnakeNode pSnakeHead;//蛇头Food Recipe[FOOD_MAX];//食物清单enum DIRECTIONS Direction;//运动方向enum STATUS Status;//游戏状态int Score;//总分数int SleepTime;//睡眠时间int Attached;//附加分数
}Snake, *pSnake;//函数定义//设置光标位置
void SetPos(int x, int y);//游戏开始
int GameBegin(pSnake ps);
//欢迎界面
int WelComeToGame();
//创建地图26/58
void CreatMap();
//初始化贪吃蛇
void InitSnake(pSnake ps);
//初始化食物
void InitRecipe(pSnake ps);//游戏运行
void GameRun(pSnake ps, int flag);
//打印提示信息
void PrintHelpInfo();
//打印实时信息
void PrintTimelyInfo(pSnake ps);
//暂停
void Pause(pSnake ps);
//蛇行
void SnakeMove(pSnake ps, int flag);
//是否即将触碰食物
int IsTouchingFood(pSnakeNode pn, pSnake ps);
//没吃到食物
void NoFood(pSnake ps);
//改变某食物坐标
void FoodPosModify(pSnake ps, int pos);
//检测是否撞墙
void TouchingWall(pSnakeNode pn, pSnake ps, int flag);
//检测是否撞到自己
void TouchingSelf(pSnakeNode pn, pSnake ps);//游戏结束
void GameEnd(pSnake ps);

3.2 Snake.c

#define _CRT_SECURE_NO_WARNINGS
#include "Snake.h"
//设置光标位置
void SetPos(int x, int y)
{HANDLE HandOutPut = GetStdHandle(STD_OUTPUT_HANDLE);COORD pos = { x, y };SetConsoleCursorPosition(HandOutPut, pos);
}//欢迎界面
int WelComeToGame()
{SetPos(45, 14);wprintf(L"%ls", L"欢迎来到贪吃蛇小游戏");SetPos(45, 16);wprintf(L"%ls", L"1.撞墙模式(撞墙会死)");SetPos(45, 17);wprintf(L"%ls", L"2.循环模式(撞墙不会死)");int choice = 0;SetPos(43, 16);printf(">");do{if (KEY_PRESS(VK_UP))//撞墙模式{SetPos(43, 16);printf(">");SetPos(43, 17);printf(" ");choice = 0;}else if (KEY_PRESS(VK_DOWN))//循环模式{SetPos(43, 17);printf(">");SetPos(43, 16);printf(" ");choice = 1;}else if (KEY_PRESS(VK_RETURN)){break;}} while (1);SetPos(45, 25);system("pause");system("cls");SetPos(37, 14);wprintf(L"用上下左右来控制蛇的移动,按F3加速,按F4减速\n");SetPos(48, 15);wprintf(L"加速能获得更高的分数\n");SetPos(48, 17);system("pause");system("cls");return choice;
}//创建地图26/58
void CreatMap()
{int i = 0;//上for (i = 0; i < 29; i++){wprintf(L"%lc", WALL);}//下SetPos(0, 26);for (i = 0; i < 29; i++){wprintf(L"%lc", WALL);}//左右for (i = 1; i < 26; i++){SetPos(0, i);wprintf(L"%lc", WALL);SetPos(56, i);wprintf(L"%lc", WALL);}
}//初始化贪吃蛇
void InitSnake(pSnake ps)
{//初始化贪吃蛇属性ps->pSnakeHead = NULL;ps->Direction = RIGHT;ps->Score = 0;ps->Status = NORMAL;ps->SleepTime = 200;ps->Attached = 0;//创建蛇pSnakeNode cur = NULL;for (int i = 0; i < ORIGIN_LEN; i++){cur = (pSnakeNode)malloc(sizeof(SnakeNode));if (cur == NULL){perror("InitSnake::malloc");return;}cur->next = NULL;cur->x = ORIGIN_X + 2 * i;cur->y = ORIGIN_Y;//头插cur->next = ps->pSnakeHead;ps->pSnakeHead = cur;}//打印蛇cur = ps->pSnakeHead;while (cur){SetPos(cur->x, cur->y);wprintf(L"%lc", BODY);cur = cur->next;}}//获取合法的食物坐标
void GetPos(pSnake ps, int* x, int* y)
{again:do{*x = rand() % 54 + 2;*y = rand() % 25 + 1;} while (*x % 2 != 0);pSnakeNode cur = ps->pSnakeHead;while (cur){if (cur->x == *x && cur->y == *y)goto again;cur = cur->next;}for (int i = 0; i < FOOD_MAX; i++){if (ps->Recipe[i].x == *x && ps->Recipe[i].y == *y)goto again;}
}//初始化食物
void InitRecipe(pSnake ps)
{int x = 0;int y = 0;WCHAR shapes[FOOD_MAX] = FOOD_SHAPES;int weights[FOOD_MAX] = FOOD_WEIGHTS;for (int i = 0; i < FOOD_MAX; i++){GetPos(ps, &x, &y);ps->Recipe[i].x = x;ps->Recipe[i].y = y;ps->Recipe[i].shape = shapes[i];ps->Recipe[i].weight = weights[i];SetPos(x, y);wprintf(L"%lc", ps->Recipe[i].shape);}
}//游戏开始
int GameBegin(pSnake ps)
{system("mode con cols=100 lines=30");system("title 贪吃蛇");//欢迎界面int flag = WelComeToGame();//创建地图27/58CreatMap();//初始化贪吃蛇InitSnake(ps);//初始化食物InitRecipe(ps);return flag;
}//打印提示信息
void PrintHelpInfo()
{SetPos(64, 16);wprintf(L"%ls", L"不能咬到自己");SetPos(64, 17);wprintf(L"%ls", L"用上下左右来控制蛇移动");SetPos(64, 18);wprintf(L"%ls", L"按F3加速,按F4减速");SetPos(64, 19);wprintf(L"%ls", L"按ESC退出游戏,按空格暂停游戏");
}//打印实时信息
void PrintTimelyInfo(pSnake ps)
{SetPos(64, 9);printf("总分数:%d\n", ps->Score);for (int i = 0; i < FOOD_MAX; i++){SetPos(64, 11 + i);wprintf(L"%lc", ps->Recipe[i].shape);printf("的分数为:%d", ps->Recipe[i].weight);}SetPos(64, 11 + FOOD_MAX);printf("附加分数为:%d", ps->Attached);
}//暂停
void Pause(pSnake ps)
{while (1){Sleep(200);if (KEY_PRESS(VK_SPACE)){break;}if (KEY_PRESS(VK_ESCAPE)){ps->Status = END_NORMAL;break;}}
}//是否即将触碰食物(是,则返回食物下标;否,则返回-1)
int IsTouchingFood(pSnakeNode pn, pSnake ps)
{for (int i = 0; i < FOOD_MAX; i++){if (pn->x == ps->Recipe[i].x && pn->y == ps->Recipe[i].y)return i;}return -1;
}//没吃到食物
void NoFood(pSnake ps)
{pSnakeNode cur = ps->pSnakeHead;while (cur->next->next){cur = cur->next;}SetPos(cur->next->x, cur->next->y);printf("  ");free(cur->next);cur->next = NULL;
}//改变某食物坐标
void FoodPosModify(pSnake ps, int pos)
{int x = 0;int y = 0;GetPos(ps, &x, &y);ps->Recipe[pos].x = x;ps->Recipe[pos].y = y;SetPos(x, y);wprintf(L"%lc", ps->Recipe[pos].shape);
}//检测是否撞墙
void TouchingWall(pSnakeNode pn, pSnake ps, int flag)
{if (flag == 1){if (pn->x == 0){pn->x = 54;}if (pn->x == 56){pn->x = 2;}if (pn->y == 26){pn->y = 1;}if (pn->y == 0){pn->y = 25;}}else{if (pn->x == 0 || pn->x == 56 || pn->y == 26 || pn->y == 0){ps->Status = END_WALL;}}
}//检测是否撞到自己
void TouchingSelf(pSnakeNode pn, pSnake ps)
{pSnakeNode cur = ps->pSnakeHead;while (cur){if (cur->x == pn->x && cur->y == pn->y){ps->Status = END_SELF;return;}cur = cur->next;}
}//蛇行
void SnakeMove(pSnake ps, int flag)
{pSnakeNode newhead = (pSnakeNode)malloc(sizeof(SnakeNode));if (newhead == NULL){perror("SnakeMove::malloc");return;}switch (ps->Direction){case UP:newhead->x = ps->pSnakeHead->x;newhead->y = ps->pSnakeHead->y - 1;break;case DOWN:newhead->x = ps->pSnakeHead->x;newhead->y = ps->pSnakeHead->y + 1;break;case LEFT:newhead->x = ps->pSnakeHead->x - 2;newhead->y = ps->pSnakeHead->y;break;case RIGHT:newhead->x = ps->pSnakeHead->x + 2;newhead->y = ps->pSnakeHead->y;break;}//检测是否撞墙TouchingWall(newhead, ps, flag);//检测是否撞到自己TouchingSelf(newhead, ps);newhead->next = ps->pSnakeHead;ps->pSnakeHead = newhead;SetPos(newhead->x, newhead->y);wprintf(L"%lc", BODY);//判断是否即将碰到食物int judge = IsTouchingFood(newhead, ps);if (judge == -1){//还没吃到食物,删掉最后一个结点NoFood(ps);}else{//修改某食物坐标FoodPosModify(ps, judge);ps->Score += ps->Recipe[judge].weight + ps->Attached;}}//游戏运行
void GameRun(pSnake ps, int flag)
{//打印提示信息PrintHelpInfo(ps);do{//打印实时信息PrintTimelyInfo(ps);//检测按键if (KEY_PRESS(VK_UP) && ps->Direction != DOWN){ps->Direction = UP;}else if (KEY_PRESS(VK_DOWN) && ps->Direction != UP){ps->Direction = DOWN;}else if (KEY_PRESS(VK_LEFT) && ps->Direction != RIGHT){ps->Direction = LEFT;}else if (KEY_PRESS(VK_RIGHT) && ps->Direction != LEFT){ps->Direction = RIGHT;}else if (KEY_PRESS(VK_SPACE)){//暂停Pause(ps);}else if (KEY_PRESS(VK_ESCAPE)){ps->Status = END_NORMAL;}else if (KEY_PRESS(VK_F3)){//加速if (ps->SleepTime > 80){ps->SleepTime -= 30;ps->Attached += 2;}}else if (KEY_PRESS(VK_F4)){//减速if (ps->SleepTime < 320){ps->SleepTime += 30;ps->Attached -= 2;}}SnakeMove(ps, flag);Sleep(ps->SleepTime);} while (ps->Status == NORMAL);
}
//游戏结束
void GameEnd(pSnake ps)
{SetPos(24, 12);switch (ps->Status){case END_NORMAL:printf("退出游戏!\n");break;case END_WALL:printf("撞墙啦牢底!\n");break;case END_SELF:printf("紫砂啦牢底!\n");break;}SetPos(24, 13);//释放蛇身链表pSnakeNode cur = ps->pSnakeHead;while (cur){pSnakeNode del = cur;cur = cur->next;free(del);}
}

3.3 test.c

#define _CRT_SECURE_NO_WARNINGS
#include "Snake.h"void SnakeGame()
{Snake snake = { 0 };//光标隐藏HANDLE HandOutPut = GetStdHandle(STD_OUTPUT_HANDLE);CONSOLE_CURSOR_INFO CursorInfo;GetConsoleCursorInfo(HandOutPut, &CursorInfo);CursorInfo.bVisible = false;SetConsoleCursorInfo(HandOutPut, &CursorInfo);int ch = 0;do{fflush(stdin);//游戏开始int flag = GameBegin(&snake);//游戏运行GameRun(&snake, flag);//游戏结束GameEnd(&snake);printf("要再来一次吗(Y/N):");ch = getchar();while (getchar() != '\n');KEY_PRESS(VK_RETURN);} while (ch == 'Y' || ch == 'y');SetPos(0, 28);
}int main()
{setlocale(LC_ALL, "");srand((unsigned int)time(NULL));SnakeGame();return 0;
}

这篇关于C语言贪吃蛇(可在头文件中添加食物,选择撞墙是否会死)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/918782

相关文章

如何选择适合孤独症兄妹的学校?

在探索适合孤独症儿童教育的道路上,每一位家长都面临着前所未有的挑战与抉择。当这份责任落在拥有孤独症兄妹的家庭肩上时,选择一所能够同时满足两个孩子特殊需求的学校,更显得尤为关键。本文将探讨如何为这样的家庭做出明智的选择,并介绍星贝育园自闭症儿童寄宿制学校作为一个值得考虑的选项。 理解孤独症儿童的独特性 孤独症,这一复杂的神经发育障碍,影响着儿童的社交互动、沟通能力以及行为模式。对于拥有孤独症兄

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个?

跨平台系列 cross-plateform 跨平台应用程序-01-概览 cross-plateform 跨平台应用程序-02-有哪些主流技术栈? cross-plateform 跨平台应用程序-03-如果只选择一个框架,应该选择哪一个? cross-plateform 跨平台应用程序-04-React Native 介绍 cross-plateform 跨平台应用程序-05-Flutte

Codeforces Round #113 (Div. 2) B 判断多边形是否在凸包内

题目点击打开链接 凸多边形A, 多边形B, 判断B是否严格在A内。  注意AB有重点 。  将A,B上的点合在一起求凸包,如果凸包上的点是B的某个点,则B肯定不在A内。 或者说B上的某点在凸包的边上则也说明B不严格在A里面。 这个处理有个巧妙的方法,只需在求凸包的时候, <=  改成< 也就是说凸包一条边上的所有点都重复点都记录在凸包里面了。 另外不能去重点。 int

如何选择SDR无线图传方案

在开源软件定义无线电(SDR)领域,有几个项目提供了无线图传的解决方案。以下是一些开源SDR无线图传方案: 1. **OpenHD**:这是一个远程高清数字图像传输的开源解决方案,它使用SDR技术来实现高清视频的无线传输。OpenHD项目提供了一个完整的工具链,包括发射器和接收器的硬件设计以及相应的软件。 2. **USRP(Universal Software Radio Periphera

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX