从c++代码移植为c代码的俄罗斯方块游戏,为了在dev-cpp环境中编译运行图形界面,所以还是需要使用c++编译器。本例只是展示用C代码实现c++面向对象编程思路。
本例使用了EGE图形库:https://xege.org/ EGE20.8版本。

/*
  Copyright zmofun           All rights reserved!
       http://www.zmofun.com
                 2017.2.5        
dev-cpp版本,参考以下资料移植:
https://blog.csdn.net/qq_39151563/article/details/100161986 

2021.2.24 update
*/



#include "graphics.h"
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <time.h>

#define ESC 0x1b
#define LEFTA 0x125
#define UPA   0x126
#define DOWNA 0x128
#define RIGHTA 0x127
#define KEYK 0x6b
#define KEYJ 0x6a
#define KEYL 0x6c
#define KEYI 0x69


#define DEBUG 0

typedef struct shape
{
  int px,py,width;
  int l,c;
  int s[5][5];
  int b[5][5];
  void (*getnextsh)(int ,int ,int ,int ,int,struct shape *);
  void (*init)(int x,int y,int w,int il,int ic,int level,struct shape *This);
  void (*rotate)(struct shape *This);
  void (*paint)(struct shape *This);
  void (*paintnext)(int x,int y,struct shape *This);
  void (*erase)(struct shape *This);
  void (*move)(int direct,struct shape *This);
}SHAPE;


typedef struct gamebox
{
  int px,py,boxwidth,boxperline,boxpercolumn,keyup,keydown,keyleft,keyright;
  int pxmess;
  int score,level,speed,layer;
  int begin;
  int controlkey[4];
  clock_t inter;
  SHAPE curshape;
  void (*gamebegin)(struct gamebox * This);
  int (*gameconfiged)(int key,struct gamebox * This);
  void (*showmessage)(struct gamebox * This);
  void (*showscore)(struct gamebox * This);
  void (*addscore)(struct gamebox * This);
  void (*paint)(struct gamebox * This);
  void (*paintstick)(struct gamebox * This);
  int (*gameover)(struct gamebox * This);
  int (*canmove)(int direct,struct gamebox * This);
  int (*canrotate)(struct gamebox * This);
  int stick[41][22];
  void (*init)(int x,int y,int boxw,int w,int h,int messx,int keyin[4],struct gamebox * This);
  void (*play)(int key,struct gamebox * This);
}GAMEBOX;

typedef struct game
{
  GAMEBOX box[2];
  void (*init)(struct game * This);
  void (*run)(struct game * This);
}GAME;


void shape_move(int d,SHAPE *This);
void shape_erase(SHAPE *This);
void shape_paint(SHAPE *This);
void shape_paintnext(int x,int y,SHAPE *This);
void shape_rotate(SHAPE *This);
void shape_getnextsh(int x,int y,int il,int ic,int level,SHAPE *This);
void shape_init(int x,int y,int w,int il,int ic,int level,SHAPE *This);
int gamebox_canrotate(GAMEBOX *This);
int gamebox_gameover(GAMEBOX *This);
void gamebox_addscore(GAMEBOX *This);
void gamebox_paintstick(GAMEBOX *This);
void gamebox_gamebegin(GAMEBOX *This);
void gamebox_showscore(GAMEBOX *This);
void gamebox_showmessage(GAMEBOX *This);
void gamebox_init(int x,int y,int boxw,int w,int h,int messx,int *keyin,GAMEBOX *This);
void gamebox_paint(GAMEBOX *This);
int gamebox_canmove(int direct,GAMEBOX *This);
int gamebox_gameconfiged(int key,GAMEBOX *This);
void gamebox_play(int key,GAMEBOX *This);
void game_init(GAME *This);
void game_run(GAME *This);


void shape_move(int d,SHAPE *This)
{
  This->erase(This);
  switch(d)
  {
    case 1:
      This->px=This->px-This->width/5;
      This->c--;
      break;
    case 2:
      This->px=This->px+This->width/5;
      This->c++;
      break;
    default:
      This->py=This->py+This->width/5;
      This->l++;
      DEBUG?printf("shape.l %d ,shape.py %d\n",This->l,This->py):0;
      break;
  }
  This->paint(This);
}

