用C写的俄罗斯方块游戏 By: hoodlum1980 编程论坛
/************************************
* 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 编程论坛的更多相关文章
- 【转】shell脚本写的俄罗斯方块游戏
亲测一个很好玩的shell脚本写的俄罗斯方块游戏,脚本来自互联网 先来讲一下思维流程 一.方块的表示 由于shell不能定义二维数组,所以只能用一维数组表示方块,俄罗斯方块主要可以分为7类,每一类方块 ...
- Python 写一个俄罗斯方块游戏
使用 Python 的 PyGame 库写一个俄罗斯方块游戏的逐步指南 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人 ...
- 60行代码:Javascript 写的俄罗斯方块游戏
哈哈这个实在是有点意思 备受打击当初用java各种类写的都要几百行啦 先看效果图: 游戏结束图: javascript实现源码: [javascript] view plaincopyprint? & ...
- 从零开始---控制台用c写俄罗斯方块游戏(1)
从零开始---控制台用c写俄罗斯方块游戏(1) 很少写博文,一来自身知识有限,二来自己知道,已经有很多这样的博文了,三就是因为懒,文笔也一般,四来刚出来工作,时间也不多 之所以写这篇博文,是因为应群里 ...
- electron写俄罗斯方块游戏(Tetris)
背景 在折腾ES6,突然想起大学时用c语言写过俄罗斯方块,本项目中主要是利用ES6的Class特性进行面向对象编程.项目采用node.js v6.2.0 + electron v1.1.0 进行桌面开 ...
- 教你看懂网上流传的60行JavaScript代码俄罗斯方块游戏
早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用C写一个功能基本齐全的俄罗斯方块的话,大 ...
- 俄罗斯方块游戏JavaScript代码
JavaScript代码俄罗斯方块游戏 早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用 ...
- C语言写的俄罗斯方块
源:C语言写的俄罗斯方块 2014年最后一天, 任天堂将风靡全球30年的经典游戏<<俄罗斯方块>>下架. 作为全球最畅销的游戏, 其移植版本遍布各个平台. 下面这个是我去年在5 ...
- C++编写简单的俄罗斯方块游戏
代码地址如下:http://www.demodashi.com/demo/14593.html C++编写简单的俄罗斯方块游戏 使用C++编写一个简单的俄罗斯方块游戏. 1 环境要求 使用C++图形库 ...
随机推荐
- $.when().then()
当两个Ajax请求是成功的则执行函数myFunc,如果任一个有错误则执行myFailure. $.when($.ajax("/page1.php"), $.ajax("/ ...
- Oracle命令:授权-收回权限-角色
Oracle命令:授权-收回权限-角色 oracle grant 不论授予何种权限,每条授权(grant)语句总是由三部分组成: 1) 接受者部分是准备获得权限的一个或多个用户的列表. 2)关键字权限 ...
- ubuntu 开机显示错误:无法应用原保存的显示器配置
无法应用原保存的显示器配置CRTC 63:尝试 800x600@60Hz 模式输出在 1366x768@60Hz (通过 0)CRTC 63:尝试 2560x1600@60Hz 模式输出在 1366x ...
- 开源文档管理工具Joomla的网站安装
1.配置PHP开发环境(Apache.PHP.MySQL) 2.安装Joomla网站: 1. 下载安装包 http://www.joomla.org/download.html 2. 登陆Jo ...
- Regularization on GBDT
之前一篇文章简单地讲了XGBoost的实现与普通GBDT实现的不同之处,本文尝试总结一下GBDT运用的正则化技巧. Early Stopping Early Stopping是机器学习迭代式训练模型中 ...
- Devexpress VCL Build v2015 vol 15.2 开始测试
增加了几个小玩意,与大版本变化根本无法匹配. 具体可以官网了解 https://www.devexpress.com/Subscriptions/New-2015.xml?product=vcl
- Web前端之CSS_day3-4
1.行高 1.1 初始行高 行高=文字大小+上间距+下间距 默认文字大小:16px 默认文字行高:18px 注意:行高=盒子的高度,可以让文字垂直居中显示 1.2 行高单位 a. px 行高设置多少就 ...
- VC++ 将IP字符串转为 DWORD值
CString strIP="192.168.1.184"; DWORD dwAddress= ntohl( inet_addr(strIP)); m_IPAddr.SetAddr ...
- JQuery中ajax请求写法
$.ajax({ type: "POST", url: "ygdwController.do?getonygdw", data : "id=" ...
- openjudge ROADS
726:ROADS 总时间限制: 1000ms 内存限制: 65536kB 描述 N cities named with numbers 1 ... N are connected with one- ...