news 2026/9/28 8:05:47

基于EasyX的C++五子棋游戏设计与实现:从绘图到AI判定

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于EasyX的C++五子棋游戏设计与实现:从绘图到AI判定

简介:一份基于easyx图形库的C++五子棋游戏完整源码,适合C++初学者、游戏开发爱好者以及图形界面编程入门者学习与实践。项目实现了棋盘绘制、落子交互、胜负判断等核心玩法,并通过easyx完成窗口渲染和鼠标操作,整体逻辑清晰,便于拆解学习。资源包共36个文件,大小22.92MB,包含3个cpp源文件、3个头文件,以及14个jpg、3个png等图像素材和4个mp3、2个wav、1个ogg等音频素材,此外图像与音频素材较丰富,视觉和听觉体验完整;还附带Visual Studio解决方案文件与Git配置,既可直接在VS中编译运行,也能了解工程配置与版本管理方式。作为综合练习项目,它覆盖了C++语法、面向对象设计、easyx绘图、游戏循环、鼠标事件响应以及简单AI对战算法,适合课程设计、毕业设计或自主练手;已有203人浏览学习,是一份值得参考的C++游戏开发源码。

1. 一个「能交作业、能学 C++」的窗口程序,为什么值得自己写一遍

如果你正在找一套能跑、能看懂、能改的 C++ 练手项目,基于 easyx 库的 C++ 五子棋游戏设计源码正好卡在这个位置:它不需要引入 Qt、SDL、raylib 这类重框架,只用一个轻量图形库把背景、棋盘、鼠标、棋子全部画出来,核心逻辑全部落在纯 C++ 的数据结构和算法上。做完这套东西,你会同时摸清三件事:C++ 程序是怎么从 main 函数跑到图形界面的、二维数组在真实游戏里怎么当棋盘用、以及胜负判定这种看似简单的问题里藏着哪些边界条件。适合的人群很具体:正在做课程设计的学生、想从控制台程序往图形界面挪一步的初学者、以及想给 C++ 语法找个实际场景的开发者。它不能帮你做网络对战或 3D 特效,但能把「面向对象 + 消息处理 + 算法」这三个 C++ 入门必过的坎一次性踩完,下面按我实际写这套源码的顺序展开。

2. 把源码跑通之前,先想清楚 easyx 解决的是哪一层问题

2.1 为什么选 easyx 而不是 SFML、SDL、raylib

五子棋这种程序,九成工作量在「棋盘绘制、鼠标交互、胜负判断」三件事上,真正需要图形库提供的其实只有窗口创建、画线、画圆、接收鼠标这些基础能力。easyx 恰好把 Windows API 封装成了一组类似 Turbo C 风格的绘图函数,几十行代码就能出一个窗口;SFML 和 raylib 虽然更现代,但需要你额外处理事件循环、渲染纹理和坐标系,对还不熟悉指针和类的大多数初学者来说,学习曲线直接翻了一倍。

更关键的是编译链路的差别。easyx 走的是 VC 编译器路线,在 Visual Studio 里装完就能用,#include <easyx.h> 再加一条链接配置就完事;SDL 和 raylib 要走 CMake、装依赖库、配 include 和 lib 路径,任何一个环节版本对不上就报一大堆 LNK2019。如果你只是想让五子棋源码尽快跑起来而不是研究图形引擎,easyx 是最稳的选择。

2.2 从源码下载到第一帧画面:三个前置步骤

拿到源码包后,不要急着用记事本打开就编译,先按工序来。

第一步,装 Visual Studio(常见做法是装 VS2019 或 VS2022,社区版足够),安装时勾选「使用 C++ 的桌面开发」。第二步,去 easyx 官网下载与 VS 版本匹配的安装包,双击安装,安装程序会自动把头文件和静态库写到 VS 的 VC 目录里,不需要手工配置 include 路径。第三步,在 VS 里新建一个空项目,把源码文件拖进去,然后在项目属性的「链接器 → 输入 → 附加依赖项」里确认包含easyx.h对应的库。

下面这段是这套五子棋源码最常见的入口写法:

