/************************************
* Desc: 俄罗斯方块游戏
* By: hoodlum1980
* Email: jinfd@126.com
* Date: 2008.03.12 22:30
************************************/
#include <stdio.h>
#include <bios.h>
#include <dos.h>
#include <graphics.h>
#include <string.h>
#include <stdlib.h>
#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[][]; /* 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= ;
int CellSize= ;
int BoardLeft= ;
int BoardTop= ; /* next block grid */
int NBBoardLeft= ;
int NBBoardTop= ;
int NBCellSize= ; /* score board position */
int ScoreBoardLeft= ;
int ScoreBoardTop=;
int ScoreBoardWidth=;
int ScoreBoardHeight=;
int ScoreColor=LIGHTCYAN; /* infor text postion */
int InfoLeft=;
int InfoTop=;
int InfoColor=YELLOW; int BorderColor=DARKGRAY;
int BkGndColor=BLACK;
int GameRunning=true;
int TopLine=BoardHeight-; /* top empty line */
int TotalScore=;
char info_score[];
char info_help[];
char info_common[]; /* our board, Board[x][y][0]-isFilled, Board[x][y][1]-fillColor */
unsigned char Board[BoardWidth][BoardHeight][];
char BufferCells[][]; /* 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=;
if(bioskey())
{
key=bioskey();
}
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()*random()+random()+random())%;
block->size=;/* because most blocks' size=3 */
memset(block->c,,);
switch(key)
{
case :
block->name='T';
block->color=RED;
block->c[][]=;
block->c[][]=, block->c[][]=;
block->c[][]=;
break;
case :
block->name='L';
block->color=YELLOW;
block->c[][]=;
block->c[][]=;
block->c[][]=, block->c[][]=;
break;
case :
block->name='J';
block->color=LIGHTGRAY;
block->c[][]=;
block->c[][]=;
block->c[][]=, block->c[][]=;
break;
case :
block->name='z';
block->color=CYAN;
block->c[][]=, block->c[][]=;
block->c[][]=, block->c[][]=;
break;
case :
block->name='';
block->color=LIGHTBLUE;
block->c[][]=, block->c[][]=;
block->c[][]=, block->c[][]=;
break;
case :
block->name='o';
block->color=BLUE;
block->size=;
block->c[][]=, block->c[][]=;
block->c[][]=, block->c[][]=;
break;
case :
block->name='I';
block->color=GREEN;
block->size=;
block->c[][]=;
block->c[][]=;
block->c[][]=;
block->c[][]=;
break;
}
} /* get next block! */
void NextBlock()
{
/* copy the nextBlock to curBlock */
curBlock.size=nextBlock.size;
curBlock.color=nextBlock.color;
curBlock.x=(BoardWidth-)/;
curBlock.y=-curBlock.size;
memcpy(curBlock.c,nextBlock.c,);
/* generate nextBlock and show it */
EraseBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
GenerateBlock(&nextBlock);
nextBlock.x=,nextBlock.y=;
DrawBlock(&nextBlock,NBBoardLeft,NBBoardTop,NBCellSize);
} /* rotate the block, update the block struct data */
int _INNER_HELPER RotateCells(char c[][],char blockSize)
{
char temp,i,j;
switch(blockSize)
{
case :
temp=c[][];
c[][]=c[][], c[][]=c[][], c[][]=c[][], c[][]=temp;
temp=c[][];
c[][]=c[][], c[][]=c[][], c[][]=c[][], c[][]=temp;
break;
case : /* only 'I' block arived here! */
c[][]=-c[][], c[][]=-c[][], c[][]=-c[][];
c[][]=-c[][], c[][]=-c[][], c[][]=-c[][];
break;
}
} /* judge if the block can move toward the direction */
int CanMove(int dx,int dy)
{
int i,j,tempX,tempY;
for(i=;i<curBlock.size;i++)
{
for(j=;j<curBlock.size;j++)
{
if(curBlock.c[i][j])
{
/* cannot move leftward or rightward */
tempX = curBlock.x + i + dx;
if(tempX< || tempX>(BoardWidth-)) return false; /* make sure x is valid! */
/* cannot move downward */
tempY = curBlock.y + j + dy;
if(tempY>(BoardHeight-)) 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>= && Board[tempX][tempY][]) return false;
}
}
}
return true;
} /* judge if the block can rotate */
int CanRotate()
{
int i,j,tempX,tempY;
/* update buffer */
memcpy(BufferCells, curBlock.c, );
RotateCells(BufferCells,curBlock.size);
for(i=;i<curBlock.size;i++)
{
for(j=;j<curBlock.size;j++)
{
if(BufferCells[i][j])
{
tempX=curBlock.x+i;
tempY=curBlock.y+j;
if(tempX< || tempX>(BoardWidth-))
return false;
if(tempY>(BoardHeight-))
return false;
if(tempY>= && Board[tempX][tempY][])
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=;i<block->size;i++)
{
for(j=;j<block->size;j++)
{
if(block->c[i][j] && (block->y+j)>=)
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/,
bdTop+cellSize*(j+block->y)+cellSize/,
BorderColor);
}
}
}
} /* Rotate the block, if success, return true */
int RotateBlock(Block *block)
{
char temp,i,j;
int b_success;
if(block->size==)
return true;
if(( b_success=CanRotate()))
{
EraseBlock(block,BoardLeft,BoardTop,CellSize);
memcpy(curBlock.c,BufferCells,);
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=;i<block->size;i++)
{
for(j=;j<block->size;j++)
{
if(block->c[i][j] && (block->y+j>=))
{
floodfill(
bdLeft+cellSize*(i+block->x)+cellSize/,
bdTop+cellSize*(j+block->y)+cellSize/,
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(,))
{
curBlock.y++;
}
DrawBlock(block,BoardLeft,BoardTop,CellSize);
return ;/* 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,,BoardWidth*BoardHeight*);
memset(nextBlock.c,,);
strcpy(info_help,"P: Pause Game. --by hoodlum1980");
initgraph(&gdriver,&gmode,"");
setcolor(BorderColor);
for(i=;i<=BoardWidth;i++)
{
line(BoardLeft+i*CellSize, BoardTop, BoardLeft+i*CellSize, BoardTop+ BoardHeight*CellSize);
}
for(i=;i<=BoardHeight;i++)
{
line(BoardLeft, BoardTop+i*CellSize, BoardLeft+BoardWidth*CellSize, BoardTop+ i*CellSize);
}
/* draw board outer border rect */
rectangle(BoardLeft-CellSize/, BoardTop-CellSize/,
BoardLeft+BoardWidth*CellSize+CellSize/,
BoardTop+BoardHeight*CellSize+CellSize/); /* draw next block grids */
for(i=;i<=;i++)
{
line(NBBoardLeft+i*NBCellSize, NBBoardTop, NBBoardLeft+i*NBCellSize, NBBoardTop+*NBCellSize);
line(NBBoardLeft, NBBoardTop+i*NBCellSize, NBBoardLeft+*NBCellSize, NBBoardTop+ i*NBCellSize);
} /* draw score rect */
rectangle(ScoreBoardLeft,ScoreBoardTop,ScoreBoardLeft+ScoreBoardWidth,ScoreBoardTop+ScoreBoardHeight);
DisplayScore(); /* set new seed! */
gettime(&sysTime);
srand(sysTime.ti_hour*+sysTime.ti_min*+sysTime.ti_sec); GenerateBlock(&nextBlock);
NextBlock(); /* create first block */
setcolor(DARKGRAY);
outtextxy(InfoLeft,InfoTop+,"Up -rotate Space-drop");
outtextxy(InfoLeft,InfoTop+,"Left-left Right-right");
outtextxy(InfoLeft,InfoTop+,"Esc -exit");
DisplayInfo(info_help);
} /* set the isFilled and fillcolor data to the board */
void _INNER_HELPER FillBoardData()
{
int i,j;
for(i=;i<curBlock.size;i++)
{
for(j=;j<curBlock.size;j++)
{
if(curBlock.c[i][j] && (curBlock.y+j)>=)
{
Board[curBlock.x+i][curBlock.y+j][]=;
Board[curBlock.x+i][curBlock.y+j][]=curBlock.color;
}
}
}
} /* draw one line of the board */
void _INNER_HELPER PaintBoard()
{
int i,j,fillcolor;
for(j=max((TopLine-),);j<BoardHeight;j++)
{
for(i=;i<BoardWidth;i++)
{
fillcolor=Board[i][j][]? Board[i][j][]:BkGndColor;
setfillstyle(SOLID_FILL,fillcolor);
floodfill(BoardLeft+i*CellSize+CellSize/,BoardTop+j*CellSize+CellSize/,BorderColor);
}
}
} /* check if one line if filled full and increase the totalScore! */
void _INNER_HELPER CheckBoard()
{
int i,j,k,score=,sum=,topy,lines=;
/* we find the top empty line! */
j=topy=BoardHeight-;
do
{
sum=;
for(i=;i< BoardWidth; i++)
{
sum+=Board[i][topy][];
}
topy--;
} while(sum> && topy>); /* remove the full filled line (max remove lines count = 4) */
do
{
sum=;
for(i=;i< BoardWidth; i++)
sum+=Board[i][j][]; 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=;i<BoardWidth;i++)
{
Board[i][k][]=Board[i][k-][];
Board[i][k][]=Board[i][k-][];
}
}
/*make the top line empty! */
for(i=;i<BoardWidth;i++)
{
Board[i][topy][]=;
Board[i][topy][]=;
}
topy++; /* move the topline downward one line! */
lines++; /* lines <=4 */
TotalScore+=score;
score*=; /* adding: 10, 30, 70, 150 */
}
else
j--;
} while(sum> && j>topy && lines<);
/* speed up the game when score is high, minimum is 400 */
FrameTime=max(-*(TotalScore/), );
TopLine=topy;/* update the top line */
/* if no lines remove, only add 1: */
if(lines==)
TotalScore++;
} /* display the score */
void _INNER_HELPER DisplayScore()
{
setcolor(BkGndColor);
outtextxy(ScoreBoardLeft+,ScoreBoardTop+,info_score);
setcolor(ScoreColor);
sprintf(info_score,"Score: %d",TotalScore);
outtextxy(ScoreBoardLeft+,ScoreBoardTop+,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=;
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=,j,key=,tick=;
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,,))
{
UpdateBoard();
NextBlock();
if(!CanMove(,))
goto GameOver;
}
tick=;
}
delay();
}
switch(key)
{
case K_LEFT:
MoveBlock(&curBlock,-,);
break;
case K_RIGHT:
MoveBlock(&curBlock,,);
break;
case K_DOWN:
MoveBlock(&curBlock,,);
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();
}