void shape_erase(SHAPE *This)
{
  int i,j;
  setbkcolor(BLUE);
  setcolor(YELLOW);
  setfillstyle(SOLID_FILL,BLUE);
  for(i=0;i<5;i++)
    for(j=0;j<5;j++)
      if (This->s[i][j])
    bar(This->px+j*(This->width/5)+1,This->py+i*(This->width/5)+1,
          This->px+(j+1)*(This->width/5)-1,This->py+(i+1)*(This->width/5)-1);
}
void shape_paint(SHAPE *This)
{
  DEBUG?printf("shape paint ,px,  %d, py:  %d\n",This->px,This->py):0;
  int i,j;
  setbkcolor(BLUE);
  setcolor(YELLOW);
  setfillstyle(SOLID_FILL,BLUE);
  for(i=0;i<5;i++)
    for(j=0;j<5;j++)
      if (This->s[i][j]){
        DEBUG?printf(" (i,j) %d,%d ",i,j):0;
        //bar3d(This->px,This->py,This->px+50,This->py+50,1,1,0);
        bar3d(This->px+j*(This->width/5)+1,This->py+i*(This->width/5)+1,
          This->px+(j+1)*(This->width/5)-1,This->py+(i+1)*(This->width/5)-1,0,1);
      }
  delay_ms(0);
  DEBUG?printf("\n"):0;
}
void shape_paintnext(int x,int y,SHAPE *This)
{
  int i,j;
  setbkcolor(BLUE);
  setcolor(YELLOW);
  setfillstyle(SOLID_FILL,BLUE);
  bar(x,y,x+This->width,y+This->width);
  for(i=0;i<5;i++)
    for(j=0;j<5;j++)
      if (This->b[i][j])
    bar3d(x+j*(This->width/5)+1,y+i*(This->width/5)+1,
          x+(j+1)*(This->width/5)-1,y+(i+1)*(This->width/5)-1,0,1);
}

void shape_rotate(SHAPE *This)
{
  int i,j;
  int t[5][5];
  for(i=0;i<5;i++)
    for(j=0;j<5;j++)
    t[i][j]=This->s[i][j];

  This->erase(This);
  for(i=0;i<5;i++)
    for(j=0;j<5;j++)
      This->s[i][j]=t[4-j][i];
  This->paint(This);
}

void shape_getnextsh(int x,int y,int il,int ic,int level,SHAPE *This)
{
  int no,i;
  int shapeall[9][25]={
    {0,0,0,0,0, 0,0,1,0,0, 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,1,1,1,0, 0,0,1,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0, 0,0,1,0,0},
    {0,0,0,0,0, 0,1,0,0,0, 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,0,0,1,0, 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,1,1,0,0, 0,1,1,0,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,1,0,1,0, 0,1,1,1,0, 0,0,0,0,0, 0,0,0,0,0},
    {0,0,0,0,0, 0,1,1,0,0, 0,0,1,0,0, 0,0,1,1,0, 0,0,0,0,0},
    {0,1,1,0,0, 0,0,1,0,0, 0,0,1,1,0, 0,1,1,0,0, 0,0,0,0,0}
    };
  srand(time(NULL));
  no=rand()%6+level;
  This->px=x;
  This->py=y;
  This->l=il;
  This->c=ic;
  for(i=0;i<25;i++)
    {
      This->s[i/5][i%5]=This->b[i/5][i%5];
      This->b[i/5][i%5]=shapeall[no][i];
    }
}

void shape_init(int x,int y,int w,int il,int ic,int level,SHAPE * This)
{
  This->px=x;
  This->py=y;
  This->l=il;
  This->c=ic;
  This->width=w;

  This->getnextsh=shape_getnextsh;
  This->init=shape_init;
  This->rotate=shape_rotate;
  This->paint=shape_paint;
  This->paintnext=shape_paintnext;
  This->erase=shape_erase;
  This->move=shape_move;

  This->getnextsh(x,y,il,ic,level,This);
}