#include <easyx.h> #include <conio.h> int main() { initgraph(WINDOW_WIDTH, WINDOW_HEIGHT); // 创建绘图窗口 setbkcolor(WHITE); // 设置背景色 cleardevice(); // 用背景色清空屏幕 // 游戏主循环放在这里 // ... getch(); // 按任意键退出 closegraph(); // 关闭窗口 return 0; }

这段代码里,initgraph是 easyx 的窗口初始化函数,两个参数是窗口宽和高,单位是像素;setbkcolor接受一个颜色常量,cleardevice让背景色立即生效。注意getch()在这里的作用是让窗口停留,如果没有它,程序执行完closegraph窗口会一闪而过,你甚至看不到棋盘画出来。主循环里要处理鼠标消息和绘制逻辑,后面两章展开。

2.3 源码文件和组织结构:先认清这四块再动手改

一套完整的五子棋源码包,通常拆成四个角色。文件里一般有一个入口文件(main.cpp)、一个棋盘与绘制相关的模块、一个逻辑判定模块、一个公共头文件。我第一次拿到这类源码时习惯先画一张静态关系表,理清哪些函数会被谁调用。

文件/职责内容范围关键函数示例
main.cpp窗口生命周期、游戏主循环main()、gameLoop()
board.h / board.cpp棋盘初始化、绘制、棋子落盘initBoard()、drawBoard()
judge.h / judge.cpp落子合法性、五子连珠判定isValidMove()、checkWin()
common.h常量、全局数据结构、公共类型BOARD_SIZE、StoneType

BOARD_SIZE通常定义成 15,棋盘数组用二维数组int board[15][15]表示,0 代表空,1 代表黑子,2 代表白子。这样设计的好处是判定函数不需要关心绘图,它只读数组里的值,逻辑和界面彻底解耦。改代码时你只需要记住:棋盘数组是唯一的数据真相,画出来的棋子只是它的投影。

3. 从空白窗口到能落子:棋盘绘制和坐标换算是这套源码的第一道坎

3.1 棋盘参数设计:一个 40 像素格子和一条留白公式

画棋盘之前先定参数。标准五子棋是 15 乘 15 条线交叉点落子,不是格子中心落子,所以窗口尺寸要刚好容纳 14 个间隔加两侧留白。我习惯用下面这组数值:窗口 640 乘 640,格子尺寸CELL_SIZE = 40,棋盘外侧留白BOARD_MARGIN = (640 - 14 * 40) / 2 = 40。这样整个 15 路棋盘在水平和垂直方向完全居中。

#define BOARD_SIZE 15 #define CELL_SIZE 40 #define WINDOW_WIDTH 640 #define WINDOW_HEIGHT 640 #define BOARD_MARGIN ((WINDOW_WIDTH - (BOARD_SIZE - 1) * CELL_SIZE) / 2)

BOARD_MARGIN这个宏不用手算成 40,让编译器算更安全,因为一旦你改大窗口尺寸或格子尺寸,留白会自动重新居中。这套参数是整个源码的骨架,鼠标坐标换算、棋盘绘制、AI 落子都要引用它,改任何一处之前先想想其他函数会不会跟着变。

3.2 绘制棋盘:直线、交叉点、天元和星位

多数源码把棋盘绘制拆成两个函数:画线画交叉点,再画星位。画线部分循环 15 次,每次画一条横线和一条竖线,line函数接收起点和终点坐标,使用 easyx 的黑色画笔。落在交叉点上的天元和五个星位按固定坐标画实心小圆。

