写一段一个简单的c程序序

&主题:很多年前写的一段不忍直视的C程序
&浏览:2118&& 回帖:74 &&
泡网分: 13.284
帖子: 2160
注册: 2008年08月
imokay 发表于
STL那个性能啊,我估计在某些情况下可能还真不如java快,瓶颈在内存分配和释放,STL用几个队列来管理内存,每次内存分配和释放的开销比java大得多。“STL用几个队列来管理内存。”,呵呵呵
泡网分: 9.706
注册: 2008年11月
色苑杂谈 发表于
内存泄漏也不只是属于菜鸟、初哥,对于高大上的专业选手貌似也难以杜绝。
微软的工程师曾经讲过一个故事,大意是一个客户因为软件不定期崩溃来求援的前前后后。这家客户开发了一个服务器软件,每运行若干时间之后即崩溃,一直找不到问题所在,最后只好用了一个笨办法暂时对付:同时开几台服务器,每台服务器定时轮流重启,让它的用户感觉不到服务的中止。最后微软的工程师帮助找到了隐蔽的内存泄漏,问题彻底解决。我这里就有一个软件,我自己设计的,vc6设计的平台,加载运行N多个vb6设计的com组件,每过10天就因为内存耗尽崩溃一次。由于混合了vc6和vb6,查这个内存泄漏问题很不容易。
泡网分: 38.241
帖子: 6618
注册: 2004年08月
nahcooo 发表于
scanf需要带入一个地址做参数,如果你代入的是100,就写在内存中100这个位置,如果代入200就写入在200这个位置。
所以char a[100],代入a的话,就是代入a[0]的地址,即&a[0]。字符串就会写入在这个位置,而如果代入一个整数x的话(且这个x未赋值,就会将字符串写入到随便的一个位置)
Turbo C是在C下的,16位,int的值在0-65535范围内。也就是说,必然对应着内存中0-64K的位置,这个位置虽然是乱来的,但不会超出。
你这个程序是强制性的随机制定一个位置(处于0-64K),将字符串写在那里,至于那里原来是什么数据,是不是系统必要的关键信息,就不管了
32位的gcc下,int取值范围是0-4GB,很难保证它的“随机值”是可写的地址。碰到不可写的地址就崩了。就是这样。1、char a[100],是实际上做了个malloc,分配了101个字节位置。至于引用,都是指针没有区别。
2、16位下,int变量是-3,占用一个字(两个字节);32位下,是-~+,占用4个字节
3、LZ的做法,只有一个两字节变量在数据段,而数据段不会那么短,后面其实是一堆没有用到的随机的垃圾数据和位置。当scanf给它赋值时,是把输入的字符串加上一个结束标志0放到了变量指针开始处,只要不超出数据段,就能放下,而不会影响任何其他数据(因为没有)或代码,所以能够正常运行。而要超出数据段,恐怕得拷贝个几万字的中篇小说粘贴到输入处才有可能(16位典型数据段64KB)。32位也一样,不过是数据段更大了,估计得上百部百万字级别的长篇小说才够(32位典型数据段256MB)。
4、LZ的程序如果写成这样,用Turbo C这种典型的16位程序来做,运行3遍,第一次输入1个字符,第二次输入2个字符,第三次输入3个以上字符,肯定能看到区别:
& && &&&int x,y;
& && &&&scanf(&%s&,x);
& && &&&printf(&%s\n&,x);
& && &&&printf(&%s&,y);
比如第一次输入:A,最后输出y时,一般是一长串乱码(没变过的数据段中的随机的垃圾数据);第二次输入:AB,输出的y会是空的,因为上来遇到的就是结尾0;第三次输入ABCDE,输出的y会是CDE。
泡网分: 1.242
注册: 2011年08月
大学搬迁,很多专业老师都没来,只好找物理、数学老师,C程序老师凑数给我们上课。
让文科生必修C程序,有王法吗?最后重修3个学分,240块
泡网分: 38.241
帖子: 6618
注册: 2004年08月
arondes 发表于
这里面还有一个小“技巧”
如果写成scanf(&%s&,&x);是不行的,还就非得写成scanf(&%s&,x);对于int来说,x就已经是指针了,&x是指向变量位置的指针的指针,这个一般在代码段,你把数据往代码段放,不是不允许编译就是代码崩溃。
泡网分: 31.208
精华: 1帖子: 15864
注册: 2008年08月
智者见障 发表于
大学搬迁,很多专业老师都没来,只好找物理、数学老师,C程序老师凑数给我们上课。
让文科生必修C程序,有王法吗?最后重修3个学分,240块真可怜。不过话说回来文科生过计算机二级好像是有这个要求
泡网分: 31.208
精华: 1帖子: 15864
注册: 2008年08月
IBMX31 发表于
1、char a[100],是实际上做了个malloc,分配了101个字节位置。至于引用,都是指针没有区别。
2、16位下,int变量是-3,占用一个字(两个字节);32位下,是-~+,占用4个字节
3、LZ的做法,只有一个两字节变量在数据段,而数据段不会那么短,后面其实是一堆没有用到的随机的垃圾数据和位置。当scanf给它赋值时,是把输入的字符串加上一个结束标志0放到了变量指针开始处,只要不超出数据段,就能放下,而不会影响任何其他数据(因为没有)或代码,所以能够正常运行。而要超出数据段,恐怕得拷贝个几万字的中篇小说粘贴到输入处才有可能(16位典型数据段64KB)。32位也一样,不过是数据段更大了,估计得上百部百万字级别的长篇小说才够(32位典型数据段256MB)。
4、LZ的程序如果写成这样,用Turbo C这种典型的16位程序来做,运行3遍,第一次输入1个字符,第二次输入2个字符,第三次输入3个以上字符,肯定能看到区别:
& && &&&int x,y;
& && &&&scanf(&%s&,x);
& && &&&printf(&%s\n&,x);
& && &&&printf(&%s&,y);
比如第一次输入:A,最后输出y时,一般是一长串乱码(没变过的数据段中的随机的垃圾数据);第二次输入:AB,输出的y会是空的, ...经验证结果如下:
泡网分: 11.439
帖子: 10073
注册: 2012年06月
智者见障 发表于
大学搬迁,很多专业老师都没来,只好找物理、数学老师,C程序老师凑数给我们上课。
让文科生必修C程序,有王法吗?最后重修3个学分,240块王法不是要求必须过计算机二级?
我们学校的文科生大多选的VFP
泡网分: 0.083
注册: 2014年02月
泡网分: 7.24
帖子: 1065
注册: 2009年11月
imokay 发表于
STL那个性能啊,我估计在某些情况下可能还真不如java快,瓶颈在内存分配和释放,STL用几个队列来管理内存,每次内存分配和释放的开销比java大得多。这是技巧问题,跟语言无关。弄个池就可以解决的问题
泡网分: 31.225
帖子: 15039
注册: 2008年11月
x86在实模式下有个段寻址,数据段和代码段不是同一个,所以楼主的程序虽然狗血,但侥幸不会覆盖到代码,所以不会出问题。但程序再复杂一点,会覆盖其他变量,结果不可预料。
32位系统下是线性地址空间,指针指向text区会触发异常,程序立刻完蛋
本帖由 V2.5.0 iPad 客户端发布
泡网分: 7.24
帖子: 1065
注册: 2009年11月
dhhd 发表于
C/C++没有垃圾回收机制, 内存泄漏很正常. Java和OC都有完善的垃圾回收机制, 这点上比C/C++好很多.
不过没有垃圾回收的好处也在性能上体现了, 只是对编程要求更高.
博德之门毕竟还是游戏, 有bug比较正常. 但是要是更加严谨的软件, 比如科学计算类的软件, 一跑能跑好几天甚至好几个星期的, 这种错误不能犯凡事有利有弊,java的垃圾回收在android上就是卡顿的重要原因,搞得android开发写new都战战兢兢的
泡网分: 8.256
主题: 1080
帖子: 7293
注册: 2012年12月
一张图搞懂java的垃圾回收机制
泡网分: 0.007
注册: 2011年02月
IBMX31 发表于
1、char a[100],是实际上做了个malloc,分配了101个字节位置。至于引用,都是指针没有区别。
2、16位下,int变量是-3,占用一个字(两个字节);32位下,是-~+,占用4个字节
...资深错了,char a[100]是在栈里分配的,不用malloc。malloc是从堆里面分配的。
16位下的int变量长度也不一定的。int 有short int, long int,而且在各个环境下还不一样,所以写程序如果要做到各种机器和系统下都能用,一般是不能写成int的。
泡网分: 0.007
注册: 2011年02月
arondes 发表于
我已经很多年没有接触C语言了,昨天写一个一百行的小程序发现漏洞百出,而且几乎全部跟指针/数组/字符串/内存分配这些有关。因为平时主要用的R,不需要声明变量,也不需要手动管理内存,特别方便,所以我几乎都忘了当初是怎么折腾的了。
抱着怀旧的目的,找出Turbo C 2.0,看了看自己最开始学习C语言的时候写的代码,感觉十分奇葩。更奇葩的是这样的代码居然可以顺利编译,运行结果也看不出问题。
void main()
& & & & scanf(&%s&,x);
& & & & printf(&%s&,x);
这段程序用Turbo C编译运行起来十分正常 但是刚刚用GCC试了下,好像就不行
当初我对C的字符串感到疑惑的一个地方在于,因为不知道用户会输入多长的东西,所以不知道该如何分配x的大小。但是教材上说C的字符串得预先分配,比如:char x[100]这样,那该咋办呢?那时候上网也不方便,我有问题都不知道怎么解决,全是瞎猜瞎蒙。于是乎我异想天开的居然“实验”出了这么一个办法,就是完全不管什么内存,什么变量类型,硬是用int即可。而且经测试,即使是用户输入好几行的内容,也照样可以。
十多年过去了,自己由于没有从事码农方面的工作,所以至今对C还是一知半解。但是看到这段代码,还是感到很欣慰。现 ...这个确实是因为野指针没有跑出范围,所以当年没有死人。
想当年的TurboC/BorlandC,默认是好像是小模式,然后还有微模式、小模式、紧凑模式、大模式和巨模式,就是为了解决8位、16位、32位的问题的。不同模式下分配的空间是不同的。
C语言虽然灵活,但是没有人给你做错误检查,做错了也没有人给你擦屁股,所以出点问题很正常,还很不好查。
泡网分: 25.886
精华: 1帖子: 3136
注册: 2004年10月
nokia6120c 发表于
我这里就有一个软件,我自己设计的,vc6设计的平台,加载运行N多个vb6设计的com组件,每过10天就因为内存耗尽崩溃一次。由于混合了vc6和vb6,查这个内存泄漏问题很不容易。那个微软工程师也介绍了自己对付内存泄漏的秘诀。。。机器一直开着,直到崩溃,然后转储内存,查看其中的内容。从概率上讲,绝大多数的内存空间都是被泄漏的部分所占据的,从泄漏的内容大致可以反推出泄漏的代码。据作者介绍,几乎是屡试不爽。
泡网分: 4.194
帖子: 3303
注册: 2013年07月
nahcooo 发表于
scanf需要带入一个地址做参数,如果你代入的是100,就写在内存中100这个位置,如果代入200就写入在200这个位置。
所以char a[100],代入a的话,就是代入a[0]的地址,即&a[0]。字符串就会写入在这个位置,而如果代入一个整数x的话(且这个x未赋值,就会将字符串写入到随便的一个位置)
Turbo C是在C下的,16位,int的值在0-65535范围内。也就是说,必然对应着内存中0-64K的位置,这个位置虽然是乱来的,但不会超出。
你这个程序是强制性的随机制定一个位置(处于0-64K),将字符串写在那里,至于那里原来是什么数据,是不是系统必要的关键信息,就不管了
32位的gcc下,int取值范围是0-4GB,很难保证它的“随机值”是可写的地址。碰到不可写的地址就崩了。就是这样。那怎麽知道哪个内存地址可用呢?怎么知道那个地址不被别的占用?要访问、返回确认内存是否可用先?如果不可用呢?那单是确定内存地址就要几行代码吧? 本帖最后由 luber2008 于
21:31 编辑
泡网分: 31.225
帖子: 15039
注册: 2008年11月
  微模式
  在微模式下,整个程序只有一段,这个段内包含代码、静态和全局数据、堆栈和堆。因为只有一个段,在执行时DOS将把寄存器CS、DS、SS设置为相等,全都指向这个段。在这个段内,代码是首先装入的,地址最低,接着是静态变和全局变量,然后是堆,最后地堆栈。堆和堆栈都是动态的,堆从低地址往高地址增长,栈从高地址往低地址增长。若两者相碰,则表示内存空间已耗尽。在微模式下,所有指针都是near,且都是相对于寄存器CS、DS和SS的。对于用微模式编译并连接生成的 .exe文件,DOS的exe2bin实用程序转换为 .COM文件。从下表演示程序的输出结果可以看出,函数a 比函数main的地址低,变量b比变量d的地址低。这是因为,在连接时是x.obj在前,y.obj在后。
  小模式
  小模式是常用的模式,本书中大部分例子都是用小模式编译的。虽然小模式与微模式一样,都是小数据、小程序模式,但它与微模式有两点重要的差别。第一,代码和数据/堆栈/堆段是分开的,所以CS不等于DS和SS。第二,除了和数据/堆栈共用一个段的堆外,还有一个远堆,以far指针进行存取。从数据/堆栈段的末尾直到常规内存的末尾都是属于远堆。因为代码、静态数据和(近)堆仍然在同一个段内,所以小模式下缺省的数据指针和函数指针都是near。结果,在小模式下不能直接通过该模式下的Turbo C 函数来处理远堆中的变量。然而,只要程序提供自己的操作函数,就可以存取整个远堆中的任一单元,即可以使用整个常规内存。
  紧凑模式
  紧凑模式在概念上是最简单的,代码、静态数据、堆栈、堆各有其自己的段。堆只有远堆,没有近堆。像小模式和中模式中的远堆一样,堆是用far指针来存取的。可以用Turbo C的库函数来处理堆变量。所有数据指针都是far,函数指针都是near。从演示程序的输出中可以看出,CS、DS、SS三个寄存器的值彼此不等。值得注意的是,静态数据的总量仍不可超过64K字节。
  中模式
  在数据/堆栈/堆的分配方面,中模式与小模式是一样的,差别在于码段的分配。在中模式下,来自不同源文件的码模式放在不同的码段内。严格地讲,同一源文件内的各函数也是放在不同代码段内。各码段的总空间数只受微机上可用内存的限制。因为有多个码段,所以Turbo C必须用far函数指针。在演示程序输出的结果中函数a 的地址为74F9:000E,函数main的地址为74FE:0004。函数a 的地址较低,是因为在连接时包含函数a的x.obj在前。在中模式下,堆仍然有近堆和远堆之分。
  大模式
  在静态数据/堆栈/堆的分配方面,大模式等同于紧凑模式。在代码的分配方面,大模式等同于中模式。无论是数据指针还是函数指针,一律都是远指针。与紧凑模式一样,静态数据的总量不可超过64K字节。
  巨模式
  巨模式取消了静态数据总量不可超过64K字节的限制。来自不同源文件的代码放在不同的段内,来自不同源文件的静态数据也是放在不同的段内,只有堆栈是合在一起的。以前举的例子就是利用了这一特点。从演示程序的输出中也可以看,当从函数main内调用函数a 时,不但CS改变了,DS也改变了。当然,两个函数共用了同一个堆栈,否则就无法正确返回。应该注意的是,不要把巨模式和巨指针混为一谈,在巨模式下缺省的指针仍是far而不是huge。