int gamebox_canrotate(GAMEBOX *This)
{
  int i,j;
  int t[5][5];
  for(i=0;i<5;i++)
    for(j=0;j<5;j++)
      {
    t[i][j]=This->curshape.s[4-j][i];
    if(t[i][j]&&This->stick[This->curshape.l+i][This->curshape.c+j])
      return 0;
      }
  return 1;
}
int gamebox_gameover(GAMEBOX *This)
{
  int i,j;
  if (This->curshape.l<1)
    return 1;
  else
    {
      for(i=0;i<5;i++)
    for(j=0;j<5;j++)
      if(This->curshape.s[i][j])
        This->stick[i+This->curshape.l][This->curshape.c+j]=This->curshape.s[i][j];
    }
  This->addscore(This);
  return 0;
}
void gamebox_addscore(GAMEBOX *This)
{
  int i,j,line,ln,high,addspeed;
  int t[40];
  line=0;
  for (i=This->boxpercolumn-1;i>=0;i--)
    { t[i]=0;
      for(j=1;j<This->boxperline+1;j++)
    t[i]+=This->stick[i][j];
      if(t[i])
    high=i;
      if (t[i]==This->boxperline)
     {
       line++;
       t[i]=1;
     }
      else
    t[i]=0;
    }
  for(i=This->boxpercolumn-1;i>=high;i--)
    {
      if(t[i])
    {
      ln=i-1;
      while(t[ln])
       ln--;
      for(j=1;j<This->boxperline+1;j++)
       { This->stick[i][j]=This->stick[ln][j];
         This->stick[ln][j]=0;
       }
      t[ln]=1;
    }
    }
  This->paintstick(This);
  addspeed=This->score/100;
  if (line>3)
    This->score+=2*line*100;
  else
    This->score+=line*100;
  if(addspeed!=This->score/1000)
    This->speed=(This->speed+1)%10;
  This->showscore(This);
}

void gamebox_paintstick(GAMEBOX *This)
{
  int i,j;
  setbkcolor(BLUE);
  setcolor(YELLOW);
  setfillstyle(SOLID_FILL,BLUE);
  for (i=0;i<This->boxpercolumn;i++)
    for(j=1;j<This->boxperline+1;j++)
       if (This->stick[i][j])
     bar3d(This->px+This->boxwidth*(j-1)+1,This->py+This->boxwidth*i+1,
           This->px+This->boxwidth*j-1,This->py+This->boxwidth*(i+1)-1,0,1);
       else
     bar(This->px+This->boxwidth*(j-1)+1,This->py+This->boxwidth*i+1,
           This->px+This->boxwidth*j-1,This->py+This->boxwidth*(i+1)-1);
}
void gamebox_gamebegin(GAMEBOX *This)
{
  int i,j,b;
  int randnum[400]={1,1,0,1,0,1,0,1,0,1,
            1,1,0,1,0,0,1,0,1,0,
            0,0,1,0,1,0,1,0,1,0,
            0,1,0,0,1,0,1,0,0,1,
            0,1,0,1,0,1,0,1,0,1,
            1,0,0,1,0,1,0,1,0,1,
            1,1,0,0,1,0,1,0,1,0,
            0,1,0,0,1,0,0,1,0,0,
            1,0,0,1,0,0,1,0,1,0,
            1,0,0,1,0,1,0,1,0,1,
            1,1,0,0,1,0,1,0,1,0,
            0,1,0,0,1,0,0,1,0,0,
            1,1,0,1,0,1,0,1,0,1,
            1,1,0,1,0,0,1,0,1,0,
            0,0,1,0,1,0,1,0,1,0,
            1,1,0,1,0,1,0,1,0,1,
            1,1,0,1,0,0,1,0,1,0,
            0,0,1,0,1,0,1,0,1,0,
            0,1,0,0,1,0,1,0,0,1,
            0,1,0,1,0,1,0,1,0,1,
            1,0,0,1,0,1,0,1,0,1,
            1,1,0,0,1,0,1,0,1,0,
            0,1,0,0,1,0,0,1,0,0,
            1,0,0,1,0,0,1,0,1,0,
            0,1,0,0,1,0,1,0,0,1,
            0,1,0,1,0,1,0,1,0,1,
            1,0,0,1,0,1,0,1,0,1,
            1,1,0,0,1,0,1,0,1,0,
            0,1,0,0,1,0,0,1,0,0,
            1,0,0,1,0,0,1,0,1,0,
            1,0,1,0,1,0,1,0,1,0};

  for(i=0;i<This->boxpercolumn-1;i++)
    for(j=1;j<This->boxperline+1;j++)
      This->stick[i][j]=0;

  for (i=0;i<This->layer;i++)
    for(j=1;j<This->boxperline+1;j++)
       {
     b=rand()%20+i;
     This->stick[This->boxpercolumn-1-i][j]=randnum[b+j];
       }
  This->paintstick(This);
  This->curshape.getnextsh(This->px+This->boxwidth*(This->boxperline/2-3),This->py,0,This->boxperline/2-2,This->level,&(This->curshape));
  This->curshape.paint( &(This->curshape) );
  This->curshape.paintnext(This->pxmess-15,This->py+200, &(This->curshape));
  This->score=0;
  This->showscore(This);
  This->begin=1;
}


