C语言零基础项目:吃豆人小游戏!详细思路+源码分享

描述

每天一个C语言小项目,提升你的编程能力!

《吃豆游戏》是一款休闲小游戏,和贪吃蛇,球球大作战吃食物都是有差不多的游戏逻辑。

这个游戏本身很简单,一共3关,吃掉画面上全部小豆子就过关,被敌人碰到就over。吃大豆子可以让敌人暂时能被你吃,但是后面关卡,敌人恢复时间很短,敌人速度也很快。

当然现在你用代码自己开发的话,设置多少关卡,什么样的难度都看你自己咯!

游戏中使用了图片【https://codebus.cn/f/a/0/0/135/boxman.zip】

源码

本项目编译环境:Visual Studio 2019/2022,EasyX插件

代码展示:

 

#include 
#include 
#include 
#include 


#define M 640                       //开屏大小
#define N 480     
#define rank 1                      //游戏等级                  
 
int  g_sum   = 0;                   //统计吃豆的个数
int  g_score = 0;                   //分数统计
bool g_win   = true;                //成败的标志
IMAGE image[5];                     //装载图片
enum {LEFT=1, RIGHT, UP, DOWN};     //方向的控制
struct figure            //人物属性
{
  int x;           //人物图纸坐标      
  int y;
  int x1;                //人物方向移动
  int y1;
  int x2;           //人物物理坐标
  int y2;
}you,enemy[5];          


/*0豆子,1可以移动地方,2墙壁,3自己,4敌人*/ 
int a[15][20]= {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 
        2,1,0,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};/*数组就是地图*/ 


int b[15][20]= {2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 
        2,1,0,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};/*数组就是地图*/ 


////////////////////////////函数声明/////////////////////////////////
void Init_begin();                  //初始化开始界面
void Initia();                    //初始化界面
void Init_score();                  //记分板
void Init_loss();                  //失败的界面
void Init_win();                  //成功的界面
void Init_leave();                  //离开的界面
void Init_copy();                  //图形复制
void enemymove();                     //敌人运动
void randdire(struct figure *sth);              //使方向随即改变
bool judgemeet();                  //相遇判断
void youmove(int k ,int speed) ;          //对自己进行移动
void mobile();                    //自己移动
void eatbean();                      //判断是否吃小黄点
void play();                    //开始游戏
int  sjs(int a,int b);                //产生a,b之间的数
void enemymeetroad(int i);              //敌人与路
void enemymeetbean(int i) ;                //敌人遇豆子
void load_image();                  //加载图片
void Game_levels();                                 //游戏等级设定                   


/////////////////////////////////////////////////////////////////////


void Init_begin()                   //初始化开始界面
{
  setbkcolor(BLACK);
  char init[20] = "吃豆子游戏";
  int x = M/2 - 250,y = 100;
  setcolor(CYAN);
    setfont(100, 0,"楷体",0,0,FW_DEMIBOLD,false,false,false);
  outtextxy(x,y,init);
  Sleep(400);


   
  RECT r = {x + 50, 250, 540, 460};
  setfont(24, 0, "宋体");
  setcolor(BROWN);
  outtextxy(x + 50, 250,"吃豆子游戏规则:");
  setfont(18, 0, "宋体");
  drawtext("

1:游戏中,操作者可以通过方向键(上、下、左、右)或字母键(‘w’、‘s’、‘a’、‘d’)来调整方向    
2:游戏中途可以按‘空格键’来暂停游戏    
3:按‘ESC’推出游戏",
    &r, DT_WORDBREAK);




  setfont(24, 0,"楷体");
  setcolor(DARKGRAY);
    outtextxy(M/2 - 107,y + 300, "按");
  setcolor(RED);
  outtextxy(M/2 - 80, y + 300, "回车键");
  setcolor(DARKGRAY);
  outtextxy(M/2 , y + 300, "开始游戏");
  char put ;
  put = getch();
  while(put != 13)
       put = getch();
}


/*0豆子,1可以移动地方,2墙壁,3自己,4敌人*/
void Initia()                     //初始化界面
{
  cleardevice();
  setbkcolor(RGB(72,12,12));


  for( int i = 0;i < 15;i++)                      
    for(int j = 0;j < 20;j++)
       putimage(100+j*20,100+i*20,&image[a[i][j]]);


  you.x=9;            you.y=5;          //敌人和自己的初始图纸坐标 
  enemy[0].x=15; enemy[0].y=2; 
  enemy[1].x=1;  enemy[1].y=4; 
  enemy[2].x=16; enemy[2].y=8; 
  enemy[3].x=13; enemy[3].y=12; 
  enemy[4].x=7;  enemy[4].y=13; 


  you.x2 = you.x * 20 + 100;            //图纸坐标转化为屏幕坐标
  you.y2 = you.y * 20 + 100;
  for(i=0;i<5;i++)
  {
    enemy[i].x2 = enemy[i].x * 20 + 100;        
    enemy[i].y2 = enemy[i].y * 20 + 100;
    enemy[i].x1 = 0;  enemy[i].y1 = 1;
  }
  Init_score();
}


