- 浏览: 269019 次
- 性别:
- 来自: 济南
-
文章分类
最新评论
JavaFX游戏开发--第二课 基础游戏框架
之前有一个第一课,讲精灵动画的。那个时候JavaFX 2.2还没出来,所以那一课中根本就没有用到Canvas。
但是既然在JavaFX 2.2出来后,新增加了Canvas,那么就大不一样了。
这一章教程中,我们将在JavaFX中创建一个简单的游戏框架。
首先大家看一看结构,主要的几个类。
这一课,我们只讲基础游戏框架,所以我们只看WApplication,WSystem,WObject 和 WScreen这四个类。
由这四个类组成一个简单的游戏框架。
首先是所有的游戏Object的基类WObject:
package org.wing.jfx.game.core.component; import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.scene.canvas.GraphicsContext; /** * @author wing * @date 2012/8/25 */ public abstract class WObject{ protected DoubleProperty widthProperty = new SimpleDoubleProperty(0); protected DoubleProperty heightProperty = new SimpleDoubleProperty(0); protected DoubleProperty xProperty = new SimpleDoubleProperty(0); protected DoubleProperty yProperty = new SimpleDoubleProperty(0); protected BooleanProperty visibleProperty = new SimpleBooleanProperty(true); protected BooleanProperty updateProperty = new SimpleBooleanProperty(true); public WObject(double x, double y, double width, double height){ this.xProperty = new SimpleDoubleProperty(x); this.yProperty = new SimpleDoubleProperty(y); this.widthProperty = new SimpleDoubleProperty(width); this.heightProperty = new SimpleDoubleProperty(height); } public WObject(){ this.xProperty = new SimpleDoubleProperty(0); this.yProperty = new SimpleDoubleProperty(0); this.widthProperty = new SimpleDoubleProperty(0); this.heightProperty = new SimpleDoubleProperty(0); } public abstract void draw(GraphicsContext gc); public abstract void update(); public DoubleProperty widthProperty() { return widthProperty; } public double getWidth(){ return widthProperty.get(); } public void setWidth(double width){ this.widthProperty.set(width); } public DoubleProperty heightProperty() { return heightProperty; } public double getHeight(){ return heightProperty.get(); } public void setHeight(double height){ this.heightProperty.set(height); } public DoubleProperty xProperty() { return xProperty; } public double getX(){ return xProperty.get(); } public void setX(double x){ this.xProperty.set(x); } public DoubleProperty yProperty() { return yProperty; } public double getY(){ return yProperty.get(); } public void setY(double y){ this.yProperty.set(y); } public BooleanProperty visibleProperty(){ return visibleProperty; } public void setVisible(boolean isVisible){ this.visibleProperty.set(isVisible); } public boolean isVisible(){ return visibleProperty.get(); } public BooleanProperty updateProperty(){ return updateProperty; } public void setUpdate(boolean isUpdate){ this.updateProperty.set(isUpdate); } public boolean isUpdate(){ return updateProperty.get(); } public void moveX(double x){ this.xProperty.set(getX() + x); } public void moveY(double y){ this.yProperty.set(getY() + y); } public boolean isCollisionWith(WObject baseObject){ if(getX() + getWidth() > baseObject.getX() && getX() < baseObject.getX() + baseObject.getWidth() && getY() + getHeight() > baseObject.getY() && getY() < baseObject.getY() + baseObject.getHeight()){ return true; } return false; } }
这个类很简单,主要是x,y,width,height,visible,update几个属性,使用了JavaFX中可进行绑定的Property。
另外是几个简单的移动碰撞的方法。
可能以后会增加一些别的东西,但是目前这个类就是这样的。
接下来是WScreen类,这个类是继承于Canvas的,意味着这是一个容器,可以绘制的容器。由于我们的WObject并
未继承任何JavaFX的系统类,那么所有的WObject都需要在WScreen中渲染。而且还需要WScreen提供一个刷新界
面的方法。
package org.wing.jfx.game.core.screen; import java.util.ArrayList; import java.util.List; import org.wing.jfx.game.core.component.WObject; import javafx.animation.KeyFrame; import javafx.animation.Timeline; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.input.KeyEvent; import javafx.util.Duration; /** * Screen * @author wing * 2012/8/25 */ public abstract class WScreen extends Canvas { protected enum GameState {GAME_MENU, GAME_START, GAME_CONTINUE, GAME_HELP, GAME_SET,GAME_EXIT,GAME_PAUSE}; private List<WObject> mObjects = new ArrayList<WObject>(); private Timeline timeline; private KeyFrame keyFrame; private int duration = 10; protected GameState mGameState = GameState.GAME_MENU; public WScreen(double width, double height) { super(width, height); initTimeLine(); } public void initEvents(){ getParent().getScene().setOnKeyPressed(new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent event) { onKeyPressed(event); } }); getParent().getScene().setOnKeyReleased(new EventHandler<KeyEvent>() { @Override public void handle(KeyEvent event) { onKeyReleased(event); } }); } protected abstract void onKeyPressed(KeyEvent event); protected abstract void onKeyReleased(KeyEvent event); /** * add the object * @param baseObject the object to be add */ public void addObject(WObject baseObject){ this.mObjects.add(baseObject); } /** * remove the object * @param baseObject the object to be remove */ public void removeObject(WObject baseObject){ this.mObjects.remove(baseObject); } /** * remove the object with the index * @param index the index of the object */ public void removeObjectAtIndex(int index){ this.mObjects.remove(index); } /** * draw the objects * @param gc */ public void draw(GraphicsContext gc){ gc.clearRect(0, 0, getWidth(), getHeight()); for (int i = 0; i < mObjects.size(); i++) { WObject wObject = mObjects.get(i); if (wObject.isVisible()) { wObject.draw(gc); } } } /** * update all the objects */ public void update(){ for (int i = 0; i < mObjects.size(); i++) { WObject wObject = mObjects.get(i); if (wObject.isUpdate()) { mObjects.get(i).update(); } } } /** * init the timeline */ private void initTimeLine() { timeline = new Timeline(); timeline.setCycleCount(Timeline.INDEFINITE); keyFrame = new KeyFrame(Duration.millis(duration), new EventHandler<ActionEvent>() { @Override public void handle(ActionEvent arg0) { draw(getGraphicsContext2D()); update(); } }); timeline.getKeyFrames().add(keyFrame); } /** * start the update timeline */ public void start(){ timeline.play(); } /** * pause the update timeline */ public void pause(){ timeline.pause(); } /** * stop the update timeline */ public void stop(){ timeline.stop(); } }
由上面的代码可见,我们包含一个游戏状态的枚举(目前没有用到),一个WObject的列表。然后通过创建一个无
限循环的Timeline来进行所有的WObject的绘制和刷新(可能有更好的方法,但目前这个游戏框架中暂时这样做)。
同时可以进行timeline的控制。
同样的,这里也暂时只提供了KeyPressed和KeyReleased两个事件方法,不过鼠标的事件添加也是很简单的。
下面看看WSystem,这个类暂时很简单,只是记录窗口的大小的类。因为只是简单的框架,其他的东西可能在后续
添加进去。
一般来说使用公共静态变量之类的并不符合Java规范,不过要纠结于此的话,可以将它更改为单例模式,并赋予一
些set get方法。
public class WSystem { public static int WIDTH = 800, HEIGHT = 600; public static void init(int width, int height){ WIDTH = width; HEIGHT = height; } }
再下面看看WApplication,这个是继承与JavaFX中的Application类,作为应用程序的启动类,JavaFX的这个游戏框
架中,任何示例的主类都需要继承WApplication。
package org.wing.jfx.game.core; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.stage.Stage; public abstract class WApplication extends Application { private Group mGroup; private Scene mScene; @Override public void start(Stage primaryStage) throws Exception { loadBefore(); mGroup= new Group(); mScene = new Scene(mGroup, WSystem.WIDTH, WSystem.HEIGHT); loadEnd(); showStage(primaryStage); } protected abstract void loadBefore(); protected abstract void loadEnd(); protected void showStage(Stage stage){ stage.setScene(mScene); stage.show(); } protected Scene getScene(){ return mScene; } protected Group getRoot(){ return mGroup; } public void setWindowSize(int width, int height){ WSystem.init(width, height); } }
这里的方法也是很容易理解的。
那么,我们就来看看如何使用这个简单的框架来构造JavaFX程序吧。
首先我们创建一个Rect继承WObject,这样会出现两个需要实现的方法:draw 和 update。
我们这里就简单的画一个矩形,然后在update方法进行移动。
package org.wing.jfx.game.test; import javafx.scene.canvas.GraphicsContext; import javafx.scene.paint.Color; import org.wing.jfx.game.core.component.WObject; public class Rect extends WObject { public Rect(double x, double y, double width, double height){ super(x, y, width, height); } @Override public void draw(GraphicsContext gc) { gc.setFill(Color.CHOCOLATE); gc.fillRect(getX(), getY(), getWidth(), getHeight()); } @Override public void update() { moveX(1); } }
这就是这个框架中自己实现的一个简单的Object。
然后创建一个自己的Screen。命名为TestScreen,然后继承WScreen。
当然,只出现了两个Key事件的方法,我们可以在TestScreen中创建上面的Rect,然后添加到TestScreen中,再通
过Key事件来进行控制。
package org.wing.jfx.game.test; import javafx.scene.input.KeyEvent; import org.wing.jfx.game.core.WSystem; import org.wing.jfx.game.core.screen.WScreen; public class TestScreen extends WScreen { private Rect player; public TestScreen(double width, double height) { super(width, height); player = new Rect(50, 50, 100, 100); addObject(player); } @Override protected void onKeyPressed(KeyEvent event) { switch (event.getCode()) { case UP: player.moveY(-1); break; case DOWN: player.moveY(1); break; case ENTER: addObject(new Rect(Math.random() * WSystem.WIDTH, Math.random() * WSystem.HEIGHT, 100, 100)); break; default: break; } } @Override protected void onKeyReleased(KeyEvent event) { } }
如上面的代码所示,我们在构造函数中创建了一个坐标50,50 宽 100 高 100 的Rect。然后在事件处理中,上下控
制Rect的移动,通过Enter键,在屏幕上随机增加一个Rect。
由于我们在Rect的Update方法中增加了Move的操作,所以所有的Rect将一直往右移动。
下面创建我们的主类MainClass继承WApplication:
package org.wing.jfx.game.test; import javafx.scene.paint.Color; import javafx.stage.Stage; import org.wing.jfx.game.core.WApplication; import org.wing.jfx.game.core.WSystem; public class MainClass extends WApplication { @Override protected void loadBefore() { setWindowSize(800, 600); } @Override protected void loadEnd() { TestScreen testScreen = new TestScreen(WSystem.WIDTH, WSystem.HEIGHT); getRoot().getChildren().add(testScreen); testScreen.start(); testScreen.initEvents(); getScene().setFill(Color.BLACK); } @Override protected void showStage(Stage stage){ super.showStage(stage); stage.setTitle("JavaFX游戏开发 第二课 基础游戏框架"); } public static void main(String[] args) { launch(args); } }
这个就是我们的主类了,我们在loadBefore中设定了窗口的大小,在loadEnd中创建了TestScreen,启动了
TestScreen的循环Timeline,载入了TestScreen的事件,并设定场景背景为黑色,然后重写了父类的showStage方法
修改了程序的标题。
后面的就是用这个简单的游戏框架创建的简单的程序了,只要整个框架搭建好,后面每次进行游戏开发的时候,就
可以节省很多的代码量了。
运行结果倒是不怎样,不过我们在这一章中,主要是构建了游戏框架。
在下一章中,我们会增加动画精灵以及地图的绘制。
转载请注明出处:http://blog.csdn.net/ml3947
相关推荐
第二章 多窗口类浏览器设计 11 2.1 多窗口类浏览器需求分析 11 2.1.1 Activity简介 11 2.1.2 Fragment简介 11 2.1.3 多窗口类浏览器需求 12 2.2 多窗口浏览器模式的实现机制 12 2.2.1安卓移动端多窗口浏览器框架 12 ...
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。在编写C程序时,需要注意变量的声明和定义、指针的使用、内存的分配与释放等问题。C语言中常用的数据结构包括: 1. 数组:一种存储同类型数据的结构,可以进行索引访问和修改。 2. 链表:一种存储不同类型数据的结构,每个节点包含数据和指向下一个节点的指针。 3. 栈:一种后进先出(LIFO)的数据结构,可以通过压入(push)和弹出(pop)操作进行数据的存储和取出。 4. 队列:一种先进先出(FIFO)的数据结构,可以通过入队(enqueue)和出队(dequeue)操作进行数据的存储和取出。 5. 树:一种存储具有父子关系的数据结构,可以通过中序遍历、前序遍历和后序遍历等方式进行数据的访问和修改。 6. 图:一种存储具有节点和边关系的数据结构,可以通过广度优先搜索、深度优先搜索等方式进行数据的访问和修改。 这些数据结构在C语言中都有相应的实现方式,可以应用于各种不同的场景。C语言中的各种数据结构都有其优缺点,下面列举一些常见的数据结构的优缺点: 数组: 优点:访问和修改元素的速度非常快,适用于需要频繁读取和修改数据的场合。 缺点:数组的长度是固定的,不适合存储大小不固定的动态数据,另外数组在内存中是连续分配的,当数组较大时可能会导致内存碎片化。 链表: 优点:可以方便地插入和删除元素,适用于需要频繁插入和删除数据的场合。 缺点:访问和修改元素的速度相对较慢,因为需要遍历链表找到指定的节点。 栈: 优点:后进先出(LIFO)的特性使得栈在处理递归和括号匹配等问题时非常方便。 缺点:栈的空间有限,当数据量较大时可能会导致栈溢出。 队列: 优点:先进先出(FIFO)的特性使得
在 Qt 框架中,要在 QTableWidget的表头中添加复选框,可以通过继承 QHeaderView 并重写 paintSection 方法来实现。 介绍一种继承 QHeaderView的方法分别实现QTableWidget中添加复选框,可全选/全不选/部分选。
分段划线测量表格通用版.doc
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
本资源源自《啊哈算法》的高级算法实践,专注于讲解基于队列优化的Bellman-Ford算法在单源最短路径问题上的应用,并提供了Java语言的实现代码。哈磊老师以其独特的教学视角,不仅详细解析了传统Bellman-Ford算法的原理及其在处理含有负权边图中的优势,还深入介绍了如何通过队列优化(通常指SPFA算法)来加速这一过程,减少不必要的松弛操作,提高算法效率。 Java实现部分,代码实现清晰,注释详尽,从初始化距离数组、设置源节点开始,逐步展示如何维护一个队列来记录待检查的顶点,并通过队列进行有效的顶点遍历和松弛操作。本资源通过实例演示了如何高效地更新路径长度,检测负权环,并最终确定从源点到图中所有其他顶点的最短路径。 这份资源特别适合对图算法有深入学习需求的学生、工程师以及算法爱好者,尤其是那些关注算法性能优化和实际应用的人士。通过学习这份资源,你不仅能掌握Bellman-Ford算法的核心逻辑,还将理解如何通过队列优化策略提升算法的执行效率,为解决复杂的网络最短路径问题提供有力工具。在算法学习和软件开发的道路上,这将是一块宝贵的垫脚石,助你攀登更高的算法高峰。
基于一阶倒立摆线性二次型最优控制
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
计算机毕业设计资源包含(项目部署视频+源码+LW+开题报告等等),所有项目经过助教老师跑通,有任何问题可以私信博主解决,可以免费帮部署。
基于Java的教师考勤管理系 统 成绩查看 请假申请 考勤管理 用户 注册登录 个人中心 系统管理 学生管理 管理员 老师管理 成绩管理 考勤信息管理 请假信息管理 个人中心 公告管理 个人中心 学生考勤管理 教师 学生请假申请管理 成绩管理 班级管理 公告管理
EhLib.v10.2.42 for Delphi 5-12.src.rar
chromedriver-win64_118.0.5957.0.zip
资源包括: 1.Java爬虫实战代码 2.selenium学习笔记 3.代码演示视频 4.谷歌浏览器chrom124.0.6350.0 chrome-linux64.zip chrome-mac-arm64.zip chrome-mac-x64.zip chrome-win32.zip chrome-win64.zip 5.谷歌浏览器驱动器Chromedriver124.0.6350.0 chromedriver-linux64.zip chromedriver-mac-arm64.zip chromedriver-mac-x64.zip chromedriver-win32.zip chromedriver-win64.zip 特别说明:Chrome 为测试版(不会自动更新) 仅适用于自动测试。若要进行常规浏览,请使用可自动更新的标准版 Chrome。)
无尽之剑3.5震撼来袭!自创游戏,完美还原我的世界细节! 更新日志 3.5:更新图签,优化战斗盔甲防御机制 3.0:更新附魔,更改合成机制 2.5:更新撸树功能 2.0:更新盔甲 1.5:更新工作台(合成)功能 1.0:更新打怪,挖矿功能 0.5:框架搞好了
【单页简历模版15份】 一份优秀的简历能为求职就业的过程做好铺垫。 简历模版 一份简历最关键的地方之一就是一个简历模板,选择一个好的简历模版最为关键。在选择的时候一定要选择比较清晰直观的模版。 有的反例就是:个人信息在左边一栏,总的来说,没有那么直观。 简历是不断迭代优化的,所以个人比较喜欢WORD版本的简历模版。当然,也有人喜欢用类似超级简历之类的软件网站来生成简历,有时候也是可以的。 简历一般不宜过长,要保证简洁,一般1到2页即可。一般一页最好,但如果个人亮点足够多(比如多段高含金量的实习经历),也可以扩展到2页,没有必要为了一页删减去自己的亮点。 一份合格的简历应该怎么写:https://blog.csdn.net/qq_33445788/article/details/139545096?spm=1001.2014.3001.5502 如何让简历如虎添翼,如何应对面试游刃有余? 解锁这几个秘技!【后端篇】:https://blog.csdn.net/qq_33445788/article/details/139691619?spm=1001.2014.3001.5502
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
php+sql成绩查询系统(系统+论文+答辩PPT).zip
C语言是一种广泛使用的编程语言,它具有高效、灵活、可移植性强等特点,被广泛应用于操作系统、嵌入式系统、数据库、编译器等领域的开发。C语言的基本语法包括变量、数据类型、运算符、控制结构(如if语句、循环语句等)、函数、指针等。下面详细介绍C语言的基本概念和语法。 1. 变量和数据类型 在C语言中,变量用于存储数据,数据类型用于定义变量的类型和范围。C语言支持多种数据类型,包括基本数据类型(如int、float、char等)和复合数据类型(如结构体、联合等)。 2. 运算符 C语言中常用的运算符包括算术运算符(如+、、、/等)、关系运算符(如==、!=、、=、<、<=等)、逻辑运算符(如&&、||、!等)。此外,还有位运算符(如&、|、^等)和指针运算符(如、等)。 3. 控制结构 C语言中常用的控制结构包括if语句、循环语句(如for、while等)和switch语句。通过这些控制结构,可以实现程序的分支、循环和多路选择等功能。 4. 函数 函数是C语言中用于封装代码的单元,可以实现代码的复用和模块化。C语言中定义函数使用关键字“void”或返回值类型(如int、float等),并通过“{”和“}”括起来的代码块来实现函数的功能。 5. 指针 指针是C语言中用于存储变量地址的变量。通过指针,可以实现对内存的间接访问和修改。C语言中定义指针使用星号()符号,指向数组、字符串和结构体等数据结构时,还需要注意数组名和字符串常量的特殊性质。 6. 数组和字符串 数组是C语言中用于存储同类型数据的结构,可以通过索引访问和修改数组中的元素。字符串是C语言中用于存储文本数据的特殊类型,通常以字符串常量的形式出现,用双引号("...")括起来,末尾自动添加'\0'字符。 7. 结构体和联合 结构体和联合是C语言中用于存储不同类型数据的复合数据类型。结构体由多个成员组成,每个成员可以是不同的数据类型;联合由多个变量组成,它们共用同一块内存空间。通过结构体和联合,可以实现数据的封装和抽象。 8. 文件操作 C语言中通过文件操作函数(如fopen、fclose、fread、fwrite等)实现对文件的读写操作。文件操作函数通常返回文件指针,用于表示打开的文件。通过文件指针,可以进行文件的定位、读写等操作。 总之,C语言是一种功能强大、灵活高效的编程语言,广泛应用于各种领域。掌握C语言的基本语法和数据结构,可以为编程学习和实践打下坚实的基础。
chromedriver-win64_116.0.5804.0.zip