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

【C语言】小游戏-三字棋

大家好,我是深鱼~


目录

一、游戏介绍

 二、文件分装

 三、代码实现步骤

1.制作简易游戏菜单

 2.初始化棋盘

3.打印棋盘

4.玩家下棋

5.电脑随机下棋

6.判断输赢

7.判断棋盘是否满了

 四、完整代码

game.h(相关函数的声明,整个代码要引用的头文件以及宏定义)

game.c(实现游戏的相关函数)

test.c(:整个游戏相关的测试)


一、游戏介绍

《三子棋》是一款古老的民间传统游戏,又被称为黑白棋、圈圈叉叉棋、井字棋、一条龙、九宫棋等。游戏分为双方对战,双方依次在9宫格棋盘上摆放棋子,率先将自己的三个棋子连成一条线的一方则视为胜利者


 二、文件分装

源文件:内含函数实现,变量定义等内容

头文件:内含函数声明、宏定义、结构体定义等内容 

实现这个三子棋,我创建了三个文件

源文件:

test.c:整个游戏相关的测试

game.c:实现游戏的相关函数

头文件:

game.h: 相关函数的声明,整个代码要引用的头文件以及宏定义


 三、代码实现步骤

1.制作简易游戏菜单

(1)定义一个menu函数来打印游戏菜单,菜单中需要有游戏菜单选项:1.开始游戏  0.退出游戏,当我们输入1就进入游戏,0就退出游戏

(2)考虑到玩家可能玩一局以后还想继续玩,就用do while循环打印菜单,while(input),当输入的值为0,就跳出循环(退出游戏),如果输入非0值就再次进入循环(再次选择)

(3)玩家选择了进入游戏还是退出游戏需要判断,就用switch case语句来进行判断

test.c

#include"game.h"
void menu()
{printf("*****************************************\n");printf("**********      1.开始游戏      *********\n");printf("**********      0.退出游戏      *********\n");printf("*****************************************\n");}int main()
{int input = 0;srand((unsigned int)time(NULL));do//实现玩多盘游戏{ menu();//打印菜单printf("请选择1/0:>\n");scanf("%d", &input);//选择进入游戏/退出游戏switch (input)//判断输入input的值决定是进入游戏还是退出游戏{case 1:game();//三子棋游戏的实现break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);//当input为0,跳出循环;为1再玩一盘游戏(重新进入循环);为其他值进入循环重新选择return 0;
}

考虑到game.c和test.c可能都要用printf函数的头文件#include<stdio.h>,我们直接把这个头文件写进game.h,那么test.c这个文件只需引用#inlclude"game.h"即可

系统头文件一般用<>

用户自己定义的则可以使用" ",加快搜索速度

效果展示:

选择1,进入game()

选择0,退出游戏:

选择非1非0(选择错误),重新选择 

 


 2.初始化棋盘

(1)首先我们需要定义一个二维数组来存放数据,可以采用宏定义

宏定义:方便程序的修改,如果我们要改变棋盘的大小,直接修改宏定义的数字即可

(2)初始化棋盘我们定义一个InitBoard(board)函数,将棋盘全部初始化为' '

game.h

//宏定义:
//为了方便直接改变棋盘的大小,在头文件里面定义(ROW和COL就是常量)
#define ROW 3 //没有逗号     //行
#define COL 3                //列//初始化数组为空格
void InitBoard(char board[ROW][COL]);

game.c

