编程论坛's Archiver

stnlcd 发表于 2005-5-24 21:31

[原创]自己写的坦克游戏及源代码(下)

<P>void Kill_Em(int x,int y)  {/*如果我方的子弹碰到敌方那么就杀死敌方*/
    Tk_Link p=Tk_List;
char format_EM[10];
int flag=1;
while(p&amp;&amp;flag)  {                         /*查找被我方坦克所击中的敌方坦克*/
        if(x&lt;=p-&gt;x+1&amp;&amp;x&gt;=p-&gt;x-1&amp;&amp;y&lt;=p-&gt;y+1&amp;&amp;y&gt;=p-&gt;y-1)  {
   flag=0;
   Draw_Tankone(p-&gt;x,p-&gt;y,Tk_No,0);  /*在屏幕上擦除这个坦克(参数Tk_No表示在屏幕中擦除这个坦克)*/
   Delete_Tklink(p-&gt;x,p-&gt;y);         /*在坦克事件链表上删除这个坦克*/
   ++kill_tks;                       /*你所杀死的坦克数目++*/
   erase_scores();                   /*显示分数*/
   outtextxy(520,450,itoa(kill_tks-Me_Deads,format_EM,10));
  }
     p=p-&gt;next;
}
}</P>
<P>int Check_is_zd(int x,int y)  {  /*检查前方是否是一个子弹,用于子弹与子弹的碰撞*/
int tx,ty,i;
int num=0;
for(i=0;i&lt;9;i++)  {
      tx=x+i/3-1;  ty=y+(i+3)%3-1;
     if(Gm_Array[tx][ty])  ++num;
}
if(num&gt;2)  return 0;
return 1;
}</P>
<P>void Mul_zd(void)  {   /*处理子弹事件链表中的每一个子弹*/
    Zd_Link p=Zd_List;
int flag_ok=1;
int x,y,type,drct,xd,yd;
int f_tp;
while(p)  {        /*从事件链表中依次取出子弹*/
  flag_ok=1;
  x=p-&gt;x;  y=p-&gt;y; type=p-&gt;type; drct=p-&gt;drct;
  xd=x+ct_dx[drct-1];  yd=y+ct_dy[drct-1];

     if(xd&lt;0||xd&gt;M_Max-1||yd&lt;0||yd&gt;N_Max-1)  flag_ok=0,f_tp=9;/*如果子弹到达了游戏的边界。。*/
  else if(Gm_Array[xd][yd])  {                             /*检查子弹运行前方的情况*/
   f_tp=Gm_Array[xd][yd];
   if(Check_is_zd(xd,yd))  f_tp=8;
   flag_ok=0;
  }
  if(flag_ok)  {                   /*如果子弹前方没有东西则子弹继续飞行*/
   Gm_Array[xd][yd]=type;
   Draw_Node(xd,yd,type);
   if(p-&gt;is_fst) p-&gt;is_fst=0;   /*如果坦克是第一次打出子弹.....*/
   else  {
    Gm_Array[x][y]=Dt_Zero;
    Draw_Node(x,y,Dt_Zero);
   }
   p-&gt;x=xd;  p-&gt;y=yd;
  }
  else  {
   if(type==Dt_Me&amp;&amp;f_tp==Dt_Em)       Kill_Em(xd,yd); /*自己的子弹打到敌人则处理杀敌事件*/
   else if(type==Dt_Em&amp;&amp;f_tp==Dt_Me)  Game_Over();    /*敌人的子弹打到自己处理“游戏结束”事件*/
   if(!p-&gt;is_fst)  {                                  /*处理子弹与子弹相遇的情况*/
       Gm_Array[x][y]=Dt_Zero;
       Draw_Node(x,y,Dt_Zero);
    if(f_tp==8)  {   
     Gm_Array[xd][yd]=Dt_Zero;
     Draw_Node(xd,yd,Dt_Zero);                  /*销毁子弹*/
     Delete_Zdlink(xd,yd);
    }
   }
   Delete_Zdlink(x,y);  
  }
  p=p-&gt;next;
}
}</P>
<P>
void Control_Tank(Tk_Link p,Tk_Direct direct)  {
static char Rot_lb[4][4]={9,0,-1,1,0,9,1,-1,1,-1,9,0,-1,1,0,9};  
/*旋度表:9表示向前,0表示向后转,-1表示左转,1表示右转*/
char rot=Rot_lb[p-&gt;drct-1][direct-1];  /*查旋度表,根据坦克当前的方向和想要操作的方向确定坦克的行进状态*/
if(rot==9)  {                          /*处理坦克前进*/
  if(Front_Ok(p,direct))  {          /*如果前方没有障碍前进*/
      Move_Tank(p-&gt;x,p-&gt;y,direct);
      p-&gt;x+=ct_dx[direct-1];
      p-&gt;y+=ct_dy[direct-1];
  }
}
else if(Check_f_again(p))  {           /*如果满足旋转的条件,则旋转处理*/
  Rot_Tank(p-&gt;x,p-&gt;y,rot);
        p-&gt;drct=rot_d[p-&gt;drct-1][rot+1];   /*刷新方向*/
}
}</P>
<P>void Init_Tklink(void)  {                  /*初始化坦克事件链表*/
    Tk_List=(Tk_Link)malloc(sizeof(Tk_Node));
Tk_List-&gt;x=10;  Tk_List-&gt;y=15;         /*默认情况下链表中只有自己(在链表的第一个结点上)*/
Tk_List-&gt;type=Dt_Me;
Tk_List-&gt;drct=Tk_Up;
Tk_List-&gt;next=NULL;
}</P>
<P>void Init_Zdlink(void)  {                  /*初始化子弹链表(为空)*/
Zd_List=NULL;
}</P>
<P>void Insert_Tklink(int x,int y,Dt_Type type,Tk_Direct drct)  { /*在坦克事件链表上插入一个新的子弹*/
Tk_Link p=Tk_List,s;
s=(Tk_Link)malloc(sizeof(Tk_Node));
s-&gt;x=x;  s-&gt;y=y;  s-&gt;type=type;  s-&gt;drct=drct;  s-&gt;next=NULL;
while(p&amp;&amp;p-&gt;next)  p=p-&gt;next;
p-&gt;next=s;
}</P>
<P>void Insert_Zdlink(int x,int y,Dt_Type type,Tk_Direct drct)  {
Zd_Link p=Zd_List,s;            /*在子弹链表上插入一个新的子弹*/
s=(Zd_Link)malloc(sizeof(Zd_Node));
s-&gt;x=x;  s-&gt;y=y;  s-&gt;type=type;  s-&gt;drct=drct;  s-&gt;next=NULL;  s-&gt;is_fst=1;
while(p&amp;&amp;p-&gt;next)  p=p-&gt;next;
if(p)  p-&gt;next=s;
else   Zd_List=s;
}</P>
<P>int  Delete_Zdlink(int x,int y)  {  /*在子弹链表上删除数据为(x,y)的坦克*/
Zd_Link p=Zd_List,q;
while(p&amp;&amp;(p-&gt;x!=x||p-&gt;y!=y))  {
  q=p;  p=p-&gt;next;
}</P>
<P> if(p)  {
  if(p==Zd_List)  Zd_List=Zd_List-&gt;next;
  else q-&gt;next=p-&gt;next;</P>
<P>  free(p);
  return 1;
}
else  return 0;
}</P>
<P>int Delete_Tklink(int x,int y)  { /*删除一个坦克*/
Tk_Link p=Tk_List,q;</P>
<P> while(p&amp;&amp;(p-&gt;x!=x||p-&gt;y!=y))  {
  q=p;  p=p-&gt;next;
}
if(p)  {
  if(p==Tk_List)  Tk_List=Tk_List-&gt;next;
  else q-&gt;next=p-&gt;next;
  free(p);
  return 1;
}
else return 0;
}</P>
<P>void Delete_Allt(void)  {         /*删除所有的坦克*/
Tk_Link p=Tk_List;
while(p)  {
  Tk_List=Tk_List-&gt;next;
  free(p);
  p=Tk_List;
}
}</P>
<P>void Delete_Allz(void)  {         /*删除所有的子弹*/
Zd_Link p=Zd_List;
while(p)  {
  Zd_List=Zd_List-&gt;next;
  free(p);
  p=Zd_List;
}
}