void load_image()                                  //加载图片
{
  loadimage(&image[0],"IMAGE", "0.jpg");
  loadimage(&image[1],"IMAGE", "1.jpg");
  loadimage(&image[2],"IMAGE", "2.jpg");
  loadimage(&image[3],"IMAGE", "3.jpg");
  loadimage(&image[4],"IMAGE", "4.jpg");
}


void Init_score()                      //记分板
{
  setbkcolor(RGB(72,12,12));
  char infor[10];
  itoa(g_score,infor,10);
  setcolor(CYAN);
  setfont(28,0,"Arial");
  outtextxy(M - 140,90,"当前分数为");
  setfillstyle(RGB(72,12,12));
  bar(M - 40,140,M - 20,170);
  outtextxy(M - 80,140,infor);
}


int sjs(int a,int b)                               //产生a,b之间的数                        
{
  return a+rand()%(b-a+1);
}


void Init_copy()                                   //图形复制
{ 
  for(int i = 0;i < 15;i++)
    for(int j = 0;j < 20;j++)
      a[i][j] = b[i][j];
}


void enemymeetbean(int i)                  //敌人遇豆子
{
  int x = enemy[i].x2  ;
  int y = enemy[i].y2  ;
  for(int j = 0;j<20;j++)
  {
    putimage(x,y,&image[0]);
    enemy[i].x2 += enemy[i].x1;
    enemy[i].y2 += enemy[i].y1;
    putimage(enemy[i].x2,enemy[i].y2,&image[4]);
  }
}


void enemymeetroad(int i)                        //敌人遇路
{
  int x = enemy[i].x2 ;
  int y = enemy[i].y2  ;
  for(  int j = 0;j < 20;j++)
  {
    putimage(x,y,&image[1]);
    enemy[i].x2 += enemy[i].x1;
    enemy[i].y2 += enemy[i].y1;
    putimage(enemy[i].x2,enemy[i].y2,&image[4]);
  }
}


void enemymove()                         //敌人运动
{ 
  Game_levels();
  for(int i = 0;i < 5;i++)                     //判断是否与墙壁相遇,如果相遇,随即改变方向
  {
    if(a[enemy[i].y+enemy[i].y1][enemy[i].x+enemy[i].x1] == 2  ||  abs(enemy[i].y1) == abs(enemy[i].x1)) 
      randdire(&enemy[i]);
  }
  for(i = 0;i < 5;i++)
  {
    if(a[enemy[i].y ][enemy[i].x] == 0)
      enemymeetbean(i);
    else  
      enemymeetroad(i);
    enemy[i].x+=enemy[i].x1;
    enemy[i].y+=enemy[i].y1;
    if(judgemeet()) break;
  }
  Sleep(180);
}


void Game_levels()                                  //游戏等级设定                   
{
  if( sjs (1,rank) == 1)
    {
    int t = rand() % 5;
    enemy[t].x1 = enemy[t].x - you.x > 0 ? -1 : 1;  
      enemy[t].y1 = enemy[t].y - you.y > 0 ? -1 : 1;
  }
  for(int i = 0;i < 5;i++)
  {
    if(enemy[i].x == you.x && enemy[i].y + 1 == you.y)
    {enemy[i].x1 = 0 ;     enemy[i].y1 = 1;}
    if(enemy[i].x == you.x && enemy[i].y - 1 == you.y)
    {enemy[i].x1 = 0 ;     enemy[i].y1 = -1;}
    if(enemy[i].x + 1 == you.x && enemy[i].y == you.y)
    {enemy[i].x1 = 1 ;     enemy[i].y1 = 0;}
    if(enemy[i].x - 1 == you.x && enemy[i].y == you.y)
    {enemy[i].x1 = -1 ;    enemy[i].y1 = 1;}
  }
}


void randdire( struct figure *sth)            //使方向随即改变 
{
   int b=1;
   int x,y;
   while(b)
   {
     x =sjs(-1,1);
     y=sjs(-1,1);
     if(a[sth->y + y][sth->x + x] != 2 && abs(y) != abs(x))
     {
      b = 0;
      sth->x1 = x;
      sth->y1 = y;
    }
     else b = 1;
  }
}


bool judgemeet  ()                           //相遇判断
{
  for(int i = 0;i < 5;i++)
  {
    if(enemy[i].x == you.x && enemy[i].y == you.y )
    {
      g_win  = false;
      Init_loss();
      return true;
      break;
    }
  }
  return false;
}


void eatbean()                 //判断是否吃小黄点
{
  if(a[you.y][you.x] == 0)
  {
      a[you.y][you.x] = 1;
    g_sum++;
    g_score += 10;
    Init_score();
    a[you.y][you.x] = 1;
  }
}