本帖由 V2.5.0 iPad 客户端发布
泡网分: 9.298
帖子: 5155
注册: 2010年03月
无忌这么多码农?有没有玩jvm优化的?
泡网分: 9.706
注册: 2008年11月
色苑杂谈 发表于
那个微软工程师也介绍了自己对付内存泄漏的秘诀。。。机器一直开着,直到崩溃,然后转储内存,查看其中的内容。从概率上讲,绝大多数的内存空间都是被泄漏的部分所占据的,从泄漏的内容大致可以反推出泄漏的代码。据作者介绍,几乎是屡试不爽。这倒是个思路。回头学习一下
泡网分: 32.578
帖子: 3176
注册: 2003年02月
wayli 发表于
无忌这么多码农?有没有玩jvm优化的?做咩?我搞过点。
泡网分: 4.145
帖子: 1847
注册: 2002年02月
北大青鸟学的高级程序员。。。忘的一干二净了。。。惭愧啊。。。
泡网分: 21.415
帖子: 21893
注册: 2004年06月
nahcooo 发表于
因为你写的是python/java一类,当然这么写,因为这么写的性能就是一坨屎。
C++不是不能这么写,只是写出来的性能也就是java一个级别了。但“原因还不明显”是错的,因为当你发现程序性能不够理想的时候,稍微有点经验的C++程序员都能看到这一段并且改进它。
全部用C是很快,但是太啰嗦太麻烦了,写点驱动啦,完成个算法什么还好。那种需要处理用户界面,需求变来变去改来改去的程序就要了命了。
全部用JAVA/C#是很方便,各种高大上的设计模式就是专门针对需求变化的,但是一旦遇到性能瓶颈就很麻烦。
C++的魅力在于,你可以用面向对象的方式来构建你的程序,来使它有着平常只有java才能具备的设计模式。而当你发现某个环节比较影响性能的时候,可以很轻松地,迅速地将这个性能瓶颈用C重写,如果还不够,可以内联汇编的方式重写这一段,整个过程顺利而自然。java想重写这一段得用JNI,还得处理各种java对象与C对象之间的转换,C#同理。python想这么做更是让你抓破头皮。只有C++能轻松完成。STL不是不能用,很多情况下它还很好用。而且STL用好了并不慢,C++是开发效率和运行效率间一个很好的平衡点。
个别时候,C++可能还快些。。。。
[url]http://www.oschina.net/translate/sorting- ...c++和java/c#& &各自都适合应用在什么场合下呢?
泡网分: 1.22
帖子: 1103
注册: 2011年10月
&C++的魅力在于,你可以用面向对象的方式来构建你的程序,来使它有着平常只有java才能具备的设计模式。&
好奇,23个设计模式里,除了涉及封装性的单子模式外,不知哪个模式是java可以用c不能用的?
我猜,是不是混淆了编程范式和设计模式这两个概念吧?
泡网分: 21.503
帖子: 8332
注册: 2008年06月
ygqiang 发表于
c++和java/c#& &各自都适合应用在什么场合下呢?windows/Linux本地应用程序,Android app和metro app。
本帖由安卓客户端发布
泡网分: 21.503
帖子: 8332
注册: 2008年06月
巨大防抖 发表于
&C++的魅力在于,你可以用面向对象的方式来构建你的程序,来使它有着平常只有java才能具备的设计模式。&
好奇,23个设计模式里,除...故意让C语言去实现那些设计模式就是没事找事。C语言需要注重的是效率,简单明快地去实现算法。去实现设计模式就是本末倒置。不说别的,你先搞个抽象工厂出来看看,当然要搞是搞得出来的,但让一个没有继承重载多态的C语言实现这个的代码还能看吗?还具备复用性吗?还具备之前的高执行效率吗?
本帖由安卓客户端发布
泡网分: 1.22
帖子: 1103
注册: 2011年10月
nahcooo 发表于
windows/Linux本地应用程序,Android app和metro app。这个问题应该这样回答:c++/c,针对有硬件操控需要和严格实时性要求的应用,其中,c++适合尤其适合在硬件操控逻辑和严格实时应用逻辑相对复杂的情况。
对于一切并无严格实时性要求和硬件操控需要,并且逻辑相对复杂,对性能有一定要求的,需要长期运行的本机应用(包括作为服务的应用),java/c#比较适合。
如果面向迅速开发,性能要求不高的应用,而且编程人员又对于计算机科学并不十分了解,那么php、ruby、Python一类的动态编程语言会是一个比较好的选择。
泡网分: 1.22
帖子: 1103
注册: 2011年10月
nahcooo 发表于
故意让C语言去实现那些设计模式就是没事找事。C语言需要注重的是效率,简单明快地去实现算法。去实现设计模式就是本末倒置。不说别的,你先搞个抽象工厂出来看看,当然要搞是搞得出来的,但让一个没有继承重载多态的C语言实现这个的代码还能看吗?还具备复用性吗?还具备之前的高执行效率吗?要用c语言模拟多态,其实并不是那么复杂。用结构和指针模拟就行了,其实最初版本的c++就是这样干的,不存在代码能看不能看的问题,应该说,当初c++发明人设计出这种模拟方式,还是相当优美而有技巧的。
当然,能不能是一个问题,有没有这个必要是另一个问题。
泡网分: 1.22
帖子: 1103
注册: 2011年10月
c语言难以模拟的,是封装性。靠语言的本身机制似乎无法实现——所以只能靠程序员“假装知道”,或者通过注解说明某段代码是封装的。
抽象性和多态性,模拟起来并不复杂。
泡网分: 31.208
精华: 1帖子: 15864
注册: 2008年08月
现在回忆起来,C语言里面最让我感到烦心的东西莫过于两样:宏定义和指针。宏定义我自己几乎从来不用,但是别人可能会用,有时还用很多。指针是谁也不能不用,但有时候会难免不小心出错,要关注的细节太琐碎
&版权所有:&&桂ICP备号&增值电信业务经营许可证  小弟初学,这段代码在VC上图形函数库是不存在的  有一疑问:怎么改写成C++语言?  #include &stdio.h&  #include &stdlib.h&  #include &dos.h&  #include &graphics.h&
/*图形函数库*/  /*定义按键码*/  #define VK_LEFT
0x4b00  #define VK_RIGHT 0x4d00  #define VK_DOWN
0x5000  #define VK_UP
0x4800  #define VK_ESC
0x011b  #define TIMER 0x1c
/*设置中断号*/  /*定义常量*/  #define MAX_BOX 19
/*总共有19种各形态的方块*/  #define BSIZE 20
/*方块的边长是20个象素*/  #define Sys_x 160
/*显示方块界面的左上角x座标*/  #define Sys_y 25
/*显示方块界面的左上角y座标*/  #define Horizontal_boxs 10
/*水平的方向以方块为单位的长度*/  #define Vertical_boxs 15
/*垂直的方向以方块为单位的长度,也就说长是15个方块*/  #define Begin_boxs_x Horizontal_boxs/2
/*产生第一个方块时出现的起始位置*/  #define FgColor 3
/*前景颜色,如文字.2-green*/  #define BgColor 0
/*背景颜色.0-blac*/  #define LeftWin_x Sys_x+Horizontal_boxs*BSIZE+46
/*右边状态栏的x座标*/  #define false 0  #define true 1  /*移动的方向*/  #define MoveLeft 1  #define MoveRight 2  #define MoveDown 3  #define MoveRoll 4  /*以后坐标的每个方块可以看作是像素点是BSIZE*BSIZE的正方形*/  /*定义全局变量*/  int current_box_
/*保存当前方块编号*/  int Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*x,y是保存方块的当前坐标的*/  int flag_newbox=
/*是否要产生新方块的标记0*/  int speed=0;
/*下落速度*/  int score=0;
/*总分*/  int speed_step=30;
/*每等级所需要分数*/  void interrupt (*oldtimer)(void);/* 指向原来时钟中断处理过程入口的中断处理函数指针 */  struct BOARD
/*游戏底板结构,表示每个点所具有的属性*/  {  
/*当前状态 只有0和1,1表示此点已被占用*/  
/*颜色,游戏底板的每个点可以拥有不同的颜色.增强美观*/  }Table_board[Vertical_boxs][Horizontal_boxs];  /*方块结构*/  struct SHAPE  {  char box[2];
/*一个字节等于8位,每4位来表示一个方块的一行  如:box[0]="0x88",box[1]="0xc0"表示的是:  1000  1000  1100  0000*/  
/*每个方块的颜色*/  
/*下个方块的编号*/  };  /*初始化方块内容.即定义MAX_BOX个SHAPE类型的结构数组,并初始化*/  struct SHAPE shapes[MAX_BOX]=  {  /*  *
口口口  *
  */  {0x88,
1},  {0xe8,
2},  {0xc4,
3},  {0x2e,
0},  /*  *
口口 口口口  *
口  * 口口 口口口 口
  */  {0x44,
5},  {0x8e,
6},  {0xc8,
7},  {0xe2,
4},  /*  *
口口  */  {0x8c,
YELLOW, 9},  {0x6c,
YELLOW, 8},  /*  *
口口  * 口口
口口  * 口  */  {0x4c,
11},  {0xc6,
10},  /*  *
口  * 口口口
口  */  {0x4e,
13},  {0x8c,
14},  {0xe4,
15},  {0x4c,
12},  /* 口  * 口  * 口
口口口口  * 口  */  {0x88,
17},  {0xf0,
16},  /*  * 口口  * 口口  */  {0xcc,
18}  };  unsigned int TimerCounter=0;
/*定时计数器变量*/  /* 新的时钟中断处理函数 */  void interrupt newtimer(void)  {  (*oldtimer)();
/* call the old routine */  TimerCounter++;/* increase the global counter */  }  /* 设置新的时钟中断处理过程 */  void SetTimer(void interrupt(*IntProc)(void))  {  oldtimer=getvect(TIMER); /*获取中断号为TIMER的中断处理函数的入口地址*/  disable(); /* 设置新的时钟中断处理过程时,禁止所有中断 */  setvect(TIMER,IntProc);  /*将中断号为TIMER的中断处理函数的入口地址改为IntProc()函数的入口地址  即中断发生时,将调用IntProc()函数。*/  enable();
/* 开启中断 */  }  /* 恢复原有的时钟中断处理过程 */  void KillTimer()  {  disable();  setvect(TIMER,oldtimer);  enable();  }  void show_intro(int xs,int ys)  {  char stemp[50];  setcolor (15);  rectangle(xs,ys,xs+239,ys+100);  sprintf(stemp," -Roll
-Downwards");  stemp[0]=24;  stemp[8]=25;  setcolor(14);  outtextxy(xs+40,ys+30,stemp);  sprintf(stemp," -Turn Left
-Turn Right");  stemp[0]=27;  stemp[13]=26;  outtextxy(xs+40,ys+45,stemp);  outtextxy(xs+40,ys+60,"Esc-Exit ");  setcolor(FgColor);  }  /*显示分数*/  void ShowScore(int score)  {  int x,y;  char score_str[5];/*保存游戏得分*/  setfillstyle(SOLID_FILL,BgColor);  x=LeftWin_x;  y=100;  bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);  sprintf(score_str,"%3d",score);  outtextxy(x,y,"SCORE");  outtextxy(x,y+10,score_str);  }  /*显示速度*/  void ShowSpeed(int speed)  {  int x,y;  char speed_str[5];/*保存速度值*/  setfillstyle(SOLID_FILL,BgColor);  x=LeftWin_x;  y=150;  bar(x-BSIZE,y,x+BSIZE*3,y+BSIZE*3);  /*确定一个以(x1,y1)为左上角,(x2,y2)为右下角的矩形窗口, 再按规定图模和颜色填充。*/  sprintf(speed_str,"%3d",speed+1);  outtextxy(x,y,"Level");  outtextxy(x,y+10,speed_str);  /*输出字符串指针speed_str所指的文本在规定的(x, y)位置*/  outtextxy(x,y+50,"Nextbox");  }  /**********初始化界面*******  *参数说明:  *
x,y为左上角坐标  *
m,n对应于Vertical_boxs,Horizontal_boxs  *
分别表示纵横方向上方块的个数(以方块为单位)  *
BSIZE Sys_x Sys_y  **********************************/  void initialize(int x,int y,int m,int n)  {  int i,j,  oldx=x;  for(j=0;j&n;j++)  {  for(i=0;i&m;i++)  {  Table_board[j][i].var=0;  Table_board[j][i].color=BgC  line(x,y,x+BSIZE,y);  line(x,y,x,y+BSIZE);  line(x,y+BSIZE,x+BSIZE,y+BSIZE);  line(x+BSIZE,y,x+BSIZE,y+BSIZE);  x+=BSIZE;  }  y+=BSIZE;  x=  }  Curbox_x=x;  Curbox_y=y;/*x,y是保存方块的当前坐标的*/  flag_newbox=
/*是否要产生新方块的标记0*/  speed=0;
/*下落速度*/  score=0;
/*总分*/  ShowScore(score);  ShowSpeed(speed);  }  /*
删除一行满的情况  *
这里的y为具体哪一行为满  */  int DelFullRow(int y)  {  /*该行游戏板往下移一行*/  int n,top=0;
/*top保存的是当前最高点,出现一行全空就表示为最点了,移动是到最高点结束*/  register m,  for(n=y;n&=0;n--)/*从当前行往上看*/  {  totoal=0;  for(m=0;m&Horizontal_m++)  {  if(!Table_board[n][m].var)totoal++;
/*没占有方格+1*/  if(Table_board[n][m].var!=Table_board[n-1][m].var)
/*上行不等于下行就把上行传给下行 xor关系*/  {  Table_board[n][m].var=Table_board[n-1][m].  Table_board[n][m].color=Table_board[n-1][m].  }  }  if(totoal==Horizontal_boxs)
/*发现上面有连续的空行提前结束*/  {  top=n;    }  }  return(top);
/*返回最高点*/  }  /*找到一行满的情况*/  void setFullRow(int t_boardy)  {  int n,full_numb=0,top=0;
/*top保存的是当前方块的最高点*/    /*  t_boardy 口
6  口口口口口口
口口口口口口
8  */  for(n=t_boardy+3;n&=t_n--)  {  if(n&0 || n&=Vertical_boxs ){} /*超过低线了*/  for(m=0;m&Horizontal_m++)
/*水平的方向*/  {  if(!Table_board[n+full_numb][m].var)
/*发现有一个是空就跳过该行*/  }  if(m==Horizontal_boxs)
/*找到满行了*/  {  if(n==t_boardy+3)
/*第一次献给了n,最高的*/  top=DelFullRow(n+full_numb);
/*清除游戏板里的该行,并下移数据*/  else  DelFullRow(n+full_numb);  full_numb++;
/*统计找到的行数*/  }  }  if(full_numb)  {  int oldx,x=Sys_x,y=BSIZE*top+Sys_y;  oldx=x;  score=score+full_numb*10;
/*加分数*/  /*这里相当于重显调色板*/  for(n=n&t_boardy+4;n++)  {  if(n&=Vertical_boxs)
/*超过低线了*/  for(m=0;m&Horizontal_m++)
/*水平的方向*/  {  if(Table_board[n][m].var)  setfillstyle(SOLID_FILL,Table_board[n][m].color);/*Table_board[n][m].color*/  else  setfillstyle(SOLID_FILL,BgColor);  bar(x,y,x+BSIZE,y+BSIZE);  line(x,y,x+BSIZE,y);  line(x,y,x,y+BSIZE);  line(x,y+BSIZE,x+BSIZE,y+BSIZE);  line(x+BSIZE,y,x+BSIZE,y+BSIZE);  x+=BSIZE;  }  y+=BSIZE;  x=  }  ShowScore(score);  if(speed!=score/speed_step)  {speed=score/speed_ ShowSpeed(speed);}  else  {ShowSpeed(speed);}  }  }  /*  * 将新形状的方块放置在游戏板上,并返回此方块号  */  int MkNextBox(int box_numb)  {  int mask=128,t_boardx,t_boardy,n,m;  t_boardx=(Curbox_x-Sys_x)/BSIZE;  t_boardy=(Curbox_y-Sys_y)/BSIZE;  for(n=0;n&4;n++)  {  for(m=0;m&4;m++)  {  if( ((shapes[current_box_numb].box[n/2]) & mask) )  {  Table_board[t_boardy+n][t_boardx+m].var=1;/*这里设置游戏板*/  Table_board[t_boardy+n][t_boardx+m].color=shapes[current_box_numb]./*这里设置游戏板*/  }  mask=mask/(2);  if(mask==0)mask=128;  }  }  setFullRow(t_boardy);  Curbox_x=Sys_x+Begin_boxs_x*BSIZE,Curbox_y=Sys_y;/*再次初始化座标*/  if(box_numb==-1) box_numb=rand()%MAX_BOX;  current_box_numb=box_  flag_newbox=  return(rand()%MAX_BOX);  }  /*  *
擦除(x,y)位置开始的编号为box_numb的box.  */  void EraseBox(int x,int y,int box_numb)  {  int mask=128,t_boardx,t_boardy,n,m;  setfillstyle(SOLID_FILL,BgColor);  for(n=0;n&4;n++)  {  for(m=0;m&4;m++)
/*看最左边四个单元*/  {  if( ((shapes[box_numb].box[n/2]) & mask) )/*最左边有方块并且当前游戏板也有方块*/  {  bar(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);  line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE);  line(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE,y+n*BSIZE+BSIZE);  line(x+m*BSIZE,y+n*BSIZE+BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);  line(x+m*BSIZE+BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);  }  mask=mask/(2);  if(mask==0)mask=128;  }  }  }  void ErasePreBox(int x,int y,int box_numb)  {  int mask=128,t_boardx,t_boardy,n,m;  setfillstyle(SOLID_FILL,BgColor);  for(n=0;n&4;n++)  {  for(m=0;m&4;m++)
/*看最左边四个单元*/  {  if( ((shapes[box_numb].box[n/2]) & mask) )/*最左边有方块并且当前游戏板也有方块*/  {  bar(x+m*BSIZE,y+n*BSIZE,x+m*BSIZE+BSIZE,y+n*BSIZE+BSIZE);  }  mask=mask/(2);  if(mask==0)mask=128;  }  }  }  /* 判断是否可以移动  * x,y为当前方块位置  * box_numb为方块号  * direction 方向标志   *
返回true 和false  #define MoveLeft -1  #define MoveRight 1  #define MoveDown 0  */  int MoveAble(int x,int y,int box_numb,int direction)  {  int n,m,t_boardx,t_
/*t_boardx 当前方块最左边在游戏板的位置*/    if(direction==MoveLeft)
/*如果向左移*/  {  mask=128;  x-=BSIZE;  t_boardx=(x-Sys_x)/BSIZE;  t_boardy=(y-Sys_y)/BSIZE;  for(n=0;n&4;n++)  {  for(m=0;m&4;m++)
/*看最左边四个单元*/  {  if((shapes[box_numb].box[n/2]) & mask)/*最左边有方块并且当前游戏板也有方块*/  {  if((x+BSIZE*m)&Sys_x)return(false);/*碰到最左边了*/  else if(Table_board[t_boardy+n][t_boardx+m].var) /*左移一个方块后,此4*4的区域与游戏板有冲突*/  {  return(false);  }  }  mask=mask/(2);  if(mask==0)mask=128;  }  }  return(true);  }  else if(direction==MoveRight)
/*如果向右移*/  {  x+=BSIZE;  t_boardx=(x-Sys_x)/BSIZE;  t_boardy=(y-Sys_y)/BSIZE;  mask=128;  for(n=0;n&4;n++)  {  for(m=0;m&4;m++)
/*看最右边四个单元*/  {  if((shapes[box_numb].box[n/2]) & mask)/*最右边有方块并且当前游戏板也有方块*/  {  if((x+BSIZE*m)&=(Sys_x+BSIZE*Horizontal_boxs) )return(false);/*碰到最右边了*/  else if( Table_board[t_boardy+n][t_boardx+m].var)  {  return(false);  }  }  mask=mask/(2);  if(mask==0)mask=128;  }  }  return(true);  }  else if(direction==MoveDown)
/*如果向下移*/  {  y+=BSIZE;  t_boardx=(x-Sys_x)/BSIZE;  t_boardy=(y-Sys_y)/BSIZE;  mask=128;  for(n=0;n&4;n++)  {  for(m=0;m&4;m++)
/*看最下边四个单元*/  {  if((shapes[box_numb].box[n/2]) & mask)/*最下边有方块并且当前游戏板也有方块*/  {  if((y+BSIZE*n)&=(Sys_y+BSIZE*Vertical_boxs) ||
Table_board[t_boardy+n][t_boardx+m].var)  {  flag_newbox=    }  }  mask=mask/(2);  /*mask依次为:00,  10/  */  if(mask==0)mask=128;  }  }  if(flag_newbox)  {  return(false);  }  else  return(true);  }  else if(direction==MoveRoll)
/*转动*/  {  t_boardx=(x-Sys_x)/BSIZE;  t_boardy=(y-Sys_y)/BSIZE;  mask=128;  for(n=0;n&4;n++)  {  for(m=0;m&4;m++)
/*看最下边四个单元*/  {  if((shapes[box_numb].box[n/2]) & mask)/*最下边有方块并且当前游戏板也有方块*/  {  if((y+BSIZE*n)&=(Sys_y+BSIZE*Vertical_boxs) )return(false);/*碰到最下边了*/  if((x+BSIZE*n)&=(Sys_x+BSIZE*Horizontal_boxs) )return(false);/*碰到最左边了*/  if((x+BSIZE*m)&=(Sys_x+BSIZE*Horizontal_boxs) )return(false);/*碰到最右边了*/  else if( Table_board[t_boardy+n][t_boardx+m].var)  {  return(false);  }  }  mask=mask/(2);  if(mask==0)mask=128;  }  }  return(true);  }  else  {  return(false);  }  }  /*  *显示指定的方块  */  void show_box(int x,int y,int box_numb,int color)  {  int i,ii,ls_x=x;  if(box_numb&0 || box_numb&=MAX_BOX)/*指定的方块不存在*/  box_numb=MAX_BOX/2;  setfillstyle(SOLID_FILL,color);  /*********************************   *
移位来判断第哪一位是1  *
方块是每1行用半个字节来表示  *
128d=b  *********************************/  for(ii=0;ii&2;ii++)   {  int mask=128;  for(i=0;i&8;i++)  {  if(i%4==0 && i!=0)
/*表示转到方块的下一行了*/  {  y+=BSIZE;  x=ls_x;  }  if((shapes[box_numb].box[ii])&mask)  {  bar(x,y,x+BSIZE,y+BSIZE);  line(x,y,x+BSIZE,y);  line(x,y,x,y+BSIZE);  line(x,y+BSIZE,x+BSIZE,y+BSIZE);  line(x+BSIZE,y,x+BSIZE,y+BSIZE);  }  x+=BSIZE;  mask/=2;  }  y+=BSIZE;  x=ls_x;  }  }  void main()  {  int GameOver=0;  int key,   int Currentaction=0;/*标记当前动作状态*/  int gd=VGA,gm=VGAHI,  initgraph(&gd,&gm,"");  errorcode = graphresult();   if (errorcode != grOk)
  {  printf("\nNotice:Graphics error: %s\n", grapherrormsg(errorcode));  printf("Press any key to quit!");  getch();   exit(1);
  }  setbkcolor(BgColor);  setcolor(FgColor);  randomize();  SetTimer(newtimer);  initialize(Sys_x,Sys_y,Horizontal_boxs,Vertical_boxs);/*初始化*/  nextbox=MkNextBox(-1);  show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);  show_box(LeftWin_x,Curbox_y+200,nextbox,shapes[nextbox].color);  show_intro(Sys_x,Curbox_y+320);  getch();  while(1)  {  /* Currentaction=0;  flag_newbox=  检测是否有按键*/  if (bioskey(1)){key=bioskey(0);
}  switch(key)  {  case VK_LEFT:  if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveLeft))  {EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x-=BSIZE;Currentaction=MoveL}    case VK_RIGHT:  if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveRight))  {EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_x+=BSIZE;Currentaction=MoveR}    case VK_DOWN:  if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown))  {EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE;Currentaction=MoveD}  else flag_newbox=    case VK_UP:/*旋转方块*/  if(MoveAble(Curbox_x,Curbox_y,shapes[current_box_numb].next,MoveRoll))  {EraseBox(Curbox_x,Curbox_y,current_box_numb);current_box_numb=shapes[current_box_numb].  Currentaction=MoveR  }    case VK_ESC:  GameOver=1;    default:    }  if(Currentaction)  {
/*表示当前有动作,移动或转动*/  show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);  Currentaction=0;  }  /*按了往下键,但不能下移,就产生新方块*/  if(flag_newbox)  {  /*这时相当于方块到底部了,把其中出现点满一行的清去,置0*/  ErasePreBox(LeftWin_x,Sys_y+200,nextbox);  nextbox=MkNextBox(nextbox);  show_box(LeftWin_x,Curbox_y+200,nextbox,shapes[nextbox].color);  if(!MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown))/*刚一开始,游戏结束*/  {  show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);  GameOver=1;  }  else  {  flag_newbox=  }  Currentaction=0;  }  else
/*自由下落*/  {  if (Currentaction==MoveDown || TimerCounter& (20-speed*2))  {  if(MoveAble(Curbox_x,Curbox_y,current_box_numb,MoveDown))  {  EraseBox(Curbox_x,Curbox_y,current_box_numb);Curbox_y+=BSIZE;  show_box(Curbox_x,Curbox_y,current_box_numb,shapes[current_box_numb].color);  }  TimerCounter=0;  }  }  if(GameOver )/*|| flag_newbox==-1*/  {  printf("game over,thank you! your score is %d",score);  getch();    }  }  getch();  KillTimer();  closegraph();  }
楼主发言:1次 发图:0张 | 更多
  网上可以下载一个叫easyx的库,装上之后,在vc中也可以运行tc的图形库了。
  话说你学C学多久了,,,,
请遵守言论规则,不得违反国家法律法规回复(Ctrl+Enter)

我要回帖

更多关于 linux运行c程序 的文章

 

随机推荐