void Init(void)  {                /*对游戏中的所有数据和数据结构进行初始化*/
int i,j;
for(i=0;i&lt;M_Max;i++)          /*对游戏矩阵初始化*/
for(j=0;j&lt;N_Max;j++)  Gm_Array[i][j]=Dt_Zero;
    cs_tks=4;   
    kill_tks=0;
Me_Deads=0;
Init_Tklink();
Init_Zdlink();           
Draw_Tankone(10,15,Tk_Up,1);  /*在边框的四个角出产生4个坦克*/
Insert_Tklink(1,1,Dt_Em,Tk_Down);
Draw_Tankone(1,1,Tk_Down,0);
Insert_Tklink(1,28,Dt_Em,Tk_Down);
Draw_Tankone(1,28,Tk_Down,0);
Insert_Tklink(19,1,Dt_Em,Tk_Up);
Draw_Tankone(19,1,Tk_Up,0);
Insert_Tklink(19,28,Dt_Em,Tk_Up);
Draw_Tankone(19,28,Tk_Up,0);
}</P>
<P>void Move_Tank(int x,int y,Tk_Direct type)  {    /*按照要求的方向移动坦克*/
static char mtdata[4][7]={{0,2,4,6,8,-2,0},  /*为了提高效率采用查表法进行处理*/
                           {6,8,0,2,4,2,0},   /*7个数据表示所要检查或者处理的7个关键点*/
                              {0,6,2,4,8,0,-2},  /*4表示方向:上,下,左,右*/
                           {2,8,0,4,6,0,2}};
int i,tx,ty;
int t_type=Gm_Array[x][y];
for(i=0;i&lt;5;i++)  {
  tx=x+mtdata[type-1][i]/3-1;  ty=y+(mtdata[type-1][i]+3)%3-1; /*进行地址变换*/
  if(!(i/2))  {
   Draw_Node(tx,ty,Dt_Me);
   Gm_Array[tx][ty]=t_type;
  }
  else  {
   Draw_Node(tx,ty,Dt_Zero);
   Gm_Array[tx][ty]=Dt_Zero;
  }
}
tx=x+mtdata[type-1][5];  ty=y+mtdata[type-1][6];
Draw_Node(tx,ty,Dt_Me);
Gm_Array[tx][ty]=t_type;
}       </P>
<P>void Draw_Node(int x,int y,Dt_Type type)  {  /*在屏幕上画一个基础方块(由方块组成了坦克)*/
int x_x=x*20+10;
int y_y=y*20+10;
    if(type==Dt_Zero)     setfillstyle(SOLID_FILL,BLACK);
else    setfillstyle(SOLID_FILL,YELLOW);
bar(y_y+2,x_x+2,y_y+18,x_x+18);
}</P>
<P>
/*在屏幕上画一个坦克(当方向为no的时候表示擦除坦克)*/
void Draw_Tankone(int x,int y,Tk_Direct d,int who)  {/*who 0:敌人,1:自己*/
static Dt_Type dtdata[5][9]={{0,0,0,0,0,0,0,0,0}, /*全0表示不画坦克(擦除坦克)*/
                              {0,1,0,1,1,1,1,0,1}, /*一个向上的坦克模型*/
                           {1,0,1,1,1,1,0,1,0}, /*一个向下的坦克*/
         {0,1,1,1,1,0,0,1,1}, /*一个向左的坦克*/
                              {1,1,0,0,1,1,1,1,0}}; /*一个向右的坦克*/
/*例如一个向上的坦克:0,1,0,1,1,1,1,0,1表示   0 1 0
                                                       1 1 1
                1 0 1   */
int i=0,tx,ty;
for(i=0;i&lt;9;i++) {
  tx=x+i/3-1;  ty=y+(i+3)%3-1;               /*进行地址变换*/
        Draw_Node(tx,ty,dtdata[d][i]);
  if(dtdata[d][i])  Gm_Array[tx][ty]=who+1;  /*修改游戏矩阵*/
  else              Gm_Array[tx][ty]=Dt_Zero;
    }
}</P>
<P>void Rot_Tank(int x,int y,int LR)  {        /*在屏幕上旋转一个坦克*/
static char tk[8]={2,1,0,3,6,7,8,5};    /*坦克边缘数据(因为旋转一个坦克只需要旋转它边缘部分*/
    static char tk_l[8]={8,5,2,1,0,3,6,7};  /*向左旋转的检查位置数据(需要对照tk表)*/
static char tk_r[8]={0,3,6,7,8,5,2,1};  /*向右旋转的检查位置数据*/
static char tk_bk[8]={6,7,8,5,2,1,0,3}; /*向后*/
Dt_Type  tk_tp[8];
int i=0,tx,ty;
Dt_Type disp;
for(i=0;i&lt;8;i++)  {
     if(LR==-1) tx=x+tk_l[i]/3-1,  ty=y+(tk_l[i]+3)%3-1;       /*如果是左旋,则查tk_l表进行地址变换*/
  else if(LR==0)  tx=x+tk_bk[i]/3-1,  ty=y+(tk_bk[i]+3)%3-1;
  else if(LR==1)  tx=x+tk_r[i]/3-1,  ty=y+(tk_r[i]+3)%3-1;
  tk_tp[i]=Gm_Array[tx][ty];
  tx=x+tk[i]/3-1;  ty=y+(tk[i]+3)%3-1;
  Draw_Node(tx,ty,tk_tp[i]);
}
    for(i=0;i&lt;8;i++)  {                     /*旋转完了,改变游戏矩阵*/
  tx=x+tk[i]/3-1;  ty=y+(tk[i]+3)%3-1;
  Gm_Array[tx][ty]=tk_tp[i];
}
}</P>