void youmove(int k)                        //对自己进行移动
{
   switch(k)
  {
  case LEFT:
     you.x1 = -1;you.y1 = 0;
    break;
  case RIGHT:
       you.x1 = 1;you.y1 = 0;
    break;
  case DOWN:
       you.x1 = 0;you.y1 = 1;
    break;
  case UP:
      you.x1 = 0;you.y1 = -1;
    break;
  }
   if(a[you.y + you.y1][you.x + you.x1] != 2)
   {
     int x = you.x2 ;
     int y = you.y2 ;
     for(int j = 0 ;j < 10;j++)
     {
      putimage(x,y,&image[1]);
      you.x2 += you.x1 * 2;
      you.y2 += you.y1 * 2;
      putimage(you.x2,you.y2,&image[3]);
     }
     you.x += you.x1;
     you.y += you.y1;
     eatbean();
   }
 }
 
void Init_loss()                            //失败的界面
{
  cleardevice();
  char str[] = "挑战失败,还需继续努力呀!";
  LOGFONT f;
  getfont(&f);
  f.lfHeight = 48;
  strcpy(f.lfFaceName , "楷体");
  f.lfQuality = ANTIALIASED_QUALITY;
  f.lfWeight = FW_NORMAL;
  setcolor(LIGHTGREEN);
  setfont(&f);
  outtextxy(20,200,str);


  char tryagain[] = "是否想继续挑战?(Y/N)";
  f.lfHeight = 28;
  setfont(&f);
  setcolor(BROWN);
  outtextxy(90,300,tryagain);


  char yesorno ;
  int keep = 1 ;
  while(keep)
  {
    yesorno = getch();
    if(yesorno == 'Y' || yesorno == 'y' || yesorno == 'N' || yesorno == 'n')
      keep = 0;
  }
    
  if(yesorno == 'Y'|| yesorno == 'y')
  {
    g_win   = true;
    g_score = 0;
    g_sum   = 0;
    cleardevice();
    Init_copy();
    Initia();
  }
  else  Init_leave();
}


void Init_leave()
{
  cleardevice();
  char str[] = "下次继续努力吧!";
  LOGFONT f;
  getfont(&f);
  f.lfHeight = 48;
  strcpy(f.lfFaceName , "楷体");
  f.lfQuality = ANTIALIASED_QUALITY;
  f.lfWeight = FW_NORMAL;
  setcolor(LIGHTGREEN);
  setfont(&f);
  outtextxy(150,200,str);
  Sleep(2000);
  exit(0);
}


void Init_win()                             //成功的界面                        
{
  cleardevice();
  char str[] = "恭喜你通过了游戏!!!";
  LOGFONT f;
  getfont(&f);
  f.lfHeight = 48;
  strcpy(f.lfFaceName , "楷体");
  f.lfQuality = ANTIALIASED_QUALITY;
  f.lfWeight = FW_NORMAL;
  setcolor(LIGHTGREEN);
  setfont(&f);
  outtextxy(50,200,str);
  Sleep(4000);


  char tryagain[] = "是否想再次挑战?(Y/N)";
  f.lfHeight = 28;
  setfont(&f);
  setcolor(BROWN);
  outtextxy(70,300,tryagain);


  char yesorno ;
  yesorno = getch();
  if(yesorno == 'y' || yesorno == 'Y')
  {
    g_win   = true;
    g_score = 0;
    g_sum   = 0;
    cleardevice();
    Init_copy();
      Initia();                 
  }
  else  exit(0);
}


void stop()                                 //游戏暂停
{
  char key = 'a';
  char stop[] = "游戏暂停中";
  setcolor(RED);
  setfont(28,0,"楷体");
  outtextxy(230,50,stop);
  Sleep(100);
  while(key != ' ')
  key = getch();
  setcolor(RGB(72,12,12));
  outtextxy(230,50,stop);
}


void play()
{
  setbkcolor(RGB(72,12,12));
  char key;             //获取字母
  int t;                //记录方向
    while(g_win)
  {
    enemymove();
      judgemeet();
    while(kbhit())
    {
      key = getch();
      switch(key)
      {
      case 'a':
      case  75:        t = LEFT;    youmove(t );       break;
      case 'd':
      case  77:     t = RIGHT;  ;  youmove(t );       break;
      case 's':
      case  80:       t = DOWN;      youmove(t );        break;
      case 'w':
      case  72:    t = UP;      youmove(t );       break;
      case  27:    Init_leave();  break;
      case  32:    stop();      break;
      default :                       break;
      }
    }
    if(g_sum == 50)        Init_win();
  }
}


void main()
{
  initgraph(M,N);
  load_image();
  Init_begin();
  setbkcolor(RGB(72,12,12));
   
  srand((unsigned)time(NULL));
  Initia(); 
  play();
  closegraph();
}

 

大家赶紧去动手试试吧!

  审核编辑:汤梓红

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分