用C写的俄罗斯方块游戏 By: hoodlum1980 编程论坛的更多相关文章

  1. 【转】shell脚本写的俄罗斯方块游戏

    亲测一个很好玩的shell脚本写的俄罗斯方块游戏,脚本来自互联网 先来讲一下思维流程 一.方块的表示 由于shell不能定义二维数组,所以只能用一维数组表示方块,俄罗斯方块主要可以分为7类,每一类方块 ...

  2. Python 写一个俄罗斯方块游戏

    使用 Python 的 PyGame 库写一个俄罗斯方块游戏的逐步指南 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人 ...

  3. 60行代码:Javascript 写的俄罗斯方块游戏

    哈哈这个实在是有点意思 备受打击当初用java各种类写的都要几百行啦 先看效果图: 游戏结束图: javascript实现源码: [javascript] view plaincopyprint? & ...

  4. 从零开始---控制台用c写俄罗斯方块游戏(1)

    从零开始---控制台用c写俄罗斯方块游戏(1) 很少写博文,一来自身知识有限,二来自己知道,已经有很多这样的博文了,三就是因为懒,文笔也一般,四来刚出来工作,时间也不多 之所以写这篇博文,是因为应群里 ...

  5. electron写俄罗斯方块游戏(Tetris)

    背景 在折腾ES6,突然想起大学时用c语言写过俄罗斯方块,本项目中主要是利用ES6的Class特性进行面向对象编程.项目采用node.js v6.2.0 + electron v1.1.0 进行桌面开 ...

  6. 教你看懂网上流传的60行JavaScript代码俄罗斯方块游戏

    早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用C写一个功能基本齐全的俄罗斯方块的话,大 ...

  7. 俄罗斯方块游戏JavaScript代码

    JavaScript代码俄罗斯方块游戏 早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用 ...

  8. C语言写的俄罗斯方块

    源:C语言写的俄罗斯方块 2014年最后一天, 任天堂将风靡全球30年的经典游戏<<俄罗斯方块>>下架. 作为全球最畅销的游戏, 其移植版本遍布各个平台. 下面这个是我去年在5 ...

  9. C++编写简单的俄罗斯方块游戏

    代码地址如下:http://www.demodashi.com/demo/14593.html C++编写简单的俄罗斯方块游戏 使用C++编写一个简单的俄罗斯方块游戏. 1 环境要求 使用C++图形库 ...

