
.
.
如何用C语言编写游戏
网络游戏是常谈的话题,是交互式娱乐的主力军,是一种高层次
的综合艺术,更是一个民族的文化,世界观的全新传播方式作为游戏
玩家的我们,是不是想设计一个属于自己的游戏呢?
爱玩是人的天性,而C语言是我们计算机专业都要学习的一门基
础学科.一般来说,是比较枯燥的.那么,我们能不能通过编一些小
游戏来提高它的趣味性呢?这样学习程序设计,就不会是一件艰苦
,枯燥的事,它变得象电脑游戏一样充满好奇,富有乐趣.这正是
我要写这文档目的.
1,总是从Hello,world开始
学习编程的第一个程序,一般就是打印一个亲切的词语——"Hell
o,world!".让我们来看看这个最简单的C程序:
#incolude
intmain()
{
printf("Hello,
.
.
world!");/*在屏幕上输出字符串"Hello,world!"*/
return0;/*退出main函数,并返回0*/
}
下面我们发现几个值得改进的地方,1,程序的运行结果一闪而过
.2,每执行这个程序一次都能看见上次运行留下的字符.3,我们
还希望屏幕输出一个笑脸来欢迎我们.(大家不要小看了这个笑脸
曾经有人发贴专门问呢)让我们来改进一下这个程序吧!
1,在return语句的前面加一句:getch();,表示按任意键结
束.2,在printf语句前用clrscr函数清屏,要使用这个函数和get
ch函数,需要在程序开头再包含头文件conio.h.3,ASCII码也有
许多非常好玩的字符,比如ASCII码值为2的就是一个笑脸,我们可
.
.
以用printf("%c",2)来输出一个笑脸.
现在我们把Hello,world程序改成一个更好看的Hello,world了.下
面让我们开始做游戏吧!
2,心动的开始,一个运动中的笑脸
大家小时侯喜欢看动画片吗?哈哈,我猜你们都喜欢吧!下面就让
我们来做一个小动画吧.在屏幕上显示一个运动的小笑脸,而且当
它到达屏幕的边缘时会自动弹回来.
先在程序定义一个在屏幕中运动的点的结构:
structmove_point
{
intx,y;/*该点的位置,包括x坐标和y坐标*/
.
.
intxv,yv;/*该点在x轴,y轴的速度*/
};
运动的原理是,先擦去物体先前的轨迹,让物体按其速度移动一段
距离,再画出该物体.让我们看到以下代码:
gotoxy(man.x,man.y);/*把光标移到指定的坐标*/
printf("");/*输出一个空格,把先前的字符擦去*/
然后我们让物体按其速度运动:
man.x+=;/*水平方向按x轴的速度运动*/
man.y+=;/*垂直方向按y轴的速度运动*/
运动后还要判断物体是否出界,如果出了界,就令物体反弹,即让
它下一刻的速度等于现在的速度的相反数.最后打印出这个笑脸:
.
.
gotoxy(man.x,man.y);
printf("%cb",2);/*输出ASCII码值为2的"笑脸"字符*/
怎么样?是不是很有趣呢?不过这个笑脸一直是自己运动,能不能
让我们来控制它运动呢?答案是肯定的,让我们继续往下学吧!
3,交互的实现——让我们来控制笑脸运动
这个程序的主要功能是接受按键,如果接收的是方向键,就让笑脸
顺着方向移动,如果接收的是ESC键就退出程序,其他按键则忽略
处理.接受按键我们用以下两条语句:
while(bioskey(1)==0);/*等待按键*/
key=bioskey(0);/*把接收的按键的键盘码赋给变量key*/
然后用switch语句来判断按键以及执行相关操作,如下:
.
.
switch(key)/*对变量key的值进行判断*/
{
caUP:/*如果按的是向上键*/
…break;/*让物体向上运动,并退出switch*/
caDOWN:/*如果按的是向下键*/
…break;/*让物体向下运动,并退出switch*/
caLEFT:/*向左键*/
…break;;/*向左运动*/
caRIGHT:/*向右键*/
…break;/*向右运动*/
.
.
赞
6
2004-9-919:26回复
c闲人
202位粉丝
2楼
default:
break;/*其他按键则忽略处理*/
}
怎么样,是不是有了玩游戏的感觉了?不过这个程序没有什么目的
,也没有什么判断胜负的条件.下面我们就利用这个能控制它移动
的笑脸来做一个更有趣的游戏吧!
.
.
4,在迷宫中探索
小时侯,我常在一些小人书和杂志上看见一些迷宫的游戏,非常喜
欢玩,还常到一些书上找迷宫玩呢.好的,现在我们用C语言来编
个迷宫的游戏,重温一下童年的乐趣.
首先,我们定义一个二维数组map,用它来保存迷宫的地图,其中m
ap[x][y]=='#'表示在(x,y)坐标上的点是墙壁.DrawMap函数
在屏幕上输出迷宫的地图和一些欢迎信息.
在main函数里,我们定义了"小人"man的坐标和"目的地"des的
坐标.在游戏循环中,我们增加了一些用来判断胜负的语句:
if(man.x==des.x&&man.y==des.y)/*如果人的坐标等于目
的地的坐标*/
.
.
{
gotoxy(35,3);
printf("Ok!Youwin!");/*输出胜利信息*/
….
}
在判断按键时,如果玩家按的是方向键,我们还要先判断前面是不
是有"墙壁",如果有的话,就不能往前移动了.好的,我们在判
断按键的switch语句的各个分支加上了判断语句,如下:
if(map[…][…]=='#')break;/*如果前面是墙壁,就不执行
下去*/
哇噻!真棒,我们做出了一个完整的游戏了.当然你还可以通过修
.
.
改二维数组map来修改迷宫的地图,让它更有挑战性.不过,我们
要设计一个更好玩的游戏——
5,聪明的搬运工
大家一定玩过"搬运工"的游戏吧!这是在电脑和电子字典上较流
行的益智游戏,让我们动手做一个属于自己的"搬运工"吧!
程序依然用数组map来保存地图,数组元素如果为空格则表示什么
也没有,'b'表示箱子,'#'表示墙壁,'*'表示目的地,'i
'表示箱子在目的地.我们以后每推一下箱子,不但要改变屏幕的
显示,也要改变map相应元素的值.
游戏的主循环依然是接受按键.当接收一个方向键,需要判断小人
前面一格的状态,如果是空地或目的地,则人物可以直接移动;如
.
.
果是墙壁,则不可移动;如果是箱子或目的地上的箱子,则需要继
续判断箱子前面一格的状态:如果前一格是空地或目的地,则人推
箱子前进,否则不可移动.好的,我们在switch中增加了这些判断
语句.
程序还有一个重要的功能就是判断胜利.数组Des用来记录全部目
的地的坐标,我们每执行一步操作后,程序就要通过Des数组判断
这些目的地上是否都有箱子了.
真棒啊!我们可以做游戏了.而且是一个老少皆宜,趣味十足的游
戏呢!当然,我们可以通过修改map数组来制作不同的游戏地图,
我们还可以相互分享好的游戏地图呢.
尾声:
.
.
在C++等高级语言还没出来的时候,很多应用程序也是C语言开发的
.C语言在与硬件联系紧密的编程中,也占有重要地位.
其实我觉得学习编程,可以通过一些小游戏,实用的例子来学习.
象学习音乐的人,不是要等到把全部乐理学完后才演奏一个完整的
曲子.而是刚开始学时就有一些简单的曲子让你演奏,让你立刻就
有成就感,让你很快就能卖弄出来在别人面前表现自己了.通过编
游戏来学习编程,把学习变成游戏,不失为学习计算机的一种好方
法.
好了,编游戏就这么简单,希望大家也尝试用C语言或其他的语言
来做几个自己喜欢的小游戏.
.
.
时间延迟函数
函数名:delay
功能:将程序的执行暂停一段时间(毫秒)
用法:voiddelay(unsignedmilliconds);
重画屏幕区域的函数
函数名:getimage
功能:将指定区域的一个位图存到主存中
用法:voidfargetimage(intleft,inttop,intright,int
bottom,voidfar*bitmap);
函数名:putimage
功能:在屏幕上输出一个位图
用法:voidfarputimage(intx,inty,voidfar*bitmap,int
op);
图像大小函数
函数名:imagesize
功能:返回保存位图像所需的字节数
用法:unsignedfarimagesize(intleft,inttop,intright,
intbottom);
异或模式函数
.
.
函数名:twritemode
功能:设置图形方式下画线的输出模式
用法:voidfartwritemode(intmode);
参数MODE可以被设置位COPY_PUT或者XOR_PUT两种模式。当
mode被设置为XOR_PUT,其后的图形操作将都采用异或方式。此外之
前提到的putimage()函数也可以采用异或模式向屏幕复制图像。
检测键盘输入函数
函数名:kbhit
功能:检查当前按下的键
用法:intkbhit(void);
键盘接口函数
函数名:bioskey
功能:直接使用BIOS服务的键盘接口
用法:intbioskey(intcmd);
该函数通过bois中断0x16执行键盘操作,由参数cmd来决定具
体的操作。
Cmd具体操作
0读取按键的ascii码
.
.
1测试是否有按键如果没有按键返回0如果按键为ctrl+brk返
回-1如果是其他按键返回按键本身键值(直到此按键被取出后恢复
0)
2返回shiftkey状态
以下是当cmd为2的时候,返回值的具体含义
cmd返回值触发特殊键
0X01Leftctrl
0X02Leftalt
0X04Rightctrl
0X08Rightalt
0X10Scrolllock
0X20Numlock
0X40Capslock
0X80Sysrq
bioskey()函数的优点在于:
1.和kbhit()函数一样可以在不影响主程序运行的情况下检测是否有
按键;
2.可以方便地检测普通键具体ASCII码和扫描码;
3.可以方便地检测功能键具体扫描码;
4.可以检测特殊按键;
.
.
5.只需要一个函数就能解决检测按键和读入按键的任务。
声音与延迟函数
函数名:sound
功能:以指定频率打开PC扬声器
用法:voidsound(unsignedfrequency);
函数名:nosound
功能:关闭PC扬声器
用法:voidnosound(void);
函数名:delay
功能:将程序的执行暂停一段时间(毫秒)
用法:voiddelay(unsignedmilliconds);
sound()函数用于让pc喇叭发声,nosound()函数用于使正在发声的
pc喇叭静音。要使程序中的发声的具体方法,是调用sound()函数并
延迟一定时间,然后使用nosound()函数静音,具体语句实现方法如
下:
sound(100);
delay(100);
nosound();
.
.
产生随即数函数
函数名:rand
功能:随机数发生器
用法:voidrand(void);
函数名:random
功能:随机数发生器
用法:intrandom(intnum);
初始化随机数函数
函数名:randomize
功能:初始化随机数发生器
用法:voidrandomize(void);
in86()函数
函数名:int86
功能:通用8086软中断接口
用法:intint86(intintr_num,unionREGS*inregs,unionREGS
*outregs);
其中intr_num为软中断号,函数通过inregs寄存器向中断发出
具体功能命令,函数将中断调用结果返回寄存器outregs。
memt()函数
.
.
函数名:memt
功能:设置s中的所有字节为ch,s数组的大小由n给定
用法:void*memt(void*s,charch,unsignedn);
标准VGA显示模式表
模式(16进制)适配器显示类型颜色字符格式屏幕大小字符大
小缓冲区首址属性类型
0/1CGA文本16/1640*25320*2008*8B8000彩色
EGA文本16/6440*25320*3508*14B8000彩色
赞
0
2004-10-2221:37回复
c闲人
202位粉丝
2楼
VGA文本16/256K40*25360*4009*16B8000彩色
CGA文本16/1680*25640*2008*8B8000彩色
.
.
2/3EGA文本16/6480*25640*3508*14B8000彩色
VGA(3+)文本16/256K80*25720*4009*16B8000彩色
CGA图形4/1640*25320*2008*8B8000彩色
4/5EGA图形4/6440*25320*2008*8B8000彩色
VGA图形4/256K40*25320*2008*8B8000彩色
CGA图形2/1640*25640*2008*8B8000单色
6EGA图形2/6440*25640*2008*8B8000单色
VGA图形2/256K40*25640*2008*8B8000单色
7MDA/EGA文本单色80*25720*3509*14B0000单色
VGA(7+)文本单色80*25720*4009*16B0000单色
DEGA图形16/6440*25320*2008*8A0000彩色
VGA图形16/256K40*25320*2008*8A0000彩色
EEGA图形16/6480*25640*2008*8A0000彩色
VGA图形16/256K80*25640*2008*8A0000彩色
FEGA/VGA图形单色80*25640*3508*14A0000单色
10EGA图形16/6480*25640*3508*14A0000彩色
VGA图形16/256K80*25640*3508*14A0000彩色
11VGA图形2/256K80*30640*4808*16A0000彩色
12VGA图形16/256K80*30640*4808*16A0000彩色
13VGA图形256/256K40*25320*2008*8A000彩色
常规内存函数
.
.
申请函数:
malloc(),farmalloc(),calloc(),farcalloc(),realloc(),fareall
oc()
函数名:malloc
功能:内存分配函数
用法:void*malloc(unsignedsize);
函数名:farmalloc
功能:从远堆中分配存储块
用法:voidfar*farmalloc(unsignedlongsize);
函数名:calloc
功能:分配主存储器
用法:void*calloc(size_tnelem,size_telsize);
函数名:farcalloc
功能:从远堆栈中申请空间
用法:voidfar*farcalloc(unsignedlongunits,unsignedling
unitsz);
.
.
函数名:realloc
功能:重新分配主存
用法:void*realloc(void*ptr,unsignednewsize);
函数名:farrealloc
功能:调整远堆中的分配块
用法:voidfar*farrealloc(voidfar*block,unsignedlong
newsize);
使用函数:memcpy(),memt(),memmove(),movedata()
函数名:memcpy
功能:从源source中拷贝n个字节到目标destin中
用法:void*memcpy(void*destin,void*source,unsignedn);
.
.
函数名:memt
功能:设置s中的所有字节为ch,s数组的大小由n给定
用法:void*memt(void*s,charch,unsignedn);
函数名:memmove
功能:移动一块字节
用法:void*memmove(void*destin,void*source,unsignedn);
函数名:movedata
功能:拷贝字节
用法:voidmovedata(intgsrc,intoffsrc,intgdest,int
offdest,unsignednumbytes);
.
.
释放函数:free(),farfree()
函数名:free
功能:释放已分配的块
用法:voidfree(void*ptr);
函数名:farfree
功能:从远堆中释放一块
用法:voidfarfree(void);
指针操作函数:MK_FP(),FP_OFF(),FP_SEG()
函数名:MK_FP
功能:设置一个远指针
.
.
用法:voidfar*MK_FP(unsignedg,unsignedoff);
函数名:FP_OFF
功能:获取远地址偏移量
用法:unsignedFP_OFF(voidfar*farptr);
函数名:FP_SEG
功能:获取远地址段值
用法:unsignedFP_SEG(voidfar*farptr);
XMS功能调用索引表:
功能号功能版本
功能00H功能01H功能02H功能03H功能04H功能05H功能06H
功能07H功能08H功能09H功能0AH功能0BH功能0CH功能0DH
功能0EH功能0FH功能10H功能11H取XMS版本号请求高内存区
HMA释放高内存区HMA全程启用A20全程停用A20局部启用A20局
部停用A20查询A20状态查询自由扩展内存分配扩展内存块释放
扩展内存块移动扩展内存块锁住扩展内存块扩展内存块解锁取
EMB句柄信息重新分配扩展内存块请求上位存储块UMB释放上位
存储块UMBXMS规范V2.0XMS规范V2.0XMS规范V2.0XMS规范
.
.
V2.0XMS规范V2.0XMS规范V2.0XMS规范V2.0XMS规范V2.0XMS
规范V2.0XMS规范V2.0XMS规范V2.0XMS规范V2.0XMS规范V2.0
XMS规范V2.0XMS规范V2.0XMS规范V2.0XMS规范V2.0XMS规范
V2.0
以下是一个用线和矩形绘制的简单赛车
#include
#include
voidmain(void){
intgdriver=DETECT,gmode;
initgraph(&gdriver,&gmode,"");
tbkcolor(7);
twritemode(XOR_PUT);
tcolor(BLUE);
tlinestyle(SOLID_LINE,0,3);
rectangle(280,350,320,390);
rectangle(270,340,330,350);
rectangle(290,320,310,340);
rectangle(270,390,330,400);
tcolor(5);
line(290,350,290,390);
.
.
line(300,300,300,320);
line(300,350,300,390);
line(310,350,310,390);
line(285,300,315,300);
getch();
clograph();
}
接下来我们试着绘制赛道,周围的绿化树木和简单的集装箱车
代码如下:
#include
#include
#include
#include
#include
const
intu=26;
inti=2;
intj=3;
voidroad(void)
.
.
{
inth;
for(h=0;h<4;h++)
line(150+h*100,0,150+h*100,472);
for(h=0;h<3;h++)
{
tlinestyle(3,0,1);
line(200+h*100,0,200+h*100,472);
ttextstyle(1,HORIZ_DIR,3);
}
}
voidtree(void)
{
intw;
intpoly[14];
tcolor(10);
tlinestyle(SOLID_LINE,0,3);
for(w=-3;w<3;w=w+2)
.
.
{
line(85,-25+u*15+w*157,85,35+u*15+w*157);
line(95,-25+u*15+w*157,95,35+u*15+w*157);
line(105,-25+u*15+w*157,105,35+u*15+w*157);
line(115,-25+u*15+w*157,115,35+u*15+w*157);
line(75,-9+u*15+w*157,75,19+u*15+w*157);
line(125,-9+u*15+w*157,125,19+u*15+w*157);
}
for(w=-2;w<3;w=w+2)
{
poly[0]=530;
poly[1]=u*15+w*157;
poly[2]=515;
poly[3]=25+u*15+w*157;
poly[4]=485;
poly[5]=25+u*15+w*157;
poly[6]=470;
poly[7]=u*15+w*157;
.
.
poly[8]=485;
poly[9]=-25+u*15+w*157;
poly[10]=515;
poly[11]=-25+u*15+w*157;
poly[12]=poly[0];
poly[13]=poly[1];
drawpoly(7,poly);
}
}
voidtruck(void)
{
tcolor(2);
tlinestyle(SOLID_LINE,0,3);
rectangle(170+i*100,j*10,230+i*100,60+j*10);
rectangle(160+i*100,70+j*10,240+i*100,260+j*10);
line(180+i*100,70+j*10,180+i*100,260+j*10);
.
.
line(200+i*100,70+j*10,200+i*100,260+j*10);
line(220+i*100,70+j*10,220+i*100,260+j*10);
}
voidcar(void)
{
tcolor(BLUE);
tlinestyle(SOLID_LINE,0,3);
rectangle(280,350,320,390);
rectangle(270,340,330,350);
rectangle(290,320,310,340);
rectangle(270,390,330,400);
tcolor(5);
line(290,350,290,390);
line(300,300,300,320);
line(300,350,300,390);
line(310,350,310,390);
line(285,300,315,300);
}
.
.
voidmain(void)
{
intgdriver=DETECT,gmode,w;
initgraph(&gdriver,&gmode,"");
tbkcolor(7);
tcolor(WHITE);
twritemode(XOR_PUT);
road();
tree();
truck();
car();
getch();
clograph();
}
用c做的简单的坦克大战小游戏(给初学者点动力)
c闲人
202位粉丝
.
.
1楼
#include
#include
#include
#include
#include
#defineKEY_ESC0x01
#defineKEY_SPACE0x39
#defineKEY_UP0x48
#defineKEY_LEFT0x4b
#defineKEY_RIGHT0x4d
#defineKEY_DOWN0x50
/*1石头,2砖块,3水,5老家,8玩家,9敌人*/
intmap[20][20]={1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,9,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,2,2,2,2,0,0,2,2,2,2,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,2,0,0,2,0,1,1,1,1,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,2,2,2,2,2,2,2,0,0,0,0,0,0,0,2,2,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,2,0,1,
1,0,1,1,1,1,3,3,3,3,0,0,0,0,0,0,0,2,0,1,
.
.
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,2,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,1,1,1,1,3,3,3,0,1,
1,0,0,0,2,2,2,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,0,0,0,3,3,3,1,1,1,1,1,1,1,0,0,0,0,1,
1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,
1,0,2,2,0,0,0,0,0,0,0,0,3,0,0,0,0,0,0,1,
1,0,2,2,0,0,0,0,2,2,2,0,0,0,2,2,0,0,0,1,
1,0,0,0,0,0,0,8,2,5,2,0,0,0,0,0,0,0,0,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1};
structf
{
intx;
inty;
intdirection;
};
structplay
{
intx;/*行坐标*/
inty;/*列坐标*/
.
.
intdirection;/*方向*/
structffire[5];/*5颗子弹*/
intscore;/*分数*/
}Playone;
structa
{
intx;
inty;
intcolor;
intdirection;
intdirectiontwo;/*用来判断走的路是否往返*/
intfireplay;/*是否攻击的变量,随机生成*/
structffire;
}amy[5];/*敌人的结构体,其实可以添加不同的颜色来表示不同种类
的坦克*/
charkey_state[128],key_presd[128];
voidInit();/*图象驱动开始*/
voidEnd();/*图象驱动结束*/
voidDrawMap();/*画地图*/
voidDrawWater(intx,inty);/*画水*/
voidDrawBrick(intx,inty);/*画砖*/
voidDrawTone(intx,inty);/*画石头*/
.
.
voidDrawHome(intx,inty);/*画老家*/
voidDrawBlack(intx,inty);/*去除内容*/
voidDrawPlay(intx,inty);/*画玩家*/
voidDrawAmy(intx,inty,inti);/*画敌人*/
voidScore();/*输出分数*/
voidGamePlay();/*玩游戏过程*/
voidGameOver();/*游戏失败*/
voidTimeDelay(unsignedlongmicroc);/*延时函数传入微秒
数*/
intGetKey(intScanCode);/*这里开始都是按键函数*/
voidinterruptfar(*OldInt9Handler)();
voidfarinterruptNewInt9();
voidInstallKeyboard();
voidShutDownKeyboard();
voidmain(void)
{
Init();
DrawMap();
GamePlay();
End();
}
voidTimeDelay(unsignedlongmicroc)/*延时函数传入微秒数
.
.
*/
{
unionREGSr;
=0x86;
=microc>>16;
=microc;
int86(0x15,&r,&r);
}
voidInit()/*图象驱动开始*/
{intgd=DETECT,gm;
initgraph(&gd,&gm,"d:tctc");
cleardevice();
InstallKeyboard();
}
voidEnd()/*图象驱动结束*/
{
ShutDownKeyboard();
clograph();
}
voidDrawTone(intx,inty)/*画石头*/
{
tfillstyle(SOLID_FILL,7);
.
.
bar(100+x*20-9,50+y*20-9,100+x*20+9,50+y*20+9);
赞
2
2004-8-2000:42回复
c闲人
202位粉丝
2楼
}
voidDrawWater(intx,inty)/*画水*/
{
tfillstyle(SOLID_FILL,BLUE);
bar(100+x*20-9,50+y*20-9,100+x*20+9,50+y*20+9);
}
voidDrawBrick(intx,inty)/*画砖*/
{
tfillstyle(SOLID_FILL,6);
.
.
bar(100+x*20-9,50+y*20-9,100+x*20+9,50+y*20+9);
tcolor(15);
line(100+x*20-9,50+y*20-4,100+x*20+9,50+y*20-4);
line(100+x*20-9,50+y*20+4,100+x*20+9,50+y*20+4);
line(100+x*20-4,50+y*20-9,100+x*20-4,50+y*20+9);
line(100+x*20+4,50+y*20-9,100+x*20+4,50+y*20+9);
}
voidDrawHome(intx,inty)/*画老家*/
{
tcolor(0);
tfillstyle(SOLID_FILL,GREEN);
fillellip(100+x*20,50+y*20,9,9);
}
voidDrawBlack(intx,inty)/*去除内容*/
{
tcolor(0);
tfillstyle(SOLID_FILL,0);
bar(100+x*20-9,50+y*20-9,100+x*20+9,50+y*20+9);
}
voidDrawPlay(intx,inty)/*画玩家*/
{
tcolor(4);/*玩家为红色*/
.
.
circle(100+x*20,50+y*20,7);
switch(ion)/*判断玩家方向*/
{
ca1:line(100+x*20,50+y*20,100+x*20,50+y*20-9);break;/*
上*/
ca2:line(100+x*20,50+y*20,100+x*20+9,50+y*20);break;/*
右*/
ca3:line(100+x*20,50+y*20,100+x*20,50+y*20+9);break;/*
下*/
ca4:line(100+x*20,50+y*20,100+x*20-9,50+y*20);break;/*
左*/
}
}
voidDrawAmy(intx,inty,inti)/*画敌人*/
{
if(amy[i].color==12)
tcolor(12);
elif(amy[i].color==13)
tcolor(13);
el/*这里是判断三种颜色的坦克*/
tcolor(14);
circle(100+x*20,50+y*20,7);
.
.
switch(amy[i].direction)/*判断玩家方向*/
{
ca1:line(100+x*20,50+y*20,100+x*20,50+y*20-9);break;/*
上*/
ca2:line(100+x*20,50+y*20,100+x*20+9,50+y*20);break;/*
右*/
ca3:line(100+x*20,50+y*20,100+x*20,50+y*20+9);break;/*
下*/
ca4:line(100+x*20,50+y*20,100+x*20-9,50+y*20);break;/*
左*/
}
}
voidScore()/*输出分数*/
{
chars[10];
+=10;
sprintf(s,"%d",);
tfillstyle(SOLID_FILL,0);
bar(550,100,640,130);
ttextstyle(0,0,2);
tcolor(YELLOW);
outtextxy(550,115,s);
.
.
}
voidDrawMap()/*画地图*/
{inti,j,k;
for(i=0;i<20;i++)
{
for(j=0;j<20;j++)
if(map[i][j]==1)
DrawTone(j,i);
elif(map[i][j]==2)
DrawBrick(j,i);
elif(map[i][j]==3)
DrawWater(j,i);
elif(map[i][j]==5)
DrawHome(j,i);
elif(map[i][j]==8)
{
Playone.x=i;
Playone.y=j;
ion=1;
DrawPlay(j,i);
for(k=0;k<5;k++)
[k].direction=-1;/*5颗子弹的方向都为-1,表示
.
.
不存在*/
}
elif(map[i][j]==9)
{
amy[0].x=1;amy[0].y=1;amy[0].direction=amy[0].directiontwo=
3;/*第一个敌人*/
amy[0].color=12;
DrawAmy(j,i,0);
}
}
for(i=1;i<5;i++)/*敌人都没出现*/
amy[i].direction=amy[i].ion=-1;
outtextxy(210,450,"2003.10.1milo_zy");
ttextstyle(0,0,2);/*首次输出得分*/
tcolor(9);
outtextxy(525,80,"Score");
tcolor(YELLOW);
outtextxy(550,115,"0");
}
voidfarinterruptNewInt9(void)
{
.
.
unsignedcharScanCode,temp;
ScanCode=inportb(0x60);
temp=inportb(0x61);
outportb(0x61,temp|0x80);
outportb(0x61,temp&0x7f);
if(ScanCode&0x80)
{
ScanCode&=0x7f;
key_state[ScanCode]=0;
}
el
{
key_state[ScanCode]=1;
2004-8-2000:42回复
c闲人
202位粉丝
3楼
key_presd[ScanCode]=1;
.
.
}
outportb(0x20,0x20);
}
voidInstallKeyboard(void)
{
inti;
for(i=0;i<128;i++)
key_state[i]=key_presd[i]=0;
OldInt9Handler=getvect(9);/*中断向量值*/
tvect(9,NewInt9);/*中断程序NewInt9地址
存入指定的中断向量表中INT09H*/
}
voidShutDownKeyboard(void)
{
tvect(9,OldInt9Handler);
}
intGetKey(intScanCode)
{
intres;
.
.
res=key_state[ScanCode]|key_presd[ScanCode];
key_presd[ScanCode]=0;
returnres;
}
voidGameOver()/*游戏失败*/
{
tcolor(0);
tfillstyle(SOLID_FILL,0);/*把老家给去除*/
fillellip(100+9*20,50+18*20,9,9);
nosound();
tcolor(RED);
ttextstyle(0,0,4);
outtextxy(150,5,"GAMEOVER");
while(1)
{
if(GetKey(KEY_ESC))
break;
}
}
voidGamePlay()/*玩游戏的过程*/
{
inti,j,lo=0;/*lo是1的时候表示失败*/
.
.
intt=0;
randomize();
while(1)
{
for(i=0;i<5;i++)/*画敌人的子弹*/
{
if(amy[i].ion>0)
putpixel(100+amy[i].fire.y*20,50+amy[i].fire.x*20,11);
}
for(i=0;i<=4;i++)/*画玩家子弹*/
{
if([i].direction>0)/*大于0表示玩家子弹存在
*/
putpixel(100+[i].y*20,50+[i].x*20,1
1);
}
TimeDelay(500000);/*关键的时间改动*/
for(i=0;i<5;i++)/*去敌人的子弹*/
{
if(amy[i].ion>0)
.
.
putpixel(100+amy[i].fire.y*20,50+amy[i].fire.x*20,0);
}
for(i=0;i<=4;i++)/*去玩家除子弹*/
{
if([i].direction>0)
putpixel(100+[i].y*20,50+[i].x*20,0
);
}
for(i=0;i<=4;i++)/*玩家子弹位置的变化*/
{
if([i].direction<0)
continue;
if([i].direction==1)
{[i].x--;[i].y=[i].y;}
elif([i].direction==2)
{[i].y++;[i].y=[i].y;}
elif([i].direction==3)
{[i].x++;[i].y=[i].y;}
.
.
elif([i].direction==4)
{[i].y--;[i].y=[i].y;}
/*打到石头或者砖头的情况下减少子弹*/
if(map[[i].x][[i].y]==1)/*打到
石头*/
[i].direction=-1;/*子弹消失*/
if(map[[i].x][[i].y]==2)/*打到
砖头*/
{
[i].direction=-1;
DrawBlack([i].y,[i].x);/*砖头
打掉*/
map[[i].x][[i].y]=0;/*被打掉
的地方变成可走的地方*/
}
if(map[[i].x][[i].y]==5)/*自己
打到老家*/
{lo=1;break;}
for(j=0;j<5;j++)
{
if(amy[j].direction<0)/*不存在的不判断*/
.
.
continue;
if(amy[j].x==[i].x&&amy[j].y==[i].y
)/*打中敌人*/
{
[i].direction=-1;
DrawBlack([i].y,[i].x);
map[[i].x][[i].y]=0;/*被打掉的
地方变成可走的地方*/
amy[j].ion=amy[j].direction=-1;/*这个敌人消
失*/
Score();/*输出得分*/
}
}
}
for(i=0;i<5;i++)/*敌人子弹位置的变化*/
2004-8-2000:42回复
c闲人
202位粉丝
.
.
4楼
{
if(amy[i].direction<0||amy[i].ion<0)
continue;
if(amy[i].ion==1)
{amy[i].fire.x--;amy[i].fire.y=amy[i].fire.y;}
elif(amy[i].ion==2)
{amy[i].fire.y++;amy[i].fire.x=amy[i].fire.x;}
elif(amy[i].ion==3)
{amy[i].fire.x++;amy[i].fire.y=amy[i].fire.y;}
elif(amy[i].ion==4)
{amy[i].fire.y--;amy[i].fire.x=amy[i].fire.x;}
/*打到石头或者砖头的情况下减少子弹*/
if(map[amy[i].fire.x][amy[i].fire.y]==1)/*打到石头*/
amy[i].ion=-1;/*子弹消失*/
if(map[amy[i].fire.x][amy[i].fire.y]==2)/*打到砖头*/
{
amy[i].ion=-1;
DrawBlack(amy[i].fire.y,amy[i].fire.x);/*砖头打掉*/
map[amy[i].fire.x][amy[i].fire.y]=0;/*被打掉的地方变
成可走的地方*/
.
.
}
if(map[amy[i].fire.x][amy[i].fire.y]==5)/*敌人打到老家
*/
{lo=1;break;}
if(amy[i].fire.x==Playone.x&&amy[i].fire.y==Playone.y)/*打
中玩家*/
{
for(j=0;j<5;j++)
[j].direction=-1;/*玩家子弹都消失*/
amy[i].ion=-1;
DrawBlack(amy[i].fire.y,amy[i].fire.x);
map[amy[i].fire.x][amy[i].fire.y]=0;/*被打掉的地方变成
可走的地方*/
lo=1;break;/*好人被打掉后就失败*/
}
}
nosound();
for(i=0;i<5;i++)/*敌人方向随机的改变*/
{
if(amy[i].direction<0)
continue;
.
.
while(1)
{
amy[i].directiontwo=random(4)+1;
if(amy[i].direction==1&&amy[i].directiontwo==3)
continue;
if(amy[i].direction==3&&amy[i].directiontwo==1)
continue;
if(amy[i].direction==2&&amy[i].directiontwo==4)
continue;
if(amy[i].direction==4&&amy[i].directiontwo==2)/*这里4
个if是判断有没有往返走*/
continue;
if(amy[i].directiontwo==3&&(map[amy[i].x+1][amy[i].y]==3||m
ap[amy[i].x+1][amy[i].y]==1||map[amy[i].x+1][amy[i].y]==2))
continue;
if(amy[i].directiontwo==1&&(map[amy[i].x-1][amy[i].y]==3||m
ap[amy[i].x-1][amy[i].y]==1||map[amy[i].x-1][amy[i].y]==2))
continue;
if(amy[i].directiontwo==2&&(map[amy[i].x][amy[i].y+1]==3||m
.
.
ap[amy[i].x][amy[i].y+1]==1||map[amy[i].x][amy[i].y+1]==2))
continue;
if(amy[i].directiontwo==4&&(map[amy[i].x][amy[i].y-1]==3||m
ap[amy[i].x][amy[i].y-1]==1||map[amy[i].x][amy[i].y-1]==2))
continue;/*以上4个是是否碰到了墙壁或者水什么的*/
DrawBlack(amy[i].y,amy[i].x);/*把原来的地方擦掉*/
amy[i].direction=amy[i].directiontwo;
if(amy[i].direction==1)
{amy[i].x--;amy[i].y=amy[i].y;}
if(amy[i].direction==3)
{amy[i].x++;amy[i].y=amy[i].y;}
if(amy[i].direction==2)
{amy[i].y++;amy[i].x=amy[i].x;}
if(amy[i].direction==4)
{amy[i].y--;amy[i].x=amy[i].x;}
if(amy[i].x==Playone.x&&amy[i].y==Playone.y)/*相撞*/
lo=1;
if(map[amy[i].x][amy[i].y]==5)/*敌人撞到老家*/
lo=1;
DrawAmy(amy[i].y,amy[i].x,i);/*画敌人*/
if(amy[i].ion<0)
.
.
amy[i].fireplay=random(4);
if(amy[i].fireplay==1&&amy[i].ion<0)/*发射*/
{
amy[i].ion=amy[i].direction;/*子弹方向与敌
人方向一致*/
2004-8-2000:42回复
c闲人
202位粉丝
5楼
amy[i].fire.x=amy[i].x;
amy[i].fire.y=amy[i].y;
}
break;
}
}
if(lo)/*因为失败而跳出循环显示失败*/
{GameOver();break;}
if(GetKey(KEY_ESC))
.
.
break;
if(GetKey(KEY_UP))/*往上*/
{
if(ion==1&&map[Playone.x-1][Playone.y]!=1&&ma
p[Playone.x-1][Playone.y]!=2)
{
if(map[Playone.x-1][Playone.y]==3)
continue;
DrawBlack(Playone.y,Playone.x);/*这个if是移动,前提是
方向与按下的到向一致*/
Playone.x--;
ion=1;
DrawPlay(Playone.y,Playone.x);
}
el/*只调整炮头方向*/
{
DrawBlack(Playone.y,Playone.x);
ion=1;
DrawPlay(Playone.y,Playone.x);
}
}
.
.
elif(GetKey(KEY_DOWN))/*往下*/
{
if(ion==3&&map[Playone.x+1][Playone.y]!=1&&ma
p[Playone.x+1][Playone.y]!=2)
{
if(map[Playone.x+1][Playone.y]==3)
continue;
DrawBlack(Playone.y,Playone.x);
Playone.x++;
ion=3;
DrawPlay(Playone.y,Playone.x);
}
el
{
DrawBlack(Playone.y,Playone.x);
ion=3;
DrawPlay(Playone.y,Playone.x);
}
}
if(GetKey(KEY_RIGHT))/*往右*/
{
.
.
if(ion==2&&map[Playone.x][Playone.y+1]!=1&&ma
p[Playone.x][Playone.y+1]!=2)
{
if(map[Playone.x][Playone.y+1]==3)
continue;
DrawBlack(Playone.y,Playone.x);
Playone.y++;
ion=2;
DrawPlay(Playone.y,Playone.x);
}
el
{
DrawBlack(Playone.y,Playone.x);
ion=2;
DrawPlay(Playone.y,Playone.x);
}
}
if(GetKey(KEY_LEFT))/*往左*/
{
if(ion==4&&map[Playone.x][Playone.y-1]!=1&&ma
.
.
p[Playone.x][Playone.y-1]!=2)
{
if(map[Playone.x][Playone.y-1]==3)
continue;
DrawBlack(Playone.y,Playone.x);
Playone.y--;
ion=4;
DrawPlay(Playone.y,Playone.x);
}
el
{
DrawBlack(Playone.y,Playone.x);
ion=4;
DrawPlay(Playone.y,Playone.x);
}
}
if(GetKey(KEY_SPACE))/*发射子弹*/
{
for(i=0;i<5;i++)/*用循环来找是否有子弹可以用*/
if([i].direction<0)
{
sound(300);
.
.
[i].direction=ion;/*子弹方向
与坦克方向一致*/
[i].x=Playone.x;
[i].y=Playone.y;
break;/*找到后就跳出循环*/
}
}
if(map[Playone.x][Playone.y]==5)/*玩家自己撞到老家*/
lo=1;
for(i=0;i<5;i++)/*判断是否因自己控制撞到敌人*/
{
if(amy[i].direction<0)
continue;
if(amy[i].x==Playone.x&&amy[i].y==Playone.y)/*相撞*/
lo=1;
}
if(lo)/*因为失败而跳出循环显示失败*/
{GameOver();break;}
t++;/*加到一定的程序就出现新的敌人*/
if(t==30)/*到了增加敌人的时候*/
{t=0;
for(i=0;i<5;i++)
.
.
if(amy[i].direction<0)
{
amy[i].direction=amy[i].directiontwo=3;
amy[i].x=1;
amy[i].y=random(3);/*方向随机*/
if(amy[i].y==0)
amy[i].y=1;
elif(amy[i].y==1)
amy[i].y=9;
el/*这里和上面的两个判断是判断敌人的初始位置*/
amy[i].y=18;
amy[i].color=random(3)+12;/*颜色随机*/
DrawAmy(amy[i].y,amy[i].x,i);
break;/*找到一个后就出循环*/
}
}
}
}
#include"graphics.h"
#include"stdlib.h"
#include"dos.h"
.
.
#include"bios.h"
#defineLEFT0x4b00
#defineRIGHT0x4d00
#defineDOWN0x5000
#defineUP0x4800
#defineESC0x011b
#defineENTER0x1c0d
/*2墙壁,1可以移动地方,3自己,4敌人*/
inta[15][20]={2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
2,1,1,0,0,0,1,0,1,0,0,0,1,1,1,1,1,1,0,2,
2,1,2,2,2,1,1,2,1,1,0,0,0,1,1,4,1,1,0,2,
2,1,1,0,2,1,1,2,0,1,1,2,2,2,2,2,0,0,0,2,
2,4,1,0,2,1,1,2,1,1,1,0,1,1,1,1,0,1,1,2,
2,1,2,1,2,1,1,2,1,3,2,2,1,1,1,1,2,2,1,2,
2,1,2,1,2,1,1,1,1,1,1,1,1,0,0,0,1,1,1,2,
2,1,2,1,0,1,1,1,1,2,1,0,1,2,2,2,1,1,1,2,
2,1,0,1,0,1,2,1,1,2,1,0,1,2,1,1,4,1,1,2,
2,1,0,2,0,1,2,1,1,2,1,0,1,2,1,1,1,1,1,2,
2,1,0,2,1,1,2,1,1,2,1,0,2,2,1,0,0,0,1,2,
2,1,1,2,1,1,2,1,1,2,1,0,2,1,1,2,2,1,1,2,
2,1,2,2,1,2,2,1,1,1,1,0,1,4,1,2,0,0,1,2,
2,1,0,0,0,0,0,4,0,1,1,0,1,1,1,1,0,0,1,2,
.
.
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2};/*数组就是
地图*/
structplay/*游戏中人物的结构体*/
{
intx;
inty;
};
structplayyou,them[5];
intsum=0;/*统计吃的豆子个数,吃满50颗就算胜利*/
intxx[5][2];/*判断敌人方向用的结构体*/
intfal=0;
voidTimeDelay(unsignedlongmicroc)/*延时函数传入微秒数
*/
{
unionREGSr;
=0x86;
=microc>>16;
=microc;
int86(0x15,&r,&r);
}
drawblackdou(intx,inty)/*吃豆子的函数*/
{
.
.
tcolor(0);
circle(100+y*20,100+x*20,3);
sum++;/*吃到豆子后就加一*/
a[x][y]=1;/*吃到后这里就成为普通平地*/
}
begain()/*开始函数*/
{inti,j;
sleep(1);
for(i=0;i<15;i++)
for(j=0;j<20;j++)
if(a[i][j]==2)/*代表墙壁*/
{
tfillstyle(SOLID_FILL,BLUE);
bar(100+j*20-10,100+i*20+10,100+j*20+10,100+i*20-10);
}
elif(a[i][j]==3)/*代表自己*/
{
tcolor(RED);
circle(100+j*20,100+i*20,9);
}
elif(a[i][j]==4)/*代表敌人*/
.
.
{
tcolor(GREEN);
circle(100+j*20,100+i*20,9);
}
elif(a[i][j]==0)/*代表豆子*/
{
tcolor(YELLOW);
circle(100+j*20,100+i*20,3);
}
you.x=5;you.y=9;/*敌人也自己的开始坐标*/
them[0].x=2;them[0].y=15;
them[1].x=4;them[1].y=1;
them[2].x=8;them[2].y=16;
them[3].x=12;them[3].y=13;
them[4].x=13;them[4].y=7;
}
voidmovethem(structplay*them)/*敌人移动的过程*/
{inti,loop;
randomize();
for(i=0;i<5;i++)
{
if(you.x==them[i].x&&(them[i].y+1)==you.y)
.
.
them[i].y++;
elif(you.x==them[i].x&&(them[i].y-1)==you.y)
them[i].y--;
elif(you.y==them[i].y&&(them[i].x+1)==you.x)
them[i].x++;
elif(you.y==them[i].y&&(them[i].x-1)==you.x)/*只要控制
者在身边就立即靠上去*/
them[i].x--;
el
{
loop:
xx[i][0]=rand()%4+1;/*这里的方向采取随机赋值,原则是新的
方向不可以和原来的方向相反*/
if(xx[i][0]==1&&xx[i][1]==2||xx[i][0]==2&&xx[i][1]==1)
gotoloop;
if(xx[i][0]==3&&xx[i][1]==4||xx[i][0]==4&&xx[i][1]==3)
gotoloop;
xx[i][1]=xx[i][0];
if(xx[i][0]==1)/*四个方向*/
{them[i].x--;
.
.
赞
0
2004-8-2000:46回复
c闲人
202位粉丝
2楼
if(a[them[i].x][them[i].y]==2)/*如果碰墙壁的话就回到原
来的地方等待随机的方向*/
{them[i].x++;gotoloop;}
}
elif(xx[i][0]==2)
{them[i].x++;
if(a[them[i].x][them[i].y]==2)
{them[i].x--;gotoloop;}
}
elif(xx[i][0]==3)
{them[i].y++;
if(a[them[i].x][them[i].y]==2)
.
.
{them[i].y--;gotoloop;}
}
elif(xx[i][0]==4)
{them[i].y--;
if(a[them[i].x][them[i].y]==2)
{them[i].y++;gotoloop;}
}
}
}
}
fun(structplay*them)/*移动中的判断*/
{
inti;
tcolor(0);/*把敌人的老位置删除*/
for(i=0;i<5;i++)
circle(them[i].y*20+100,them[i].x*20+100,9);
movethem(them);/*根据控制者的位置来决定敌人的移动方向*/
}
win()/*胜利的话*/
{
cleardevice();
ttextstyle(0,0,4);
.
.
while(!kbhit())
{
tcolor(rand()%13+1);
outtextxy(200,200,"YOUWIN!");
delay(1000);
}
}
fal1()/*失败画面*/
{
cleardevice();
ttextstyle(0,0,4);
while(!kbhit())
{
tcolor(rand()%13+1);
outtextxy(180,200,"GAMEOVER!");
delay(1000);
}
}
loyes()/*判断是否失败*/
{inti;
for(i=0;i<5;i++)
if(them[i].x==you.x&&them[i].y==you.y)
.
.
fal=1;/*如果失败的话*/
}
main()
{intgd=DETECT,gm;
intkey,i;
initgraph(&gd,&gm,"c:tc");
cleardevice();
begain();/*开始画面*/
while(1)
{
while(!kbhit())
{
tcolor(GREEN);/*重画敌人*/
for(i=0;i<5;i++)
circle(them[i].y*20+100,them[i].x*20+100,9);
TimeDelay(280000);
fun(them);/*处理敌人*/
for(i=0;i<5;i++)
if(them[i].x==you.x&&them[i].y==you.y)
fal=1;/*如果失败的话*/
loyes();/*判断是否失败*/
.
.
if(fal)
break;
}
if(fal)
break;
key=bioskey(0);
tcolor(0);/*把自己原来位置的人给删除掉*/
circle(100+you.y*20,100+you.x*20,9);
if(key==ESC)
break;
elif(key==UP)/*这里开始的判断主要是是否吃到豆子和碰到
墙壁*/
{you.x--;
if(a[you.x][you.y]==2)you.x++;
elif(a[you.x][you.y]==0)
drawblackdou(you.x,you.y);}
elif(key==DOWN)
{you.x++;if(a[you.x][you.y]==2)you.x--;
elif(a[you.x][you.y]==0)
drawblackdou(you.x,you.y);}
elif(key==RIGHT)
{you.y++;if(a[you.x][you.y]==2)you.y--;
.
.
elif(a[you.x][you.y]==0)
drawblackdou(you.x,you.y);}
elif(key==LEFT)
{you.y--;if(a[you.x][you.y]==2)you.y++;
elif(a[you.x][you.y]==0)
drawblackdou(you.x,you.y);}
if(sum==50)
break;
tcolor(RED);/*执行了一次键盘后再画出自己的位置*/
circle(100+you.y*20,100+you.x*20,9);
loyes();/*自己走上去碰到敌人的可能*/
if(fal)
break;
}
if(sum==50)/*吃满豆子了*/
{win();getch();}
if(fal)
{fal1();getch();}
clograph();
}
.
.
本文发布于:2023-03-06 04:26:56,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/zhishi/a/167804801713781.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:c语言游戏.doc
本文 PDF 下载地址:c语言游戏.pdf
| 留言与评论(共有 0 条评论) |