C语言程序设计-俄罗斯方块源程序
其中的主要逻辑有:
(1)由于c的随机性函数不好,所以每次游戏开始根据bios时间设置种子。
(2)得分越高,方块下降速度越快(每200分为单位)。
(3)每下落一个方块加1分,每消除一行加10分,两行加30分,三行加70分,四行加150分。初试分数为100分。
游戏控制:
up-旋转;空格-下落到底;左右下方向键-控制方向。P-开始或暂停游戏。ESC-退出。
特点:
(1)由于tc不支持中文,所以基本都是英文注释。
(2)函数命名尽可能规范的表达其内部处理目的和过程。
(3)代码加上注释仅有577行。(我下载过的两个俄罗斯方块代码一个在1087行,一个在993行,我的比它们代码少)。
(4)除了消除空格时算法比较复杂,其他算法都比较简单易读。
(5)绘图效率和局部代码效率扔有待提高。
(6)FrameTime参数可能依据不同硬件环境进行具体设置,InitGame需要正确的TC路径。
俄罗斯方块源于大约9年前上大一时的一个梦,我们在学习c语言时,我的同寝室友邀请我合作一起完成俄罗斯方块(课外作业性质),但是当时限于我们的水平比较菜和学习状态比较懒散,我们没有完成。大一的时候我在机房里无意发现别人留下的俄罗斯方块程序,运行,老师发现后激动的问我是我写的吗,我惭愧的摇摇头。那时看到别人做c的大程序深感羡慕(自己只是写几十行的程序)。数年后我仍然看到有不同样式的实现,但是我一直没有实现它,知道今天忽然有这个想法去做,算是弥补多年前的遗憾和心愿吧。
---------------------------------------------
Q&A:
----------------------------------------------
Q:我编译时出现错误:fatal error C1083: Cannot open include file: 'bios.h': Nosuch file or directory,该如何解决?
A:正文中的代码,是使用Borland公司的TC2.0编译的,编译结果运行在Windows的16位虚拟机上。bi os.h是属于TC的头文件,在VC或者其他编译器中可能没有这个头文件。因此会产生这个错误。
解决办法:
(1)可以下载附件中的压缩包,是使用VC6.0进行编译的版本,编译结果是Windows程序,运行在wind ows 32系统上。两者之间的算法完全一致,区别仅仅是绘图时采用的接口不同,TC下采用BGI(进入图形模式),VC下采用的是GDI(使用DC进行绘图)。
(2)下载TC2.0进行编译。
Q:使用TC3.0进行编译时,提示未能初始化图形模式,请使用initgraph函数。
A:这是因为TC3.0的BGI文件的路径和TC2.0有所不同。TC2.0的BGI文件位于TC路径下。而TC3.0的BGI文件位于BGI文件夹中。请把initgame函数中的initgraph函数中的第三个参数设置为正确的路径。例如:initgraph(&..,&..,"C:\\TC\\BGI");
Q:编译后运行时,弹出错误对话框报告16位虚拟机遇到不可执行的指令,点击确定后退出。
A:该问题在某些环境中出现,可能是基于软件或者硬件环境造成,具体原因暂时未知。为避免该问题,请加载附件中的压缩包VC6.0版本。
-----------------------------------------------------------------
TC2.0的代码如下(VC6.0版本代码见附件):
程序代码:
/************************************
* Desc: 俄罗斯方块游戏
* By: hoodlum1980
* Email: jinfd@https://www.360docs.net/doc/3d18981817.html,
* 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->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][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 { for(j=0;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,curBlock.size); for(i=0;i { for(j=0;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*NBCellSiz e); line(NBBoardLeft, NBBoardTop+i*NBCellSize, NBBoardLeft+4*NBCellSize, NBBoardTop+ i*NBCellS ize); } /* draw score rect */ rectangle(ScoreBoardLeft,ScoreBoardTop,ScoreBoardLeft+ScoreBoardWidth,ScoreBoardTop+ScoreBoardHei ght); 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 { for(j=0;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]=curBlock.color; } } } } /* 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(); } /*学无止境*/ #include void Init(); void Down(); void GoOn(); void ksdown(); void Display(int color); void Give(); int Touch(int x,int y,int dx,int dy); int GeyKey(); void Select(); void DetectFill(); void GetScores(); void Fail(); void Help(); void Quit(); void DrawBox(int x,int y,int Color); void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch); void DrawNext(int Color); int Heng=12,Shu=20; /*横竖*/ int Position[MAX][MAX]; int middle[MAX][MAX]; int ActH,ActS; 【转载】88行代码实现俄罗斯方块游戏(含讲解) 来源:https://www.360docs.net/doc/3d18981817.html,/p/8 在正式阅读本文之前,请你记得你应该用娱乐的心态来看, 本代码所使用到的技巧,在工作了的人眼里会觉得很纠结,很蛋疼,很不可理喻,很丑, 注意,是你蛋疼,不关我的事 通常,写一个俄罗斯方块,往往动不动就几百行,甚至上千行,而这里只有88行 正所谓头脑风暴,打破常规。这里将使用很多不平常的手段来减少代码 以下是Win-TC可以成功编译并执行的代码(代码保证单行长度不超过80字符,如果你是Win7系统,那请看后文): 程序代码: #include"graphics.h" #include #include 1、新建“.h”头文件,将“头文件” 代码粘贴至其中, 2、新建“.c”源文件,将“源代码” 代码粘贴到其中。 3、新建空白工程,将头文件和源代码 添加进去,调试使用。 //头文件 //1.自定义枚举类型,定义7种形态的游戏方块 typedef enum tetris_shape { ZShape=0, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape }shape; //2.函数声明 //(1)操作方块函数 int maxX();//取得当前方块的最大x坐标 int minX();//取得当前方块的最小x坐标 void turn_left();//当前方块逆时针旋转90度 void turn_right(); int out_of_table(); void transform(); int leftable(); int rightable(); int downable(); void move_left(); void move_right(); //(2)操作游戏桌面的函数 int add_to_table(); void remove_full(); //(3)控制游戏函数 void new_game(); void run_game(); void next_shape(); int random(int seed); //(4)绘图函数 void paint(); void draw_table(); //(5)其他功能函数 void key_down(WPARAM wParam); void resize(); void initialize(); void finalize(); //(6)回调函数,用来处理Windows消息 LRESULT CALLBACK WndProc (HWND,UINT,WPARAM,LPARAM); //源代码 //1.文件包含 #include C语言课程设计报告 俄罗斯方块程序设计报告 一、问题描述 俄罗斯方块(Tetris,俄文:Тетрис)是一款电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。 在本次设计中,要求支持键盘操作和若干种不同类型方块的旋转变换,并且界面上显示下一个方块的提示以及当前的玩家的得分,随着游戏的进行,等级越高,游戏难度越大,即方块的下落速度越快,相应的等级,等级越高,为玩家提供了不同的选择。 二、功能分析 I、俄罗斯方块游戏需要解决的问题包括: ⑴、随机产生方块并自动下移 ⑵、用Esc键退出游戏 ⑶、用键变体 ⑷、用键和键左右移动方块 ⑸、用空格键使游戏暂停 ⑹、能正确判断满行并消行、计分、定级别 ⑺、设定游戏为不同级别,级别越高难度越大 II、俄罗斯方块游戏需要设计的功能函数包括: ⑴、声明俄罗斯方块的结构体 ⑵、函数原型声明 ⑶、制作游戏窗口 ⑷、制作俄罗斯方块 ⑸、判断是否可动 ⑹、随机产生俄罗斯方块类型的序号 ⑺、打印俄罗斯方块 ⑻、清除俄罗斯方块的痕迹 ⑼、判断是否满行并删除满行的俄罗斯方块 三、程序设计 1、程序总体结构设计 (1)、游戏方块预览功能。在游戏过程中,游戏界面右侧会有预览区。由于在此游戏中存在多种不同的游戏方块,所以在游戏方块预览区域中显示随机生成的游戏方块有利于游戏玩家控制游戏的策略。 (2)、游戏方块控制功能。通过各种条件的判断,实现对游戏方块的左移、右移、自由下落、旋转功能,以及行满消除行的功能。 (3)、游戏数据显示功能。在游戏玩家进行游戏过程中,需要按照一定的游戏规则给玩家计算游戏分数。例如,消除一行加100分,游戏分数达到一定数量 注意:本源代码包含 来如鹏挺长时间了,受益很多希望更多的朋学加入进来 做俄罗斯方块是因为无意中在杨老师的帖子看到说最少也要能做出俄罗斯方块这样的东西出来,我想这个意思能做出俄罗斯方块就说明水平到了一个层次了吧。 刚才注意到音乐播放器居然下载超过400次!我反醒我上传的代码很少解释 而且做的都是没有趣味的东西。 俄罗斯方块如鹏已经有好几个同学做出来了,但是我想还有很多同学做不出来,我抛砖引玉,其实俄罗斯方块并不复杂 今天先告诉大家第一步, 在屏幕上把方块显示出来 cfree 新建一个工程选窗口程序显示helloworld的 win32的 api 图形函数都要用到 HDC 这是一个保存窗口图形的数据的句柄 比如我要画一个正方形可以用 Rectangle (hdc,标X,左上角坐标y,右下角坐标x,右下角坐标y); 为了方便我们直接在 switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); // 这个下面添加代码 Rectangle (hdc,50,50,100,100); 然后编译运行 这是效果就是一个正方形没别的东西?别着急哈,慢慢来。 俄罗斯方块每块都是四部分的所以要画4个 这里面需要一小点数学知识 把这些复制到刚才的位置看一下效果 { int x,y; const int size=50;//方块大小 x=y=50;//从窗口的左上角位置开始画 //第一个方块 Rectangle (hdc,x,y,x+size,y+size); x+=size; //向右一块位置画第二个方块 Rectangle (hdc,x,y,x+size,y+size); x+=size; //向右一块位置画第三个方块 Rectangle (hdc,x,y,x+size,y+size); //最后一个方块 //相对于第三个方块左下角的位置 x-=50;y-=50; Rectangle (hdc,x,y,x+size,y+size); } 这个画好像很麻烦我们可以自定义一个函数huafangkuai 专门负责画这个正方形以后所有的其他函数也必须经过他才能画正方形 这个类似于win32 api的封装思想 void huafangkuai(int x,int y,int color); x y是方块的坐标color 就是color 函数原理是x y 是相对于游戏里的坐标而不是屏幕坐标 屏幕坐标要经过函数自己转换这样我们就可以把心关注在游戏的事情而不必分心了void huafangkuai(HDC hdc,int x,int y,int color) { const int BEGINX= 50;//游戏图形的开始位置 const int BEGINY= 50 ; const int FSIZE= 35 ; //方块大小 int screenx=BEGINX +x*FSIZE; //方块左上角的坐标是x乘方块大小再加上起始位置 int screeny=BEGINY +y*FSIZE; Rectangle (hdc,screenx,screeny,screenx+FSIZE,screeny+FSIZE); } 这样我们再画就四个就容易多了 color 先不管 int x,y; x=5;y=5; huafangkuai(hdc,x,y,0); huafangkuai(hdc,x+1,y,0); huafangkuai(hdc,x+2,y,0); 1. using System; using System.Collections.Generic; using System.Text; using System.Drawing;//add namespace俄罗斯方块 { public class Block { private short width; private short height; private short top; private short left; private int ID; //方块部件的ID public int[,] shape;//存储方块部件的形状,0为空白,1为有砖块 public Block()//构造函数 { Random randomGenerator = new Random(); int randomBlock = randomGenerator.Next(1, 6);//产生1—4的数 this.ID = randomBlock; switch (this.ID) { case 1: //横条形 this.Width = 4; this.Height = 1; this.Top = 0; this.Left = 3; shape = new int[this.Width, this.Height]; shape[0, 0] = 1; shape[1, 0] = 1; shape[2, 0] = 1; shape[3, 0] = 1; break; case 2://正方形 this.Width = 2; this.Height = 2; this.Top = 0; this.Left = 4; // Creates the new shape for this block. shape = new int[this.Width, this.Height]; shape[0, 0] = 1; shape[0, 1] = 1; shape[1, 0] = 1;shape[1, 1] = 1; break; case 3://T形 this.Width = 3; this.Height = 3; this.Top = 0; this.Left = 4; // Creates the new shape for this block. shape = new int[this.Width, this.Height]; shape[0, 0] = 1; shape[1, 0] = 1; shape[2, 0] = 1; shape[1, 1] = 1; shape[1, 2] = 1; break; case 4://L形 this.Width = 2; this.Height = 3; this.Top = 0; this.Left = 4; ````````` 学院:数计学院 班级:13级数媒班 学号: 姓名: 摘要 …………………………………………………………………………………………………….. 关键字: 目录 第一部分设计总概........................................................................................................................... 摘要………………………………………………………………………………………………… 一、设计目的............................................................................................................................. 二、设计要求............................................................................................................................. 三、设计内容............................................................................................................................. 四、系统分析与设计................................................................................................................. 第二部分数据结构设计................................................................................................................... 第三部分功能实现与程序调试………………………………………………………………….第四部分完成设计........................................................................................................................... 一、实习日记............................................................................................................................. 二、实习总结............................................................................................................................. 三、教师评语............................................................................................................................. 四、程序使用说明书…………………………………………………………………………. 第一部分设计总概 一、设计目的 二、设计要求 三、设计内容 四、系统分析与设计 //不多说,直接可以拷贝下面的东西,就可以运行。 package day04; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.applet.*; import https://www.360docs.net/doc/3d18981817.html,ng.String.*; import https://www.360docs.net/doc/3d18981817.html,ng.*; import java.io.*; public class ERSBlock extends JPanel implements ActionListener,KeyListener//应该是继承JPanel { static Button but[] = new Button[6]; static Button noStop = new Button("取消暂停"); static Label scoreLab = new Label("分数:"); static Label infoLab = new Label("提示:"); static Label speedLab = new Label("级数:"); static Label scoreTex = new Label("0"); static Label infoTex = new Label(" "); static Label speedTex = new Label("1"); static JFrame jf = new JFrame(); static MyTimer timer; static ImageIcon icon=new ImageIcon("resource/Block.jpg"); static JMenuBar mb = new JMenuBar(); static JMenu menu0 = new JMenu("游戏 "); static JMenu menu1 = new JMenu("帮助 "); static JMenuItem mi0 = new JMenuItem("新游戏"); static JMenuItem mi1 = new JMenuItem("退出"); static JMenuItem mi1_0 = new JMenuItem("关于"); static JDialog dlg_1; static JTextArea dlg_1_text = new JTextArea(); static int startSign= 0;//游戏开始标志 0 未开始 1 开始 2 暂停 static String butLab[] = {"开始游戏","重新开始","降低级数","提高级数","游戏暂停","退出游戏"}; static int game_body[][] = new int[19][10]; static int game_sign_x[] = new int[4];//用于记录4个方格的水平位置 static int game_sign_y[] = new int[4];//用于记录4个方格的垂直位置 不多说,,直接可以拷贝下面的东西,然后记得把那个BLOCK的名字改成你自己的类名,这个很关键哦,不然是错的可别怪我,呵呵~~ import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.applet.*; import https://www.360docs.net/doc/3d18981817.html,ng.String.*; import https://www.360docs.net/doc/3d18981817.html,ng.*; import java.io.*; public class Block extends JPanel implements ActionListener,KeyListener//应该是继承JPanel { static Button but[] = new Button[6]; static Button noStop = new Button("取消暂停"); static Label scoreLab = new Label("分数:"); static Label infoLab = new Label("提示:"); static Label speedLab = new Label("级数:"); static Label scoreTex = new Label("0"); static Label infoTex = new Label(" "); static Label speedTex = new Label("1"); static JFrame jf = new JFrame(); static MyTimer timer; static ImageIcon icon=new ImageIcon("resource/Block.jpg"); static JMenuBar mb = new JMenuBar(); static JMenu menu0 = new JMenu("游戏 "); static JMenu menu1 = new JMenu("帮助 "); static JMenuItem mi0 = new JMenuItem("新游戏"); static JMenuItem mi1 = new JMenuItem("退出"); static JMenuItem mi1_0 = new JMenuItem("关于"); static JDialog dlg_1; static JTextArea dlg_1_text = new JTextArea(); static int startSign = 0;//游戏开始标志 0 未开始 1 开始 2 暂停 static String butLab[] = {"开始游戏","重新开始","降低级数","提高级数","游戏暂停","退出游戏"}; static int game_body[][] = new int[19][10]; static int game_sign_x[] = new int[4];//用于记录4个方格的水平位置 static int game_sign_y[] = new int[4];//用于记录4个方格的垂直位置 static boolean downSign = false;//是否落下 static int blockNumber = 1;//砖块的编号 static int gameScore = 0;//游戏分数 static int speedMark = 1; //包含头文件 #include 口口口口口口口口 口口口口口口口口 */ {0x0660, 0x0660, 0x0660, 0x0660, BLUE}, /* 口 口口口口口口口 口口口口口口口 口*/ {0x4460, 0x02E0, 0x0622, 0x0740, MAGENTA}, /* 口 口口口口口口口 口口口口口口口 口*/ {0x2260, 0x0E20, 0x0644, 0x0470, YELLOW}, /* 口口 口口口口口口口口 口口口口口口 */ {0x0C60, 0x2640, 0x0C60, 0x2640, CYAN}, /* 口口 口口口口口口口口 口口口口口口 */ {0x0360, 0x4620, 0x0360, 0x4620, GREEN}, /* 口口口 口口口口口口口口口口 口口口 */ {0x4E00, 0x4C40, 0x0E40, 0x4640, BROWN}}; /* //定义俄罗斯方块的信息的结构体 struct blockinfo { int id; //7中方块中的哪一种 byte dir:2; //1种方块中四个方向中的哪个 char x,y; //方块的坐标(不是屏幕中的而是自己设置的游戏区域中的)} curblock,nextblock; */ // 定义游戏区 //unsigned char area[width][high] = {0}; //函数声明 其中的主要逻辑有: (1)由于c的随机性函数不好,所以每次游戏开始根据bios时间设置种子。 (2)得分越高,方块下降速度越快(每200分为单位)。 (3)每下落一个方块加1分,每消除一行加10分,两行加30分,三行加70分,四行加150分。初试分数为100分。 游戏控制: up-旋转;空格-下落到底;左右下方向键-控制方向。P-开始或暂停游戏。ESC-退出。 特点: (1)由于tc不支持中文,所以基本都是英文注释。 (2)函数命名尽可能规范的表达其内部处理目的和过程。 (3)代码加上注释仅有577行。(我下载过的两个俄罗斯方块代码一个在1087行,一个在993行,我的比它们代码少)。 (4)除了消除空格时算法比较复杂,其他算法都比较简单易读。 (5)绘图效率和局部代码效率扔有待提高。 (6)FrameTime参数可能依据不同硬件环境进行具体设置,InitGame需要正确的TC路径。 俄罗斯方块源于大约9年前上大一时的一个梦,我们在学习c语言时,我的同寝室友邀请我合作一起完成俄罗斯方块(课外作业性质),但是当时限于我们的水平比较菜和学习状态比较懒散,我们没有完成。大一的时候我在机房里无意发现别人留下的俄罗斯方块程序,运行,老师发现后激动的问我是我写的吗,我惭愧的摇摇头。那时看到别人做c的大程序深感羡慕(自己只是写几十行的程序)。数年后我仍然看到有不同样式的实现,但是我一直没有实现它,知道今天忽然有这个想法去做,算是弥补多年前的遗憾和心愿吧。 --------------------------------------------- Q&A: ---------------------------------------------- Q:我编译时出现错误:fatal error C1083: Cannot open include file: 'bios.h': Nosuch file or directory,该如何解决? A:正文中的代码,是使用Borland公司的TC2.0编译的,编译结果运行在Windows的16位虚拟机上。bi os.h是属于TC的头文件,在VC或者其他编译器中可能没有这个头文件。因此会产生这个错误。 解决办法: (1)可以下载附件中的压缩包,是使用VC6.0进行编译的版本,编译结果是Windows程序,运行在wind ows 32系统上。两者之间的算法完全一致,区别仅仅是绘图时采用的接口不同,TC下采用BGI(进入图形模式),VC下采用的是GDI(使用DC进行绘图)。 (2)下载TC2.0进行编译。 Q:使用TC3.0进行编译时,提示未能初始化图形模式,请使用initgraph函数。 A:这是因为TC3.0的BGI文件的路径和TC2.0有所不同。TC2.0的BGI文件位于TC路径下。而TC3.0的BGI文件位于BGI文件夹中。请把initgame函数中的initgraph函数中的第三个参数设置为正确的路径。例如:initgraph(&..,&..,"C:\\TC\\BGI"); Q:编译后运行时,弹出错误对话框报告16位虚拟机遇到不可执行的指令,点击确定后退出。 A:该问题在某些环境中出现,可能是基于软件或者硬件环境造成,具体原因暂时未知。为避免该问题,请加载附件中的压缩包VC6.0版本。 #include bool bAuto; //是否自动求解的标志 bool Pause; //是否暂停的标志 int Map[ROW][COL]; //俄罗斯方块的地图(被占据的方格为1,否则为0) int CurrentBox[4][4]; //当前落下的方块 int CurrentY, CurrentX; //当前落下方块的当前位置(指左上角位置) int NextBox[4][4]; //下一个将落下的方块 int Box[MAX_CLASS][4][4] = //7种方块形状 { { {0,0,0,0}, {1,1,1,1}, {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}, {1,1,0,0}, {0,1,1,0}, {0,0,0,0} }, { {0,0,0,0}, {0,1,1,0}, {1,1,0,0}, {0,0,0,0} }, { {0,1,1,0}, {0,0,1,0}, {0,0,1,0}, {0,0,0,0} }, { {0,1,1,0}, {0,1,0,0}, {0,1,0,0}, {0,0,0,0} /*学无止境*/ #include <> #include <> #include <> #define ESC 27 #define UP 328 #define DOWN 336 #define LEFT 331 #define RIGHT 333 #define BLANK 32 #define BOTTOM 2 #define CANNOT 1 #define CAN 0 #define MAX 30 #define F1 315 #define ADD 43 #define EQUAL 61 #define DEC 45 #define SOUNDs 115 #define SOUNDS 83 #define PAUSEP 80 #define PAUSEp 112 void Init(); void Down(); void GoOn(); void ksdown(); void Display(int color); void Give(); int Touch(int x,int y,int dx,int dy); int GeyKey(); void Select(); void DetectFill(); void GetScores(); void Fail(); void Help(); void Quit(); void DrawBox(int x,int y,int Color); void OutTextXY(int x,int y,char *String); void DispScore(int x,int y,char Ch); void DrawNext(int Color); int Heng=12,Shu=20; /*横竖*/ int Position[MAX][MAX]; int middle[MAX][MAX]; int ActH,ActS; #include **** 届毕业设计Java小游戏俄罗斯方块 ┊┊┊┊┊┊┊┊┊┊┊┊┊装┊┊┊┊┊订┊┊┊┊┊线┊┊┊┊┊┊┊┊┊┊┊┊┊ 摘要 在现今电子信息高速发展的时代,电子游戏已经深入人们的日常生活,成为老少皆宜的娱乐方式。但是游戏设计结合了日新月异的技术,在一个产品中整合了复杂的设计、艺术、声音和软件,所以并不是人人皆知。直到今天,在中国从事游戏设计的人仍然很少,但是游戏行业的发展之快,远超如家电、汽车等传统行业,也正因为如此,游戏人才的教育、培养远落后于产业的发展。 俄罗斯方块是个老幼皆宜的小游戏,它实现由四块正方形的色块组成,然后存储在一个数组的四个元素中,计算机随机产生不同七种类型的方块,根据计算机时钟控制它在一定的时间不停的产生,用户根据键盘的四个方向键控制翻转、向左、向右和向下操作,(控制键的实现是由键盘的方向键的事件处理实现)。然后程序根据这七种方块堆叠成各种不同的模型。 论文描述了游戏的历史,开发此游戏的环境,游戏开发的意义。遵循软件工程的知识,从软件问题定义开始,接着进行可行性研究、需求分析、概要设计、详细设计,最后对软件进行了测试,整个开发过程贯穿软件工程的知识体系。 此次设计在Microsoft Windows 7系统下,以Java为开发语言,在eclipse开发平台上进行游戏的设计与实践。从游戏的基本玩法出发,主要就是俄罗斯方块的形状和旋转,我在设计中在一个图片框中构造了一些的网状小块,由这些小块组合成新的形状,每四个小块连接在一起就可以构造出一种造型,因此我总共设计了7中造型,每种造型又可以通过旋转而变化出2到4种形状,利用随机函数在一个欲览窗体中提前展示形状供用户参考,在游戏窗体中用户就可以使用键盘的方向键来控制方块的运动,然后利用递归语句对每一行进行判断,如果有某行的方块是满的,则消除这行的方块,并且使上面的方块自由下落,最后就可以得出用户的分数。 关键词:游戏设计,算法,数组,事件C语言俄罗斯方块游戏源代码
俄罗斯方块C语言代码
C++俄罗斯方块代码(北邮版)
C语言课程设计俄罗斯方块源代码
俄罗斯方块C语言程序设计报告
C.C++语言-俄罗斯方块源码
教你用c语言写俄罗斯方块
俄罗斯方块源代码
C语言编写俄罗斯方块实验报告
俄罗斯方块完整源代码
JAVA俄罗斯方块源代码
俄罗斯方块程序代码
C语言程序设计-俄罗斯方块源程序
VC++ 6.0 MFC 俄罗斯方块 自动求解 代码 源程序
C语言俄罗斯方块游戏源代码
C语言俄罗斯方块(详解..)
Java小游戏俄罗斯方块附完整源代码_毕业设计