<P>
</P>

tary 发表于 2005-5-25 16:43

强啊.!!

C还没学到这步, 很多都看不懂...

david2234 发表于 2005-6-3 12:58

偶也看不懂

泾水荣梦 发表于 2005-6-3 23:26

我学了两年
算是白学了
所谓高手,莫过于此

牛虻 发表于 2005-6-4 10:42

这个程序有bug,人控制的坦克是无敌的,不好玩[em06]

stnlcd 发表于 2005-6-4 23:21

不是不能死!你每被子弹击中一次就会产生一个死亡事件。它的处理函数在gameover()里面,如果“想死”的话在gameover()函数里改就可以了。我学c语言也只有1年半多点而已了,我开发这个游戏只是为了大家学习交流用,这个程序里面我采用了许多比较先进和高效的算法,还是值得研究一下的。
[em01]

激情依旧 发表于 2005-6-5 08:03

    无言了。学了一年就这样了。我学了2年连文件都还不了解。[em06][em06]

badboy001 发表于 2005-6-5 15:48

好强啊!

chandy 发表于 2005-6-27 10:11

怎么我运行不了的
[em04]

leiyuzi 发表于 2005-6-30 21:48

学了这么多年的语言,算是白学了啊。
什么也看不懂啊!

high20033763 发表于 2006-2-13 15:42

