C代码 俄罗斯方块游戏
从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;
}
评论已关闭