-
程序=算法+数据结构
-
算法
-
数据结构
-
搜索算法
- 地图寻路问题
- 博弈问题
- 更为广泛的运用
-
智能算法
- 遗传算法
- 模拟退火算法
- 禁忌搜索
- 人工神经网络
-
优化
- 数学方法的改进
- 预运算来节省时间(空间换时间来避免重复运算)或是重复运算来节省空间。
- 简化算法求得近似解来取代精确解(或最优解)
- 改进数据组织方式,用更少的操作处理更多的数据,甚至避免几余数据的处理。
-
Pascal和C并没有非常严格的语义上的区别,只是在当初语言设计的哲学上略有不同。Pascal想传达一种规则的结构化观念,让使用者潜移默化地接受这种观念;而C语言则想尽可能地贴近机器的固有模型,提供一种程序员更容易接受的描述工具。
-
似乎在今天,由BASIC入门来编程的人越来越少,C作为主流的时代也正在过去。有时我也有点怀念BASIC,这个简约主义的编程语言 几乎每个受过逻辑学教育的人,都可以快速地理解它并帮助自己解决些问题。从理解编程这件事情本身,我不觉得有比BASIC更好的选择.
-
今天,C对于C++的优势在于简捷,而非高效。当然,由于C++更多的时候容易被编译成更大的代码体积,在内存空间有限到不足以储存下程序代码本身后,还留出大块的内存应付数据的动态分配,所以它没有像 C那样更适合做小内存的嵌入式系统开发。
-
虽然今天C或者C++已经非常贴近机器的原始模型,编译过的代码可以以最高的效率运行,甚至许多糟糕的汇编程序员写出来的代码不如编译器产生的,但这并不能成为拒绝学习汇编的理由。 在合适的场合用汇编写出合适的代码,可以使你的程序跑得更快;而且,绝大多数C++编译器也无法生成一些特殊的指令集,比如 MMXSSE,做特定的优化(这是由语言本身的特性决定的,而非编译器厂商):
了解汇编,也就能了解你的代码最终会以怎样的形态运行于CPU,这对于你理解高级语言,比如 C/C++ 都是很有帮助的。
-
在32位操作系统环境下,每个进程拥有一片连续的内存空间,程序本身和其需要的数据一起共存于此。这片空间的每个字节都可以用一个32位无符号整数定位,每个字节都有唯一的空间位置,我们称之为地址。这里的内存一般并非真正的物理意义上的储存设备,我们把它叫做地址空间。
-
今天,不少人有学会了C++或者Java别的语言就会一通百通的感觉说这话的人,言语中往往透着一种自信。而自信若是过了头,就很容易变成自负。将所有语言看成同类,未免有点坐并观天的嫌疑。
-
C#或许是为了解决 Java 在实际运用中产生的问题的一种解决方案。看起来,C#比Java要美妙一些。既然我两者都没怎么用过,这里给个不恰当的评价,行家看过尽可一笑了之:Java 更像一个实验室研究出来,有着浓厚的学术气味,外观优美超过了它本来应该具有的人们所期望的实用性;而C#则是工程师的结品,外加了许多商业味道,被微软强力地推广
- 这两次变革,一次是从实模式编程到386保护模式的转变,另一次是 DOS平台向Windows平台的过渡。可见保护模式在PC发展历史中的重要性。 所谓保护模式,其实从286开始就有了。之所以叫做“保护”,是因为可以使计算机想同时干几件事情时,各自占用的资源得以被隔离和保护起来,不会因为一个程序的错误而破坏掉整个系统。
- 当一个应用程序被启动时,Windows将创建一个进程,这个进程所拥有应用程序的一个实例和私有的内存、资源这些静态的东西。同时,在创建这个进程时,操作系统还会创建出一个线程与它相关联。线程是Windows中最小的执行单位,Windows同时拥有着很多线程,每个线程都必须关联在某个特定的进程上。
- Windows工作在保护模式下。所谓保护模式,是指可以保护计算机的各种资源设备,让应用程序不能随心所欲地控制它们。在386保护模式下,赋予运行的代码ring0 到ring3 四个权限级别之一。用户加载的程序代码都是运行在最低级别(ring3)下,几乎想做任何与人交互的事情都不可能直接使用对处理器的控制指令实现,而需要经过拥有更高权限的操作系统来操作。
- COM 对于调用者来说,只能看见接口。接口之间采用单继承的模式,所有COM 接口的基类都是IUnknown。每个COM对象的实现被隐藏起来,并可以拥有多个接口。使用时,使用动态类型识别的技术把对象的 IUnkoown接口转换为需要的接口以方便调用相关的方法。
6.1 浅谈代码优化
6.2 并不仅仅是汇编
6.2.1 在算法实现时减少上下文的依赖关系
6.2.2 低效的静态变量
6.2.3 数据的组织
6.2.4 消除除法
6.2.5 避免过大的循环
6.3 汇编和C/C++的混合编程
6.3.1 使用外置的汇编编译器
6.3.2 使用内嵌汇编
6.3.3 C++的函数调用规则
6.3.4 寄存器的使用
6.3.5 _declspec(naked)
6.4 指令使用的技巧
6.4.1 LEA:别样的内存寻址指令
6.4.2 BSWAP:扩展寄存器的个数
6.4.3 缩短指令的字节数
6.4.4 避免跳转指令
6.5 Pentium 的汇编优化策略
6.5.1 UV流水线
6.5.2 AGI地址生成互锁
(Address Generation Interlock)
6.5.3 Pentium Pro,Pentium II和Pentium III
的汇编优化策略
6.5.4 Pentium 4的汇编优化策略
6.5.5 如何测试代码的速度
6.5.6 汇编能干的事情
第7章 SIMD 指令
7.1 单指令多数据编程
7.1.1 Alpha 混合
7.2 MMX
7.2.1 MMX的指令概况
7.2.2 SSE及其对MMX的扩展
7.2.3 SIMD技术在C语言环境下的使用
7.2.4 MMX 编码技巧
7.2.5 SIMD 的应用举例
7.2.6 SIMD编程注意要点
7.2.7 SIMD的性能检测
第8章 引擎中的优化
8.1 Blit的优化
8.2 脏矩形优化
8.2.1 “风魂”中改进的脏矩形算法
8.2.2 滚动优化
8.2.3 覆盖优化
8.2.4 脏矩形在3D游戏界面中的运用
8.2.5 时间和空间的权衡
8.2.6 关于估算
8.3 自己设计精灵格式
8.4 动态数据加载
8.5 小结
第9章 C 和 C++
9.1 从C到C++
9.2 C vs C++,效率至上
9.2.1 全局变量
9.2.2 函数调用的堆栈处理
9.2.3 函数调用的参数传递
9.2.4 临时变量的堆栈使用
9.2.5 代码生成
9.2.6 异常
9.2.7 inline
9.2.8 多态性
9.2.9 标准库的差异
9.2.10 动态内存分配
9.3 优雅的C++
9.3.1 消失了的宏
9.3.2 const修饰及类型转换
9.3.3 隐藏实现
9.3.4 引用而非指针
9.3.5 名字空间
9.4 C++ 的误区
9.4.1 类层次过细
9.4.2 滥用操作符重载
9.4.3 滥用标准容器
9.4.4 滥用动态类型识别和异常
9.4.5 滥用多重继承
9.4.6 忽视C++高级特性的复杂度
9.4.7 学习C++
9.5 动态内存分配的优化
9.5.1 另一种优化策略:多次分配,一次释放
9.5.2 垃圾回收
9.5.3 再论动态内存分配
9.6 template
9.6.1 封装C++的成员函数调用
9.6.2 常数数量的对象复制
9.6.3 对象计数
9.6.4 避免重复代码
9.6.5 选择最佳的容器
9.6.6 延迟运算
9.6.7 编译时计算的游戏
9.7 小结
第10章 调试
10.1 assert及程序错误的提前发现
10.1.1 崩溃的程序不说谎
10.1.2 为软件维护多个版本
10.1.3 前置条件和后置条件
10.1.4 自己实现一个assert
10.1.5 不正确的assert使用
10.1.6 为assert分级
10.1.7 assert的引申:检查函数返回值
10.1.8 释放的指针需要置空吗
10.2 让程序更利于调试
10.2.1 录像
10.2.2 实现一个log类
10.2.3 跟踪代码运行的流程
10.2.4 为内存分配加上一个壳
10.3 RELEASE版本的调试
10.4 小结
第11章 脚本
11.1 为什么需要脚本
11.2 应该用脚本做些什么
11.3 脚本不应该做什么
11.4 如何嵌入脚本语言
11.5 选择一种脚本语言
11.6 实战嵌入式脚本Lua 5
11.6.1 嵌入Lua
11.6.2 使用coroutine驱动游戏逻辑
11.6.3 封装C++中的对象
11.6.4 回调机制
11.7 反外挂技术
11.7.1 防止加速器
11.7.2 防止分析伪造网络包
11.7.3 防止逆向工程
11.7.4 防止代码钩子
11.7.5 惩戒外挂作弊者
11.7.6 安全地将信息传递给服务器
11.7.7 防止模拟输入
第12章 版本控制
12.1 常用版本控制软件
12.2 版本控制工具在项目中的使用
12.3 不仅仅是程序才需要
第13章 开发方法
13.1 失败的经验
13.2 成功的经验
13.3 对游戏开发方法的一些思考
第14章 编程和游戏
14.1 操作
14.2 角色设定
14.3 再谈技术
14.4 浅谈网络游戏
14.5 小结