还不错,回去试试

wzzhi 发表于 2006-2-22 19:57

<P>我要加油,认真学习</P>

luckboy 发表于 2006-2-26 20:44

<P><FONT color=#6f2bd5>帅哥,[em17],你真是我见到最帅的,我学了半年都不知道如何学C语言。[em09]。<BR>不知道有什么方法学这些语言呢???不如你给写一下自己学习的心德更好。。。<BR>你这么聪明以后一定非同小可啊。。</FONT></P>

cocogin 发表于 2006-3-12 15:34

....厉害,我什么时候才有这么强啊

cdmalcl 发表于 2006-9-22 08:14

[em17]

danielliujp 发表于 2006-12-4 14:06

强,我学了一年了,还是有些看不懂

jels1087101 发表于 2006-12-7 23:22

我想玩玩试试,楼主把程序贴全阿~~~~~~~~~~~~

漯河 发表于 2006-12-9 14:06

终于找到差距了

旷野乡人 发表于 2006-12-20 14:15

一年半能有我个水平,真的是很不错呀。你的学习心得真的值得分享。<BR>菜鸟跑得最快

大口木瓜 发表于 2007-11-2 13:40

关注下~~~

页: [1] 2

Powered by Discuz! Archiver 6.1.0  © 2001-2007 Comsenz Inc.