void gamebox_showscore(GAMEBOX *This)
{
  char mess[8];
  setbkcolor(BLUE);
  setcolor(YELLOW);
  setfillstyle(SOLID_FILL,BLUE);
  //settextstyle(0,0,1);
  sprintf(mess,"%d",This->score);
  bar(This->px+30,This->py-20,This->px+80,This->py-20+10);
  outtextxy(This->px+30,This->py-20,mess);
}
void gamebox_showmessage(GAMEBOX *This)
{
  char mess[5];
  setbkcolor(BLUE);
  setcolor(YELLOW);
  setfillstyle(SOLID_FILL,BLUE);
  //settextstyle(0,0,1);
  outtextxy(10,460,"Source code can download from http://www.zmofun.com!");
  outtextxy(This->pxmess,This->py+20,"LEVEL");
  sprintf(mess,"%d",This->level);
  bar(This->pxmess+20,This->py+40,This->pxmess+20+40,This->py+50);
  outtextxy(This->pxmess+20,This->py+40,mess);

  outtextxy(This->pxmess,This->py+60,"SPEED");
  sprintf(mess,"%d",This->speed);
  bar(This->pxmess+20,This->py+80,This->pxmess+20+40,This->py+90);
  outtextxy(This->pxmess+20,This->py+80,mess);

  outtextxy(This->pxmess,This->py+100,"LAYER");
  sprintf(mess,"%d",This->layer);
  bar(This->pxmess+20,This->py+120,This->pxmess+20+40,This->py+130);
  outtextxy(This->pxmess+20,This->py+120,mess);
  This->showscore(This);
}
void gamebox_init(int x,int y,int boxw,int w,int h,int messx,int *keyin,GAMEBOX *This)
{
  int i,j;
  This->px=x;
  This->py=y;
  This->boxwidth=boxw;
  This->boxperline=w;
  This->boxpercolumn=h;
  This->pxmess=messx;
  This->level=1;
  This->score=0;
  This->speed=1;
  This->layer=3;
  This->inter=clock();
  This->begin=0;

  This->gamebegin=gamebox_gamebegin;
  This->gameconfiged=gamebox_gameconfiged;
  This->showmessage=gamebox_showmessage;
  This->showscore=gamebox_showscore;
  This->addscore=gamebox_addscore;
  This->paint=gamebox_paint;
  This->paintstick=gamebox_paintstick;
  This->gameover=gamebox_gameover;
  This->canmove=gamebox_canmove;
  This->canrotate=gamebox_canrotate;
  This->play=gamebox_play;


  for(i=0;i<This->boxpercolumn;i++)
    for(j=1;j<This->boxperline+1;j++)
      This->stick[i][j]=0;
  for(i=0;i<This->boxpercolumn+1;i++)
    {
      This->stick[i][0]=1;
      This->stick[i][This->boxperline+1]=1;
    }
  for(j=0;j<This->boxperline+2;j++)
      This->stick[This->boxpercolumn][j]=1;
  for(i=0;i<4;i++)
    This->controlkey[i]=keyin[i];
  This->paint(This);

  This->curshape.init=shape_init;

  This->curshape.init(This->px+This->boxwidth*(This->boxperline/2-2),This->py,5*This->boxwidth,0,This->boxperline/2-2,This->level,&(This->curshape));
}

