admin 管理员组文章数量: 887031
2023年12月22日发(作者:投篮源码)
/************************************
* Desc: 俄罗斯方块游戏
* By: hoodlum1980
:30
************************************/
#include
#include
#include
#include
#include
#include
#define true 1
#define false 0
#define BoardWidth 12
#define BoardHeight 23
#define _INNER_HELPER /*inner helper method */
/*Scan Codes Define*/
enum KEYCODES
{
K_ESC =0x011b,
K_UP =0x4800, /* upward arrow */
K_LEFT =0x4b00,
K_DOWN =0x5000,
K_RIGHT =0x4d00,
K_SPACE =0x3920,
K_P =0x1970
};
/* the data structure of the block */
typedef struct tagBlock
{
char c[4][4]; /* cell fill info array, 0-empty, 1-filled */
int x; /* block position cx [ 0,BoardWidht -1] */
int y; /* block position cy [-4,BoardHeight-1] */
char color; /* block color */
char size; /* block max size in width or height */
char name; /* block name (the block's shape) */
} Block;
/* game's global info */
int FrameTime= 1300;
int CellSize= 18;
int BoardLeft= 30;
int BoardTop= 30;
/* next block grid */
int NBBoardLeft= 300;
int NBBoardTop= 30;
int NBCellSize= 10;
/* score board position */
int ScoreBoardLeft= 300;
int ScoreBoardTop=100;
int ScoreBoardWidth=200;
int ScoreBoardHeight=35;
int ScoreColor=LIGHTCYAN;
/* infor text postion */
int InfoLeft=300;
int InfoTop=200;
int InfoColor=YELLOW;
int BorderColor=DARKGRAY;
int BkGndColor=BLACK;
int GameRunning=true;
int TopLine=BoardHeight-1; /* top empty line */
int TotalScore=100;
char info_score[20];
char info_help[255];
char info_common[255];
/* our board, Board[x][y][0]-isFilled, Board[x][y][1]-fillColor */
unsigned char Board[BoardWidth][BoardHeight][2];
char BufferCells[4][4]; /* used to judge if can rotate block */
Block curBlock; /* current moving block */
Block nextBlock; /* next Block to appear */
/* function list */
int GetKeyCode();
int CanMove(int dx,int dy);
int CanRotate();
int RotateBlock(Block *block);
int MoveBlock(Block *block,int dx,int dy);
void DrawBlock(Block *block,int,int,int);
void EraseBlock(Block *block,int,int,int);
void DisplayScore();
void DisplayInfo(char* text);
void GenerateBlock(Block *block);
void NextBlock();
void InitGame();
int PauseGame();
void QuitGame();
/*Get Key Code */
int _INNER_HELPER GetKeyCode()
{
int key=0;
if(bioskey(1))
{
key=bioskey(0);
}
return key;
}
/* display text! */
void _INNER_HELPER DisplayInfo(char *text)
{
setcolor(BkGndColor);
outtextxy(InfoLeft,InfoTop,info_common);
strcpy(info_common,text);
setcolor(InfoColor);
outtextxy(InfoLeft,InfoTop,info_common);
}
/* create a new block by key number,
* the block anchor to the top-left corner of 4*4 cells
*/
void _INNER_HELPER GenerateBlock(Block *block)
{
int key=(random(13)*random(17)+random(1000)+random(3000))%7;
block->size=3;/* because most blocks' size=3 */
memset(block->c,0,16);
switch(key)
{
case 0:
block->name='T';
block->color=RED;
block->c[1][0]=1;
block->c[1][1]=1, block->c[2][1]=1;
block->c[1][2]=1;
break;
case 1:
block->name='L';
block->color=YELLOW;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1, block->c[2][2]=1;
break;
case 2:
block->name='J';
block->color=LIGHTGRAY;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1, block->c[0][2]=1;
break;
case 3:
block->name='z';
block->color=CYAN;
block->c[0][0]=1, block->c[1][0]=1;
block->c[1][1]=1, block->c[2][1]=1;
break;
case 4:
block->name='5';
block->color=LIGHTBLUE;
block->c[1][0]=1, block->c[2][0]=1;
block->c[0][1]=1, block->c[1][1]=1;
break;
case 5:
block->name='o';
block->color=BLUE;
block->size=2;
block->c[0][0]=1, block->c[1][0]=1;
block->c[0][1]=1, block->c[1][1]=1;
break;
case 6:
block->name='I';
block->color=GREEN;
block->size=4;
block->c[1][0]=1;
block->c[1][1]=1;
block->c[1][2]=1;
block->c[1][3]=1;
break;
}
}
/* get next block! */
void NextBlock()
{
/* copy the nextBlock to curBlock */
=;
=;
curBlock.x=(BoardWidth-4)/2;
curBlock.y=-;
memcpy(curBlock.c,nextBlock.c,16);
/* generate nextBlock and show it */
EraseBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
GenerateBlock(&nextBlock);
nextBlock.x=1,nextBlock.y=0;
DrawBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
}
/* rotate the block, update the block struct data */
int _INNER_HELPER RotateCells(char c[4][4],char blockSize)
{
char temp,i,j;
switch(blockSize)
{
case 3:
temp=c[0][0];
c[0][0]=c[2][0], c[2][0]=c[2][2], c[2][2]=c[0][2], c[0][2]=temp;
temp=c[0][1];
c[0][1]=c[1][0], c[1][0]=c[2][1], c[2][1]=c[1][2], c[1][2]=temp;
break;
case 4: /* only 'I' block arived here! */
c[1][0]=1-c[1][0], c[1][2]=1-c[1][2], c[1][3]=1-c[1][3];
c[0][1]=1-c[0][1], c[2][1]=1-c[2][1], c[3][1]=1-c[3][1];
break;
}
}
/* judge if the block can move toward the direction */
int CanMove(int dx,int dy)
{
int i,j,tempX,tempY;
for(i=0;i<;i++)
{
for(j=0;j<;j++)
{
if(curBlock.c[i][j])
{
/* cannot move leftward or rightward */
tempX = curBlock.x + i + dx;
if(tempX<0 || tempX>(BoardWidth-1)) return false; /* make sure x is
valid! */
/* cannot move downward */
tempY = curBlock.y + j + dy;
if(tempY>(BoardHeight-1)) return false; /* y is only checked lower
bound, maybe negative */
/* the cell already filled, we must check Y's upper bound before check cell ! */
if(tempY>=0 && Board[tempX][tempY][0]) return false;
}
}
}
return true;
}
/* judge if the block can rotate */
int CanRotate()
{
int i,j,tempX,tempY;
/* update buffer */
memcpy(BufferCells, curBlock.c, 16);
RotateCells(BufferCells,);
for(i=0;i<;i++)
{
for(j=0;j<;j++)
{
if(BufferCells[i][j])
{
tempX=curBlock.x+i;
tempY=curBlock.y+j;
if(tempX<0 || tempX>(BoardWidth-1))
return false;
if(tempY>(BoardHeight-1))
return false;
if(tempY>=0 && Board[tempX][tempY][0])
return false;
}
}
}
return true;
}
/* draw the block */
void _INNER_HELPER DrawBlock(Block *block,int bdLeft,int bdTop,int cellSize)
{
int i,j;
setfillstyle(SOLID_FILL,block->color);
for(i=0;i
{
for(j=0;j
{
if(block->c[i][j] && (block->y+j)>=0)
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/2,
bdTop+cellSize*(j+block->y)+cellSize/2,
BorderColor);
}
}
}
}
/* Rotate the block, if success, return true */
int RotateBlock(Block *block)
{
char temp,i,j;
int b_success;
if(block->size==2)
return true;
if(( b_success=CanRotate()))
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
memcpy(curBlock.c,BufferCells,16);
DrawBlock(block,BoardLeft,BoardTop,CellSize);
}
return b_success;
}
/* erase a block, only fill the filled cell with background color */
void _INNER_HELPER EraseBlock(Block *block,int bdLeft,int bdTop,int cellSize)
{
int i,j;
setfillstyle(SOLID_FILL,BkGndColor);
for(i=0;i
{
for(j=0;j
{
if(block->c[i][j] && (block->y+j>=0))
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/2,
bdTop+cellSize*(j+block->y)+cellSize/2,
BorderColor);
}
}
}
}
/* move by the direction if can, donothing if cannot
* return value: true - success, false - cannot move toward this direction
*/
int MoveBlock(Block *block,int dx,int dy)
{
int b_canmove=CanMove(dx,dy);
if(b_canmove)
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
curBlock.x+=dx;
curBlock.y+=dy;
DrawBlock(block,BoardLeft,BoardTop,CellSize);
}
return b_canmove;
}
/* drop the block to the bottom! */
int DropBlock(Block *block)
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
while(CanMove(0,1))
{
curBlock.y++;
}
DrawBlock(block,BoardLeft,BoardTop,CellSize);
return 0;/* return value is assign to the block's alive */
}
/* init the graphics mode, draw the board grid */
void InitGame()
{
int i,j,gdriver=DETECT,gmode;
struct time sysTime;
/* draw board cells */
memset(Board,0,BoardWidth*BoardHeight*2);
memset(nextBlock.c,0,16);
strcpy(info_help,"P: Pause Game. --by hoodlum1980");
initgraph(&gdriver,&gmode,"");
setcolor(BorderColor);
for(i=0;i<=BoardWidth;i++)
{
line(BoardLeft+i*CellSize, BoardTop, BoardLeft+i*CellSize, BoardTop+
BoardHeight*CellSize);
}
for(i=0;i<=BoardHeight;i++)
{
line(BoardLeft, BoardTop+i*CellSize, BoardLeft+BoardWidth*CellSize, BoardTop+
i*CellSize);
}
/* draw board outer border rect */
rectangle(BoardLeft-CellSize/4, BoardTop-CellSize/4,
BoardLeft+BoardWidth*CellSize+CellSize/4,
BoardTop+BoardHeight*CellSize+CellSize/4);
/* draw next block grids */
for(i=0;i<=4;i++)
{
line(NBBoardLeft+i*NBCellSize, NBBoardTop, NBBoardLeft+i*NBCellSize,
NBBoardTop+4*NBCellSize);
line(NBBoardLeft, NBBoardTop+i*NBCellSize, NBBoardLeft+4*NBCellSize,
NBBoardTop+ i*NBCellSize);
}
/* draw score rect */
rectangle(ScoreBoardLeft,ScoreBoardTop,ScoreBoardLeft+ScoreBoardWidth,ScoreBoardTop+ScoreBoardHeight);
DisplayScore();
/* set new seed! */
gettime(&sysTime);
srand(_hour*3600+_min*60+_sec);
GenerateBlock(&nextBlock);
NextBlock(); /* create first block */
setcolor(DARKGRAY);
outtextxy(InfoLeft,InfoTop+20,"Up -rotate Space-drop");
outtextxy(InfoLeft,InfoTop+35,"Left-left Right-right");
outtextxy(InfoLeft,InfoTop+50,"Esc -exit");
DisplayInfo(info_help);
}
/* set the isFilled and fillcolor data to the board */
void _INNER_HELPER FillBoardData()
{
int i,j;
for(i=0;i<;i++)
{
for(j=0;j<;j++)
{
if(curBlock.c[i][j] && (curBlock.y+j)>=0)
{
Board[curBlock.x+i][curBlock.y+j][0]=1;
Board[curBlock.x+i][curBlock.y+j][1]=;
}
}
}
}
/* draw one line of the board */
void _INNER_HELPER PaintBoard()
{
int i,j,fillcolor;
for(j=max((TopLine-4),0);j { for(i=0;i { fillcolor=Board[i][j][0]? Board[i][j][1]:BkGndColor; setfillstyle(SOLID_FILL,fillcolor); floodfill(BoardLeft+i*CellSize+CellSize/2,BoardTop+j*CellSize+CellSize/2,BorderColor); } } } /* check if one line if filled full and increase the totalScore! */ void _INNER_HELPER CheckBoard() { int i,j,k,score=10,sum=0,topy,lines=0; /* we find the top empty line! */ j=topy=BoardHeight-1; do { sum=0; for(i=0;i< BoardWidth; i++) { sum+=Board[i][topy][0]; } topy--; } while(sum>0 && topy>0); /* remove the full filled line (max remove lines count = 4) */ do { sum=0; for(i=0;i< BoardWidth; i++) sum+=Board[i][j][0]; if(sum==BoardWidth)/* we find this line is full filled, remove it! */ { /* move the cells data down one line */ for(k=j; k > topy;k--) { for(i=0;i { Board[i][k][0]=Board[i][k-1][0]; Board[i][k][1]=Board[i][k-1][1]; } } /*make the top line empty! */ for(i=0;i { Board[i][topy][0]=0; Board[i][topy][1]=0; } topy++; /* move the topline downward one line! */ lines++; /* lines <=4 */ TotalScore+=score; score*=2; /* adding: 10, 30, 70, 150 */ } else j--; } while(sum>0 && j>topy && lines<4); /* speed up the game when score is high, minimum is 400 */ FrameTime=max(1200-100*(TotalScore/200), 400); TopLine=topy;/* update the top line */ /* if no lines remove, only add 1: */ if(lines==0) TotalScore++; } /* display the score */ void _INNER_HELPER DisplayScore() { setcolor(BkGndColor); outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score); setcolor(ScoreColor); sprintf(info_score,"Score: %d",TotalScore); outtextxy(ScoreBoardLeft+5,ScoreBoardTop+5,info_score); } /* we call this function when a block is inactive. */ void UpdateBoard() { FillBoardData(); CheckBoard(); PaintBoard(); DisplayScore(); } /* pause the game, and timer handler stop move down the block! */ int PauseGame() { int key=0; DisplayInfo("Press P to Start or Resume!"); while(key!=K_P && key!=K_ESC) { while(!(key=GetKeyCode())){} } DisplayInfo(info_help); return key; } /* quit the game and do cleaning work. */ void QuitGame() { closegraph(); } /* the entry point function. */ void main() { int i,flag=1,j,key=0,tick=0; InitGame(); if(PauseGame()==K_ESC) goto GameOver; /* wait until a key pressed */ while(key!=K_ESC) { /* wait until a key pressed */ while(!(key=GetKeyCode())) { tick++; if(tick>=FrameTime) { /* our block has dead! (can't move down), we get next block */ if(!MoveBlock(&curBlock,0,1)) { UpdateBoard(); NextBlock(); if(!CanMove(0,1)) goto GameOver; } tick=0; } delay(100); } switch(key) { case K_LEFT: MoveBlock(&curBlock,-1,0); break; case K_RIGHT: MoveBlock(&curBlock,1,0); break; case K_DOWN: MoveBlock(&curBlock,0,1); break; case K_UP: RotateBlock(&curBlock); break; case K_SPACE: DropBlock(&curBlock); break; case K_P: PauseGame(); break; } } GameOver: DisplayInfo("GAME OVER! Press any key to exit!"); getch(); /* wait the user Press any key. */ QuitGame(); } 基本思想: 定义基本的7种方块(含四种状态)二维数组变量. Terial[7][4]. 用数组下标索引方块的种类和状态. 定义方块运行的区域(二维数组变量) 如(高23,宽10) 用它存储方块下落后的状态. 左移和右移判断是方块是否左右溢出、是否会叠在运行区的格子上。 同样改变状态(变形)也得判断是否会出现左右溢出、是否会叠在运行区格子上。 下落后,对运行区的空格子进行赋值。
版权声明:本文标题:小游戏源代码 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/free/1703226693h443054.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论