void drawBoard() { setlinecolor(BLACK); // 设置线颜色为黑色 for (int i = 0; i < BOARD_SIZE; i++) { // 横线:y 固定,x 从左边距到右边距 line(BOARD_MARGIN, BOARD_MARGIN + i * CELL_SIZE, BOARD_MARGIN + (BOARD_SIZE - 1) * CELL_SIZE, BOARD_MARGIN + i * CELL_SIZE); // 竖线:x 固定,y 从上边距到下边距 line(BOARD_MARGIN + i * CELL_SIZE, BOARD_MARGIN, BOARD_MARGIN + i * CELL_SIZE, BOARD_MARGIN + (BOARD_SIZE - 1) * CELL_SIZE); } // 星位坐标:天元在正中央,四隅星位对称分布 fillcircle(BOARD_MARGIN + 7 * CELL_SIZE, BOARD_MARGIN + 7 * CELL_SIZE, 4); // 其余星位:第 3、11 行与第 3、11 列的四个交点 }

这里fillcircle的前两个参数是圆心坐标,第三个是半径。星位坐标如果记不住,直接记住数字:在 15 路棋盘上,星位位于第 3、7、11 三条线与第 3、7、11 三条线的交点上,7 路交点就是天元。初学者最容易在这里漏画四个角的星位,视觉效果上棋盘会显得「缺角」。

3.3 把鼠标点转换成棋盘交叉点:半个格子是关键

棋盘的逻辑坐标和窗口像素坐标必须建立换算关系。鼠标点击位置大概率不会精准落在某条线的交点上,所以要按最近邻规则吸附。这个换算函数必须在每个下棋源码里单独抽出来,因为判定、AI、落子绘制都要复用它。

int mouseToGrid(int mousePos) { // 先判断是否落在棋盘留白区域外 if (mousePos < BOARD_MARGIN) return -1; // 距离留白最近的交叉点索引,加半个格子实现四舍五入 int grid = (mousePos - BOARD_MARGIN + CELL_SIZE / 2) / CELL_SIZE; if (grid >= BOARD_SIZE) return -1; return grid; }

参数说明:mousePos是消息结构体里带出的鼠标 x 或 y 像素坐标。加上 CELL_SIZE / 2这一步作用很关键——如果鼠标点在两个交叉点之间但更靠近右边那个,整数除法会把余数舍掉,导致吸附到左边的点;加上半个格子相当于先偏移再截断,自动完成四舍五入。越界判断返回 -1,调用方必须对它做拦截,否则数组下标负值会直接让程序翻车。

3.4 落子后的重绘:双缓冲是体验分水岭

落子不只是往数组写数字,还要把棋子画到窗口上。很多初学者在这里直接调fillcircle画一个带边框的圆,结果鼠标每点一次屏幕就闪一下。原因是窗口没有缓冲机制,绘制和擦除交错进行。

bool placeStone(int row, int col, int player) { if (board[row][col] != 0) return false; // 已有棋子,拒绝落子 board[row][col] = player; beginBatchDraw(); // 启动批量绘制 setfillcolor(player == 1 ? BLACK : WHITE); setlinecolor(player == 1 ? BLACK : WHITE); int x = BOARD_MARGIN + col * CELL_SIZE; int y = BOARD_MARGIN + row * CELL_SIZE; fillcircle(x, y, CELL_SIZE / 2 - 2); // 半径留 2 像素空隙更美观 // 白子加边线,否则白棋与浅色背景会融为一体 if (player == 2) setlinecolor(BLACK); circle(x, y, CELL_SIZE / 2 - 2); endBatchDraw(); // 统一刷新到屏幕 return true; }

beginBatchDraw和endBatchDraw是 easyx 提供的双缓冲函数对,所有绘制先进入内存画布,再一次性输出到窗口。注意棋子半径不是CELL_SIZE / 2,而是要减 2,否则相邻棋子会挤在一起。白子绘制时要把描边颜色再设回黑色,这一步很容易漏,漏了以后白子和白色背景几乎分不开。

4. 胜负判定与人机 AI:让这套源码从「能下棋」升级到「能对战」

4.1 五子连珠判定:4 个方向共用同一个方向向量表

胜负判定是一个典型的「方向扫描」问题,初学者最容易写成的劣质代码是一段五层 if 嵌套,分别数上下、左右、两条斜线,每个方向还单独写循环。这类代码跑起来没问题,但一旦要加禁手、加 AI、换棋盘尺寸,改动量会让人崩溃。

我在这类源码里一般不用整体棋盘扫描,而是从最后落子的位置出发,沿四个方向向两端扩散数同色棋子,数到大于等于 5 就判胜。四个方向用一张静态方向表描述。

const int dir[4][2] = { {1, 0}, // 水平方向:列递增 {0, 1}, // 垂直方向:行递增 {1, 1}, // 主对角线:行列同增 {1, -1} // 副对角线:行增列减 }; bool checkWin(int row, int col, int player) { for (int k = 0; k < 4; k++) { int count = 1; // 当前棋子自身算一颗 // sign 为 -1 时向负方向数,为 1 时向正方向数 for (int sign = -1; sign <= 1; sign += 2) { int nr = row + dir[k][0] * sign; int nc = col + dir[k][1] * sign; while (nr >= 0 && nr < BOARD_SIZE && nc >= 0 && nc < BOARD_SIZE && board[nr][nc] == player) { count++; nr += dir[k][0] * sign; nc += dir[k][1] * sign; } } if (count >= 5) return true; } return false; }

逻辑说明:sign变量在 -1 和 1 之间跳跃,每次只沿一个方向延伸;while条件里先做边界检查再访问数组元素,这行顺序写反就可能在遍历到棋盘边缘时把内存读穿。四条方向逐一对齐后,count累加的就是包含当前落子在内的连续同色子数量。这个函数只依赖board数组和落子坐标,所以判定时机永远是在placeStone落子完成后立即调用一次。

4.2 判定的时机选择:为什么不在每轮全盘扫描

另一个常见分歧点是:落子后扫全盘找五连,还是只从落子点往外扩散。功能上两者都能判对,但性能差距在棋盘越大时越明显。15 路棋盘全盘扫描一次是 225 个位置,每个位置扫四个方向,单轮也要近千次数组访问;而落子点扩散法只遍历与当前步相关的连通区域,实际访问量一般只有几十次,而且不依赖当前是第几手、棋盘上有无残局。

实践上还有个更隐蔽的好处:从落子点扩散天然支持「悔棋后重新判定」,因为每次只检测最近一手棋,不用重建整个盘面状态。如果你的源码里还有观战演示、棋谱回放这类功能,这个特性省很多事。

4.3 人机对战接缝:先让 AI 学会堵活四,再谈策略

源码里最常被问到的就是 AI 部分,我要说的直白一点:课程设计级别的源码,不需要上弗洛伊德和蒙特卡洛树搜索,一个「赢棋优先、堵活四优先、随机保底」的分层判断就足够打交换手五五开。

最简实现是:轮到 AI 时扫描全部空点,对每个空点临时落子,调用checkWin看自己能不能五连;能就直接下这里。若自己无胜点,再模拟玩家在同样位置落子,若玩家能五连则必须堵。两轮都没有就选一个优先位(离天元近的位置)下。这样写出来大约 40 行,关键代码也只有一张模拟表和一个随机兜底。

int findBestMove(int aiPlayer) { int opponent = (aiPlayer == 1) ? 2 : 1; for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (board[i][j] != 0) continue; // 先看自己下这手能否直接获胜 board[i][j] = aiPlayer; if (checkWin(i, j, aiPlayer)) { board[i][j] = 0; // 试探后立即还原 return i * BOARD_SIZE + j; } // 再看玩家下这手是否会赢,赢了必须堵 board[i][j] = opponent; if (checkWin(i, j, opponent)) { board[i][j] = 0; return i * BOARD_SIZE + j; } board[i][j] = 0; } } return -1; // 无攻防点,走保守落子 }

参数说明:棋盘数组在这里被当作临时状态使用,模拟落子后必须立刻归零,否则后续判定会被脏数据污染。返回值用row * 15 + col把两个坐标打包成一个整数,调用方再用除法和取模解包。这个写法在源码里很常见,也是一道经典的 C++ 编程小考题:为什么不用pair或结构体?答案是结构体更直白,但整数打包省去每次构造对象的开销,面试时能说出这点差异会显得底子更扎实。

4.4 AI 强度参数:搜索深度不是越大越好

有人拿到这类源码后会立刻改搜索深度,想做一个按不了的五子棋 AI。这里要控制预期:当前盘面模拟一层只能看到「下一手谁赢」,遇到冲活三、双活三这种需要两步以上推演的局面必然漏招。想提高强度至少要加一层:模拟我方下完后,把对手可能的应对也试一遍,选出自己的得分最高的分支。

不过深度每加一层,时间复杂度就按空位数指数膨胀。15 路棋盘中盘阶段空位有两百多个,模拟三层就是千万量级,每秒只处理鼠标消息的单线程程序根本扛不住。工程做法是给搜索加一个层数上限,同时给空点排序——优先搜索靠近已有棋子的位置,离战场太远的点直接跳过,这样即便只搜两层,棋力也能明显超过只会堵活四的新手版。

5. 编译、链接、运行阶段的高频踩坑:从 LNK 报错到白子消失

5.1 编译报错 lnk2019 / lnk2001:main 函数和窗口子系统对不上

现象:代码看起来完全没问题,编译器报链接错误,说无法解析的外部符号_main,或者WinMain入口缺失。原因:easyx 程序默认使用 Windows 窗口子系统,但项目属性里配置的入口还是控制台程序的main;反过来,控制台项目里的人又会出现找不到 WinMain 的报错。

解决:在项目属性「链接器 → 系统 → 子系统」里,把「控制台」改成「窗口」,或者保持控制台不动但确保源码里main函数明确存在。我在多个版本的 VS 里都遇到过新项目向导自动生成_tmain的情况,统一把入口函数改成标准main()就能避开一堆隐藏宏带来的问题。

5.2 中文字符串变成乱码:源文件编码和编译器默认不一致

现象:棋盘标题、菜单提示等中文文本运行时全部显示成一片乱码,英文和数字正常。原因:Windows 下 VS 的源文件保存编码和编译器读取编码不一致,最常见的组合是源文件用 UTF-8 保存而编译器按本地代码页读取。

解决:有二选一的方案。简单粗暴的是把所有中文提示改成英文或拼音;另一种是把源文件另存为 GBK/ANSI 编码,或者在main最开头调用setlocale(LC_ALL, "zh-CN")。我在这类课程设计源码里一般推荐 GBK 另存,因为要求对方改编译器选项不现实,而 GBK 是 Windows 下维护最省心的中文编码。

5.3 鼠标点击有延迟或完全无响应:消息保存在事件队列里没被取走

现象:窗口能画棋盘,但怎么点都没反应,或者反应明显慢一拍。原因:没进消息循环或消息分支写成了阻塞等待,鼠标消息堆积在队列里没被peekmessage及时取走。

解决:游戏主循环里必须用非阻塞方式取消息,并且每帧都调用一次取消息函数。常见错误写法是在循环里用getmessage,本次取不到就一直停在那里等,导致棋盘根本来不及重绘。正确姿势是peekmessage取出一条处理一条,然后马上继续画帧。主循环结构大致是:while (running) { while (peekmessage(&msg)) handle(msg); draw(); }。

5.4 棋子落下一个变成两个:重复绘制且没有清屏

现象:先落的白子点击另一处后,旧位置又出现一颗相同棋子,整个棋盘越来越乱。原因:绘制循环里用cleardevice清掉了背景,但没有调用drawBoard重绘棋盘底图,于是老棋子的绘图残留叠加到了新画面里。

解决:每帧统一流程应该是先清屏、再画棋盘、再根据board数组把所有已存在的棋子全部画一遍。注意绘制顺序不能反,棋盘底图要在最底层,棋子和星位最后覆盖。顺手做个优化:只有棋盘数组变化时才重绘,鼠标悬停但不按键时不要每次都全量刷新,能避免 CPU 占用时刻居高不下。

5.5 easyx.h 找不到:安装路径和 VS 实例没对上

现象:#include <easyx.h>直接报 fatal error C1083,无法打开包括文件。原因:装 easyx 时选错 VS 版本,或者安装时 VS 没关,安装包把文件写进了旧 VS 的目录,而当前导入的是新实例。

解决:关闭全部 VS 再重装 easyx,安装界面里会列出检测到的 VC 版本,确认和当前使用的 VS 对应。如果仍找不到,去 easyx 安装目录的 include 文件夹确认是否存在 easyx.h,然后把该目录手动填进项目属性的「C/C++ → 常规 → 附加包含目录」。这里顺便提醒一句,如果用的是 VSCode 配 C++ 环境,easyx 在不是 MSVC 的编译器上兼容性通常不太理想,常见做法还是回到 Visual Studio 一条龙。

6. 设计一个能随时反悔的落子记录:从数据栈到回放

把悔棋做成一个独立小功能,比做 AI 更能体现这套源码的数据结构功底。核心做法是用标准容器维护一个历史栈,每落一子就记录「行、列、玩家」三元组;悔棋时从栈顶弹出,把对应格子清成 0,再重绘整个棋盘。这种设计天然支持「悔到任意步骤」,因为你随时可以重建盘面。

struct StoneMove { int row, col, player; }; std::vector<StoneMove> history; // 用 vector 模拟栈 bool undoLastMove() { if (history.empty()) return false; StoneMove last = history.back(); history.pop_back(); board[last.row][last.col] = 0; redrawAllStones(); // 清屏后按 history 里的全部记录重绘 return true; }

逻辑说明:history局变量在整盘游戏中只增不减,只有当用户执行悔棋或重新开始时才 pop 或 clear。redrawAllStones里按记录顺序重新画棋子,而不是只擦除栈顶那一颗,原因是棋盘上后续棋子的位置没有变,但旧棋子被擦除后必须靠重建才能恢复到刚才的视觉效果。这套思路再往前走一步就是复盘功能:从空棋盘开始逐条执行 history,每执行一条暂停几十毫秒,就变成棋谱回放。

给这套源码再加东西时,我的习惯是永远先看数据结构能不能表达新需求。加计时器就维护一个开局时间戳;加和棋判定就维护落子计数;加音效就在placeStone成功后调用播放函数。这些改动听起来零碎,但你会发现它们全部围绕同一个数组和一个记录栈转,这正是这一类课程设计源码最好的学习价值所在——它不会教你复杂设计模式,但它逼着你把每个新增需求翻译成最朴素的 C++ 数据操作。这个习惯我保留到现在,做图形程序时仍然觉得够用,希望帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/28 8:05:47

书法字体数据闭环:204张手写汉字PNG与轻量训练实践

简介&#xff1a;本资源是一套面向书法识别与生成方向的Python实践项目&#xff0c;适用于图像处理初学者、机器学习入门者及传统文化数字化研究者&#xff0c;聚焦书法字体图像的自动化采集、预处理与模型训练全流程。压缩包共207个文件&#xff0c;含204张PNG书法字图&#x…

作者头像 李华
网站建设 2026/9/28 8:05:40

Python+PIL图片转Base64字符串:完整实战与避坑指南

做 Web 和自动化相关开发的同学&#xff0c;迟早都会碰到一个看起来简单但藏了不少坑的需求&#xff1a;把一张图片从 Python 代码里变成一长串文本&#xff0c;然后再把这串文本塞进 JSON、写进数据库、拼到接口返回值里&#xff0c;或者直接扔给前端渲染。这里面的关键组合就…

作者头像 李华
网站建设 2026/9/28 8:05:33

基于微信小程序的图书馆座位预约系统:Java毕设全模块解析

简介&#xff1a;基于微信小程序的图书馆座位预约系统&#xff0c;是一份完整的Java毕业设计资源&#xff0c;面向计算机专业毕业生、Java初学者及需要快速完成课程设计的学生。系统功能覆盖用户管理、图书馆维护、座位信息状态更新、预约选座、签到签退、论坛互动与留言反馈等…

作者头像 李华
网站建设 2026/9/28 8:04:43

每一步都是NPU推理:AX8850上贪吃蛇与Flappy Bird实战

我把一个早就想做实的想法落地了&#xff1a;在爱芯元智 AX8850 这块板子上&#xff0c;把贪吃蛇和 Flappy Bird 的每一步动作都交给 NPU 推理来决定。你没有看错&#xff0c;不是用传统游戏逻辑写死走法&#xff0c;而是让模型对当前的游戏局面做一次真实的前向推理&#xff0…

作者头像 李华
网站建设 2026/9/28 8:04:21

华为光学工程师面试全解析:从像差理论到Zemax实操与量产思维

说实话&#xff0c;华为光学工程师这个岗位的面试&#xff0c;是我见过准备难度和竞争烈度都被严重低估的方向之一。不少候选人把精力全砸在“背光学公式”和“刷Zemax操作”上&#xff0c;结果一进技术面&#xff0c;被面试官从像差图追到玻璃选型&#xff0c;再追到量产公差&…

作者头像 李华
网站建设 2026/9/28 8:03:46

深入理解指针6 - sizeof和strlen、数组和指针练习、指针运算

目录 1.sizeof和strlen的对比 2.数组和指针题练习 3.指针运算 1.sizeof和strlen的对比 1.1区分 sizeofstrlen本质 运算符 库函数 头文件不需要头文件需要<string.h>参数可以是类型&#xff0c;变量&#xff0c;表达式&#xff0c;数组名等 必须是char*或const char…

作者头像 李华