随机推荐

  1. html doctype 作用介绍

    文档模式主要有以下两个作用: 1.告诉浏览器使用什么样的html或xhtml规范来解析html文档 2.对浏览器的渲染模式产生影响:不同的渲染模式会影响到浏览器对于 CSS 代码甚至 JavaScri ...

  2. Qlikview 图标控件实现动态分组

    首先编辑一个组合字段,eg, TimeDimension, 内含2个字段(即为动态可以切换的分组字段) 将TimeDimension 作为分组字段.表达式字段 Sum(Sales),结果如图示 在图片 ...

  3. [js] js和C# 时间日期格式转换

    下午在搞MVC和EXTJS的日期格式互相转换遇到了问题,我们从.NET服务器端序列化一个DateTime对象的结果是一个字符串格式,如 '/Date(1335258540000)/' 这样的字串. 整 ...

  4. MSSQLSERVER之发布-分发-订阅

    一.环境 发布服务器 O S: Windows servier 2003 64位 Soft: Microsoft SqlServer 2008 R2 I P: 192.168.3.70 HOST-NA ...

  5. Address already in use的解决方法

    当客户端保持着与服务器端的连接,这时服务器端断开,再开启服务器时会出现: Address already in usr. 可以用netstat -anp | more 可以看到客户端还保持着与服务器的 ...

  6. 解决阿里云数据库RDS报错The table '/home/mysql/data3015/tmp/#sql_13975_23' is full

    查询任何一条语句都显示 The table '/home/mysql/data3015/tmp/#sql_13975_23' is full 查看了下数据库利用磁盘空间没有满, 阿里云的处理方式: 1 ...

  7. 第一零五天上课 PHP TP框架下分页

    控制器代码(TestController.class.php) <?php namespace Home\Controller; use Home\Controller\EmptyControl ...

  8. ghost系统到硬盘完后,重启进入winxp安装的画面变成了蓝屏

    ghost系统到硬盘完后,重启进入winxp安装的画面变成了蓝屏 原因分析: 一.系统集成的驱动和主板不兼容  这种原因引起的故障在部份品牌机上较常见,主要症状是系统能正常安装完成,但完成后重启进入系 ...

  9. Shape comparison language

      形状比较语言, 九交模型 In this topic About shape comparison language Dimensionality Extensions to the CBM SC ...

  10. VC++ MFC 按钮的全部样式Style

    Button Styles BS_3STATE 与复选框一样本样式按钮可被单击变暗.变暗状态通常用于指示本样式的按键正处于禁用状态. BS_AUTO3STATE   与三状态的复选框一样当用户选中它本 ...