void gamebox_paint(GAMEBOX *This)
{
  setbkcolor(BLUE);
  setcolor(YELLOW);
  setfillstyle(SOLID_FILL,BLUE);
  bar3d(This->px,This->py,This->px+This->boxperline*This->boxwidth,This->py+This->boxpercolumn*This->boxwidth+1,0,1);
  This->showmessage(This);
}

int gamebox_canmove(int direct,GAMEBOX *This)
{
  int i,j;
  switch(direct)
   {
     case 1:
       for(j=0;j<5;j++)
     for(i=0;i<5;i++)
       if(This->curshape.s[i][j]&&This->stick[This->curshape.l+i][This->curshape.c-1+j])
         return 0;
       break;
     case 2:
       for(j=4;j>=0;j--)
     for(i=0;i<5;i++)
       if(This->curshape.s[i][j]&&This->stick[This->curshape.l+i][This->curshape.c+1+j])
         return 0;
       break;
     case 3:
       for(i=4;i>=0;i--)
     for(j=0;j<5;j++)
       if(This->curshape.s[i][j]&&This->stick[This->curshape.l+1+i][This->curshape.c+j])
         return 0;
       break;
     default:
       break;
   }
  return 1;
}
int gamebox_gameconfiged(int key,GAMEBOX *This)
{
  if(!key)
    return 0;
  if (key==This->controlkey[0])
    {
      This->level=(This->level+1)%4;
    }
  if (key==This->controlkey[1])
    return 1;
  if (key==This->controlkey[2])
    {
      This->speed=(This->speed+1)%10;
    }
  if (key==This->controlkey[3])
    {
      This->layer=(This->layer+1)%10;
    }
  This->showmessage(This);
  return 0;
}

void gamebox_play(int key,GAMEBOX *This)
{
  if (!This->begin)
    {
     if (This->gameconfiged(key,This))
       This->gamebegin(This);
     return;
    }
  if (key==This->controlkey[0])
    if(This->canrotate(This))
      This->curshape.rotate(&(This->curshape));
  if (key==This->controlkey[2])
    if(This->canmove(1,This))
      This->curshape.move(1,&(This->curshape));
  if (key==This->controlkey[3])
    if(This->canmove(2,This))
      This->curshape.move(2,&(This->curshape));
  if (key==This->controlkey[1])
    if(This->canmove(3,This))
      This->curshape.move(3,&(This->curshape));

  if(clock()-This->inter>1900-100*This->speed)
  {
    DEBUG?printf("%ld,%ld,%ld\n",clock(),This->inter,This->speed):0;

    if(This->canmove(3,This))
    {
      This->inter=clock();
      This->curshape.move(3,&(This->curshape));
    }
    else
    {
      if(This->gameover(This))
        This->begin=0;
      else
       {
         This->curshape.getnextsh(This->px+This->boxwidth*(This->boxperline/2-3),This->py,0,
                  This->boxperline/2-2,This->level,&(This->curshape));
         This->curshape.paintnext(This->pxmess-10,This->py+200,&(This->curshape));
       }
    }
  }
}

void game_init(GAME *This)
{
  This->box[0].init=gamebox_init;
  This->box[1].init=gamebox_init;
  This->run=game_run;
}

void game_run(GAME *This)
{
  int key;
  int gdriver = DETECT, gmode, errorcode;
  int keya[8]={UPA,DOWNA,LEFTA,RIGHTA,KEYI,KEYK,KEYJ,KEYL};
  //initgraph(&gdriver, &gmode, "d:\\tc3\\bgi");
  initgraph(640, 480);  
  //errorcode = graphresult();
  errorcode =grOk;

  (This->box[0]).init(105,50,13,16,30,40,keya+4,&(This->box[0]));
  (This->box[1]).init(322,50,13,16,30,560,keya,&(This->box[1]));
  while(1)
  {
    if(kbhit()){
      key=getch();
      DEBUG?printf("key:%x\n",key):0;
    }
    else key=0;
    if (key==ESC)
      break;
    (This->box[0]).play(key,&(This->box[0]));
    (This->box[1]).play(key,&(This->box[1]));
  }
  closegraph();
}


main()
{
  GAME mygame;

  mygame.init=game_init;
  mygame.init(&mygame);

  mygame.run(&mygame);
  return 1;
}

标签: C程序设计, 俄罗斯方块, dev-cpp环境

评论已关闭