读人Readman
读人Readman
美好发现,从来不晚……
关注数: 12
粉丝数: 131
发帖数: 3,045
关注贴吧数: 2
【钢笔画-实物临摹】第二十六至二十七次作品
【钢笔画-实物临摹】第二十三次至第二十五次作品
【钢笔画-实物临摹】第二十一次至二十二次作品
【钢笔画-实物临摹】第十六次至第二十次作品
【钢笔画-实物临摹】第十一次至第十五次作品
【钢笔画-实物临摹】第六次至第十次作品
【钢笔画-实物临摹】第一次至第五次作品
【咨询】贴吧私信无法打开 许久不登录,刚看到有三个私信,但因为被提示网页私信功能正在升级,要扫码使用手机客户端……谁都知道手机客户端是怎么回事,我是坚决不会用的,或者请问谁有没有纯净版的贴吧客户端可以介绍给我?在这里先谢谢了。
【千分之一的幸存者31:长大后我就成了你】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 学习C语言肯定会有一种熟悉的陌生人的感觉。 熟悉,是因为虽然号称几十个关键字和符号,但这些关键字要么就是反映本意的英文单词,要么就是一些小学生都学过的数学符号。 同时又会有那么一些符号看起来眼熟,但意思又完全不是那么个意思,其中我觉得令我印象深刻的就属=和==了。 我怀着敬意推测,C语言在设计之初就想着要比之前和同时代的编程语言更加的人性化,最大程度贴近自然语言,要知道在C语言之前的编程语言……如果你觉得C语言已经很晦涩难懂让你崩溃的话,那么和它同时代和之前的那些编程语言就可以妥妥的直接将你送去疯人院。 为了最大程度人性化,尽量使用现有符号而非再发明新的符号显然是最好的选择。 数学基本符号的加减乘除我们不必多说,哦,似乎需要说一下,乘号不是x而是*,这个不必需要懂编程,只要会用点电脑的都知道。 只有等号是一个很特殊的符号,因为它并不表示等于,例如int b=0;你觉得我们是建立了一个整数类型的变量起了个名字叫做b,还让它等于0……打住,如果你是这样想的就已经有问题了,因为这里的意思不是让b等于零,而是把零这个数据传进变量b中,是赋予的意思,简称赋值。 那么如果需要用到真的等于这个意思的时候怎么办,很简单,增加一个等号,==变成这样,这个就不必多说了地球人都知道,就跟用星号代替叉表示乘号一样。 至于星号代替叉的原因,其实就是为了避免看走眼,因为叉号跟x实在太像,包括我现在用手机打字输入法里都是调不出来叉号的,只能写汉字。 如果还不好理解,我再换种方式,因为我就是这么理解的,赋值的意思是我把这个东西给你我你就有了这个东西,等于的意思是我就让你看看我这个东西并声称你本来就有的那个东西跟我的这个是一样的。
【千分之一的幸存者30:即时演算与CG动画】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 自从游戏诞生的第一天起,程序员们就在想方设法的完善其内容,使之更加的生动与丰富,我们如今在东京电玩展上或者美国E3展上能够看到很多游戏的预告片,这些预告片制作的极其精美,基本上可以跟好莱坞大片的预告片比肩甚至超越。 而这些预告片多半都是从游戏本体的过场动画中剪辑出来的,说起过场动画,似乎对于一个游戏来说过场动画已经是必不可少的内容。 过场动画的历史很早,我们不说太远,就超级玛丽来说,如果你在开始菜单界面稍微等一会而不进行任何操作的话,游戏就会开始进行一些自主操作的演示。 基本上任天堂的红白机游戏都有这一机制,这就可以算是过场动画了,真正把过场动画发扬光大的,大概就是索尼推出playstation的时候。 在这之前,游戏主机都使用卡带,八零后对此一般不陌生,如果有人好奇拆开卡带的塑料外壳,就会发现里面是一块电路板,样子是不是有点眼熟? 是的,内存条,它看上去就像是一块样子奇怪的内存条,这是任天堂公司独有的专利技术,具有高读取速度和保存数据的非易失性,缺点是容量非常小,大概也就不超过四个兆MB。 索尼则另辟蹊径使用光盘作为游戏数据媒介,光盘的好处是显而易见的,容量非常大,当时流行的是cd光盘,一张盘保底也有五百兆的容量,虽然读取速度慢,容易划伤,但相比起卡带的颗螺狮里做道场,游戏的开发者们更喜欢光盘。 作为玩家一开始是感受不到什么的,因为大家之前都在玩超级玛丽,就算有最终幻想那样的,也只是几个像素图在那里动来动去意思意思而已。 直到史克威尔公司推出了惊艳全场的最终幻想七,玩主机游戏的玩家也许在国内并不多,从当年那个时代过来的更少,对这种感觉如果不太能体会的话,仅从制作技术方面,你可以想象一下前一天你还在看小兵张嘎并且坚定的认为世上就只有这种黑白电影可看,然后第二天就让你坐在影院里带着立体眼镜看3Dmax巨幕阿凡达……那种冲击力,不可言喻。 说实在的最终幻想七的实际游戏画面用今天的眼光看是在不咋地,用一句调侃的话来形容就是“满屏游戏性”(满屏马赛克)。 但它的过场动画拿到今天来仍不失水准,甚至用源代码进行高清渲染之后还可以继续拿出来骗钱(卡婊:嗯?),从此以后,游戏就开始流行精美的过场动画,这些动画大多是用专业的三维软件制作并花费很多时间渲染,最后录制出来的视频文件。 再后来的发展可以说是一张光盘,占用容量第一位的就是大量的动画视频文件,这些文件甚至可以提取出来单独播放,第二位的是图片声音素材,游戏的本体代码反而是体积最小的。 在审美疲劳之后有的玩家甚至把这种塞满过场动画的游戏称为播片游戏,我倒是不觉得有什么审美疲劳,只是唯一不爽的事就是看完了极其精美的过场动画之后马上面对满屏游戏性实际画面的那种落差感,有种上当受骗的感觉。 而且对于过场动画的制作投入过多(想想3d动画电影的制作成本),对于实际游戏过程的内容制作就不那么用心了,毕竟游戏公司是要挣钱的,对一个游戏的成本投入有限,侧重一方面就势必轻视另一方面。 返璞归真,这个词的意思我也是随着年龄的增长才渐渐有所体会,很多时候你费尽心思去追求一个事物,去做一件事情,到头来发现你最初最简单甚至简陋的那个样子那个想法,才是最符合你需要的。 从PS上的合金装备一代开始,开发者发现,用代码指令去控制人物动作和语音,即时演算生成的过场更具有自由性和便利性。 玩家发现,全程画风保持了一致,尽管简陋了些,但毫无违和感和落差感,而且在游戏体验上制作的更用心了,更好玩了。 对于我这样的初学者,手头就只有一台隆隆作响的二手组装台式电脑,那么能用代码去控制素材的组合变换移动从而即时演算出一段动画,显然更符合我的实际需要。 比如007的开场,我就可以写代码,让屏幕背景全白,加载一张只有一个圆洞的黑色图片,让它自左向右移动,同时播放背景音乐,碰到屏幕边缘再回来,同时控制人物走动的图片中心和圆心保持一致,自右向左移动,圆洞和人物都走到屏幕中央停下,播放枪声音乐,命令屏幕抖动,再加载一张透明图片,让它逐渐变红,最后屏幕全黑,结束。 就是这样,你就是导演,素材就是你的员工,代码就是你们沟通的手段,你作为一个程序员,一个游戏开发者,得到了最大的自主权,自由! 如今,过场动画已经越来越多的采用即时演算,而且随着主机性能的提升,现今的即时演算已经足可比肩过去的预录制动画,甚至有超越。
【千分之一的幸存者29:牛顿迭代法与雷神之锤(二)】 本篇并非原创,而是怀着敬畏之心,搜集整理编撰得来,不敢妄自菲薄,如需转载,也不需要注明出处与作者,谢谢。 1999年12月,美国id Software公司发布了名为“雷神之锤III”的电子游戏。它是第一个支持软件加速的游戏,取得了极大成功。(由于影响力过大,文化部于2004年将它列入了非法游戏名单) Quake-III Arena (雷神之锤3)是90年代的经典游戏之一。该系列的游戏不但画面和内容不错,而且即使计算机配置低,也能极其流畅地运行。这要归功于它3D引擎的开发者约翰-卡马克(John Carmack)。事实上早在90年代初DOS时代,只要能在PC上搞个小动画都能让人惊叹一番的时候,John Carmack就推出了石破天惊的Castle Wolfstein, 然后再接再励,doom, doomII, Quake...每次都把3-D技术推到极致。他的3D引擎代码资极度高效,几乎是在压榨PC机的每条运算指令。当初MS的Direct3D也得听取他的意见,修改了不少API。 雷神之锤III并不是id Software公司的第一次成功。早在1993年开始,这家公司就以“毁灭战士”系列游戏名闻天下。1995年,“毁灭战士”的安装数超过了当年微软的windows 95。据传比尔盖茨才曾经考虑买下id software。(id software公司后来被推出过“上古卷轴”系列的Bethesda公司买下) id Software所取得的成功很大程度上要归功于它的创始人约翰·卡马克。马克尔也是一个著名的程序员,他是id Software游戏引擎的主要负责人。 回到刚才提到的雷神之锤,马克尔是开源软件的积极推动者,他于2005年公布了雷神之锤III的源代码。至此人们得以通过研究这款游戏引擎的源文件来查看它成功的秘密。 在其中一个名字为q_math.c的文件中发现了如下代码段。 float Q_rsqrt( float number ) { long i; float x2, y; const float threehalfs = 1.5F; x2 = number * 0.5F; y = number; i = * ( long * ) &y; // evil floating point bit level hacking i = 0x5f3759df - ( i >> 1 ); // what the ***? y = * ( float * ) &i; y = y * ( threehalfs - ( x2 * y * y ) ); // 1st iteration // y = y * ( threehalfs - ( x2 * y * y ) ); // 2nd iteration, this can be removed #ifndef Q3_VM # ifdef __linux__ assert( !isnan(y) ); // bk010122 - FPE? #endif #endif return y; } 这段代码的作用就是求number的平方根,并且返回它的倒数。 经过测试,它的效率比上述牛顿法程序要快几十倍。也比c++标准库的sqrt()函数要快好几倍。此段代码有一个奇怪的句子: i = 0x5f3759df - ( i >> 1 ); // what the ***? 这句话的注释是“what the ***?”,翻译过来就是“我靠?” 任何受过程序训练的人看到这句大概都会在想,这句话到底在搞什么鸟? 之所以会出现这种奇怪的注释,要么是此段程序的作者(可能是马克尔)根本不知道该如何解释清楚,或者是维护这段程序的程序员完全看不懂这句话,所以有点儿抓毛。而实际上,它的作用(再加上y = y * ( threehalfs - ( x2 * y * y ) )这句牛顿迭代)就是求平方根。 至于是为什么,可能只有作者自己知道,甚至这种灵光一闪的产物连作者自己也说不清为什么。 以雷神之锤III程序为蓝本可以写出比sqrt()更强大的求平方根函数: int sqrt(float x) { if(x == 0) return 0; float result = x; float xhalf = 0.5f*result; int i = *(int*)&result; i = 0x5f375a86- (i>>1); // what the ***? result = *(float*)&i; result = result*(1.5f-xhalf*result*result); // Newton step, repeating increases accuracy result = result*(1.5f-xhalf*result*result); return 1.0f/result; } 我们知道,越底层的函数,调用越频繁。3D引擎归根到底还是数学运算。那么找到最底层的数学运算函数(在game/code/q_math.c), 必然是精心编写的。里面有很多有趣的函数,很多都令人惊奇,估计我们几年时间都学不完。在game/code/q_math.c里发现的段代码比(float)(1.0/sqrt(x))快4倍: 注意这个函数只用了一次叠代!(其实就是根本没用叠代,直接运算)。编译,实验,这个函数不仅工作的很好,而且比标准的sqrt()函数快4倍!要知道,编译器自带的函数,可是经过严格仔细的汇编优化的啊! 这个简洁的函数,最核心,也是最让人费解的,也就是标注了“what the ***?”的一句 i = 0x5f3759df - ( i >> 1 ); 再加上y = y * ( threehalfs - ( x2 * y * y ) ); 两句话就完成了开方运算!而且注意到,核心那句是定点移位运算,速度极快!特别在很多没有乘法指令的RISC结构CPU上,这样做是极其高效的。 算法的原理其实不复杂,就是牛顿迭代法,用x-f(x)/f'(x)来不断的逼近f(x)=a的根。 没错,一般的求平方根都是这么循环迭代算的但是卡马克(quake3作者)真正牛B的地方是他选择了一个神秘的常数0x5f3759df 来计算那个猜测值,就是我们加注释的那一行,那一行算出的值非常接近1/sqrt(n),这样我们只需要2次牛顿迭代就可以达到我们所需要的精度。好吧如果这个还不算NB,接着看: 普渡大学的数学家Chris Lomont看了以后觉得有趣,决定要研究一下卡马克弄出来的这个猜测值有什么奥秘。Lomont也是个牛人,在精心研究之后从理论上也推导出一个最佳猜测值,和卡马克的数字非常接近, 0x5f37642f。卡马克真牛,他是外星人吗? 传奇并没有在这里结束。Lomont计算出结果以后非常满意,于是拿自己计算出的起始值和卡马克的神秘数字做比赛,看看谁的数字能够更快更精确的求得平方根。结果是卡马克赢了... 谁也不知道卡马克是怎么找到这个数字的。 最后Lomont怒了,采用暴力方法一个数字一个数字试过来,终于找到一个比卡马克数字要好上那么一丁点的数字,虽然实际上这两个数字所产生的结果非常近似,这个暴力得出的数字是0x5f375a86。 Lomont为此写下一篇论文,"Fast Inverse Square Root"。 论文下载地址: http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fwww.math.purdue.edu%2F~clomont%2FMath%2FPapers%2F2003%2FInvSqrt.pdf&urlrefer=0e762cb4a43bbd220b16a63e7dc6a359 http://tieba.baidu.com/mo/q/checkurl?url=http%3A%2F%2Fwww.matrix67.com%2Fdata%2FInvSqrt.pdf&urlrefer=49a8605a5525e798cb2a76362806027a 参考:<IEEE Standard 754 for Binary Floating-Point Arithmetic><FAST INVERSE SQUARE ROOT> 最后,给出最精简的1/sqrt()函数: float InvSqrt(float x) { float xhalf = 0.5f*x; int i = *(int*)&x; // get bits for floating VALUE i = 0x5f375a86- (i>>1); // gives initial guess y0 x = *(float*)&i; // convert bits BACK to float x = x*(1.5f-xhalf*x*x); // Newton step, repeating increases accuracy return x; } 大家可以尝试在PC机、51、AVR、430、ARM、上面编译并实验,惊讶一下它的工作效率。 前两天有一则新闻,大意是说 Ryszard Sommefeldt 很久以前看到这么样的一段 code (可能出自 Quake III 的 source code): float InvSqrt (float x) { float xhalf = 0.5f*x; int i = *(int*)&x; i = 0x5f3759df - (i>>1); x = *(float*)&i; x = x*(1.5f - xhalf*x*x); return x; } 他一看之下惊为天人,想要拜见这位前辈高人,但是一路追寻下去却一直找不到人;同时间也有其他人在找,虽然也没找到出处,但是 Chris Lomont 写了一篇论文 (in PDF) 解析这段 code 的算法 (用的是 Newton’s Method,牛顿法;比较重要的是后半段讲到怎么找出神奇的 0x5f3759df 的)。
【千分之一的幸存者28:牛顿迭代法与雷神之锤(一)】 作者:李文超 本篇文章我是怀着敬畏之心来撰写的,左想右想是实在没有信心能够完全驾驭,所以很多内容都来自于网络搜集整理的资料,不敢说是原创,本篇如需转载,请不必注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 本来我是抱着随笔和入门的态度来写的,基本上跟高深和专业是扯不上关系的,可为什么今天情不自禁要谈一谈牛顿迭代法呢? 你可以问自己一句,你玩过雷神之锤吗? 没有……好吧,你玩过荣誉勋章吗? 也没有……好吧,那你总该玩过使命召唤吧! 还是没有,好吧……请你出门左转,我不该打扰你的时间的。 那么,对于玩过上述游戏的人,例如,你有想过你的准星在屏幕上移动的时候,电脑是怎么判断你击中了敌人的呢? 首先,准星就要跟随你的鼠标进行运动,电脑要计算并判断这个轨迹,而这个轨迹其实是一个弧线,不管你的手怎样小心,你的鼠标在屏幕上划过的永远是一个弧线,要跟踪这条弧线,并尽量精确的判断这个轨迹上的所有点,就必须用数学方法,因为要考虑到运行效率,毕竟是紧张刺激的射击游戏,用数学方法才能达到最高的运行效率。 这才是牛顿迭代法在这里的真正作用。 牛顿迭代法(简称牛顿法)由英国著名的数学家牛顿爵士最早提出。但是,这一方法在牛顿生前并未公开发表。 牛顿迭代法(Newton's method)又称为牛顿-拉夫逊(拉弗森)方法(Newton-Raphson method),它是牛顿在17世纪提出的一种在实数域和复数域上近似求解方程的方法。多数方程不存在求根公式,因此求精确根非常困难,甚至不可能,从而寻找方程的近似根就显得特别重要。方法使用函数f(x)的泰勒级数的前面几项来寻找方程f(x) = 0的根。牛顿迭代法是求方程根的重要方法之一,其最大优点是在方程f(x) = 0的单根附近具有平方收敛,而且该法还可以用来求方程的重根、复根,此时线性收敛,但是可通过一些方法变成超线性收敛。另外该方法广泛用于计算机编程中。 已经证明,如果是连续的,并且待求的零点是孤立的,那么在零点周围存在一个区域,只要初始值位于这个邻近区域内,那么牛顿法必定收敛。 并且,如果不为0, 那么牛顿法将具有平方收敛的性能. 粗略的说,这意味着每迭代一次,牛顿法结果的有效数字将增加一倍。 迭代法也称辗转法,是一种不断用变量的旧值递推新值的过程,跟迭代法相对应的是直接法(或者称为一次解法),即一次性解决问题。迭代算法是用计算机解决问题的一种基本方法。它利用计算机运算速度快、适合做重复性操作的特点,让计算机对一组指令(或一定步骤)重复执行,在每次执行这组指令(或这些步骤)时,都从变量的原值推出它的一个新值。 牛顿法的作用是使用迭代的方法来求解函数方程的根。简单地说,牛顿法就是不断求取切线的过程。 对于形如f(x)=0的方程,首先任意估算一个解x0,再把该估计值代入原方程中。由于一般不会正好选择到正确的解,所以有f(x)=a。这时计算函数在x0处的斜率,和这条斜率与x轴的交点x1。 f(x)=0中精确解的意义是,当取得解的时候,函数值为零(即f(x)的精确解是函数的零点)。因此,x1比x0更加接近精确的解。只要不断以此方法更新x,就可以取得无限接近的精确的解。 但是,有可能会遇到牛顿迭代法无法收敛的情况。比如函数有多个零点,或者函数不连续的时候。 下面介绍使用牛顿迭代法求方根的例子。牛顿迭代法是已知的实现求方根最快的方法之一,只需要迭代几次后就能得到相当精确的结果。 下面这种方法可以很有效地求出根号a的近似值:首先随便猜一个近似值x,然后不断令x等于x和a/x的平均数,迭代个六七次后x的值就已经相当精确了。 例如,我想求根号2等于多少。假如我猜测的结果为4,虽然错的离谱,但你可以看到使用牛顿迭代法后这个值很快就趋近于根号2了: ( 4 + 2/ 4 ) / 2 = 2.25 ( 2.25 + 2/ 2.25 ) / 2 = 1.56944.. ( 1.56944..+ 2/1.56944..) / 2 = 1.42189.. ( 1.42189..+ 2/1.42189..) / 2 = 1.41423.. 这种算法的原理很简单,我们仅仅是不断用(x,f(x))的切线来逼近方程x^2-a=0的根。根号a实际上就是x^2-a=0的一个正实根,这个函数的导数是2x。也就是说,函数上任一点(x,f(x))处的切线斜率是2x。那么,x-f(x)/(2x)就是一个比x更接近的近似值。代入f(x)=x^2-a得到x-(x^2-a)/(2x),也就是(x+a/x)/2。 二分法是一步步逼近零点,比较好理解,但收敛的速度比较慢。而牛顿迭代法是用切线来逼近零点的,收敛的速度很快,但要求的条件也高。首先要有一个区间,在这个区间的端点函数值反向,其次第一次迭代点不能随意取,否则第一次迭代后的点可能跑出原先的区间,收敛性就不一定能保证了(即有的情况也能有收敛性,有的情况就没有收敛性了,全看函数的性能)。 同样的方法可以用在其它的近似值计算中。Quake III的源码中有一段非常牛B的开方取倒函数。
【千分之一的幸存者27:从零开始】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 从零开始,这句话和这个概念其实我们并不陌生,但这个概念我们更多的是用在生活中去做事情的方面,是比较抽象的,意思是一切现成的东西都还没有,需要你自己去从无到有的创造出来。 但是一旦具体到数字排序的时候,我们就会本能的从一开始,往后二三四五……这个样子去排列和处理数字。 因为我们本能的知道现实生活中零是没有意义的,零就是什么都没有,所以我们在现实中计数往往都是从一开始,你不可能手捧一团空气占个位置说这也算一个。 但计算机不同,电脑不同,电脑这种实体是脱胎于数学模型的,它的先天以及后天条件都决定了它计数是从0到9,而不是从一到十,任何时候计数都是从零开始,真正的从零开始。 比如说数组,你建立了一个数组,命名为int i[10];这个意思就是这个数组可以有十个位置供你存储数据,然后你往里面保存了十个数据。分别是12345678910。 接下来,你命令电脑,把第一个数据给我调出来! 然后电脑给你了一个2。 …… 直男的第一反应可能是泪流满面拍桌子,声情并茂,声泪俱下:“说好的电脑永远不出错呢?说好的机器永远不会背叛人类呢?童话里都是骗人的!” …… 其实电脑一点都没错,你为错的是世界,错的其实是你自己。因为电脑调取数据是从第零号位开始的,你往里面存了12345678910,真是的情况是,1被保存在第零号位上,2被保存在第一号位上,依次类推……。 C语言的作用是让人与电脑进行沟通,沟通是对等的,甚至人要迁就一点电脑的性子,而不是粗暴的让电脑服从人的想法,当然现在更多更新的高级编程语言越来越趋向于人性化,趋向于自然语言的形式,也许有一天程序员可以像《光环》里士官长与蔻塔娜那样与电脑进行沟通与交流。 我,期待着这一天。
【千分之一的幸存者26:最熟悉的陌生人(三)】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 相信没有人不知道数是什么,也相信没有人不知道组是什么,但把这两个字组合到一起就不知道什么意思了? 汉字确实博大精深,看似平常的两个字组合一下确实能变成另外一个东西的意思,但这其中又是有规律的,组合也要遵守基本法嘛。 我们先说说你在键盘上面敲字,输入的数据保存在哪里? 都这个时候了你要是还说保存在硬盘里……那我也拿你没办法,我只能再说一遍,所有对于数据的操作,包括输入,全部都是在内存中完成的。 你可以看作是全部都在内存条里操作,这下知道为什么内存越大电脑反应速度越快了吧。 什么,你说是保存在硬盘里? 也对,也不对,因为保存在硬盘这一步是对数据进行操作完成之后,最后的最后的步骤才是保存到硬盘,下一次你再打开这个文件的时候,程序又会把所有数据都加载到内存里供你操作。 你又会问……你话咋嫩多累……问题多其实是好事,有问题说明至少你有主动学习的意愿,否则你一点兴趣都没有,连问题都是懒得问的。 你又会问,为啥不在硬盘上操作呢?非要倒腾到内存里完事再倒腾到硬盘里这么麻烦?冯诺依曼那老不死…… (赶紧捂嘴)你小声点吧,你以为科学家们愿意这么麻烦吗,唯一的原因就是,现在仍然找不到一种物质,既具有闪电般的读取速度,又具有泰山般的数据存储稳定性。 换句话说,科学家们也想让硬盘内存合二为一,但是没辙,至少目前还没辙,而且也不关人家冯老先生的事,人家只是描述了这么一个抽象的模型,预言了大概结构而已,真正电子计算机人家连什么样都没看见就驾鹤西归了。 所以,咱们先说数据在内存中是怎么保存的。 之前咱们说使用变量,先定义一个int i然后就可以往里面保存数字了,但问题是这个i只能接收一个数字,多半个都不行。 而很显然你要往里面输入的数据可不止一个数字,比如说聊qq,至少都是一次一句话,这么一串连续的数据你想用一个int类型的变量i来保存,连做梦都不行,因为电脑说一就是一说二就是二,没有商量的余地,C语言也是一门逻辑严谨的编程语言,否则也活不到今天早就被淘汰了。 你会想,那我多定义几个int变量不就行了吗?好主意,恭喜你迈出了第一步,不管成不成,迈出这第一步很重要。 C语言的设计者大概也是这么想的,但是他没有这么直男,沿着这个思路,他设计了一个新的类型的变量,用于保存大型连续的数据。 这个类型就是数组。 数据的组。 int还是那个int,i还是那个i,只是后面跟的不再是一个单一的数字,而是[]。 完整的形态是int i = [x]; 这个大括号是什么意思呢,没什么意思,就是告诉电脑,我要申请在内存中一块连续的空间用来暂时存放数据,这块空间有多长呢?看我方括号里面的数字,这个x你写多少就是多少个位置,你写一个10,那就是十个int类型的位置分配给你,你就可以储存比较大的数据了。 能存储多大的数据,就要看你申请多少内存空间了,理论上只要你的内存条撑得住,你申请多少空间都可以。
【千分之一的幸存者24:最熟悉的陌生人】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 我们上次提到了,在你写代码的时候,‘A’和A是完全的两码事,一开始肯定有人想不通,难道加了个印号,A就不是A了? 因为咱们是在C语言的范围内来讨论的,所以这个带不带引号的事情咱们只在这里说。 从某种意义上,你写的代码分为两个部分,一部分是告诉电脑怎么后台运行,一部分是告诉电脑怎么显示给人看的。a就是后台运行的部分,‘a’则是显示给人看的。 具体他们怎么个不一样法呢? 编码不一样。 我们知道,电脑根本不能识别除机器码以外的任何语言,也就是说它只认识一串串的零和一,C语言是什么?能吃吗? 当然,只要经过编译器编译,C语言也是可以吃的,而且很美味。我们只说在C语言内部,对于各种字符的代表码有一套自己的规定,你翻开任何一本C语言的教科书,大概都能在后面的附录找到这样一张码表,上面密密麻麻写满了各种数字对应的键盘符号。 这张码表叫做阿斯克贰码表,就跟国际单位制一样,都是大家开会讨论统一口径之后的结果,不管好不好用,总之大家都在用就是了。 这张码表其实跟摩尔斯电码表没有本质上的区别,都是用一组简易字符来代表一组更复杂的字符,摩尔斯码表只用点和划的不同组合就能代表英文中的所有字符,阿斯克贰码表使用一组数字来代表键盘上的所有符号。 当然,我敢说你现在手上八成是没有一本教材的,更别提码表了,那我就来举个例子,有点直观感受,你翻开码表。 这张表项目很多,然而我们只用看两列,十进制值和终端显示。 我们以最简单的0来说,当你用手指一路滑下来,你就会发现,终端显示(输出到屏幕)的0在这张表上对应的其实是48,也就是说你想在运行程序的时候在屏幕上显示出0这个数字,你写代码的时候就要命令电脑显示代号为48的那个字符。 这样说我觉得应该是可以说明白了,如果以后有想到更通俗易懂的方法我们会再来谈。
【千分之一的幸存者23:“花”非花,“叶”非叶】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 上次咱们推测了指针的起源,简单来说就是电脑很傻,他每次需要往函数里面传参数的时候都是暴力复制一份进去,内存占用立即翻倍,非常直男,简直直男癌,如果程序代码达到一定规模,内存和硬盘占用更是几何倍数增长。 于是C语言的设计者为了解决这一问题就增加了一个新的数据类型叫做指针,专门用来保存变量的地址,这样电脑就知道调用数据的时候按着这个地址去找到数据而不是复制一份。 等等,你说为什么做这种修修补补的事情?直接把C语言重新设计不就好了? 如果你跟谁有仇,就请你教唆他在千千万万广大奋战在第一线日夜不息的码农们说出这句话。保证他活不过三分钟。 无知者永远都是无谓的,你知道设计一个编程语言出来需要多么巨大的精力与天赋吗?修修补补的工作量已经不是人干事了,还推翻重新设计……你瞅啥!说你呢!怎么的,来来,咱俩唠唠…… 以上都只是推测,我人微言轻,根本不可能有机会当面向C语言的设计者请教真相,但改代码的工作量真不是人干事,我觉得宁愿重新写也不愿意改。 曾经有一篇文章叫做来自地狱的客户,讲的就是一线基层技术人员遇到的各种恶心事,其中就有程序员与产品经理。 说起来产品经理也算是程序员的客户了,一般来说产品经理必须应该是技术出身,这样他才懂得一个项目的可行性是否靠谱,但现状就是,产品经理几乎都是销售出身,他们根本不懂技术,他们也不屑于了解技术,他们眼中营销才是王道,你们这些如工蚁般的码农就只配舔脚。 最常见的情况就是,我又一拍脑袋想到了一个不错的点子,你把这个功能实现进去吧,改改代码而已嘛,下班之前拿给我看。 第二天, 产品经理:我不是让你昨天下班之前给我看实现效果的吗! 码农:劳资TM还没下班! 嘿嘿,说多了,咱们这次应该说的不是这个,应该是字符。在代码里,“a”和a代表的意思完全不同,前者代表一个字符,是个数据,后者代表一个变量名,是用来保存东西的。 为什么要说这些,因为为了接近人类的输入习惯,在网页上输入个用户名密码,发个邮件之类的,全部都是以字符的形式输入,接收,传输至服务器的,但是服务器根本就不能直接处理这些字符,服务器只认识0和1,所以你就要在编写代码的时候设计一套算法,把接收到的字符全部都转换成编码。 第一次看到不理解很正常,慢慢会理解的,我也是有不理解的事物,后来的某一天忽然就明白了,所以不用急,日子长着呢。 这一篇写的比较匆忙,还望见谅,毕竟是业余爱好。
【千分之一的幸存者22:指针之殇】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 其实本来想说说变量的简单用法的,不过翻了翻前面发现已经涉及过了,而且还举了例子,如果想不起来的话我可以再写一下。 int i = 0; scanf(%d,&i); printf(“%d”,i); 这三行鬼画符的意思就是,立项一个变量起名字为i;接收用户输入的数字保存在i里;把变量i里面保存的数值输出至屏幕。 诶?好像有多了什么东西?%d是什么鬼? %d不是鬼,就像int表示整数一样,C语言对于数据类型是要求程序员自己来把握控制的,%d的意思就是十进制,也就是计算机会以十进制的形式接收,保存和输出你的数据。 我们知道现在数字的进制除了十进制还有很多,例如计算机只能看懂二进制,时分秒是六十进制……所以我们需要在编程序的时候对数据类型和进制操一下心。 因为咱们这里只谈C语言(我也只会c),后来出现的很多更高级的编程语言是不需要程序员操心这种事情的,编译器会帮你把这些事都干了,但是有所长就有所短,如果你是个中学生的话,不妨先去了解一下Python,没有规定一定要从哪一门语言开始学起,甚至Python见效更快,至少我对它的第一印象就是“卧槽!居然可以这样!”当然如果你直接从Python开始恐怕就体会不到我这句话的意境了。 然后简单说一下指针。 首先谈谈我对于指针的看法,我觉得这个翻译虽然符合整体意思,但对于第一次看到它的人来说并不容易理解,因为我们脑子里首先想到的就是一根针,没有别的,就是一根针,这玩意跟编程有毛关系? 教科书一般就是跟你解释,这个指针是一种变量类型,专门保存的是数据的地址云云。 而我想推测一下源头,谈一谈它是怎么来的,为什么会设计这样一个东西,要知道世间万物有果必有因,了解了根本,就好理解它了。 函数我们已经知道了,函数运行可以没有参数,那它就是执行的一系列预设动作,只能完成一种固定行为,出一个结果;函数也可以有参数,你把相应的参数传进去,它会按照既定程序运算,根据参数的不同得出不同的结果。 函数的调用方式是在主函数里写出需要调用的函数名,在相应位置填入参数,这个数值就会被传出主函数,传到被调用的函数里面,然后计算,然后得出结果。 开始一切的一切都是美好的,直到有一天,做了一个大项目,说白了就是一个大程序,几十万行代码那种,需要调用的函数次数多的无法计数,然后就发现在调试运行的时候,程序的反应开始变慢,程序的体积也变得非常之大。 C语言的那个年代电脑硬盘普遍的也就百多个兆(MB),人们对于程序的体积有着近乎变态的要求,不像如今一个游戏几十个GB都稀松平常(真不知道老滚那些几百个GB的版本是怎么弄得),所以程序越小,运行越快,人们就越喜欢。 于是C语言的设计者就开始试图解决这个问题,他最终找到了原因,就是函数的参数传输方面有缺陷,我们预想的是数据直接被读进函数中,中间没有什么幺蛾子,但实际发现函数在接受参数的时候是整个把数据复制了一份运行完了再拷出来! 这就不行了呀,一个数据虽然只占8bit的空间,但一旦代码达到几十万行,规模变得很大的时候……那真是有多少内存都不够你用的。 必须想个办法。 于是,指针被设计了出来。 一般教科书会写成int *p = &i;但我认为应该把*和int写在一起而不是跟p写在一起,因为int*才是一个完整的类型名称。 上面那行鬼画符的意思其实就是我定义了一个int*类型的变量,这个变量的名字起名叫做p,它保存的是变量i的内存地址,&这个符号的意思是取地址,i前面加上这个符号就意味着你把i在内存中的地址取出来了,最后,你在往函数中传参数的时候也别写i了,直接写这个p就行,函数就会顺着这个地址找到数据,而不会再傻乎乎的去复制一份来运行了。 然后设计者觉得很有成就感,一定要起个特殊的名字纪念一下,嗯,就叫指针吧!不爽是吗,你咬我啊!有本事你也设计一个自己的编程语言啊,你就可以尽情享受去难为别人的感觉了。 以上纯属脑补,与真实无关。 是不是似曾相识?好像某软就喜欢这样先把产品推出来然后漫长的打补丁更新,因为人无完人,事物也没有完美的,但是我们可以一直去完善它,让它接近完美。
【千分之一的幸存者21:预则立不预则废】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 中国有句古话叫做,凡事预则立不预则废。 往好听了说就是,如果你想要达成这个目的,你就要先做好相应的准备,不管是前期调研还是物质上的准备都要做好,然后坚定的去实现它,否则你先期的投入就白费了。 往不好听了说就是,别占着茅坑不拉屎,后面拎着裤子排队等的人都快一个加强连了,你不上让别人上! 在C语言里就是变量的定义与使用。 变量我们前面有稍微提及过,它是什么个意思呢?意思就是地上本来没有坑,然后你挖了个坑,在这个坑的边上竖了一块牌子,上书“我的坑_1”,你声称这个坑你已经占了,虽然里面是空的什么都没有,但是你已经先占了,以后再往里面放点什么或者拿出来点什么都随你的便,甚至你不想用这个坑了还能再填上,这都是你的自由。 当然,挖坑不填是不好的习惯,千万不要学坏,要知道上一个挖坑无数的家伙已经被某个不知名的病娇粉丝在月黑风高之夜填进了他自己曾挖过的一个坑里,至今坟头草都有三尺高了。 一个程序最基本的作用就是处理你的输入,然后输出结果给你看。 你的输入的数值必须有个什么地方暂时保存一下,不然没法往下进行了,你肯定是知道先是保存在内存里,然后是保存在硬盘里,但是系统是怎么接收,怎么调用的,就必须靠编程语言编写的程序来给它指令。不然计算机是没有自己思想的,它就只会傻傻的等你给他指令。 在C语言里,你的输入被保存在变量里,不管你输入什么,想对你输入的数值进行怎样的操作,都需要先把它保存在变量中,然后对这个变量进行操作,C语言就是这么设计的。 想要使用一个变量,就要先定义它,也就是俗称的立项,这个项目尽管还没有实际的内容,但先立项再说。 最常见的变量定义就是 int i = 0; 我来解释一下,C语言要求对变量数字类型有精确的定义,也就是你准备往这个变量里面保存的数值是整数还是小数?也就是俗称的带不带小数点。 int的意思就是整数,作为初学者我们用到的最多的就是整数,int后面跟的就是你给这个变量起的名字,我这里是起了个名字叫做i,其实你起什么名字都行,阿猫阿狗都可以,只要不跟C语言的关键字冲突就行,而且本来关键字就没几个,可以说天大地大任你翱翔。 为什么要让它等于0呢? 因为C语言不允许有完全的空项目存在,哪怕你给这个变量里面塞一个0,0就是什么都没有,也不允许完全空着,这就是预则立不预则废的意义。 这里说了整数是int,那小数是什么呢?能看到这的人应该多少都是有自主学习能力的,你可以自己查嘛,内事不决问百度,外事不决问谷歌。况且我这是个随笔,不是真正的教科书教程,正常的顺序应该是看了我的文章,产生了兴趣,觉得编程并不可怕,再去阅读已经出版的纸质入门书籍,觉得有地方不理解了可以再来看看我对这个问题是怎么看的,兴许就又能豁然开朗一下。 那么我们已经知道了怎样立项定义一个变量,那么它怎么用?我之前说过,C语言中的函数和关键字都是分工明确的,没有谁可以单独拿出来大包大揽,必须相互配合使用,下一次我们就讨论一下变量的简单使用。
【千分之一的幸存者20:人人都爱for循环】 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 当你不接触C语言的时候你总会胸中豪情万丈,欲与天公试比高,总想在心中把这世上的编程语言排个名次,分个高下,弄个兵器谱之类的东西,你也当一把百晓生的瘾。 然后有一天你与C语言不期而遇了,你知道了它的博大与内涵,你开始虚怀若谷,你开始谦虚谨慎,那种xx天下第一,xx语言是世界上最好的编程语言,之类的话再也不会从你的口中说出。 就连在C语言范围内,你也不会再计较什么哪种方法那种形式是最好的,因为一千个读者心中就有一千个哈姆雷特,不管什么用法,只要你用着顺手,用着喜欢,就是好的用法。 for循环也是。 for作为一种循环,它能做的事while大法几乎都能做,如果你偏爱,并且沉迷于while的简洁,那你完全不用了解for循环也是可以的。 我一开始也很喜欢while而疏远for,因为相对while来说,for的结构稍微复杂那么一点点,而且思路并不是那种很流畅的自然思路,而是需要你分析理解一下设计者定下的规则。 毕竟是一种与计算机交流的语言,不能完全像自然语言那样去写,否则就不需要专门设计编程语言了,我们直接写一篇作文给电脑去读好了(当然,经过几十年的发展,编程语言越来越有这种向自然语言贴近的趋势,希望有一天电脑可以直接听懂我们的自然语言吧) for的结构看上去怪怪的: for(1初始条件;2循环条件;3循环后动作) { 4需要循环执行的动作; } 我为什么要编号,因为不编号就没法讲了,打字都要累死。其实也没那么累啦,只是更方便讲顺序而已。 看好了,它的运行顺序是,先执行1,再执行2,然后是4,最后是3,然后又回到2,如果2的条件仍然成立的话就继续执行4,执行完一次之后再回到3,然后再回到2……如此往复,直到2的条件变得不成立为止。 我知道这可能有点抽象了,不是我一贯的风格,我最初也是这样纠结了很久,不过在某一时刻豁然开朗之后马上就理解了这个概念,然后就不觉得它是个问题了,可能就是俗话说的难者不会会者不难吧。 咱们来举个例子。 for(你爹的怒气值为零;当你爹的怒气值小于一百的时候;怒气值每次加一) { 你把你爹收藏多年的全套小浣熊百变天书一张一张给撕了个干净; } 最终就是当你爹的怒气值突破一百的时候,跳出循环,接下来等待你的是什么我想也不必多说吧。 for循环就很适合干这种类型的事情,它的结构更紧凑清晰,至于你觉得能用它干什么,这就看你个人的感悟了,我只是举个例子而已,我绝对没有因为我儿子把我的收藏品糟蹋了而打他屁屁。 所以从某种程度上来说,也许for循环不是最好的循环,但人人都会喜欢for循环。 PS:for的意思是为了谁谁谁而去做某件事,可能跟当这个字没什么关系,不过本身它也是为了实现跟while不一样的作用而被设计出来的,为了大括号里的循环动作能够一直持续下去,它要在小括号里的条件中不停的来回转跳,我是这样理解的。
【千分之一的幸存者19:while好do while也好 作者:李文超 本文系原创,如需转载,请注明作者及出处。 这是一系列随笔性质的文章,待全部写完后作者会统一进行校对和整理,使之更具有系统性和逻辑性。 本文在759833857的qq空间和草间低语的新浪微博同步更新。欢迎感兴趣朋友来交流。 如果说到有一个单词比if还简单,那必须是do。 do是啥意思? 翻译成汉字比if还简单,你听说过一句话叫做“不服就是干!”没有? do就是一个字——干! 具体它是干什么用的呢?你有没有想过游戏刚启动时候的主界面菜单是怎么个运行原理? 它简单的用法是这样的: do { 魂斗罗 1p模式 2p模式 设置 退出 } while(退出不被按下) 这个do就是专门配合while使用的,作用就是先执行一次你的指令,然后再开始循环,像是开始界面的菜单之类的就可以这样实现。 其实循环还有一个for循环用的比较多,但是结构比while稍微复杂一点,我们下次再讲,让我想一个怎么能简单的把它说明白。
【千分之一的幸存者18:while大法好】 作者:李文超 本文系原创,如需转载,请注明作者和出处。 if很简单,但是说到简单程度和if不相上下而且又同等重要的关键字,非while莫属。 这个单词的字母数量是稍微多了一点,但它的含义非常简单,一个汉字足以表述——当。 什么是当? 当,可以是only you。 当,也可以是山无棱天地合才敢与君绝。 但设计C语言的前辈显然没有这种文艺情怀,当的意思就是它最原本的意思。 当达成怎么样条件的时候,就会发生些什么事情。 不过不同于if是做选择,while的作用是做循环,因为有很多时候我们需要让程序循环跑动起来解决问题。 简单用法如下。 while(条件) { 执行语句; } 举个周怡(这个梗看不懂的请勿在意),举个例子,你正在玩游戏的时候,红警,正激战的如火如荼,忽然尿急,这时你只需要轻轻按下esc键,就会跳出游戏回到主菜单界面暂停,你就可以去放水了(《文明》的玩家请闭嘴)。 这里你认为游戏程序的代码是怎么设计的呢? 如果以前你不知道的话,那么现在你就知道了,甚至你可以把它简单的写出来。 while(玩家没有按下esc键的时候) { 正常执行游戏; } 看到了吧,不能按照直男的思路去考虑,如果你想的是当玩家按下esc键的时候就跳出游戏的话,那么你还是用的if的选择思想,循环思想的核心是首先确保大括号内的执行语句能够顺畅的循环执行,小括号里的条件要反着来考虑。 顺便说一句,使用循环代码结构最多的程序就是游戏程序,最起码一个游戏至少是一个大循环而且还是死循环,其中又套着n多的小循环,刚才说的不断循环检查你是否按下esc键只是很小的一个例子。 好像提到了什么不得了的东西?死循环? 其实没什么大不了的,说开了也就这么回事,while()的小括号里不管你写什么判断条件,最终的目的就仅仅是判断这个结果是否成立,也就是说是真还是假,也就是说是1还是0,也就是说是高电平还是低电平,也就是说是通电还是断电。 而所谓的死循环,就是一个跳不出的循环,一旦进去在里面转到死也出不来,俗称死循环。 写法更是简单while(1)就行了。 因为本质上就是在判断是0还是1。C语言的设计者把0规定为不成立,把1规定为成立,这也在兼顾与计算机沟通的基础上尽可能的贴近自然语言。 经常可以看到争论哪个编程语言最好的话题,就跟甜咸豆腐脑,甜咸粽子,甜咸月饼等等一样,这是个没有结论的话题,而我也绝不会说C语言是最好的编程语言没有之一这种话,C语言的最大优点在于自由,这个自由随着你学习的深入会有不同的感悟,希望有同样感兴趣的朋友交流一下心得体会。
【千分之一的幸存者17:天道好轮回else饶过谁】 作者:李文超 本文系原创,如需转载,请注明出处及作者。 上回我们谈了if的简单用法,但你仔细想想就会发现,很多经常遇到的问题都不能简单的用二选一的方式去解决,更确切地说是不够用。 比如你要收集网站注册用户的大数据,要给用户的年龄分开层次,少年,青年,中年,老年,这个时候只能做二选一的if就不够用了,那怎么办? 这个时候else就出场了,它是专门配合if使用的。 就如同if一样,else也跟它的字面意思完全一致——否则。 它的用法就是 if(用户的年龄在10-20岁之间) { printf(小小少年啊快去驾驶巨型机器人拯救地球,如果你有自闭倾向那更是要逆天啊!); } else if(年龄在20-40岁之间) { printf(年轻人不好好搬砖做什么白日梦,这个月奖金别想要啦!); } else if(年龄在40-50岁之间) { printf(儿子考上大学没,落实工作没,有对象没,结婚房子准备好没,老母亲这个月又让保健品骗了多少钱……人到中年不容易啊……); } else { printf(人间五十年,如梦似幻,一切如过眼云烟,老伴的神志还清醒吗,腿脚还利索吗,孩子工作也忙,自己顾自己吧); } 看出来了没有,这就是else的用法,如果一个条件不满足,计算机就会根据我们的指令继续判断这个数据是否符合下一个条件,一旦条件成立,就执行对应大括号中的内容,你有n个条件它就判断n次,所以理论上你可以把所有可能的条件都写进去,做到滴水不漏,这个if判断一条漏网之鱼也不会放过。当然现实中你有限的时间和精力是几乎不会允许你这样做的。 它的格式也很简单明了。 如果第一个条件不成立,就再试下一个否则如果的条件,最后不再增加条件了,就用一个else来结束,计算机看到最后这个else就知道这一套if语句已经到最后了,该结束了。 当然,还是那句话,小括号中的条件以及大括号中的执行语句怎么写是你的自由,愿意自己编写特定指令也可以,愿意调用现成的函数也可以。 估计会有人说为什么我接触到的C语言跟你写的不一样,我看到的是if后面不用跟大括号,就算跟大括号的话前半个括号也是直接紧跟在if后面的啊,我们学校教科书就这样写的,谭浩强老先生钦定的呢! C语言是一门很自由的编程语言,自由到可怕,它对于程序员的写作风格限制的很少,打个比方,它只检查一句话后面有分号了没有,至于你是紧跟着写还是换一行写,它完全不在乎。 前面我就说过,只要符合基本语法,不管你写成什么鬼样子都能编译通过并运行,无非就是文风好的程序员写的程序大家愿意看,文风不好的人写的程序不光别人不愿意看,过段时间估计自己都看不懂了。 在这里我无意指摘谭老先生什么,在那个国内编程还没有起步的年代,他先搞出了这么一批教程能为后来者指个路,就像早期的汉化游戏,不管汉化文本水平如何,能有个汉化版,英文单词变成汉字,就已经很好了,很不容易了。 他的教材确实也符合C语言语法规范,也能编译通过,但仅适合教学之用(如今甚至已经不太适合,因为在更深入浅出通俗易懂的C语言教程大量出现的今天,他的系列书籍已经对很多初学者造成了晦涩难懂的恐惧),而且文风不太好,很凌乱,就像一篇没有标点没有分段的流水账文章。 至于什么文风是好的文风?个人有个人的见解,我的基本思想是,勤用大括号,勤换行,勤缩进,勤对齐,从我举的例子中我就一直在这样做。
【千分之一的幸存者16:简单的if语句】 作者:李文超 本文系原创,如需转载,请注明出处及作者。 我觉得在C语言里最容易学习的恐怕就是if语句了。 因为就连小学生都知道英文的if是什么意思,这个仅有两个字母组成的单词写作i和f,读作“逸付”没错,照我标的汉字去读就行了,相信和我一样用汉字去标注英文单词读音的朋友不在少数。 if的意思就是如果,十分简单,十分明了,很多老师甚至都不屑于讲它,只让我们看看书背下来就行了。 在C语言中if也没有别的意思,尽管是一门编程语言,尽管是美帝人编写的,但C语言设计的初衷就是贴近生活,贴近自然,设计者绝不会把if规定成别的意思给自己也给大家找麻烦。 它的作用是什么呢?判断。 判断一个条件成立不成立,如果成立,就执行接下来的指令,如果不成立就跳过接下来的指令。 它的出现主要就是为了解决判断问题,比如在完全实名制并且普及分级制度的情况下,你要上岛国网站,先要注册帐号才能登陆,关键资料中必须填写本人身份证号,这个时候就需要程序代码中用到if语句来判断接收到的这串数字中的年龄信息,如果未满十八岁,就要判断为不成立,然后调用另一个函数在屏幕上打上一个大大的拒绝访问字样,更歹毒一点的可以要求先输入父母的联系方式,然后自动给这个死孩子的爸妈手机发一条信息,你家孩子于何年何月何日何时何分试图登陆呵呵网站,要杀要刮悉听尊便。 格式的话很简单 if(你的条件) { 如果条件成立后需要执行的代码语句; } 是不是简单到难以置信,是的,C语言里if就是这么个用法,如果觉得这还太抽象,我曾见过一个比较好的办法,就是先用汉字写出来,再逐个翻译成英文。 如果(从用户输入中接收到的年龄信息小于18岁) { 在屏幕上显示“赶紧把家里拖鞋鸡毛掸子藏起来出去躲躲吧,这不是你该来的地方!”; 向此熊孩子的父母发送消息“你家孩子于xx年xx月xx日xx时xx分xx秒在xx位置试图访问xx网站,事已败露,可能出逃或顽抗到底,他还是个孩子,请务必不要放过他!” } 具体怎么判断,怎么发消息,这就是另外的函数需要做的事情了,咱们在这里只谈if,莫谈国事。 至于条件和执行括号里面能写些什么?些什么都行,只要符合C语言的语法,天官赐福,百无禁忌,想写什么都行,能写什么就要看你自己的水平了。 水平低的再不济也会写一个x1+x2>3吧?从前面咱们讲的scanf里面接收到用户输入的两个数字,保存到x1和x2中,再把这两个变量相加,再用if判断这个相加的结果是否大于3如果大于,条件就成立,反之就不成立。 执行语句咱们之前虽然就只说了一个printf,但这就够用了呀,至少已经可以在屏幕上显示出你想在条件成立时想说的话了,程序结构就是这么简单。 无论再复杂的大程序,细分到一个个语句的时候都是简单明了的,就像一个1写在纸上你看着很简单,但是一万个1并排写在纸上你就会觉得复杂无比,就是这么回事。 细分法是编程中的基本思想,需要牢记。
【千分之一的幸存者15:眼见非实】 作者:李文超 本文系原创,如需转载,请注明作者和出处。 如果硬要分类的话,我是个单机游戏玩家,本来对联网部分是不感兴趣的,但是仔细想一想,其实联机对战合作的内容早已有之,至少从我的印象中从红警95开始,那时几乎没有汉化版游戏,对于英文的剧情战役玩者寥寥,二大多是被联机对战拉进rts大坑的。 那么这里我就谈一谈对于联机原理的个人见解,不一定是主流做法,我姑且这么一说,您也姑且这么一听。 从最直接的效果上看,就是两个玩家,两台电脑,同一款游戏,一个玩家可以看到另一个玩家在自己电脑屏幕上的实时动作,简单来说就是这样。 看起来好像是通过一根网线,把一名玩家控制的角色模型直接传输到另一名玩家的电脑里,或者是通过什么办法把两个玩家的游戏地图无缝拼接起来。 一般人们都会想到这种最暴力最直接的方法,就像摩尔斯最初一直在纠结希望电报机的接收端确实的可以在纸上写出些什么来一样,这种实现方式并不是不可以,只是成本太高,不太实用而已。 (顺带说一句,后来确实实现了电报机的发送端直接在键盘上打字,接收端直接出字条的目的,这个由爱迪生实验室搞出来的东西有个响亮的名字叫做电传打字机) 那么我们来看看现实中条件有什么,一个游戏,确切地说是两个一模一样的游戏,在绘制场景以及人物移动素材方面两个游戏完全一样。 那么我们可不可以这样想,两个游戏同时启动,连接,描绘同样的场景,人物1是你,人物2是他,两台电脑之间肯定有一个局域网交换数据的通信协议,规定了怎样互相收发数据,这时两台电脑检测到了两个游戏的启动并连接,于是,在两台电脑上都打开了同一场景并绘制了两个人物。 然后你按下了前进键,你控制的1号人物在你的电脑里开始向前走。那么在你朋友的电脑里他是怎么看见你的动作的呢? 很简单,你的电脑不断的把你人物的移动坐标一连串的发送给你朋友的电脑,他的电脑接收到这一连串的坐标数字,真的就只是一串数字而已(这样可以最大程度保证传输速度,要知道联机游戏最优先保证的就是流畅度),然后他的游戏程序会按照接收到的坐标不断描绘再刷新再描绘他电脑里的1号人物的位置。 这样最后的结果就是看上去你控制的角色在他电脑里即时的移动。反过来他的人物在你电脑里也是一样的,由于相互传输的仅是数字而已,占用带宽非常少,就可以保证哪怕在地球另一端,你们俩也可以像面对面打牌一样联机对战。 总结一下一句话就是,你和你的朋友并不是处于一个世界里,而是分别处于两个完全相同的世界里,所有的一切都被复制成了两份,你们互相在看对方的拷贝罢了。 也许实现方法有所区别,但我觉得原理和思想大概就是这样的。以后如果有做涉及到这方面的事情的话,起码可以在最开始不至于跑偏方向。
【千分之一的幸存者14:编程工具哪家强?】 本文系原创,如需转载,请注明出处和作者。 如果说人们对于编程,写代码存在未知的恐惧,那多半是由于对其工具的不了解。 古语云,工欲善其事,必先利其器,人们在了解一件事情怎样做之前,通常要先了解做这件事的工具如何使用,如果连工具都不会用,那真的就只能歇菜了。 那么就让我们大声喊出这句话,挖掘机技术哪家……不对,是编程工具哪家强?中国山东找……什么也不用找,编程工具就像西门吹雪的剑一样,无处不在,存在于天地之间,你我身边,你敢说你身边没有一张纸? 是的,纸就是编程工具之一,最早的计算机运行程序的方式就是在一张长长的纸条上像像八音盒滚轮那样打上间距不一的孔,然后由进纸口卷进去,另一端吐出来。 程序员的工作就是打孔,不过那就太早了,比C语言早的多,我们不必说的太多。 就C语言来说,编程工具可以用百花齐放来形容,毕竟有年头了,各个平台都有适用于C语言的工具,就拿Windows系统来说。 学校考试教科书教学,基本离不开VC++6.0,它的特点是,大家都在用,考试指定唯一软件,而且就教学来说也够用。 然后是我自己在用的devc++,这个界面比前一个好看,用着也更舒服,也够简单,用于学习足够了,关键是体积小,安装简单。 最后是VS系列,我目前在制作一个游戏,用的是VS2012,它功能够强大,但是体积超大,安装也麻烦,除去下载时间,光安装时间就要个把小时,还不保证一定能启动,总之很麻烦就是了。 一般的过程,不管你用的是什么软件,都是新建一个空白文件,然后开始写C语言代码,写完了之后点击编译运行。 很多教材都不讲编译是怎么回事,所以弄的人一头雾水,简单来说,电脑只认识0和1,也就是说本来你是应该敲键盘写下一大串,无数行的0和1的,有密集恐惧症的人估计干不了这个事,而且这也不是人干的事,否则也不会后来出现这么多种类的高级编程语言了。 那么既然电脑根本不认识你写的C语言代码,那你写这个还有嘛用啊? 有,有一个叫做编译器的东西可以把你的C语言代码翻译成无数的电脑能看懂的0和1,所以你总能看到编译运行这个词,编译必须在最前面。 在此,对于编写设计编译器的前辈致敬,那工作量,真不是人干的事,但真正的程序员都是喜欢前期费事后期省心的人,一想到后期的便利,前期再辛苦也有动力继续干下去。 因为编译器不仅要翻译,还要查错,你的代码有写错的地方它会给你指出来,怎么形容这种辛苦呢,用欣赏一幅画和画一幅画来类比可能比较合适。 那种从头开始自己找编辑器,编译器,配置引擎之类的我就不说了,因为我自己也没那水平,将来学会了再说。目前的话学习知识我觉得devc++比较好,要做项目的话还是老老实实用VS吧。
【千分之一的幸存者13:阴魂不散的冯诺依曼】 本文系原创,如需转载,请注明作者和出处。 阴魂这个词其实一个中性词,既无褒义也无贬义,只是用来描述一个事物的名词而已,如果有人觉得这是对于冯老前辈的不尊敬,那我先致个歉。 为何会提到冯诺依曼呢,主要是因为他在电子计算机还尚未真正问世之前就对它的基本架构做了准确的设定,那就是三大块。而且直到今天不管计算机的性能再怎么提升,再怎么所谓的“革命”,依然没能脱离这个框架,冯诺依曼,一个百年前的人物,至今计算机界仍处在他的思想影响之下。 输入,处理和输出。 处理部分还可以再细分为内存,处理,存储,处理,内存。 输入简单的理解就是键盘打字,输出就是屏幕显示,处理就是CPU运算,那存储和内存又是怎么回事? 为何要分为存储和内存,从字面意义上看不都是存东西吗? 先别急,我们慢慢道来。 我们如今的电脑,硬盘没有一个TB都不好意思跟人打招呼,但如果你去问早期的,家用电脑还没出现时,只有大型实验室才有的大型计算机,去问它的硬盘多大?估计人家会反问你一句,硬盘是什么,能吃吗? 是的,早期的计算机压根就没有硬盘这种东西,所以我才说存储而不说硬盘,因为计算机设计的初衷是为了计算数据,输入就是人工输入数字,经过计算,将结果以编码的形式打印在纸条上,人们把这些纸条用文件夹或者资料盒保存起来,压根就没有硬盘什么事。 随着后来的发展,在前人的基础上,计算机性能不断提升,需要处理的数据从形式到质量上都大大增加了,谁也不想计算一次结果就要用一间房子去堆放那些纸质数据。后来就出现了磁盘这种东西,我们通常把它叫做软盘,原理跟磁带差不多,通过磁头对盘面单位磁性物质的影响去改变其状态以达到记录0和1数据的目的。顺便说一句,后来磁盘虽然淘汰了,但磁带式存储仍然至今应用中,许多大公司都会用磁带存储重要数据,它相比于硬盘的优势在于寿命长,而且硬盘一旦出问题整盘数据就全毁了,磁带就算出问题,只要剪掉有问题的那一段,把剩下的两端一粘,就能把数据损坏减少到最少。 说回软盘,一般软盘也就四个兆的容量,但是相对于纸条,这个容量已经是天文数字,人们在使用的时候通过软驱把它插进去,用完了拔出来。然而软盘终究是暴露在空气中的,能够对它产生危害的因素很多,磁盘的转速也限制了数据的读取速度。 所以后来出现了硬盘,硬盘只是软盘的魔改版,使用了更加硬质的材料,数据单位密度更大,真空封装,针对软盘的缺点全面改良,而且很成功,是至今为止最成功的存储器。 是不是觉得好像少了什么? 是的,内存! 计算机在一开始就是有内存的,因为在计算数据的过程中必须有一个东西能够暂时性的将之前输入的数据保留一下,否则你连一加一再加一这样的运算都无法完成。 最初在CPU中有一个叫做寄存器的东西(当然现在也有),干的就是这个活,但是一块CPU就这么大点地方,制造工艺很复杂,总之,又设计了一个叫做内存的东西来专门干这个活,就像九十年代出现雷神之锤和古墓丽影之前所有的电脑都没听说过显卡这种东西一样,一直到CPU本身的3d处理能力出现瓶颈时,就设计了显卡来专门协同处理3d数据。 内存的作用就是将所有输入输出的带待处理的已处理的数据都暂时保存起来,随时可以调用,它的两大特点。 一,速度快!硬盘根本不能比,就算如今出现了固态硬盘也只是相比于硬盘有所提升,和内存的反应速度还是不能比。 二,不能断电,一断电就灰飞烟灭!(所以内存又叫闪存) 也许你要说了,为啥就不能又像内存这么快还又能断电不丢失数据呢? 很不幸,自古忠孝不能两全,这两个特性也只能此消彼长,而不能两全其美,但是一直都在探索中,总有一天我们可以将内存和硬盘合二为一,那时计算机的运行速度将再上一个台阶。 以前我曾经不解过,为什么同样是操作系统,win98和win2000就只需要几十个兆的内存就能跑起来,而到了XP时代动辄需要一个g,win7没有四个g就别想流畅起来。 后来才想通,你所看到的那些华丽的界面,多样的功能,包括你开机启动的那些软件……所有你看到的一切都是加载在内存中的,你以为你打开了d盘,e盘就是看到了硬盘里面?真正的硬盘里面你根本看不见,你能看见的盘符,文件夹,文档,音乐,视频……全都是已经加载到内存里的,所以你想想内存要多大才够用?为什么内存越大电脑反应速度越快?就因为内存越大加载的东西就越多,内存小了你开的进程多就会导致电脑把暂时不用的数据写回到硬盘里,等你再调用的时候再读取,有时候你觉得电脑假死了?死机了?其实只是在后台拼命加载你想要的数据罢了,只是你的指令太多,内存反应不过来在那排着队呢。 明白了这一点,我们就知道了,在写代码的时候,我们的数据都是在内存中进行操作的,存储部分需要另外设计,这个思想很重要。
【千分之一的幸存者12:printf的对立面】 本文系原创,如需转载,请注明出处及作者。 既然有输出,就肯定有输入,printf想对应的函数就是scanf。 这是一个怎样的函数呢? 作用就是获取用户的输入,然后呢,没有然后了,它的作用就如同printf那样简单,就只是单纯的获取输入而已。 最常见的样子是这样的,scanf("%d",&xx);,它是个什么意思呢? scanf不用多说它的字面意思就是指输入,双引号里面的内容就是告诉电脑,用户的输入就在这个双引号里面,给我把这个里面的内容获取出来,保存到xx变量里面。 诶?好像多出了一些不明所以的东西?什么叫变量?为什么要把获取到的输入保存到变量里面? 我之所以用一个xx来表示变量,是因为这个变量的名字是由你来起名字的,变量,顾名思义,可以改变的量,变量就相当于一个空箱子,你在这个空箱子上写了一个名字来命名它,然后你就可以留着它,以后任何数据都可以随时往里面保存,但每次只能保存一个,而且新保存的数据会把上一次的数据覆盖掉,这就是变量。 在我一开始看到变量在scanf的作用时我是不能接受的,因为不能你说一定要用我就要用,凭什么不能直接把scanf的输入用printf直接输出到屏幕上来? 这是个好想法,也是一般直男的想法,但是这样想是误会了C语言,没有站在一个设计者的角度去考虑问题。 在C语言中,函数的作用是很单纯的,尤其是预设函数,你自己编写的函数另当别论。 scanf就只管输入,别的不管,printf就只管输出,别的不管,变量就只管保存数据,别的也不管。 做个比喻的话,C语言的预设函数就相当于剪刀锤子锯子这种最简单原始的工具,它们的作用很简单,但是给予使用者的发挥空间很大,你很清楚你手中的工具是什么样子的,它能干什么,怎么用,一锤子下去能砸出多深的坑,你心里都有数。 这就是C语言设计者的初衷,当然也有时代因素的限制在里面,毕竟几十年的东西了。 后来的很多高级语言就相当于电锯,电钻,甚至加工中心,功能很强大,操作命令也很简单,但你不知道它里面是怎么一回事,你也不知道它是怎么运行的,你就像一个女司机一样(这里绝没有性别歧视的意思)开着自动挡的汽车,只要踩油门和刹车即可,别的什么都不用你操心,车子坏了打个电话就只要等着售后维修人员来就行。 C语言不是这样,我们常说C语言其实一门中级语言,既有高级语言的特征,又接触到了计算机运行底层的东西,就是这么回事。 这种各司其职,相互配合的思想一直贯穿了整个C语言的始终,我们如果一开始就在心中建立这种概念,于今后的学习不管是编程还是别的东西,都是很有益处的。
【千分之一的幸存者11:万物皆可printf】 本文系原创,如需转载,请注明出处和作者。 不只是C语言,任何一门编程语言的学习,开篇第一句话都会让你学习在屏幕上输出一个hello world,你好,世界! 这其实就是图个彩头,据说当年C语言的创始人用它写出的第一个程序就是在屏幕上输出这句话,成了后来编程学习图吉利的一种行为,其本质上就跟教师敬孔子,木匠敬鲁班,屠夫敬张飞,摸金校尉敬曹操,卸岭力士敬项羽……等等一样。 别以为程序员就很科学,你是没见过那些祈求佛祖保佑不出bug的代码注释,硬是能用一行行的符号拼成一个佛祖的形象,还有三炷香呢。 但我在这里只是为了谈一个函数的用法而已,那就是各种教科书中出现频率最高,计算机考试必备,离了它就不能做题的函数,printf。 就像它的字面意思一样,print就是打印的意思,f是另一个单词的首字母我们不用管,printf的作用就是在控制台界面向屏幕输出一条信息,这个信息的内容由你决定,想写什么都可以。 我们一般看到的就是printf("世界,你好!");这个样子,单从这句话就已经能看出它的用法了。 首先是写printf,然后是一个括号,括号里面是一个双引号,双引号里面就可以写我们想要输出至屏幕上的内容了,汉字,字母,数字,空格,各种组合都可以,最后跟一个分号结束这句话。 这就是C语言的语法,固定的格式,一点也不难。但要注意一点就是所有的符号(除双引号里面的内容)都要用英文符号,用中文符号铁定报错,毕竟是美国人发明的C语言,不过你也别不爽,将来咱们学成了以后咱们自己也设计一套中文编程语言去难为难为老外们。 说句题外话,中文编程从很早开始就有人在探索,例如汉化版C的习语言,就如同我们玩的各种汉化版游戏一样,只是把C语言的各种关键字替换成了汉字而已,省去了学习英文单词的苦恼,话说回来学习C语言,在英语部分只要有初中水平就足够了,相信如今已经普及了九年义务教育的情况下,应该不至于有人会为C语言那区区几十个关键字单词而为难吧。 数学部分也是如此,总有人还没有摸到门把手就自己害怕起来,觉得需要很高的数学水平才行,结果自己放弃了,没能入门,这种现象不在少数,那么需要很高的数学水平吗?那得看情况,有一类程序员是专门搞算法的,他们整天孜孜不倦的就是在研究怎样能让计算出一个结果的过程缩短,这类人因为工作需要,自然对数学水平要求较高,不是主观的,是客观需要。 而除了搞算法之外其它所有的程序员对于数学水平都几乎没有什么要求,初中水平足矣。当你自己亲手去编写一个函数的时候你就会发现,任何问题都需要不断细分不断细分直至能用加减乘除来解决为止,用的最多的就是加减乘除,一点都不多。 说回printf,嗯……好像基本说完了,用法就是这么个用法,当然它肯定是一个函数,这个名叫printf的函数就是当初发明C语言的作者已经编写好的一堆函数中的一个,它被保存在stdio.h这个头文件(函数库)中,在你写代码之前需要用#来引用它一下。 这个函数有用吗?有用,它在教科书中无处不在,考试题几乎都是让你怎么怎么样最后用printf输出一个结果。说没用也没用,因为它只存在于控制台范围内,你想想你电脑里的哪款程序是用控制台运行的?它的实际作用主要是,你写代码的时候设计一套调试机制,在打开控制台调试的时候,输入相应的命令就可以由printf返回给你相应的结果信息。 随着深入接触你会体会到C语言的编写是很自由的,自由到可怕,基本上只要你格式不错,关键字不错的话,无论写成个什么鬼样子都能通过编译并运行,所以文风很重要,是的,我好像是用了一个跟编程毫不相干的词,文风,但实际就是如此,输出同样的结果,一千个程序员就可能有一千种不同的写法,有的代码混乱不堪无法阅读(估计写代码的人过段时间自己也看不懂了),有的人写出的代码就很清爽,错落有致,条理清晰,注释详细,外行人也很容易看懂,这就是文笔,文风,文字功底。也是C语言所独有的现象。 另外,因为尚未提及变量的定义问题,所以另一种用法我没有说,后面再说吧。
【千分之一的幸存者10:唯快不破(四)】 本文系原创,如需转载,请注明出处及作者。 也许你很难相信最初的计算机里面就是一大堆,成吨的继电器,但事实确实如此。 也正因为如此,它的计算速度在今天的我们看来简直惨不忍睹,因为无数的闸刀在不停的开开合合,单个闸刀的速度看上去很快,但无数个垒加在一起,哪怕一毫秒的延迟也会最终变得很可观,一次加法要算个十几分钟就在情理之中了。 所以改进继电器的材料和结构势在必行。 继电器的原理是一定的,但实际形态却是自由的,只要能解决实际问题,任何尝试都可以有,我只说一个,真空管。 这种东西稍微上点岁数的人都不陌生,真空管的研究和发展据说是由苏联主导的方向,而电子管是美帝的主导发展方向,冷战期间万物皆可分阵营。 真空管的思路是为了解决现实中暴露在空气中的继电器闸刀发热和氧化问题。 继电器的闸刀,不如说主体部分都是金属,一大缺陷就是容易氧化,再一个就是一开一合产生的高温,硬要说的话就是空气阻力也会让闸刀的闭合产生延迟。 真空管就是这一思路的产物,将继电器的主体部分封装在一个真空的玻璃管内,没有空气就无所谓氧化,没有空气再高的高温也燃烧不起来,没有空气更无所谓什么空气阻力……而且这样做虽然制造成本高了很多,但使用寿命比原始的继电器长了不少,体积也小了不少,使得计算机的整体体积大大缩小了,这个时候仍然离我们的桌面很远,但已经是一个进步了。 再后来的电子管也是另一种研究方向。 最终人们提炼了继电器在计算机制造方面的作用,就是只要是能够表示电流的通断就行,更进一步,只要能在电流强弱的影响下表现出截然不同的两种状态就行! 这个时候,一种物质被纳入了人们的视野,那就是,半导体。 从字面意思来看就已经很清楚了,能够通电的物质叫做导体,不能通电的物质叫做非导体,能通电但只能打个折扣并且物质状态会改变的物质就叫做半导体。 试验来试验去,终于找到了一种合适的物质,硅。 无需加工什么机械结构,从原子层面上就可以实现一个继电器的作用,使得一下子计算机的体积又呈几何数量级的缩小。 说的简单,其实这个实验的过程是十分漫长的,这就是材料学,只有材料学,是需要时间积累的,急也急不得,只能慢慢试,慢慢来,甚至很大程度上看运气。 最最后,人们把一定的硅材料,按一定的顺序排列起来,再封装起来,就变成了我们今天看到的CPU。(我说的简单,是为了方便理解,实际复杂的多) 由于电信号在原子层面上传递,因此速度变得快,非常快,快到你无法想象!尽管它仍然只能做个加减乘除法,但是速度已经弥补了其他一切缺陷,尤其是程序员为他编写了用于解决实际问题的程序之后,更加的如虎添翼。 下象棋的例子我们已经说过了,我们再说个实际的,照片比对,你怀疑这个人是通缉犯,但只有一张照片,如果人工对比就需要专人日以继夜的在档案室翻资料对比照片,如果交给计算机来做,方法没有什么不同,但它可以在一瞬间完成成千上万份资料的对比检索工作,就是一个快! 我们的CPU至今仍在发展之中,以后会发展到一个什么地步谁也不知道,总之你只要知道,你今天手中用的任意一款手机,哪怕是非智能的老年机,也比当年阿波罗登月飞船的主控电脑要更先进无数倍。
【千分之一的幸存者10:唯快不破(三)】 本文系原创,如需转载,请注明出处及作者。 一个继电器有什么用? 用处很大,前面说了在电报业的作用,这只是一个典型,还有另一个比较典型的作用就是配电室,当电压高到一定程度的时候方圆一定的范围内人都是不能靠近的,这时就需要用到继电器的原理,用一个开关去远距离操作另一个开关来实现对高压配电设备的操作。 当然我们这里并不谈电力方面的事情,我本人很胆小,不会做危险的事情,我们还是继续说回电脑的事情。 我们一般只能想到用一个开关的开合,对应去操作另一个开关的开合,但是从来都没有那一条法律规定继电器就只能这么用,我们完全可以把两个开关的对应位置反过来,一个开关打开的时候另一个开关就是闭合的。 然后我们把三个,四个,甚至更多个继电器用串联和并联的方式进行一定的组合连接,我们可以实现什么效果呢?就是当你闭合又打开开关的时候,你这个电路的状态依旧是通电的,你要再重复一次开关的动作才能使回路断开电流。 总结一下这是个什么意思呢? 一句话,你的输入被保留了。 物理界有这样一句话,如果世界即将毁灭,你只要给下个时代的文明留个信息“物质是由原子构成的”,只这一句话就能够让整个现代物理学重生。 那么“你的输入被保存了”这句话也具有同样重要的意义。 电脑只是很通俗的叫法,正式的名字叫做计算机,这也正是它的本意,它被发明出来的初衷就是为了做加减乘除运算,而且最初只能做加法。 任何一个东西都不是平白无故出现的,如果只是算算账,统计个人口数据,人力完全可以做到,那么是怎样的需求居然要大费周章的发明电子计算机这样的划时代产品? 战争。 战争是人类社会进步的催化剂。 这句话很残酷,却在一定程度上也是事实。我们今天身边各种高科技民用品基本都是由二战时的军用技术发展而来的。 我们不整那些高深的,就说拯救大兵这部片子,开场的奥马哈登陆战,为了防止枪械进水,每个士兵的枪都套着塑料袋,为了保持信息畅通,几乎每个镜头你都会看到背着无线步话机的通讯兵,用于指引飞机行进路线的雷达则间接导致了微波炉的诞生…… 那么是什么需求导致计算机必须被发明出来,究竟是怎样恐怖的数据量使得人力不能满足需求? 正是二战终极大杀器,原子弹。 原子弹是一项投资极其巨大的项目,试验和失败成本非常之高,要求绝对不能在计算数据上出错,但是人就会犯错,只是几率大小罢了,为了尽可能的摒弃人为因素的不稳定性,只能使用计算机。 那么计算机跟继电器什么关系?有一毛钱关系吗? 有,而且不止一毛钱。 前面我们说过了一定数量的继电器排列组合在一起就可以保留你的一个输入信息,这个输入信息只能是开或关,我们更早之前还说过在数学上我们可以用0代表开,1代表关,我们把这么一组继电器固定在一起封装成一个组件,然后经过无数次试验和计算,你发现八个0和1的组合可以用来表示英语中所有的字母和符号(毕竟是人家发明的)。 然后你就把八个继电器组件排在一起,再次封装,我说的封装就是指装到一个盒子里,输入和输出端露出来的那种。 最后你就可以通过开关的闭合来输入你要计算的数字了,机器永远不会背叛人类,也不会犯错。 比方说你操作了八次开关,开开开开 开开开关,就代表1。开开开开 开开开开就代表0。 你也许会说,这TM哪能用啊?还没我用纸笔写得快呢! 确实,但我仅是从最简单的层面上阐述了一个类似模型的东西,是为了方便读者理解和想象,具有完全的理论可行性,实际应用的话另当别论。(如果直接从寄存器讲起恐怕连我自己都觉枯燥的扭头就走了) 最终,无数的继电器组合在一起,就变成了最初的电子计算机,占地面积巨大就不说了,单单一启动,半座城都能停了电,就这么一个笨拙的大家伙却有一个无与伦比的优点。 计算速度快,非常快,超级快!而且永远,绝对不出错!它可以故障而停止运行,但计算结果绝不会出错!为此,一切的前期投入成本都是值得的。 另,所谓的核不扩散条约真的有用吗?尤其是在禁止核试验方面。 那为什么现在大家都不再做核试验了?因为计算机的发展已经能够满足模拟需要了,以前是计算,实际试验,收集数据,现在则是整个过程都在计算机里模拟完成。 熟悉历史的人都知道新中国研究核弹因为没有超算,动用了多少人力,用算盘打了多久才搞定数据计算的问题。如果有计算机,你几个月的手打计算,人家个把钟头就出来了,而且绝不出错,孰优孰劣?我们向那个时代的科研工作者致敬,但那种一穷二白没办法的办法却决不能再用。 天下武功,无坚不摧,唯快不破! ——火云邪神
【千分之一的幸存者10:唯快不破(二)】 本文系原创,如需转载,请注明出处及作者。 “问大家一个问题……” “天草!再问自杀!” “抠,抠,教,主……邵……” 好了,以上的梗如果看不明白也不用纠结,不影响之后的阅读,对于能看懂的朋友们,我想声明,李钊一生推! 好了,进入正题,问大家一个问题,人类史上第一次真正实现远距离信息瞬时传递的手段是什么呢? 有人说烽火台,这个虽然远,但也离不开目视距离。 有人说信鸽,但信鸽在路上飞行也是需要时间的。 我认为应该是电报。 尽管需要编码和解码,但熟练的电报员可以做到看字发报和看报写字,只要电缆能够延伸到的地方,哪怕在地球的另一端,也可以实现信息瞬间传达。 这里有一个小花絮,说的是摩尔斯在一个问题上纠结了很久,那就是他希望电报接收端(机器)能够确实的在纸上写出些什么东西,否则电报还可以更早两年出现。 电报这种东西,一般人都知道是由长和短两种信号组成的,这两种信号其实就是电流的强弱,再说白一点就是开和关。 我刚才说即使在地球的另一端也能瞬时传达,其实最早的时候,也就是整个电报业务还处在试运营阶段的时候人们就发现了一个问题,那就是电阻的作用。 顾名思义,电阻就是阻止电流通过的意思。 任何一种材料中都存在电阻,只是大小不同罢了。金银铜的电阻最小,金太贵,银很容易氧化,综合下来铜导线就成为了我们日常使用最广泛的导线材料。 但再小的电阻也是电阻,而且电阻有一个特性,就是长度越长,电阻越大,它是垒加作用的。 在电脑系统中的直接问题就是,人们发现一个电信号所能达到的极限距离是三百公里,再远信号就微弱的无法识别了。 发现了问题就要解决问题,而在那个几乎谈不上什么自动化的年代,解决办法也很直接,在每三百公里的地方盖一座房子,里面放一台电报接收机和发送机,再派一个人坐那把接收的电报再转发出去。 这个房子这台设备再加上这个人,就叫做中继站。也可以叫做信号放大器。 然后这个中继员每天兢兢业业的工作着,他先是接受一整条电报再转发出去,随着熟能生巧,他渐渐开始可以一边接听电报信号一边转发,直到他的业务熟练度升华到了一种境界,他发现接听的电信号频率和自己手指发送电报的频率完全是一致的! 然后他就找了一根小木棍,用绳子把接收端上下跳动的开关和木棍绑在了一起,再让木棍的另一端绑在发送端的开关上,然后送三百公里之外来的信号就可以自己朝下一个三百公里传送过去了。 然后这个人就失业了…… 开个玩笑,任何一个组织如果有人做出了贡献,如果不予以嘉奖反而踢走,那这个组织也就离药丸不远了。 我们刚才一直用中继站来称呼这个系统,现在它已经完全不用人力操作,仅靠电信号就能控制另一个电信号维持这个系统自动运行,我们把它的原理抽出来,然后缩小,结构简化,最后就得到了一个可以放在手心里的东西——奶茶。 开玩笑,怎么会是奶茶呢。 如果看过上一篇,你就应该有一个名字呼之欲出了,没错,就是继电器!
【千分之一的幸存者10:唯快不破(一)】 本文系原创,如需转载请注明出处和作者。 在普通人眼中,对于计算机编程的印象大多来自于影视作品,而影视作品为了故作高深(艺术需要),经常出现的镜头就是黑黑的背景下一行行绿色的字符密密麻麻的滚动出现,仔细看去,便是无数的0和1。 首先我们来说说为何选择黑底绿字这种颜色方案。 液晶显示器的出现和普及也只是2005年以后的事情,在这之前清一色都是CRT显示器,就像NBA的译名是美国职业男子篮球一样,CRT翻译过来就叫做阴极射线管。 它的工作原理是由一把电子枪不断发射高速电子粒,逐行轰击在屏幕内侧一个个小格子里,每个格子里都装有三色荧光粉,根据电子的强弱程度反映出不同的颜色。 这些小格子反映出的颜色集合在一起,就会使屏幕上出现特定的图像,连续多幅图像的变化就让人物动了起来。 过程就是这个过程,但人的肉眼根本觉查不到这些变化,原因就是,速度太快了! 早期的显示器是球面,原因无他,就是电子枪的发射距离无法很好的控制,只有把显示器做成球面才能够保证电子枪等距发射。 后来出现了纯平面显示器,有一段时间这个噱头特别火,电脑城的商家都把这个作为宣传点。无非就是终于攻克了电子发射距离控制这个技术问题。 然而只要是CRT显示器,就存在辐射,而且辐射量还不小,否则银行等长时间需要盯着电脑的岗位也不会专门给显示器加装护眼膜。 在液晶显示器普及以前的几十年间这几乎是一个无解的问题,只能从别的地方想办法。(那时网络文学才刚刚兴起,有的杂志甚至讥讽道,如果你要在电脑上看完一部长篇小说,你的眼睛也就差不多瞎了) 经过各种研究,能够最大限度减轻眼部疲劳的颜色就是黑色和绿色,其中最好的配合就是黑底绿字。不信你可以试试。这个配色方案即使到今天液晶已经完全代替阴极射线管的情况下依然是最好的方案。(像是autocad,caxa等工业用平面制图软件依然默认是这种配色方案) 然后再说为什么是0和1。 我们在说到计算机底层运行的时候,经常听到的说法就是计算机只能识别0和1,但是一般说到这里也就点到为止不再继续往下说了。 相信我们绝大部分人都曾有过再问一句,为什么是0和1,的这种想法,但是我们也都只能默默的把这个问题吃在肚子里,最后渐渐忘掉。 我就自己的理解来谈一谈,其实计算机连这两个数字都识别不了,没错,计算机就这么笨。 它能识别什么呢? 只能识别断电和通电两种状态,也就是开和关。 然后程序员把通电定义为开,用1来代表,断电定义为关,用0来代表。 还想继续往下听吗?那我们就再底层一点。这可就是一个说来话长的故事了,这一篇未必讲的完,我们可以且听下回分解。 你知道什么是继电器吗? 电子机电专业的学生可能不假思索就能说出来,一般人大概就只能挠头了。然而就算是专业人士恐怕都不能描述出继电器的本质。因为继电器发展到现在除了原理,在形态上已经大为变化。 先不说继电器是什么,因为干巴巴的说概念一点意思也没有,让我们追根朔源,找到继电器横空出世的理由。
【千分之一的幸存者9:爱恨的控制台】 本文系原创,如需转载,请注明出处及作者。 在一般人的印象中,控制台大概就是类似于挖掘机驾驶舱那样或者录音棚那样,一个大桌子,上面密密麻麻布满了按钮和操纵杆。 在稍微有点编程知识(哪怕只是擦边)的人印象中,控制台就是一个黑底白字的窗口,里面会出现一行一行稀奇古怪的符号,然后程序员就在上面打出各种指令。 在游戏玩家眼中,控制台就是按下~键,然后show me the money…… 在仅仅只是学校开过这门课,仅仅是做几道题为了应付考试的同学们印象中,它就是各种scanf,各种prinf的极其枯燥无趣的玩意,简直想象不出来为什么要学这个,明明是因为喜欢玩游戏,想抒发胸中伟大的构想,成为下一个约翰卡马克,或者约翰罗梅罗抱着极大的兴趣来学习编程,结果却被这么一个玩意泼了冷水。这些今后很有可能成为优秀程序员的苗子,一念之间就产生了心理阴影,今后再也不想看见编程两个字。 要打消这种误会,就要回到一个最根本的问题上,为什么学校教育都会从C语言开始,而且都是从控制台开始? 首先我们想一想我们在家用电脑上玩到的游戏都是运行在什么操作系统上的? Windows,很少有人会注意到这个问题,因为在很多人眼里,操作系统就等于Windows,二者是一个概念。 然后我们想一想C语言是什么时代的事物? 六十年代末七十年代初,这个时候Windows系统在哪?用李团长他娘的的一句话说就是,老婆?我老婆还不知道在哪个丈母娘肚子里呢! 别说Windows,比尔盖茨那时候恐怕还穿开裆裤呢。 也就是说那些激发我们投身伟大游戏编程事业的启蒙大作赖以生存的平台根本不存在。 而学校教育的目的是什么?或是说大学教育的目的是什么? 不是为了让你学会熟练操作某个软件,那是短期培训班应该做的事情,而是为了让你尽可能的体会到一门知识的本质,适用范围尽可能的广。 所以,才会从C语言这一平台跨度最广(不依赖于某一特定操作系统),出现时间最早,最底层(除汇编以外),而且是从控制台开始学起。 因为学校不知道将来你毕业后会从事什么平台的开发工作,所以如果一开始就从Windows程序开发教起,那就限定了你的发展方向,这是不好的。 授人以鱼不如授之以渔,这是教育的核心思想。 比方说你拜一个木匠为师,你是希望他只教你怎么做桌子椅子呢(今后你就只会做桌子和椅子),还是希望他教会你怎样正确的使用工具并且设计家具的思想? 那些很失望并且准备咬牙坚持学控制台的同学也不用泄气,C语言发展到现在,函数库不计其数,专门用于图形处理的大有所在,只要你去找,一定能够找到,选一个你用着最舒服的即可。 而且我预言,最终你一定会发现,控制台很有用,控制台也很有意思,控制台应该学。
【千分之一的幸存者8:黑暗的深处】 【千分之一的幸存者8:黑暗的深处】 本文系原创,如需转载,请注明作者和出处。 好像一下子就跳到暗黑破坏神2的分析有点跨度太大,不过这本来也就是个随笔性质的东西,以后我会再系统的整理一遍的。 为什么要说暗黑破坏神呢?更具体的说是二代呢? 因为我本人晕3D,几乎不能玩第一人称射击游戏,只有使命召唤二四五代还算可以,开阔场景比较多,一旦有大量室内场景我就会头晕想吐,所以我玩的比较多的还是斜45度角的RPG游戏。 这其中最典型的当属暗黑破坏神2,关于这个游戏的评论文章简直汗牛充栋,我就不多说了,只说它的游戏实现方式。 一九九八年,那个时代的家用电脑配置用今天的眼光看普遍都惨不忍睹,尽管游戏开发者对开发全三维游戏的愿望十分强烈,但能够达到游戏公司工作站级别的个人电脑实在凤毛麟角,不得不采取折中的办法,让玩家看起来有立体效果,同时对配置要求不高,这就是典型的暗黑2的伪3d实现方式。 去掉地图上和界面上的所有花哨元素,我们可以总结出最核心的运行机制,那就是控制人物在地图上四处走动。 最直接的方法当然是建立一个惟妙惟肖的人物三维模型,然后控制它做出动作,这是从本质上去考虑的方法。 可惜玩家孱弱的电脑根本带不起来,那么只好退而求其次,在人眼的视觉错觉上下功夫。 想想有一种会动的图片叫什么?GIF,它为什么会动呢?因为它是一种特殊的,把很多张连续的图片顺序播放,形成的动画效果。 当然九八年的时候是没法这样做的,而且GIF公司版权费很贵,那时候采用的的是另一种叫做png的格式图片。 具体怎么做呢? 首先,在你的三维建模界面把人物调整成四十五度俯视视角,然后咔嚓,截图。 然后抠图,修图。 你的人物一个动作需要用几张图片才能流畅的表达出来,你就重复的调整,截图,抠图几次。 然后把这些图片按顺序编号。 然后设计一个函数,按顺序播放这些图片,一个连贯的人物动作出来了!(比如挥剑动作) 然后再设计一个函数,检测用户的输入,当用户按下鼠标左键的时候,调用挥剑函数,这样实际中你看到的效果就是,你按下了鼠标左键,游戏中的人物做出了挥剑的动作。 这就结束了?是的,从原理上来说这就结束了。 只是你绝不希望你的人物只能向一个方向做动作吧?那样看起来一点也不立体。 所以你需要每一个动作都制作八个方向的相应图片,因为八个方向是让人物能够产生视觉上的立体感的最基本数字,你不信的话可以去点开现今任何一个网页游戏,或者早期一点的客户端网游,例如梦幻西游,你慢慢的把鼠标围绕人物画一个圈,你就会发现在你鼠标移动到某一角度的时候,人物忽然就切换了一个角度,平时玩的时候不会注意,但如果专门去留意,就会觉得很突兀,最后你计算一下,一个圈下来,你的人物刚好是切换了零度,四十五度,九十度,一百三十五度……八次方向。 当然,暗黑破坏神是暴雪出品,下的功夫也自然更大,动作图片帧数更多,图片方向也更多,玩起来非常流畅,动作也十分自然。 写到这里我曾一度举笔不定,因为一旦了解了就会明白,那些惟妙惟肖的动作,那些华丽的光影,那些光怪陆离的世界……本质上就是屏幕上一堆移动的图片而已。(用户的电脑机能再怎么孱弱,处理纯2d图片还是绰绰有余的,严格意义上讲玩这种游戏根本不需要显卡,因为显卡是专门用来协同处理3d游戏数据的) 也许以后玩暗黑破坏神的时候就再也找不回之前的那种感觉了,谁能说的清楚呢? 一切都取决于你肯投入的时间和精力,只要想,你也可以做出暗黑破坏神。 也许你会惊叹于这巨大的工作量(但凡抠过图的人都知道这意味着什么),但没办法,受限于时代。这也正是詹姆斯卡梅隆宁肯耐着性子一直等到硬件和软件技术的发展足够强大之后才开始拍摄阿凡达一样,稍微搜索一下你就会知道阿凡达是什么时候开始立项的,筹备了多少年才开始拍。 现如今我们电脑机能普遍过剩,已经不需要那种折中的办法了,但了解一下其中的原理,也有助于我们开阔眼界,继续前行。
【千分之一的幸存者7:代码的基本结构】 我一向不喜欢把事情弄得复杂化,写的这个系列文章一方面是对我自己学习经验的总结,另一方面也是希望能尽可能多的让外行人也能以很平常的心态来看待编程这件事。 所谓无知者无畏,一般来说外行人容易走两个极端,一是畏惧,人们总是会对自己不了解的东西产生恐惧,这是正常的,但也正是这一点扼杀了不计其数的可能成为优秀程序员的苗子;二是极度蔑视,觉得编程虽然我不懂但一定没什么了不起的,一个很有名的段子就是说一个不会技术的老板,对别人说我们创意策划营销……几乎什么都有了,就差个程序员了,仿佛只要有一个程序员挥一挥手,天马行空的幻想马上就可以变成无bug的现实产品,他根本不知道他的想法需要多少万行代码才能实现,一个程序员一天八小时又能够写出多少行代码?调试,测试什么的仿佛根本不需要,团队什么的也不需要,只要一个程序员从零开始就可以写出一个完整的程序,那些上千人的软件工程公司都应该早早。倒闭,根本不需要。 这两种态度都是正常的,然而是对于外行人的正常,所以我尽力想实现的一个目的就是,打消初学者的恐惧心理,打击无知者的嚣张气焰。 编程并不可怕,跟你学习任何新鲜事物的过程是一样的,带着平常心去接触它就好,但编程也不轻松,绝不是白脖子产品经理动动嘴皮子就能指望下班之前能实现的东西。 编程就像请客吃饭,就像绣花,就像做文章,是非常雅致,非常沉静,需要耐心和细致的事情,急不得,也燥不得。 我们也该说说代码的基本结构了,放心,绝对基本的专业人士都不屑于吐槽。 打开任何一个C语言的源代码,不论长短,我们都能看到首先根据程序实现的目的不同而引用了相应的函数库,这一点我们之前已经讲过了就不再重复解释。 然后就是一些自己编写的函数,因为尽管积累到现在C语言的函数库简直浩如烟海,但仍无法满足所有的实际工作需要,有句话怎么说的来着,你永远无法让所有人满意,不管你怎么做,总会有人对你不满意的,那些过度追求完美的人也许能风光一时,最终都会把自己逼疯。 所以你一定会需要自己编写一些函数。 然后就是一个main,一般我们在教材上看到的都是int main()怎么怎么样,然后在它所属的大括号里开始写代码。 这个main其实就是一个函数,我们一般把它叫做主函数,看到没,所谓程序,所谓代码,本质上就是一个大函数。 只不过这个大函数是通过你的设计,调用其他小函数来实现目的的,更进一步,你一个小函数都不调用,把所有命令一句都写在这个大函数里都行,只是工作量太大,几乎没人愿意这么干罢了。
【千分之一的幸存者6:引擎的力量】 【千分之一的幸存者6:引擎的力量】 本文系原创,若需转载,请注明作者和出处。 只要是稍微玩过电脑游戏的,八成都会对引擎这个词不陌生,基本上新上市游戏或是正在开发的游戏新闻都会提及这个游戏用的什么引擎,有什么特性,能实现什么效果,像是出现频率比较高的虚幻、霜寒等。 是不是又觉得高深莫测,高不可攀了? 一点也不高,接下来我们就从很久很久以前,在一个遥远的银河系讲起…… 当然不会那么远,不过至少也有三十多年的历史了吧。 最早开发者在开发游戏的时候,假设你就是一个游戏的开发者,你心中有一个火爆刺激的构想,外星人、肌肉男、打不完的子弹、三十条命秘籍……你给你的游戏起了个名字叫做魂斗罗。 然后呢?直接就坐下来开始写代码了吗?不。 你需要的是坐下来,然后开始考虑在这个游戏中需要实现怎样的视觉效果,比如我们的肌肉猛男虽然手持机枪无限子弹势不可挡,但只要敌人的一个小兵哪怕轻轻擦掉他一根汗毛,我们的主角也会立即翻滚着飞出去挂掉,相应的,敌兵也绝不会挨过我们一发以上的子弹。 好了,先考虑这么多,接下来我们就要编写一个函数专门用来描述主角翻滚着飞出去的动作,再编写一个函数专门用来描述敌兵中枪爆炸的动作,再编写一个函数用来判断主角是否碰到了敌兵和子弹是否碰到了敌兵,再…… 随着你不断的考虑游戏需要实现的视觉效果,再不断的编写一个又一个函数,最后你把这些函数整理起来,就构成了一个庞大的函数库,最后你设计了一个算法来调用这些函数,运行,一个游戏就制作完成了! 然后你开始着手制作下一个游戏,不断的重复这一过程,早期的游戏大致就是这样的。 后来直到有一天,你接受了一个游戏项目的开发任务,分析需求的时候你本能的发现,以前编写的很多函数都可以直接或者稍微修改一下就能利用现有的项目上,大大节省了时间和精力。 于是你就这么做了,结果非常满意。 你受到了启发,一发不可收拾,把以前所有编写过的函数整理汇集都归成了一个库,以后再制作游戏,直接引用这个库就行。 说到这,应该已经很明显了,一个游戏引擎已经诞生了! 是的,这就是引擎,本质上就是N多个函数的集合,这些函数的通用性很强,可以适应某一类或者很多类型的游戏开发。 你是否有过这样的感觉,不是同一个公司的游戏,但看上去是那么的熟悉,那就是因为他们都使用了同一个引擎的缘故,还是熟悉的配方,还是熟悉的味道。 因为引擎这种通用性很强的东西总会有人想到要拿出来卖的,毕竟也是智慧的结晶,辛勤劳动的成果,有人肯买去用,何乐而不为。 有的是一次性买断,价格很高,有的是价格很低甚至免费,但需要从你的游戏销售额中提成,我们这里不谈营销,就一笔带过了。 总之,引擎没什么神秘的,就是这么回事。 早期的游戏都是一个游戏就从头做一个引擎的,很多时间和精力都耗费在了引擎的制作上,日本厂商尤其如此,时至今日才开始稍微有所转变。 欧美的游戏厂商在这方面走的比较早,我一般不喜欢升华些什么大道理,但这确实体现了日本所谓的匠人精神和美式工业化的区别。 在这里需要致敬一下id的创始人之一,约翰卡马克,他以一人之力编写了德军总部3d,毁灭战士,雷神之锤的引擎,并且他把这些全部公开共享了,你只要能上网,就能很容易的下载到雷神之锤的引擎源代码,全部C语言撰写,当然,你能看懂多少,悟到多少就看你自己的造化了。 你想自己写一个引擎吗?当然可以,没什么是不可以的,只需付出时间和精力罢了。
【千分之一的幸存者5:语言的诱惑】 【千分之一的幸存者5:语言的诱惑】 本文系原创,如需转载,请注明作者和出处。 任何一种语言都有语法规范,有人说汉语是语法规范最为松散的一种语言,因为一句话不管你怎么随意的打散重组,最终的意思你都能看懂。 我觉得这是句玩笑而已,因为长期生活在汉语环境中,基本的语法规范已经深深烙印在你的潜意识里了,还没等到你去把那些散乱的字进行排序,你的潜意识就已经替你把这些活都干了,还记得上一篇是怎么形容函数的吗?对散乱文字的排序这一系列的动作就已经相当于变成了一个函数存在了你的潜意识中,一遇到相应的情况就会自动调用。 再举个例子,你吃饭会很自然的用筷夹家东西吃,你根本不用去操心怎么样去使用筷子,对你来说使用筷子已经变成了你的本能,而本能是属于潜意识的,也就相当于用筷子这一行为也是一个函数。 经年累月,在你的潜意识中积累了无数这样的本能行为,无数的函数可供你随时调用,这些函数聚集在一起,就被称为函数库。 C语言之所以能够成为C语言,正因为它有一个总量巨大,门类繁多的函数库。 我们哪怕看一个最简单的C语言程序代码,也会在最开头发现有#include 〈xxx.h〉的字样。这就是在C语言的语法规范下对函数库的描述,include的意思是包含,#的意思就是没别的意思,C语言的设计者就是这么规定的,不爽的话你自己可以设计一门编程语言,怎么随你舒服怎么来。 尖括号里的内容就是函数库的名字,西方人的姓名顺序都是名在前姓在后,函数库的名字也一样,小数点前面的就是函数库的名字,比如专门处理图形图像的函数库可以叫做“图.h”,小数点后面的h就表示这是一个函数库,一定要写成汉字的话就是〈图.函数库〉。 有句话叫做工欲善其事,必先利其器,在你开始编程之前,先引用一个合适的函数库是很有必要的,当然你完全可以不引用函数库,所有需要用的函数都自己编写,只是工作量超级大罢了,如果可以站在巨人肩膀上看风景的话,我想我们自己还是可以不必自己搭梯子的。(C语言诞生至今几十年,官方的非官方的函数库简直浩如烟海) 我们再来完整描述一下这句话的意思就是告诉电脑,在开始编写代码之前先引用这个函数库,以后代码中如果出现了不是用户自己编写的函数名的时候就在引用的这个函数库中搜索并调用同名的函数,然后按照函数中预设的指令去执行。 为什么只要谈到C语言就必定会谈到函数呢,因为C语言本身的特性就决定了函数和函数库实在是太重要了,因为在C语言中你需要把一个动作掰碎了揉烂了再按顺序一步一步告诉电脑怎么去做,它才能去具体的执行。 有个我印象很深的例子,比如从前有一个叫做C语言的魔法师,你去跟他学火球术,他会这么教你: 一、拿起法杖 二、平举至胸前 三、向左偏三十度 四、向上十公分 五、…… 一套分解动作下来半个小时已经过去了,你记笔记都用掉了几十页纸,但神奇的是,只要学会并熟悉了,你很快就能召唤出火球,而且次次成功,从不失手。 说句稍远点的话,C++别看只比C多了两个加号,如果是这位法师教你火球术的话倒是很省事,他会给你很多写满密密麻麻文字的符咒,然后用的时候大喊一声火球术!然后扔出去,能不能召唤出来就全看信仰了。 所以C语言也并不适合所有人学,如果看到这里并且还愿意继续看下去的你,说不定很对C语言的脾气呢。
【千分之一的幸存者4:天下武功出少林】 本文系数原创,若转载请注明出处及作者 为何是c语言? 为何几乎所有学校教材都将c语言作为教学对象? 要知道对于一个从未接触过这方面哪怕一星半点的外行人来说,一个简单的语言才是好的语言,假设我是个白脖子,但我想开始学习编程,摆在我面前的有三本书,三段简单的示例性代码,分别是pyhton、java和c。 那我肯定会毫不犹豫的选择第一个,哪怕选第二个都不会选第三个。 为什么? 因为c语言从来都谈不上简单(当然,汇编就别提了),别的语言一句话的事,它就要忙活一大段文字。那么为何普遍的会把它作为学校的教授内容呢? 我个人感受是,c的逻辑性和条理性能够帮助学习者养成良好的编程思想,c如今充其量就是一个中级语言,既有高级语言的特性,又能够涉及到底层运行的很多东西,学习以及应用它的时候你要考虑很多事情,这是很有益处的。 我们就拿考驾照来说,驾照严格的分类是有手动挡和自动挡的,但几乎所有人都会去考手动挡,自动挡简直无人问津,为何? 因为手动挡驾照能开自动挡的车,但拿着自动挡驾照你就只能看着手动挡的车干瞪眼? 手动挡更复杂? 这是表象上的,深入一点就是手动挡是在从更底层的方面在操纵汽车,你需要顾及的地方很多,档位、离合、转速、路况……坏处是很难上手,好处就是你能够在驾驶的时候更准确的把握车子的整体状况。车子就好像一张蜘蛛网,你就像是那个盘踞在网中心的蜘蛛,每一根蛛丝的颤动你都能清楚的感觉到,这就是老手们常说的驾驶手感。 相较之下,自动挡由一套操纵机构代替你做了很多事情,你可以很容易上手,但你不知道你驾驶的时候车子内部发生了什么,你的车子对你来说就像一个最熟悉的陌生人。 c语言也是这样的,它就相当于编程语言里的手动挡,而且其出现的时间和地位都是元祖、宗师级的,在c之前,有很多种可以称得上是光怪陆离的编程语言,百家争鸣,各放异彩,但在c出现之后,几乎所有后来出现的编程语言都在借鉴沿用c语言的框架、规范和思想。 是不是有句话已经呼之欲出了? 是的,天下武功出少林! 绝不敢说你学会了c语言就闭着眼睛也会Python,但可以说学会了c一定可以让你能够更快更好的学会Python或者其他语言,别的白脖子用三个月,你有c的基础就只需要一星期。 那么c是不是就只能用来当教学工具? 不,c虽然写起来很费事,但最终成品程序的运行效率是除汇编语言外其他语言都无法相比的,有句话怎么说的来着?前期费事,后期省心。不知道对别人怎么样,反正对于我这种性格的人来说,c的这个特性是正中我的红心,太对胃口了。 我们经常听到的说法是c就只能做后台方面的事情,整天和黑底白字的控制台打交道,眼前就是一堆堆密密麻麻的数字字母符号,别说实际看了,想想脑袋都要爆炸。 在如今出现了很多优秀的高级编程语言的情况下,c确实越来越向后台转移,这是事实,但并不意味着c就只能做后台,很多人在学习c的时候会产生迷茫,因为没有方向,比如学了java是为了搞手机APP,学PHP是为了做网站网页,诸如此类。 但c没有什么方向,看起来什么也做不了,但真正本质上的含义就是——c语言什么都能做! 我喜欢玩游戏,我就只举一个例子,电脑游戏从二维转向三维的划时代里程碑,雷神之锤!一直到雷神之锤2,其引擎都是纯C语言编写的,作为第一个真全三维第一人称射击游戏,还能联网对战,还要顾及到大多数玩家电脑的配置需求,那时候显卡还是个稀罕玩意,要求代码运行效率必须极其非常的高,而C语言就做到了,当然也离不开卡马克大师的精湛编程艺术。 所以,如果想成为一个程序员而不是码农,那么学习C语言还是很有必要的。
【千分之一的幸存者3:函数不是数】 为了做个同人游戏而半路出家学习编程的我一定是出了bug 我虽然不敢对最初翻译函数这个名称的译者提什么意见,如果你对相关的知识了解的足够,你就知道这个译名确实够高雅,够内涵,这样翻译当之无愧。但函数这个词毕竟是百年前由中国学者翻译的,为什么要这样起名字,有什么梗在里面,我们今天一般人都是很难去了解的,更多的只是从字面去理解它的意思,我们很容易把它和整数,小数,自然数,有理数,无理数等等相提并论,觉得它是一种数字的合集。 我曾经也是这样想的,所以在学习的时候很迷糊甚至很痛苦,因为从根本的大方向上没有上路的话,不管怎么努力收效也是甚微甚至起反效果。 今天我就来谈一谈我所认知的函数的本质。 先不谈大道理,我们讲一个小故事,很久很久以前,有一个建筑师,当然他更接近于木匠和砖瓦匠的合体,他的工作就是接受委托,给各种人盖各种房子。 盖房子需要木材,砖瓦,至于怎么盖,你心里自然是有数的,给你足够的材料和时间,你就能盖出来一座很好的房子。随着时间的推移,你的名气越来越大,订单也越来越多,你忙不过来了,很自然的,你想要扩充人手,传统的办法就是收徒弟,师傅领进门修行在个人,再加上师傅总爱留一手,十年八年之后也许你能有一个帮的上忙的人。 很显然你不想这么做,于是你苦思良久,想出一个办法,你撰写了一整套文档,这个文档详细的描述了盖房子前后的整个过程,用最直白的语言去描述,甚至详细到怎么放砖头,以怎样的角度去构建框架,只要认识字,哪怕从没摸过工具的人也能照着一步步盖出一座房子来,而且最终质量能达到你水平的百分之九十(剩下的百分之十纯属天赋以及熟练度问题)。 然后你在该套文档中把所有涉及到数量(如砖瓦数,木材数,以及各种尺寸之间的对应关系)的地方统统留白,届时就可以根据实际订单上要求的数据填进去,盖出的房子可以满足不同人的实际需求。 最后,你给这套文档起了个名字叫做《白脖子建筑法》,好了,尽管前期准备真的很花心血,但接下来你就可以敞开了招募工作人员了,只要雇得起,有多少就来多少,只要把这套方法从你的书房调用出来交给雇员让他照着去做,你就可以躺着数钱了,随时都可以调用,但只有跟你打过招呼,声明一下,才可以调用。 说到这,我想已经不言而喻了吧,没错,你的这套文档本质上就是一个函数! 前面给它起的名字就是它的函数名,文档中留白的地方需要填的数据就是这函数运行所需要的参数。 是的,本质上函数就是一套解决问题的方法,但它不是解决某一个具体问题的,而是用于解决一个大范围的普遍性问题的,由于可以传递进去不同的参数而得出不同的结果,在设计这套方法的时候需要很耗费心力,但好处就是一劳永逸,前期费事后期省心。 所以,不要再对函数这个名词进行字面上的理解了,也不要害怕它,它并不难,只是复杂而已。 说句题外话,物理这个词在百年前翻译引进的时候是不叫物理的,叫格致之学,你要是去了解一下它背后的信息量,你绝对会佩服之至,但我们一般人肯定都不会这么去做,甚至对这个名词感到厌烦,函数也是这样,我们不要觉得莫名其妙就不想去了解它,可以先抛开它的名字,看看它本质上在讲一个什么意思,最后那怕你仍然不喜欢这个名字,你大可给它起另一个名字,这都不会妨碍你的学习过程。 上一篇我们稍微讲了一下点在屏幕上的移动方式,我们就继续说这个例子,这个地方我就可以设计一个函数,函数的内容是检测并接收这个点的坐标值,一旦检测到,就执行y不变,x不断增加的这一行为,起个名字叫做“右移”,那么我以后就不用再反复的告诉电脑具体怎么执行了,我只要告诉电脑以后就调用这个函数,把xy的值输入进去,一系列的动作指令自然就会出来,只要用的时候大喊一声“右移”!就可以。 简单点说,函数就是这么回事,可能有在校的学生会跳出来反驳,我们做题的时候函数可不是这么回事啊!别急,你仔细看看,数学习题中涉及到函数的部分它的表象是一道题就让你重新设计一个函数,几乎没有什么重用性,本质上是在锻炼你们的设计函数的能力,为的是在将来你们可以设计出很高明的,重用性很强,适用范围很广的函数,所以,好好努力吧!
【千分之一的幸存者2:算法并不难】 为了做个同人游戏也是拼了 一说到算法,很多人肯定心里又是一紧,眼前仿佛已经出现了密密麻麻充满数字字母和符号的代码,滚来滚去,滚来滚去…… 不敢说我能代表大多数人的想法,不过我以前就是这样的,而且何止是心中一紧,简直是冷汗直流,面青唇白,大有庐山爆炸,心脏停止运行之势了。 现在虽然在算法上也谈不上什么造诣,不过至少不再害怕,知道它是个什么东西,我就来谈谈我的看法,还是来说1+1=2吧,电脑在检测到你前面输入了一个数,它就把这个数保存起来,然后继续等待,再检测你输入了一个数,它就会把这两个数相加,把结果输出到屏幕上让你看到一个2,“把这两个用户的输入相加求和”,这就是一个算法,再说的直白一点,就是一个计算方法而已,只不过这个方法是由你预先设计好并存在电脑里以指令的方式让电脑去执行罢了。 也许有人会嗤之以鼻,这不就只能算个数吗,我操作电脑的时候那上面花样可多了,是的,那些话样只是你眼睛看到的部分,在这些表象背后其实都是有算法在支撑着的。 我喜欢玩游戏,尤其是暗黑破坏神2那种类型的,咱们就以这个为例讲一讲无处不在的算法。 只要是完成九年义务教育的人都知道平面直角坐标系是怎么回事,咱们只谈第一象限,我们屏幕左下角就是原点,底边是x轴,左边是y轴,我们的人物就是屏幕上的一个点,如果这个点已经有了任意一个位置,我们要描述它从左向右平移这一现象,怎么办呢,很简单,在平面上构成一个点的最基本要素是什么?就是x和y。 我们根本不用管他在什么位置,我们关心的就只是他的xy坐标怎样变化而已,从左向右平移,y坐标是不变的,x坐标则是逐渐变大。 这就是人物在地图上移动的核心算法,很难吗?当然具体实现上会更复杂,但至少我们知道了它的原理并不难。 如果说的更具体一点,我们给电脑预设一些命令,让它检测到键盘上的右箭头键被按下的时候,就维持y的数值不变,把x的数值不断增大,这样表现在一个点上就是你会看到它不断的向右平移。 然后的原理就更简单了,你只需要吧这个点提换成游戏人物的图片,背景提换成制作好的地图,一个最基本的游戏雏形就出现了。 再多说一句的话,你总不想你的人物走出屏幕边界消失不见吧,要知道我们只能看到屏幕那一块方形区域的大小,但屏幕里由电脑所描绘的世界几乎是无限大的,所以你需要设计一个碰撞边界的算法让你的人物能停下。 如果直接看到这里可能有很多人扭头就走了,但是如果你已经了解了前面的人物移动算法原理,你就不会害怕了,无非还是初中几何的那些东西罢了。 假如你的屏幕分辨率是1024*768,你只需要给电脑一个命令,这个命令的内容就是,当检测到x的数值大于等于1024的时候,就不再增加x的数值,不管用户怎么按向右的方向键都不要理他,y轴也是同理。这样就可以阻止人物移动出屏幕外了。 算法很难吗? 算法没有难易之分,只有简单与复杂,为什么这么说呢?因为这是电脑,标准一点的说法叫计算机,的运行机制决定的。 你以为电脑很聪明吗?你肯定会说电脑当然很聪明,但我要说若论道聪明程度,它可能连一只虫子都比不上,你眼里看到的它的所谓聪明,其实是另一个字——快! 没错,有句话叫做,天下武功,无坚不摧,唯快不破。电脑正是这句话的直观体现,比如下棋,你凭直觉,甚至都不知道自己是怎么思考的就能走出一步很合理的棋,电脑做不到,但它能够以极快的速度瞬间检索存在硬盘里的几千几万个棋谱,然后和眼前的这一步棋一一比较,最后下出一步最优选的方案。计算速度快,就是它的唯一优势,而且在自然界无人能够超越,永远不能。 新闻上也经常有报道某某电脑下棋赢了世界大师,那我们只能说它的资料库足够大,算法足够快,并不能说它聪明。是的,除了硬件方面的参数,算法是有优劣之分的,比如你设计的算法算这个结果需要三个步骤,他设计的算法只需要两步,那就可以说他的算法比你的快,说简单点就是这样。 那么设计一个算法难吗?一点也不难,只是需要付出时间而已,因为说白了电脑只会加减乘除,就看你怎么把一个想要实现的功能不断拆分,最后一直拆到能用加减乘除来描述而已。就像汉字有横竖撇捺,怎么组合把它变成字,在把这些字组成文章就是你的本事了。 我也是想到那说到哪,可能没什么体系的感觉,以后会视情况来做整理,在这之前就当作一个随笔来看吧。
【千分之一的幸存者1:编程并不可怕】 本文系作者原创,作者系半路出家 一提起编程,给大众的印象都是高深莫测,可远观不可亵玩焉的感觉,一开始我也是这么想的,直到后来看过了一部叫做《造梦的雨果》的电影,这一部文艺片,略微带点蒸汽科幻风,具体剧情无需赘言,它给我印象最为深刻的并不是剧情,而是剧中出现的一个机械人偶。 这个人偶表面看去并无特殊之处,跟其他造型精致的人偶一样,但它的内部有一套极其精密的齿轮和杠杆,由发条驱动,一旦启动他就可以用一支蘸水笔画出一副漂亮的简笔画来。 这个人偶是有原型的,欧洲的一位能工巧匠曾造出这样一个人偶,能够写出一篇赞美诗,新闻也报道过,现在大概在某个博物馆吧。 其原理并不难,只是复杂而已,我一直强调的一个概念就是,难和复杂是两回事,前者指的是无法学习无法理解,而后者就只是单纯的把简单动作堆叠在一起罢了。其原理就是跟我们小时候玩的发条跳跳蛙一回事,发条跳跳蛙只能完成跳跃这一个往复动作,只需要一组机械模块,而写一个字,假如是汉字,就是横竖撇捺四个动作的不同顺序堆叠,理论上就是四组机械模块加上一个控制顺序的模块,一个字与另一个字之间笔画长短位置肯定是不同的,所以还需要另外几个模块配合在一起,最后由发条提供动力,把单纯的转动转化为其它方向的运动,最后让人偶的机械臂在纸上就可以写出你想要的任何预设文章。 造这样一个人偶,亦或是说制造这样一部精密机械,显然是需要花费巨大精力的,没人会想要这个人偶被制造出来却只能写固定的一行字或一篇文章。就好比你是一个工厂主,花了几千万买来一台高精度全自动机床加工中心,却发现它只能加工一种零件,连一个尺寸都变不了,那时恐怕我的太阳都不足以抒发你胸中的澎湃的感情。 所以,在人偶内部还有一组可拆卸替换的金属盘片,上面打有无数间距不同的小孔以控制齿轮机械模块完成不同的输出动作,听起来很熟悉吧,传统的音乐盒就是这么个道理。一组金属盘片就是一套预设动作,这样只要更换不同的打好洞的盘片理论上就可以让这个机械人偶做任何事情。 按照顺序完成预设指令的过程就可以称之为程序,而那个在金属盘上打孔的那位仁兄,应该就是最早的一批程序员了,因为如今的程序员其实也在做着类似的事情,只是操作对象变成了计算机(电脑)而已。 就拿个地球人都知道的东西来说,所有Windows系统都自带的计算器软件,表面上看你是输入了1+1按下=结果得出了2,实际上是程序员对电脑进行了一系列的预设命令,让电脑不断检测你的输入,然后把前后检测到的你的两次输入进行求和运算,最后输出到屏幕上让你看到。 简单点说就是这样,编程简单说就是这么回事,但是基本上我们在学校的教材都不会这么说,反而是抛出一大堆晦涩的名词变着法的故作高深,让初学者望而却步。 想来也并不只是编程教材如此,任何学习用书仿佛都为了标榜自己的高端大气上档次而故作艰深,也许是为了追求严谨,但这种一句话掰成三句还要再绕个十圈说的做法确实让一大批对编程有兴趣,将来可能成为优秀程序员的初学者倒在了门槛外。 我给这个系列的文章取名为千分之一的幸存者也是寓意如此,比方说有一千个人打算学习编程,可能有九百个人都倒在了门槛外,连门槛都没摸到,剩下的一百个人可以称之为初学者,但是这批初学者又会有九十个人倒在了前两章内容的学习中,只有十个人能够学完一本书,可以入门,这十个人中根据自己勤奋和天赋的不同,大概最后只有一个人能修成正果,成为能够写出一个完整程序的程序员(水平如何暂且不论)。 本来编程种种事情就是西方人发明的,对于非英语母语国家的人来说群众基础就无法相提并论,而很哭笑不得的另一大原因竟然是我们的教材太过故作艰深,平白葬送掉了许多人入门的契机,实在太可惜。 我也不敢说自己有多高的水平,但至少我曾经是那千分之九百九十九中的一员,深有体会。 想当初怀着无比兴奋的心情和期待开始编程的学习,却只能以傻眼和哑口无言以及一点点心有不甘合上了教科书的第一章。 但是幸好那一点点的心有不甘一直埋藏在心底,未曾熄灭,直到许多年后机缘巧合之下遇到了另一本c语言教材,之前我一直以为所有的c语言教材就都是大学里教科书那样子的(没错对于一个什么都不懂的人来说留下心理阴影就是这么容易),看了这另一本教材后我才知道,尽管不确定最后我能学成什么水平,但至少编程这件事一点也不可怕,由此一只脚才算是踏进了门,此后一个新的世界在已近而立之年的我面前渐渐展现出丰富多姿的身影,时而让我惊叹,时而令我挠头,但它始终吸引着我,能让我感受到它的魅力。 想想未入门之前的我,恍如隔世,唏嘘不已。 将心比心,也许我人微言轻,也许我势单力薄,但只要能帮助哪怕一个人一点点,能够不再重蹈我的覆辙,顺利的踏入这个门槛,那我也是极其欣慰的。
挺喜欢李钊,不过还是想问问她名字的由来,有人知道吗? 光听名字真是很难想到这是个妹子,李钊这名字太男性化了,是因为她父母太想要儿子了吗? 以前也听过一些类似的事情,例如想要女儿的结果生了儿子,就给儿子起个很女性化的名字慰藉一下。
【记录】帝剧惊魂夜_制作进度汇总 总之,一楼先空出来
【感谢】已经顺利地从樱花大战1PC版中提取到了各种声音素材 之前的那个手游评论的帖子我就不顶了,以免被认为是挖坟。 在那个帖子中大家对樱战的手游持各种意见,褒贬不一,其中我就提议既然我们有这么多的意见,这么多的想法,我们为什么不能自己做一款樱花大战的游戏,将这些想法付诸实施,而不是只顾对别人的劳动成果喷口水呢? 虽然我性子比较慢,但我还算是个行动派,从零开始学习编程,已经入门,现在准备做游戏了。 之前苦恼于樱花大战中诸多音效无法自己实现而苦恼,后来有的网友提议从PC版中仔细找找,兴许能找到一个专门存放音效的文件夹,我找了找,还真找到了,一部分损坏,但大部分都是能用的,感谢你们的提议。 接下来就会开始做,虽然不知道什么时候能出成果,不过我会坚定不移地做下去,谢谢!
一只羊也是赶两只羊也是轰,索性又扫了一本初一时画的本子 这次画工进步了一些,情节也不那么无脑了
前些天打扫房间翻出来一本小学六年级画的本子 我曾经上传过小学五年级画的本子仙剑奇侠传,后来前些天大扫除,又给翻出来一本小学六年级的画的宝莲灯的本子,分享到了网上,废话不多说,只要是八零后里面的梗应该是懂得。
【花之物语】日记篇 本文纯属抄袭,如有雷同,简直太正常了! 本文很短,就是想借以探讨一下男女思维逻辑上的不同,希望各位异性恋们总结经验,和自己的另一半相处得更融洽。 废话不多说,开搞!……稿……
【花之物语】第39话—手机篇 大家好,换了智能手机,忍不住想用手机写一篇试试,这就开始。
【请教】各位朋友,有个问题我想在这里请教一下,谢谢 这个可不是虚构,这是我实实在在的问题。
【花之物语】第38话:凶灵再现 本部承接第37话 故事嘛,当然还是胡编乱造的,如有微妙的既视感,还请您睁一眼闭一眼……
【花之物语】第37话:帝剧凶灵 本故事纯属胡编,如有雷同,还请您大人有大量,睁一眼闭一眼,请多包涵……
【花之物语】第36话-红兰:钢铁之心
【求教】有没哪位朋友会修改盟军敢死队1贴图的? 我的想法是这样,用樱花大战的相关素材替换进盟军敢死队的相应素材,做个mod版出来一定很好玩。 但是网上关于盟军敢死队的mod制作方法、教程什么的实在是乏善可陈。 我知道吧里卧虎藏龙,特来请教,有懂得这方面的朋友请指教一二,谢谢。
【PS2炽热之血】终于沉不住气了,抱怨下! 看着各种模拟PS2重制版樱花大战炽热之血的报告,各种截图,各种讨论…… 我真是心里在滴血呀,不因为别的,只因我明明坐拥一台港版90000型PS2,却玩不成! 既尴尬又悲愤! 邮购、下载自己刻盘、拜托游戏店老板给我刻盘……不管怎么样,都是只读个片头就黑屏了! 模拟呢,我的电脑又不够劲,CPU和内存勉强可以一战,但显卡真心不行,N系7600GT。 唉,也不指望能解决问题,就是抒发一下心情。 当然还是有朋友可以指教一下比较好,先谢谢了。
【花之物语】第35话【直到世界的尽头】 本文纯属胡编,如有雷同,太刺激了。 34话为什么坑了?其实我也不想坑的,但是经过观察,尽管我没被百度封,但是无疑被“拉黑”了,基本上莫名其妙的就会被抽,至少在我看来莫名其妙。 而我又不愿意迁就百度去修改一些我根本不知道在哪里的不和谐词汇,所以我只好转战百度以外的平台,以保证作品的完整性。 最后,谢谢观赏。
【花之物语】第20话【横山智佐相亲记(审判日篇)】 【花之物语】第20话【横山智佐相亲记(审判日篇)】 春天,这是一个令人身心愉悦的时节。 尤其像作者这样的未婚男子,这个时节就会很容易做春梦。 不知道这是不是一个普遍现象,出现在我们梦中的异性,都是记不清面容的。即使恍恍惚惚的当时记住了,过后醒了也会忘得一干二净。 只是记得很美,但是具体的五官已经忘记了。 大神一郎也是这样。 他是一个海军出身的年轻男子,身强力壮,精力充沛,目前就职于东京市银座区中央,全日本最大的一座剧场——大帝国剧场任职。 检票员。 当然这只是一个虚职,真正的职务是帝国华击团·花组的队长。这是一个秘密部队,专门用于对魔物作战。 就像漫画里的各种英雄战队一样,在一般市民们看不见的地方,默默地打倒一个又一个怪物,也许只有当他们的事迹被改编成漫画或者上映真人电影版的时候,才会为人所知。 平时就是进行各种公演。 想想也是,一群风华正茂的女孩子,整天憋在地下基地里待命,会出毛病的。 让她们在舞台上展现自我,成为明星、偶像、歌手,岂不快哉! 大帝国剧场就提供这样一个平台。而她们表现很不错,人气很高,除了剧场公演一票难求以外,各种广告、代言、深夜剧、电影……也都开始涉足。 当然前提是降妖除魔的任务不能缺勤。
【花之物语】第34话【剧场版:沉默的花组】 本文纯属虚构,如有雷同,请多海涵…… 话说同人小说这东西本来就不具备什么“严肃”“原创”“严谨”的属性,大家看了就图一乐呵,至少我是这么想的。 那咱们就开始吧。
【童年涂鸦之作】仙剑奇侠传同人本 各位朋友,你们好。 来到这个地方的大家都是喜欢仙剑奇侠传这个主题的,我也是。 我小时候喜欢画画,画了很多,现在有了扫描仪,就陆陆续续把那些画传了上来。 觉得喜欢的朋友呢,您给叫声好,我谢谢您。 不喜欢的朋友呢,请您也嘴下留情,我不是有意瞎您眼得罪您的,请多海涵。 我现在还不是会员,发帖需要验证码,所以更新比较慢,见谅。 咱们这就开始。
【花之物语】33话【在奎爷眼里你们都是红魂】 本文纯属虚构,如有雷同,太刺激了……
【花之物语】第32话【漫画图片顺序发错的话红着脸也要重开一贴】 之前的漫画顺序有搞错的地方,我决定重新发一次,这次一定小心。
首页
1
2
3
4
下一页