//初始化数组为空格
void InitBoard(char board[ROW][COL])
{for (int i = 0; i <ROW; i++){for (int j = 0; j <COL; j++){board[i][j] = ' ';//全部初始化为空格}}
}

3.打印棋盘

我们想打印这样打一个棋盘:用分隔线分开方便观察

(1)先打印数据(最后一个不用打印‘|’ )

(2)再打印分割行(最后一行不用打印)

game.h

//打印棋盘
void DisplayBoard(char board[ROW][COL]);

 game.c

//打印棋盘
void DisplayBoard(char board[ROW][COL])
{for (int i = 0; i < ROW; i++){//先打印数据for (int j = 0; j < COL; j++){printf(" %c ", board[i][j]);if(j<COL-1)//一行的最后一个不打印printf("|");}printf("\n");//再打印分割行(最后一行不打印)if (i < ROW - 1)//最后一行不打印{for (int j = 0; j < COL; j++){printf("---");if (j < COL - 1)//也是一行的最后一个不打印printf("|");}printf("\n");}}
}

4.玩家下棋

注意:

(1)玩家下棋输入坐标要在1-3(如果不在这个范围要重新输入),而不是数组下标的范围0-2,所以放入坐标是输入坐标分别-1得到的结果放入

(2)玩家下棋我们需要考虑坐标是否已经被占用

(3)字符的比较可以用==,既可用于常量也可用于变量比较

       字符串的比较要用strcmp函数,并且只能用于变量比较

game.h

//打印棋盘
void DisplayBoard(char board[ROW][COL]);

 game.c

//玩家下棋
void PlayerMove(char board[ROW][COL])
{int x = 0;int y = 0;printf("玩家下棋\n");while (1){printf("请输入要下棋的坐标:>\n");scanf("%d %d", &x, &y);if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//下棋的坐标必须在二维数组内部{if (board[x - 1][y - 1] == ' ')//1.输入的横纵坐标-1才是数组的下标  2.字符串的比较不能用==,但是这只是一个字符空格而已{board[x - 1][y - 1] = '*';break;}else{printf("该坐标已被占用,请输入其他坐标\n");}}else{printf("坐标非法,请重新输入\n");}}
}

5.电脑随机下棋

电脑随机下棋就需要随机生成两个随机数,但是这两个数要在棋盘范围内,那就对生成的随机数进行取模x = rand() % ROW;产生的数为0-(ROW-1),这个时候就不用-1了,因为电脑下棋不用我们自己输入,它就以数组的形式下棋就行

这里介绍三个函数

rand():

头文件:#include<stdlib.h>

这个函数返回的是0-rand max之间的值(0-32767)

在使用rand函数之前,我们要求调用srand函数,这样才能实现rand的功能

srand():

头文件:#include<stdlib.h>

要想生成一个随机数,还得给srand一个随机数(要想rand函数产生的随机数不同,就需要给srand函数输入一个不断改变的值(如果只给一个常数,那么rand给出的随机数就是同一个值,不会改变))

srand的参数需要是unsigned int(无符号整形)eg:srand((unsigned int)time(NULL));

time():

头文件:#include<time.h>

原理:时间戳:把不停在改变的时间转化为数字返回,从而给srand一个随机值

game.h

//电脑下棋
void ComputerMove(char board[ROW][COL]);

 game.c

//电脑随机下棋
void ComputerMove(char board[ROW][COL]) 
{int x = 0;int y = 0;printf("电脑下棋\n");while (1){x = rand() % ROW;//产生的数为0-(ROW-1)y = rand() % COL;if (board[x][y] == ' ')//如果这个位置已经有棋子了,再进入循环,重新生成x和y直到下了一个棋子为止{board[x][y] = '#';break;}}
}

6.判断输赢

判断输赢:设置四种结果:
玩家赢-返回*
电脑赢-#
平局-Q
游戏继续—C

game.h

//判断输赢
char IsWin(char board[ROW][COL]);

 game.c

//判断输赢:四种结果:
//玩家赢-返回*
//电脑赢-#
//平局-Q
//游戏继续—C
char IsWin(char board[ROW][COL])
{for (int i = 0; i < ROW; i++){if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')//注意要排除三个空格的情况return board[i][0];//谁的棋子连着三个就返回谁的棋子}for (int i = 0; i < COL; i++){if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')//注意要排除三个空格的情况return board[0][i];//谁的棋子连着三个就返回谁的棋子}if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ')return board[0][0];if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')return board[1][1];if (IsFull(board))return 'Q';//如果棋盘满了,就表示平局,返回Qreturn 'C';//否则就继续下棋}

7.判断棋盘是否满了

遍历二维数组,只要有一个空格就继续下棋(没满),如果都不是空格,那就是表示满了

game.h

//判断棋盘是否满了
int IsFull(char board[ROW][COL]);

 game.c

//判断棋盘是否是满的
static int IsFull(char board[ROW][COL])//staic表示只在这个game.c的文件中使用这个函数
{for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){if (board[i][j] == ' ')//只要有一个空格就继续进行return 0;}}return 1;//如果都不是空格,那就是表示全满
}

 四、完整代码

game.h(相关函数的声明,整个代码要引用的头文件以及宏定义)

//头文件:内含函数声明、宏定义、结构体定义等内容#include<stdio.h>
#include<time.h>
#include<stdlib.h>//宏定义:
//为了方便直接改变棋盘的大小,在头文件里面定义(ROW和COL就是常量)
#define ROW 3 //没有逗号     //行
#define COL 3                //列//函数声明:
//初始化数组为空格
void InitBoard(char board[ROW][COL]);//row和col为真实的行和列
//打印棋盘
void DisplayBoard(char board[ROW][COL]);
//玩家下棋
void PlayerMove(char board[ROW][COL]);
//电脑下棋
void ComputerMove(char board[ROW][COL]);
//判断输赢
char IsWin(char board[ROW][COL]);
//判断棋盘是否满了
int IsFull(char board[ROW][COL]);

game.c(实现游戏的相关函数)

//实现游戏相关的代码
#include"game.h"//这里也要包含自己定义的头文件,不然ROW和COL宏定义就不起作用了//初始化数组为空格
void InitBoard(char board[ROW][COL])
{for (int i = 0; i <ROW; i++){for (int j = 0; j <COL; j++){board[i][j] = ' ';//全部初始化为空格}}
}//打印棋盘
void DisplayBoard(char board[ROW][COL])
{for (int i = 0; i < ROW; i++){//先打印数据for (int j = 0; j < COL; j++){printf(" %c ", board[i][j]);if(j<COL-1)//一行的最后一个不打印printf("|");}printf("\n");//再打印分割行(最后一行不打印)if (i < ROW - 1)//最后一行不打印{for (int j = 0; j < COL; j++){printf("---");if (j < COL - 1)//也是一行的最后一个不打印printf("|");}printf("\n");}}
}//玩家下棋
void PlayerMove(char board[ROW][COL])
{int x = 0;int y = 0;printf("玩家下棋\n");while (1){printf("请输入要下棋的坐标:>\n");scanf("%d %d", &x, &y);if (x >= 1 && x <= ROW && y >= 1 && y <= COL)//下棋的坐标必须在二维数组内部{if (board[x - 1][y - 1] == ' ')//1.输入的横纵坐标-1才是数组的下标  2.字符串的比较不能用==,但是这只是一个字符空格而已{board[x - 1][y - 1] = '*';break;}else{printf("该坐标已被占用,请输入其他坐标\n");}}else{printf("坐标非法,请重新输入\n");}}
}//电脑随机下棋
void ComputerMove(char board[ROW][COL]) 
{int x = 0;int y = 0;printf("电脑下棋\n");while (1){x = rand() % ROW;//产生的数为0-(ROW-1)y = rand() % COL;if (board[x][y] == ' ')//如果这个位置已经有棋子了,再进入循环,重新生成x和y直到下了一个棋子为止{board[x][y] = '#';break;}}
}//判断棋盘是否是满的
static int IsFull(char board[ROW][COL])//staic表示只在这个game.c的文件中使用这个函数
{for (int i = 0; i < ROW; i++){for (int j = 0; j < COL; j++){if (board[i][j] == ' ')//只要有一个空格就继续进行return 0;}}return 1;//如果都不是空格,那就是表示全满
}//判断输赢:四种结果:
//玩家赢-返回*
//电脑赢-#
//平局-Q
//游戏继续—C
char IsWin(char board[ROW][COL])
{for (int i = 0; i < ROW; i++){if (board[i][0] == board[i][1] && board[i][0] == board[i][2] && board[i][0] != ' ')//注意要排除三个空格的情况return board[i][0];//谁的棋子连着三个就返回谁的棋子}for (int i = 0; i < COL; i++){if (board[0][i] == board[1][i] && board[0][i] == board[2][i] && board[0][i] != ' ')//注意要排除三个空格的情况return board[0][i];//谁的棋子连着三个就返回谁的棋子}if (board[0][0] == board[1][1] && board[0][0] == board[2][2] && board[0][0] != ' ')return board[0][0];if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ')return board[1][1];if (IsFull(board))return 'Q';//如果棋盘满了,就表示平局,返回Qreturn 'C';//否则就继续下棋}

test.c(:整个游戏相关的测试)

game函数的逻辑:

(1)初始化数组,并打印出来看看什么样子

(2)开始下棋,玩家先下,下完进行打印,打印完进行判断输赢,如果不是游戏继续,就直接跳出循环,输出游戏结果(玩家赢/电脑赢/平局)

(3)电脑下棋下棋的逻辑一样 

//源文件,内含函数实现,变量定义等内容#include"game.h"//系统头文件一般用<>;用户自己定义的则可以使用""
//整个游戏相关的测试
void menu()
{printf("*****************************************\n");printf("**********      1.开始游戏      *********\n");printf("**********      0.退出游戏      *********\n");printf("*****************************************\n");}void game()
{char ret = 0;char board[ROW][COL];//开始的时候,数组的内容应该全是空格InitBoard(board);//用于初始化数组为空格DisplayBoard(board);//用于打印棋盘//下棋while (1){PlayerMove(board);//玩家下棋放*DisplayBoard(board);//判断输赢ret=IsWin(board);if (ret != 'C'){break;//不是游戏继续就跳出循环,输出结果}ComputerMove(board);//电脑随机下棋放#DisplayBoard(board);//判断输赢ret = IsWin(board);if (ret != 'C'){break;}}if (ret == '*')printf("玩家赢\n");else if (ret =='#')printf("电脑赢\n");elseprintf("平局\n");
}
int main()
{int input = 0;srand((unsigned int)time(NULL));do//实现玩多盘游戏{ menu();//打印菜单printf("请选择1/0:>\n");scanf("%d", &input);//选择进入游戏/退出游戏switch (input)//判断输入input的值决定是进入游戏还是退出游戏{case 1:game();//三子棋游戏的实现break;case 0:printf("退出游戏\n");break;default:printf("选择错误,请重新选择\n");break;}} while (input);//当input为0,跳出循环;为1再玩一盘游戏(重新进入循环);为其他值进入循环重新选择return 0;
}

 本次C语言小游戏三子棋的内容就到此啦,有什么问题欢迎评论区或者私信交流,觉得笔者写的还可以,或者自己有些许收获的,麻烦铁汁们动动小手,给俺来个一键三连,万分感谢 ! 

相关文章:

【C语言】小游戏-三字棋

大家好&#xff0c;我是深鱼~ 目录 一、游戏介绍 二、文件分装 三、代码实现步骤 1.制作简易游戏菜单 2.初始化棋盘 3.打印棋盘 4.玩家下棋 5.电脑随机下棋 6.判断输赢 7.判断棋盘是否满了 四、完整代码 game.h(相关函数的声明&#xff0c;整个代码要引用的头文件以及宏…...

多线程与并发编程面试题总结

多线程与并发编程 多线程 线程和进程的区别&#xff1f; 从操作系统层面上来讲&#xff1a;进程(process)在计算机里有单独的地址空间&#xff0c;而线程只有单独的堆栈和局部内存空间&#xff0c;线程之间是共享地址空间的&#xff0c;正是由于这个特性&#xff0c;对于同…...

在多页面应用和单页面应用中(例如vue)怎么提高seo搜索引擎优化

那么 我们要先知道 搜索引擎是怎么工作的&#xff1f; 搜索引擎是通过一系列步骤来工作的&#xff0c;以下是其基本原理&#xff1a; 1、网络爬虫&#xff1a;搜索引擎使用网络爬虫&#xff08;也称为蜘蛛、机器人&#xff09;来从互联网上抓取网页。网络爬虫按照预定义的规则…...

Dubbo 2.7.0 CompletableFuture 异步

了解Java中Future演进历史的同学应该知道&#xff0c;Dubbo 2.6.x及之前版本中使用的Future是在java 5中引入的&#xff0c;所以存在以上一些功能设计上的问题&#xff0c;而在java 8中引入的CompletableFuture进一步丰富了Future接口&#xff0c;很好的解决了这些问题。 Dubb…...

pytest-xdist分布式测试原理浅析

目录 pytest-xdist执行流程&#xff1a; pytest-xdist 模块结构&#xff1a; pytest-xdist分布式测试原理&#xff1a; pytest-xdist源码浅读&#xff1a; pytest-xdist执行流程&#xff1a; 解析命令行参数&#xff1a;pytest-xdist 会解析命令行参数&#xff0c;获取用户…...

研发工程师玩转Kubernetes——PVC通过storageClassName进行延迟绑定

不同的PV可以使用相同的StorageClass&#xff0c;它们是一对多的关系。 PV可以设置节点亲和性。比如下图&#xff0c;local-storage-class-waitforfirstconsumer-pv-ubuntuc只能在节点ubuntuc上&#xff1b;local-storage-class-waitforfirstconsumer-pv-ubuntud只能在节点ubu…...

6.利用matlab完成 符号矩阵的秩和 符号方阵的逆矩阵和行列式 (matlab程序)

1.简述 利用M文件建立矩阵 对于比较大且比较复杂的矩阵&#xff0c;可以为它专门建立一个M文件。下面通过一个简单例子来说明如何利用M文件创建矩阵。 例2-2 利用M文件建立MYMAT矩阵。(1) 启动有关编辑程序或MATLAB文本编辑器&#xff0c;并输入待建矩阵&#xff1a;(2) 把…...

python获取类名__qualname__,解决django接口ObjectDoesNotExist异常寻找model的问题

在django项目中&#xff0c;经常使用类似Model.objects.get(id1)的方法取对象&#xff0c;默认抛出的异常是ObjectDoesNotExist类型&#xff0c;通过try catch可以把异常捕获&#xff0c;获取的异常是Model.DoesNotExist类型&#xff0c; 要获知其类名&#xff0c;可以使用__na…...

电流的测量(分流电流表)

在当今的大多数仪器应用中&#xff0c;可以使用两种常见的电流测量方法&#xff1a;分流电流表方法和反馈电流表方法。分流电流表方法通常与通用数字万用表 (DMM)一起使用&#xff0c;用于测量分流电阻器上的电压测量值。该电压测量结果与已知的电阻值相结合&#xff0c;得出电…...

Leetcode每日一题:23. 合并 K 个升序链表(2023.8.12 C++)

目录 23. 合并 K 个升序链表 题目描述&#xff1a; 实现代码与解析&#xff1a; 优先级队列&#xff1a; 原理思路&#xff1a; 23. 合并 K 个升序链表 题目描述&#xff1a; 给你一个链表数组&#xff0c;每个链表都已经按升序排列。 请你将所有链表合并到一个升序链表…...

越南的区块链和NFT市场调研

越南的区块链和NFT市场调研 基本介绍 https://zh.wikipedia.org/wiki/%E8%B6%8A%E5%8D%97 语言文字&#xff1a; 越南语&#xff0c; 文字以国语字&#xff08;越南罗马字&#xff09;为主&#xff0c;汉喃文&#xff08;汉字&#xff09; 货币&#xff1a;越南盾 人口(2022…...

MySQL常用语句

当涉及到与关系型数据库进行交互时&#xff0c;以下是一些常用的 SQL 语句&#xff0c;可以帮助你进行数据查询、插入、更新和删除等操作&#xff1a; 查询数据&#xff1a; 查询所有数据&#xff1a;SELECT * FROM table_name; 查询特定列数据&#xff1a;SELECT column1, col…...

Mongodb:业务应用(1)

环境搭建参考&#xff1a;mongodb&#xff1a;环境搭建_Success___的博客-CSDN博客 需求&#xff1a; 在文章搜索服务中实现保存搜索记录到mongdb 并在搜索时查询出mongdb保存的数据 1、安装mongodb依赖 <dependency><groupId>org.springframework.data</groupI…...

【vue】vue中按钮权限控制:

文章目录 一、获取权限码二、三种按钮级别的权限控制方式【1】函数方式【2】组件方式【3】指令方式 一、获取权限码 要做权限控制&#xff0c;肯定需要一个code&#xff0c;无论是权限码还是角色码都可以&#xff0c;一般后端会一次性返回&#xff0c;然后全局存储起来就可以了…...

【博客695】k8s subPathExpr作用

k8s subPathExpr作用 场景&#xff1a; 对于一个deployment或者job拉起的服务&#xff0c;所有pod都是一样的配置&#xff0c;如果都挂载了宿主机的同一个目录&#xff0c;那么就会互相干扰&#xff0c;我们希望挂载相同目录&#xff0c;且在这个目录下&#xff0c;每个pod建立…...

微信小程序中键盘弹起输入框自动跳到键盘上方处理

效果展示 键盘未弹起时 键盘弹起后&#xff1a; 实现方式 话就不多说了 我直接贴代码了 原理就是用你点击的输入框的底部 距离顶部的位置 减去屏幕高度除以2&#xff0c;然后设成负值&#xff0c;再将这个值给到最外层相对定位的盒子的top属性&#xff0c;这样就不会出现顶…...

excel将主信息和明细信息整理为多对多(每隔几行空白如何填充)

excel导出的数据是主信息和明细信息形式。 方法如下:1、首先&#xff0c;从第一个单元格开始选中要填充的数据区域。2、按CtrlG或者F5调出定位对话框&#xff0c;点击左下角的【定位条件】。3、在【定位条件】中选择【空值】&#xff0c;然后点击【确定】按钮。4、按照上述操作…...

卷积神经网络实现彩色图像分类 - P2

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;365天深度学习训练营-第P2周&#xff1a;彩色识别&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制&#x1f680; 文章来源&#xff1a;K同学的学习圈子…...

【博客694】k8s kubelet 状态更新机制

k8s kubelet 状态更新机制 场景&#xff1a; 当 Kubernetes 中 Node 节点出现状态异常的情况下&#xff0c;节点上的 Pod 会被重新调度到其他节点上去&#xff0c;但是有的时候我们会发现节点 Down 掉以后&#xff0c;Pod 并不会立即触发重新调度&#xff0c;这实际上就是和 K…...

【博客692】grafana如何解决step动态变化时可能出现range duration小于step

grafana如何解决step动态变化时可能出现range duration小于step 1、grafana中的step和resolution grafana中的 “step” grafana本身是没有提供step参数的&#xff0c;因为仪表盘根据查询数据区间以及仪表盘线条宽度等&#xff0c;对于不同查询&#xff0c;相同的step并不能…...

从20亿美金独角兽到停摆:小冰败给的不是技术,而是这三个致命决策

小冰的崛起&#xff1a;技术理想主义的黄金十年2013年底&#xff0c;微软内部启动了一个特殊的项目。与当时业界专注于"定闹钟、查天气"等任务型AI助手不同&#xff0c;这个团队选择了一条人迹罕至的路径&#xff1a;让AI先学情商&#xff0c;再学智商&#xff0c;尽…...

自然语言处理词向量:WordVec与BERT预训练模型对比

自然语言处理&#xff08;NLP&#xff09;中&#xff0c;词向量技术是理解语义的核心工具。从早期的Word2Vec到如今的BERT预训练模型&#xff0c;词向量的发展推动了机器对语言的理解能力。本文将对比这两种代表性技术&#xff0c;分析其差异与应用场景&#xff0c;帮助读者理解…...

G-Helper终极指南:解锁华硕ROG笔记本隐藏性能的黑科技神器

G-Helper终极指南&#xff1a;解锁华硕ROG笔记本隐藏性能的黑科技神器 【免费下载链接】g-helper Lightweight, open-source control tool for ASUS laptops and ROG Ally. Manage performance modes, fans, GPU, battery, and RGB lighting across Zephyrus, Flow, TUF, Strix…...

Applera1n:iOS 15-16.6设备激活锁免费绕过完整指南

Applera1n&#xff1a;iOS 15-16.6设备激活锁免费绕过完整指南 【免费下载链接】applera1n icloud bypass for ios 15-16 项目地址: https://gitcode.com/gh_mirrors/ap/applera1n 如果你手头有一台带有激活锁的二手iPhone&#xff0c;看到那个熟悉的"Hello"界…...

如何快速掌握Ultimate Plumber:Linux管道即时预览工具完全指南

如何快速掌握Ultimate Plumber&#xff1a;Linux管道即时预览工具完全指南 【免费下载链接】up Ultimate Plumber is a tool for writing Linux pipes with instant live preview 项目地址: https://gitcode.com/gh_mirrors/up1/up Ultimate Plumber&#xff08;简称up&…...

C# 14原生AOT部署Dify客户端:从“Hello World”到生产就绪的72小时极速落地路径(含Docker multi-stage构建+符号调试逆向指南)

第一章&#xff1a;C# 14原生AOT部署Dify客户端&#xff1a;全景认知与价值锚点C# 14 原生 AOT&#xff08;Ahead-of-Time&#xff09;编译能力标志着 .NET 生态在云原生与边缘计算场景中的重大演进。当这一能力与 Dify——一个开源、可私有化部署的大模型应用开发平台——深度…...

Java项目Loom化失败率高达63%?(2026 Gartner调研首发:3个被90%团队忽略的阻塞调用陷阱)

第一章&#xff1a;Java项目Loom化失败率高达63%&#xff1f;——2026 Gartner调研核心洞察2026年Gartner发布的《Java生态现代化成熟度报告》显示&#xff0c;在已启动虚拟线程&#xff08;Virtual Threads&#xff09;迁移的1,247个中大型Java项目中&#xff0c;63.2%未能完成…...

从Minecraft插件到Root权限:一次因配置不当引发的服务器安全实战复盘

从Minecraft插件到Root权限&#xff1a;服务器安全配置的深度避坑指南 深夜两点&#xff0c;服务器警报突然响起。监控面板显示有人通过Minecraft插件执行了系统级命令——这原本只是游戏社区里一个普通的生存服务器&#xff0c;现在却成了攻击者的跳板。更糟的是&#xff0c;日…...

从博弈论到广告归因:手把手拆解Shapley Value的Python代码与业务陷阱

从博弈论到广告归因&#xff1a;手把手拆解Shapley Value的Python代码与业务陷阱 在数字营销领域&#xff0c;广告主常常面临一个核心难题&#xff1a;如何公平评估各渠道对最终转化的贡献&#xff1f;传统"最后点击"归因模型简单粗暴&#xff0c;往往低估了用户旅程…...

保姆级教程:在RV1126上搞定TP2855双摄驱动配置(从DTS到V4L2全流程)

RV1126双摄驱动实战&#xff1a;TP2855从硬件连接到V4L2调试全解析 当你在RV1126开发板上接入TP2855双摄像头模组时&#xff0c;是否遇到过图像采集不稳定、数据流中断或者驱动加载失败的问题&#xff1f;作为嵌入式Linux开发者&#xff0c;摄像头驱动配置往往是项目中最棘手的…...