博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
用C写的俄罗斯方块游戏 By: hoodlum1980 编程论坛
阅读量:4966 次
发布时间:2019-06-12

本文共 11058 字,大约阅读时间需要 36 分钟。

/************************************* Desc:    俄罗斯方块游戏        * By:    hoodlum1980        * Email:    jinfd@126.com        * Date:    2008.03.12 22: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.size=nextBlock.size; curBlock.color=nextBlock.color; curBlock.x=(BoardWidth-4)/2; curBlock.y=-curBlock.size; 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
(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,curBlock.size); for(i=0;i
(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
size;i++) { for(j=0;j
size;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
size;i++) { for(j=0;j
size;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(sysTime.ti_hour*3600+sysTime.ti_min*60+sysTime.ti_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
=0) { Board[curBlock.x+i][curBlock.y+j][0]=1; Board[curBlock.x+i][curBlock.y+j][1]=curBlock.color; } } }}/* draw one line of the board */void _INNER_HELPER PaintBoard(){ int i,j,fillcolor; for(j=max((TopLine-4),0);j
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
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();}

 

转载于:https://www.cnblogs.com/hello-2015/p/4448059.html

你可能感兴趣的文章
socket tcp
查看>>
DataMining--Python基础入门
查看>>
单片机复位电路
查看>>
php json_decode失败,返回null
查看>>
获取单选按钮选中的值
查看>>
oracle 分页
查看>>
助教学期总结
查看>>
绘制基本 图形之矩形与多边形
查看>>
3-day3-list-truple-map.py
查看>>
02: djangorestframework使用
查看>>
Edit控件显示多行文字
查看>>
JS第二周
查看>>
dataTable.NET的search box每輸入一個字母進行一次檢索的問題
查看>>
Python 文件处理
查看>>
邻接表详解
查看>>
服务器一:分布式服务器结构
查看>>
迭代dict的value
查看>>
eclipse package,source folder,folder区别及相互转换
查看>>
Py 可能是最全面的 python 字符串拼接总结(带注释版)
查看>>
(转载)博弈汇总【巴什博奕,威佐夫博弈,尼姆博弈,斐波那契博弈】
查看>>