俄罗斯方块游戏--MFC

合集下载

俄罗斯方块游戏机说明书

俄罗斯方块游戏机说明书

俄罗斯方块游戏机说明书
1.游戏介绍
俄罗斯方块是一款风靡全球的游戏,它曾经造成的轰动可以说是游戏史上的一件大事。

究其历史,俄罗斯方块最早还是出现在PC机上,而我国的用户都是通过红白机了解、喜欢上它的。

对一般用户来说,它的规则简单,容易上手,且游戏过程变化无穷,而随着游戏的发展,现在已经有
了液晶屏的俄罗斯方块游戏机,画面也更加酷炫,操作更加的真实多样,用户可进行更加酣畅淋漓的游戏体验。

其模式还增加了积分制,使用户既
能感受到游戏中的乐趣,也给用户提供了一个展现自己高超技艺的场所。

通过高分记录,来展现自己的技术水平。

2.游戏规则
本次设计制作的俄罗斯方块游戏机,编写的程序在液晶屏的显示是不同的方块依次下落,可以在其下落的过程中控制它的变换,移动和开始暂停。

赢:把每行填满消除,填满一行消除一行并计算其得分情况
败:当方框内被堆满,而且无法消除时,将显示失败并显示总分
3.游戏操作
此游戏机通电后,其界面显示如下:
板子上有五个按键,依次时:开始/暂停、上下左右控制按键,可通过左右键选择需要的关卡。

按开始按键即可进入游戏界面,如下图:
可通过左右移动下落的方块,来控制方块下落的位置,消除得分。

如果来不及摆放可按暂停按键来停止下落。

当方块充满顶部且无法消除时,则显示你失败啦,需要重新来选择关卡继续游戏。

如下图:。

俄罗斯方块游戏系统设计(含完整程序)

俄罗斯方块游戏系统设计(含完整程序)

毕业设计(论文)正文题目俄罗斯方块游戏专业班级姓名学号指导教师职称俄罗斯方块游戏摘要: 在现代信息高速发展的时代,电子游戏已经深入了人们的日常生活,成为了老少咸宜的娱乐方式,但是游戏设计结合了日新月异的技术,在一个产品中整合了复杂的艺术,设计,声音和软件,所以并不是人人皆知,直到今天,在中国从事游戏设计的人仍然很少,但是游戏行业的发展之快,远超如汽车,家电等传统行业,也正因为如此,游戏人才的教育培养远落后于行业的发展。

俄罗斯方块是一个老少咸宜的小游戏,它实现有四个正方形的色块组成,然后存储于一个数组的四个元素中,计算机随机产生七种不同类型的方块,根据计算机时钟控制它在一定的时间不停的产生,用户根据键盘的四个方向键进行向左,向右,向下,翻转操作。

然后程序根据这七种方块折叠成各种不同的类型。

论文描述了游戏开发的背景,意义,算法分析,功能实现,功能测试。

以C++为开发语言进行设计与实现。

关键词:电子游戏,算法,C++,测试The Russian square pieceAbstract :In the era of high-speed development of electronic of information, computer game has enter people’s daily life, become an amusement adapt to old and young. But game design is a combination of fast-moving technology ,the complexity of integrating design,art,audio and software into a single production,so this thechnology isn’t known by everyone .up-to-date,there are few people work at game design all the same,whereas,thedevelopment of game industry more faster than traditional industry as home ap pliances and automobile,by the reason of this situation,the education and training of person with ablity of game design drop behind the development of game industry.The Russian square piece is a get-away drama with all proper old young ,it carry out to be constitute by four pieces of colours of exact square piece ,then save in one four chemical elements of the piece set ,random creation dissimilarity of calculator seven the square piece of the category type ,control it according to the calculator clock in certain time continuously creation , the customer is inside out according to four directions key control of the keyboard ,toleft ,rightwards and get down ,(the realization of the control key is to be carry out by the event handing of the direction key of the keyboard) Then the procedure pileds according to these seven kinds of square pieces various different model.The thesis has described the game history ,has developed this game history ,has developed this game environment, development significance of game .Knowledge abiding by a software engineering ,definition begins from software problem ,proceed to carry out feasibility study ,need analysis ,essentials design,the at last has carried out a testing on the software engineering knowledge hierarchy .The computer games design and practice are designed o eclipse developing platform with C++ developing instrument ,under Microsoft Windows XP system this time.Key Words: electronic game calculate way C++ test目录1引言 (1)1.1课题背景 (1)1.2毕设意义 (2)2需求与算法分析 (3)2.1需求分析 (3)2.1.1 游戏需求 (3)2.1.2游戏界面需求 (4)2.1.3 游戏形状(方块)需求 (4)2.2算法分析 (5)2.2.1定义方块的数据结构 (5)2.2.2俄罗斯方块流程 (5)3系统功能实现 (7)3.1产生主窗口 (7)3.2定义俄罗斯方块数据结构 (8)3.3游戏的主逻辑 (9)3.4销行功能实现 (11)3.5中断操作流程的实现 (13)3.6变形的实现 (15)3.7 游戏区域绘图的实现 (16)3.8 游戏方块绘制 (20)3.9 烟花燃放功能 (22)4功能测试 (24)4.1测试环境 (24)4.2图像功能测试 (24)4.3销行和计分功能测试 (27)4.4速度功能测试 (28)5总结 (29)[参考文献] (30)致谢 (31)俄罗斯方块的程序设计1引言计算机游戏产业在随着网络的发展有了长足的发展。

C++俄罗斯方块代码

C++俄罗斯方块代码

#include <>#include <>#include <>#include <>#include <ctime>#include "" //老师的文件void begin(); //开始游戏void frame(); //边框设定int * getblocks(); //方块产生void move(int line); //移动void drawblocks(int line); //方块显示void clearsquare(int line); //方块擦出void turn(int line); //方块旋转bool isavailable(int line); //判断是否能下落void remember(int line); //记忆方块位置void deleteline(int line); //方块满一行消除bool ifgameover(); //判断是否游戏结束void end(); //游戏结束#define up 72#define down 80#define left 75#define right 77#define esc 27HANDLE handle;int a1[4][4]={{1},{1,1,1}}; //七种方块的二维数组int a2[4][4]={{0,1},{1,1,1}};int a3[4][4]={{1,1},{0,1,1}};int a4[4][4]={{0,0,1},{1,1,1}};int a5[4][4]={{0,1,1},{1,1}};int a6[4][4]={{1,1,1,1}};int a7[4][4]={{1,1},{1,1}};int row=0; //列数int score=0;int level=0;int * block1=NULL;int * block2=NULL;int * block3=NULL;int coordinate[12][18]={0}; //坐标数组,边框12*18(最后一行,两边边框计算在内)int judge=0;int scorex=0;int temp[4][4]={0};void main() //主函数{int t=1;handle = initiate();while(t){t=0;begin();sndPlaySound("",SND_LOOP|SND_ASYNC);frame();WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;for(int k=1;k<=999999;k++){if(ifgameover()) //判断是否结束{textout(handle,34,10,wColors,1,"Game Over");Sleep(800);end();}else{if(k==1)block2=getblocks();block3=block2; //block2指向将出现的方块地址block2=getblocks(); //获取下一个新的方块block1=block3;row=52;clearsquare(16); //擦除next的方块block1=block2;drawblocks(15); //在next显示下一块方块图形row=34;block1=block3;for(int i=4;i<=7;i++) //所构建的方块图形最多只有占有两排,所以只用4-7即可对应{if(*(block1+i))textout(handle,26+i*2,4,wColors,1,"■"); //方块先露出下面部分}Sleep(500-50*level);for(int line=4;line<=22;line++) //方块自主下落,方块从第四排开始出现{if(isavailable(line)) //检验刚产生的方块是否碰壁,碰到已落方块{clearsquare(line); //消除方块先露初的下面分drawblocks(line); //产生完整的下落方块move(line);}else{remember(line); //落定后将这些位置对应的all数组中元素置1deleteline(line); //消行以及加分if(line==4)judge=1;break;}}}}}}void begin(){int i=1;WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_INTENSITY;WORD wColors1[2];wColors1[0]=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY;wColors1[1]=FOREGROUND_RED|FOREGROUND_INTENSITY;textout(handle,18,4,wColors,1," ◢◣◢◣");textout(handle,18,5,wColors,1," ◢◎◣◢◎◣");textout(handle,18,6,wColors,1,"◢█████████◣");textout(handle,18,7,wColors,1,"██◤^^◥██");textout(handle,18,8,wColors,1,"████");textout(handle,18,9,wColors,1,"◢████◣");textout(handle,18,10,wColors,1,"██◤●●◥██");textout(handle,18,11,wColors,1,"██◎◎██");textout(handle,18,12,wColors,1,"◥█◣T◢█◤");textout(handle,18,13,wColors,1,"██◣◢██");textout(handle,18,14,wColors,1,"◥███████◤");textout(handle,18,15,wColors,1," ");textout(handle,18,16,wColors,1,"简单◥███████◤中等"); textout(handle,18,17,wColors,1,"请按1█请按2"); textout(handle,18,18,wColors,1,"█");textout(handle,18,19,wColors,1,"◢██◣");textout(handle,18,20,wColors,1," 困难请按3");textout(handle,54,22,wColors,1,"MADE BY ");while(i){textout(handle,30,8,wColors1,2,"俄罗斯方块");Sleep(800);textout(handle,30,8,wColors1,2," ");Sleep(800);if (_kbhit()) //输入等级{switch(_getch()){case '1':{level=1;i=0; //跳出循环break;}case '2':{level=4;i=0;break;}case '3':{level=7;i=0;break;}}}}system("cls"); //清屏}void frame() //边框的设定{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_INTENSITY;WORD wColors1[1];wColors1[0]=FOREGROUND_RED|FOREGROUND_INTENSITY;for(int i=0;i<=11;i++)coordinate[i][17]=1; //底排边框定义为1for(int j=0;j<=17;j++){coordinate[0][j]=1; //两边边框定义为1coordinate[11][j]=1;}char string[5];textout(handle,59,5,wColors,1,itoa(level,string,10)); textout(handle,52,5,wColors,1,"level: ");textout(handle,52,9,wColors,1,"score: 0");textout(handle,52,13,wColors,1,"next:");textout(handle,10,6,wColors1,1,"暂停SPACE"); textout(handle,10,7,wColors1,1,"退出ESC"); textout(handle,10,8,wColors1,1,"翻转↑"); textout(handle,10,9,wColors1,1,"向右→"); textout(handle,10,10,wColors1,1,"向左←"); textout(handle,10,11,wColors1,1,"加速↓"); textout(handle,33,2,wColors,1,"来~战个痛");for(int m=13;m<=24;m++){textout(handle,2*m,3,wColors,1,"═"); //上边框}for(int n=4;n<=21;n++){textout(handle,26,n,wColors,1,"‖"); //左边框}for(int k=4;k<=21;k++){textout(handle,48,k,wColors,1,"‖"); //右边框}for(int l=13;l<=23;l++){textout(handle,2*l,21,wColors,1,"═"); //下边框}textout(handle,26,3,wColors,1,"◤");textout(handle,48,3,wColors,1,"◥");textout(handle,26,21,wColors,1,"◣");textout(handle,48,21,wColors,1,"◢");}int * getblocks() //随机方块生成{int * m=NULL;srand(time(NULL));int n=rand()%7;switch(n){case 0:m=&a1[0][0];break;case 1:m=&a2[0][0];break;case 2:m=&a3[0][0];break;case 3:m=&a4[0][0];break;case 4:m=&a5[0][0];break;case 5:m=&a6[0][0];break;case 6:m=&a7[0][0];break;}return m;}void drawblocks(int line) //出现方块{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;for(int j=0;j<=15;j++){int temp;temp=j/4;if(*(block1+j))textout(handle,row+j*2-temp*8,line+temp,wColors,1,"■");}}void clearsquare(int line) //方块消失{WORD wColors[1];wColors[0]=FOREGROUND_BLUE|FOREGROUND_INTENSITY;if(line==4) //针对消除刚产生的下排{textout(handle,34,4,wColors,1," ");textout(handle,36,4,wColors,1," ");textout(handle,38,4,wColors,1," ");textout(handle,40,4,wColors,1," ");}else{for(int m=0;m<=15;m++){int temp;temp=m/4; //得0-3对应方块数组1-4行if(*(block1+m))textout(handle,row+m*2-temp*8,line-1+temp,wColors,1," ");}}}void move(int line) //方块的左右移动,加速下落,翻转等{int mid=0,speed=100-10*level;while(mid<speed){if (_kbhit()){switch(_getch()){case 72: //翻转{turn(line);}case 75: //左移{row=row-2; //纵坐标减2if(isavailable(line)) //判断是否能移动{row=row+2;clearsquare(line+1); //消除原来图案,line+1是避免line=4程序出错row=row-2;drawblocks(line); //出现新图案}elserow=row+2; //若不能移动则纵坐标不变break;}case 77: //右移{row=row+2;if(isavailable(line)){row=row-2;clearsquare(line+1);row=row+2;drawblocks(line);}row=row-2;break;}case 80: //加速下落,即直接跳除循环{mid=speed;break;}case 27: //终止游戏{end();break;}case 32: //暂停{int flag=1;while(flag){if (_kbhit()){if(_getch()==32)flag=0;break;}elseSleep(10);}default:break;}}Sleep(8); //使方块延迟mid++;}}void turn(int line){clearsquare(line+1); //消除原来的图案int b[4][4]={0}; //保存旋转前的方块int num=0,l=0;for(int m=0;m<=3;m++){for(int n=0;n<=3;n++){b[m][n]=*(block1+m*4+n); //把b[4][4]全赋值为当前图形数组temp[m][n]=0;}}for(int i=3;i>=0;i--) //按行从下向上扫描{for(int j=0;j<4;j++) //按列从左向右扫描{if(b[i][j]) //如果为有效点,则进行90度旋转{temp[j][l]=b[i][j];num=1;}}if(num){l++;num=0;}}block1=&temp[0][0];if(isavailable(line))drawblocks(line);else{for(int p=0;p<=3;p++){for(int q=0;q<=3;q++)temp[p][q]=b[p][q];}block1=&temp[0][0];drawblocks(line);}}bool isavailable(int line) //检验,即看方块即将存在位置是否已经有1 {int x,y;for(int m=0;m<=15;m++){int temp;temp=m/4;x=row/2-13-4*temp+m; //边框左边已有13个位置y=line-4+temp; //上面已有4个位置if(*(block1+m)&&coordinate[x][y]) //相与为1则返回0,否则跳出并循环继续return 0;}}void remember(int line) //记忆{int x,y;for(int m=0;m<=15;m++){int temp;temp=m/4;x=row/2-13-temp*4+m;y=line-4+temp;if(*(block1+m)) //如果当前位置为1,则返回原位置,并设置为1coordinate[x][y-1]=1;}}void deleteline(int l) //消行{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY;int snum=0,b=0;for(int m=0;m<=16;m++) //从上向下消去方块{if(coordinate[1][m]==1&&coordinate[2][m]==1&&coordinate[3][m]==1&&coordinate[4][m]==1& &coordinate[5][m]==1&&coordinate[6][m]==1&&coordinate[7][m]==1&&coordinate[8][m]==1& &coordinate[9][m]==1&&coordinate[10][m]==1){textout(handle,28,m+4,wColors,1,"﹌﹌﹌﹌good﹌﹌﹌﹌");Sleep(750);for(int n=1;n<=m;n++){for(int j=1;j<=10;j++)coordinate[j][m-n+1]=coordinate[j][m-n];}snum++;}}for(int n=1;n<=10;n++){for(int d=0;d<=16;d++){int x,y;x=n*2+26;y=d+4;textout(handle,x,y,wColors,1," ");if(coordinate[n][d]){textout(handle,x,y,wColors,1,"■");}}}score=score+(snum*(snum+1)/2);if((score-scorex)>=30) //每得到30分自动加速{level++;scorex=score;}char string[5];textout(handle,59,9,wColors,1,itoa(score,string,10));textout(handle,59,5,wColors,1,itoa(level,string,10));}bool ifgameover() //终止游戏{if(judge==1){return 1;}elsereturn 0;}void end() //退出{WORD wColors[1];wColors[0]=FOREGROUND_GREEN|FOREGROUND_INTENSITY;textout(handle,28,22,wColors,1,"Press any key to exit");while(1){if (_kbhit()){exit(EXIT_SUCCESS);}}}。

俄罗斯方块规则说明

俄罗斯方块规则说明

俄罗斯方块规则说明
一、基本规则
1、游戏空间
玩家在一个10x20范围的空间内,进行游戏
2、游戏包含多种图形
正方形
Z型(左向,右向)
T型
L型(左向,右向)
长条
3、下落规则
每次系统随机从屏幕上方正中下落一个图形
系统会提示下一个图形
4、玩家操作
玩家使用键盘控制当前下落图形
(1)玩家可以控制图形的移动(左移或右移)
(2)玩家可以控制下落加速
(3)玩家可以旋转图形(90度旋转)
(4)当图形下落至游戏空间底部或接触其他触底图形时,下落停止,玩家无法继续操控此图形
5、消除规则
当玩家控制的下落图形填满横向一行所有空格时,本行自动消除
6、计分规则
每当玩家消除一行时,玩家得100分
一次消除的行数越多可以得到更多的分数
一次消除2行得分
一次消除3行得分
一次消除4行得分
在屏幕左上角第一行显示玩家目前游戏的得分
在屏幕左上角第二行显示玩家已经消除的行数
在屏幕左上角第三行显示玩家当前的游戏速度
在屏幕右上角第一行显示玩家的最高得分
在屏幕右侧,显示玩家每种图形使用的次数
7、结束规则
当正中图形无法下落时,游戏结束
出现GAMEOVER的字样
玩家按键,重新回到开始菜单
8、胜利规则
当消除行数达到30行,本关过关
播放奖励舞蹈画面,根据玩家本关的表现,跳舞人数会产生变化在屏幕左侧出现游戏分数计算
过关之后,图形下落速度自动加速1级。

C++MFC课程设计-俄罗斯方块

C++MFC课程设计-俄罗斯方块
OnDraw(&cDC);
OnStart();
}
//如果还有下降的空间
if (fy == 0) {//如果是刚刚新产生的图形
int lastfy = fy;
Point pt;
while (!Wall::Stop(wall, tile.curTile, fx, ++lastfy)) {} //一直到发生停止命令以后
//判定是否过关
if (Wall::Skip(wall, Speed)) {
KillTimer(Timer);
Speed = 400 / ((400 / Speed) + 1);
play = 0; //逻辑上结束了游戏
MessageBox("恭喜,过关了");
CClientDC cDC(this);
--lastfy;
pt = Point(LU.x+30*fx, LU.y+30*lastfy);
Graph::ShowShadow(&cDC, tile.curTile, pt);
}
Point pt; //清洗掉上次的图形
pt = Point(LU.x+30*fx, LU.y+30*lastfy);
COLORREF Statu_Col[10][19]; //如果被覆盖用来保留颜色,默认为0
};
主导作用的OnTimer函数:
void CMyTaskView::OnTimer(UINT nIDEvent)
{
// TODO: Add your message handler code here and/or call default
static void Completed(CDC *pDC, Wall &wall);

c++俄罗斯方块报告

c++俄罗斯方块报告
void CMyDlgDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
2.设置难度级别,不同级别速度不同
3.方向键实现下落图形的左移、右移、加速下落、变形等基本操作
编写时间处理程序
4.正确判断游戏结束
5.对游戏成绩进行记分
6.设置成绩排行榜
概要设计
(1)CMyDlgDlg //主界面
1void CMyDlgDlg::OnAbout() //关于
2void CMyDlgDlg::OnBnClickedExit() //离开按钮命令响应
CBitmap bmpBackground;
bmpBackground.LoadBitmap(IDB_GV);
BITMAP bitmap;
bmpBackground.GetBitmap(&bitmap);
CBitmap *pbmpOld=dcMem.SelectObject(&bmpBackground);
重写函数PreTranslateMessage(MSG* pMsg);
为各个菜单项添加响应的事件响应处理函数
为对话框添加四个控件按钮,并分别添加事件处理函数
声明一个bool型的变量,用于判断是否暂停游戏
接着添加几个对话框,分别是游戏设置对话框,游戏结束对话框和英雄榜对话框
第一个对话框,游戏设计对话框,Caption为“游戏设置”,ID为“IDD_NAME”,为对话框添加相应的控件

俄罗斯方块-C语言-完整代码

俄罗斯方块-C语言-完整代码
//游戏池 void printPoolBorder() {
int y; SetConsoleTextAttribute(Output,0xf0);
for(y=4;y<26;y++) {
//两条纵线 gotoxyWithFullwidth(10,y-3);//鼠标定位
gotoxyWithFullwidth(10,y-3);//鼠标定位 printf("%2s"," "); gotoxyWithFullwidth(23,y-3);//鼠标定位 printf("%2s"," "); }
bool dead;//挂 }Manager;//结构体别名
//构造存储游戏控制相关数据的结构体 typedef struct TetrisControl {
bool pause;//暂停 bool clockwise;//旋转方向;顺时针方向为ture int direction;//移动方向:0向左移动 1向右移动 //游戏池内每格的颜色 //此版本是彩色的,仅用游戏池数据无法存储颜色 int color[28][16]; }Control;//Control是结构体别名
//初始状态的游戏池 //每个元素表示游戏池的一行 //两端各置两个1,底部两行全部为1,便于进行碰撞 //这样一来游戏池的宽度为12列 共16列 //当某个元素为OXFFFF时,说明该行已经填满 //顶部4行用于给方块,不显示 //底部2行不显示,显示出来的游戏池高度为22行 static const unsigned int gs_uInitialTetrisPool[28]= {
效果图如下
俄罗斯方块-C语言-完整代码
#ifndef _DAY7_H #define _DAY7_H #include<windows.h> #include<time.h> #include<stdbool.h> #include<conio.h>//控制台输入输出函数getch通过键盘进行的操作 //游戏区域位置设计 #define COL_BEGIN 2 #define COL_END 14 #define ROW_BEGIN 4 #define ROW_END 26

俄罗斯方块规则简述

俄罗斯方块规则简述

俄罗斯⽅块规则简述〈俄罗斯⽅块规则简述〉游戏元素: [元素] ⽅块[规格] 5×5像素 [颜⾊] ⿊⾊[状态] 透明,不透明 [核⼼规则]元素: Fangkuai_bitmap(⽅块美术图⽂件名) 规格: 5×5像素⿊⾊变量: alpa (alpa=1为透明,alpa=0为不透明)场景构成:[形状] 长⽅形,长>宽[规格] 由M ×N 个元素⽅块构成,M 表⽰长,N 表⽰宽,⼀个⽅块⼤⼩为⼀个计量单位⽐如:18×12 表⽰长度为18个⽅块⼤⼩,宽度为12个⽅块⼤⼩。

[颜⾊] 透明[状态] 所有⽅块alpa=1 [核⼼规则]构成元素: M ×N 个Fangkuai_bitmap⽅块识别:引⼊数组ALL[X,Y]来对每⼀个⽅块在场景中的位置做唯⼀的标记,X 的数值对应M 的数值,Y 的数值对应N 的数值。

例如:18×12⼤⼩的场景,由18×12个⽅块组成,那么⽤ALL[X ,Y]来标记⽅块变量赋值: alpa=1(默认初始状态)积⽊⽣成:[元素] ⽅块[规格] 由4个⽅块按照⼀定规则组合⽽成,如图:共计19件[颜⾊]⿊⾊ [状态]不透明[核⼼规则]积⽊是通过场景中以下坐标标记的⽅块的alpa 值来⽣成的: [1,Y\2-1] [1,Y\2] [1,Y\2+1] [2,Y\2-1] [2,Y\2] [2,Y\2+1] [3,Y\2-1] [3,Y\2] [3,Y\2+1]⽣成积⽊的时候,更改相应的⽅块变量值,其变量alpa=0 以下坐标标记的⽅块为需要更改alpa 值的⽅块: (参考场景构成的[⽅块识别] )积⽊代号:A_1积⽊代号:A_2积⽊代号:B_1积⽊代号:B_2碰撞检测规则:[碰撞规则](在⽅块下落之前,我们要先进⾏碰撞检测。

⼀判定是否满⾜下落的条件。

)当构成积⽊的⽅块有⼀个⽅块最先与场景中其他积⽊⽅块有垂直⽅向接触时,或者与场景底部有接触时,为成功碰撞,积⽊代号:C_1积⽊代号:C_2积⽊代号:C _3积⽊代号:C_4积⽊代号:D_1积⽊代号:D_2积⽊代号:D_3积⽊代号:D_4积⽊代号:E_1 积⽊代号:F_1积⽊代号:F_2积⽊代号:G_1积⽊代号:G_2积⽊代号:G_3积⽊代号:G_4否则为碰撞检测失败。

俄罗斯方块

俄罗斯方块

俄罗斯方块说明E-Mail:leyafo@起源:俄罗斯方块(Tetris, 俄文:Тетрис)是一款风靡全球的电视游戏机和掌上游戏机游戏,它由俄罗斯人阿列克谢·帕基特诺夫发明,故得此名。

俄罗斯方块的基本规则是移动、旋转和摆放游戏自动输出的各种方块,使之排列成完整的一行或多行并且消除得分。

由于俄罗斯方块具有的数学性、动态性与知名度,也经常拿来作为游戏程序设计的练习题材。

俄罗斯方块的基本规则:1、一个用于摆放小型正方形的平面虚拟场地,其标准大小:行宽为10,列高为20,以每个小正方形为单位;2、方块共有7种,分别以S、Z、L、J、I、O、T这7个字母的形状来命名;3、通过设计者预先设置的随机发生器不断地输出单个方块到场地顶部,以一定的规则进行移动、旋转、下落和摆放,锁定并填充到场地中。

每次摆放如果将场地的一行或多行完全填满,则组成这些行的所有小正方形将被消除,并且以此来换取一定的积分或者其他形式的奖励。

而未被消除的方块会一直累积,并对后来的方块摆放造成各种影响。

4、如果未被消除的方块堆放的高度超过场地所规定的最大高度(并不一定是20或者玩家所能见到的高度),则游戏结束。

以上文字来源于百度百科.一.设计方案当前的下落方块下一次要出的方块,此区域对应一个4*4的数组. 被画红的区域坐标点映射为1显示分数,和当前游戏速度的区域游戏区域,下落方块堆放的地方.此区域对应一格21*11的数组.下文简称<游戏区>或<大数组>以上就是整个程序的界面了.程序主要由一个11*21 的2维数组 (,控制下落后的方块显示)二个4*4的二维数组 分别控制当前下落方块 和下一次方块的显示..3个数组都为int 型,有图形的地方设为1没有图形的地方设为0;1.产生方块方块一共有7种图形. 每个图形占4个格子..首先由用rand 函数 产生0~6的随机数. 然后设定好7种图形在4*4的2维数组所占的坐标点.选中其中的一个之后,在用rand 函数产生0~3的随机数进行旋转(方块最多转3次,转4次的话就会转回来了). 这样就尽可能的保证方块的随机性了.2.方块旋转田字形方块不能旋转,排除出去1字形方块旋转只需要对二维数组进行简单的行列互换即可.其他的方块的旋转规律为(1,1)的位置不动.移动其他3块方块的位置如下面左图所示 00的位置放到02 , 02的位置放到22, 22的位置放到20 以此类推.4.方块消除如果一行满了(二维数组中某一行全部为1),消除这一行.操作方法:1.先把这一行的数据全部都设置为0,2.和上面的行进行交换,直到顶部为止. (箭头表示两行数据进行交换)这一块是不必移动的 主要移动这两块区域5画图基本思路:根据2维数组的值画图,为1就画个小框,为0就不管.以2维数组的下标为坐标. 然后定义一个getpoint函数. (返回一个cpoint数组.)在此函数内部扫描2维数组, 如果为1就把当前的下标值存入cpoint数组.扫描返回的那个的cpoint数组,进行图形填充.以上就是简单的设计方案.=============================================以下是函数的说明代码一共有两个类.CData 产生数据的地方CTetrisView MFC的视图类根据CData 所产生的数据进行画图和判断方块的移动以及旋转是否合法.CData类就是上面设计方案的实现所以不用介绍了.以下介绍view类数据成员.UINT m_speed; //游戏速度UINT m_score; //游戏分数CBrush m_brush; //背景画刷BOOL m_bDone; //用于判断方块是否构建好了CDC *m_PaintDC; //游戏兼容dc , 专门用于画图CBitmap *m_Pbitmap; //兼容位图int m_y; //统一的y坐标int m_x; //统一的x坐标std::vector<CPoint>m_point; //4块方块所在的坐标CRect m_rectgame //游戏区域的矩形大小CRect m_rectnext; //下一次出方块区域的矩形大小Fmod 组件用于连续播放游戏的背景音乐.FMOD::System *system;FMOD::Sound *sound;FMOD::Channel *channel;成员函数OnDraw(CDC* pDC)游戏的主要绘图,用于绘制游戏的界面,以及刷新后的图形显示..InitGame();初始化游戏1.创建兼容设备dc ,2.填充画面背景,.3.产生当前要出的方块. 和下一块方块4.设定m_y,m_x的初始值.用于画图.5画出当前下落的方块,和下一次要出的方块.6.播放背景音乐,设定定时器.DrawBlock(vector<CPoint> point,int x,int y,CDC* pDC)根据传入的point数组,在x,y上面画矩形.矩形的大小宽=游戏矩形(m_rectgame)的宽/11;长=游戏矩形(m_rectgame)的宽/21;DrawNext(CDC *dc)画出下一次要出的方块, 画之前先把背景抹掉DownBlock(vector<CPoint>point,BOOL Style).方块下落2种下落方式,根据style判断,是哪一种下落方式FAST:马上下落,SLOW:一格一格的下落SLOW下落:扫描当前方块下面是否有方块,(扫描大数组中指定的坐标是否为1).如果到了最底部直接返回. 并把m_bdone设置为true.表示这块方块已经放好了.FAST下落:直接判断下面是否有方块,如果没有就下落一格.再递归调用此函数的FAST风格.直到下面有方块或者到最底部为止.MoveBlock(BOOL op)根据op判断方块是否是向左移动,还是向右移动.并且判断方块是否已经构建好了.然后擦除当前位置的方块.再用CanMove函数判断方块移动是否合法,不合法的话退回来.把方块画回原来的位置/合法的画在新位置上画上方块.CanMove(vector<CPoint> point)判断方块所在的位置是否合法.有2种情况是不合法的1,超出左右两边的墙了2.左右两边已经堆放了其他的方块.OnStart()响应Game------Start消息.初始化游戏.把所有的数据清0;OnTimer(UINT nIDEvent) 定时器消息(相当于电脑自动地在按键盘的向下键)擦除先前位置的方块让方块一格一格地下降.画出新位置的方块.再调用Running函数让游戏周而复始的出方块直到游戏结束.OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)响应键盘按键消息如果游戏结束,直接返回不响应按键操作.其中"+" "-" 加游戏速度和减游戏速度.ClearBlock(vector<CPoint> point,CDC* dc)把当前位置的方块图像擦除.方法跟画方块差不多.就是把那一块地方填充黑色背景.void CTetrisView::Transform()方块旋转把当前的形状保存首先判断方块旋转后是否合法不合法的情况:1.方块旋转后超出了游戏的界面. 比如靠墙的时候不能旋转;2.旋转后覆盖到了已经堆好的方块,3已经到了最底部了(方块已经构造好了).不合法的话就把原来的形状变回来.Running()程序的活水源头首先判断方块是否已经构建完成.然后判断构建完成后的方块是否已经到了最顶部了,如果到了最顶部的话就干调定时器,关调背景音乐.结束游戏.直接返回.如果方块没到顶部. 把这一次的方块准备好, 并取得下次所需的方块.设置m_x,m_y的初值(.方块最开始出现的地方.)画出当前的方块和下一次的方块.MappingArray(vector<CPoint> point)根据坐标把有方块的地方映射为1.并且判断最上面一行是否有方块.然后调用消除方块的函数,查看是否达到了消除一行的条件了.DropBlock(int sign,CDC *dc)首先调用data类的dropblock 函数判断是否达到消除一行的条件了,如果data类的m_count 大于0.就表示达到了消除方块的条件.调用Refresh()刷新整个游戏区域.Refresh()首先把游戏区的图像全部擦除,(用fillrect填充黑色).然后再根据m_gameblock二维数中为1的那以块进行画方块的操作.ShowData()显示分数信息ChangeSpeed(UINT nChar)改变游戏速度并显示。

c++俄罗斯方块算法描述_解释说明

c++俄罗斯方块算法描述_解释说明

c++俄罗斯方块算法描述解释说明1. 引言1.1 概述俄罗斯方块是一款经典的益智游戏,它以其简单却富有挑战性的玩法而受到了广大玩家的喜爱。

这款游戏的核心在于使用各种形状的方块来填满一个平面,并尽可能消除已填满的行。

本文将详细描述和解释俄罗斯方块中所涉及到的算法,并给出实现示例和优化建议。

1.2 文章结构文章主要分为五个部分:引言、俄罗斯方块算法描述、算法解释说明、实现示例和优化建议、结论与展望。

在引言部分,我们将对整篇文章进行概述,并介绍文章的结构框架。

接下来,我们将详细描述俄罗斯方块中所用到的算法,包括方块生成算法和方块下落以及碰撞检测算法。

然后,我们将重点解释游戏状态管理算法、消行判断和消行算法以及分数计算和难度调整算法。

在实现示例和优化建议部分,我们将给出一个具体的代码示例,并提供一些关于如何优化该代码的建议。

最后,在结论与展望部分,我们将总结俄罗斯方块算法描述及其实现效果,并展望未来俄罗斯方块的改进方向和研究内容。

1.3 目的本文的目的是通过详细描述和解释俄罗斯方块中所涉及到的算法,让读者对该游戏中各个环节的实现有更深入的理解。

同时,我们还希望通过给出一个具体的实现示例和优化建议,能够帮助读者更好地掌握算法在实际编程中的应用。

最后,我们也将对俄罗斯方块算法描述进行总结,并提出一些关于未来改进和研究方向的展望。

2. 俄罗斯方块算法描述:2.1 游戏规则介绍:在俄罗斯方块游戏中,玩家需要通过操作和控制方块的移动、旋转来填满游戏区域的水平行,当一行被完全填满时,该行将被消除并得分。

游戏区域由一个固定大小的矩形网格组成,起初是空的。

方块以7种不同的形态出现,并从游戏区域顶部下落。

玩家可以通过左右移动、快速下落和旋转来操作当前下落方块。

当方块无法再下落时,则会生成新的方块并开始新一轮操作。

2.2 方块生成算法:俄罗斯方块中的七种基本形态(I、J、L、O、S、T和Z)以及它们可能出现在哪个位置都是预先定义好的。

俄罗斯方块c语言程序带注释

俄罗斯方块c语言程序带注释

1,1,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,1,1,0,0,1,0,0,0,1,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,0,0,1,1,0,0,1,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,0,0,1,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,}; /*方块模板*/int shape,dir,next_shape,next_dir;struct position{int x;int y;} now_position; /*纪录现在方块的位置*/int speed_level=1;int fall_to_land,be_lined; /*判断方块是否着地的*/ /*----------------------------------------*/void clscreen();void setxy(int x,int y);void display_back();void display_interface();void display_fk(int x,int y,int shape,int dir);void init();//int getkey();/*取键盘的扫描码*/void getinput();void m_sound(int freq,int time);void eras_fk(int x,int y,int shape,int dir);/*擦除方块*/void fk_down(bool quickly = false);bool is_illegal(int x,int y,int changed_dir);/*判断方块移动后坐标是否非法,非法1,合法0*/int get_random(int n); /*生成一个0----n-1的随机数*/void check_line(); /*检查是否有行可以消去,如果有就消去*/void game_over();/*----------------------------------*/int main(){int i;init();while (true){display_back();now_position.x=10;now_position.y=2;/*复原初始坐标*/be_lined=0; /*一个方块刚出现时没有成行*/shape=next_shape;dir=next_dir;next_shape=get_random(7);next_dir=get_random(4);eras_fk(55,5,shape,dir);/*擦去前一个方块*/display_fk(55,5,next_shape,next_dir);/*显示下一个方块*/display_fk(now_position.x,now_position.y,shape,dir);/*显示目前方块*/fall_to_land=0;while (!fall_to_land){for (i=15000-1500*speed_level;i>0;i--){getinput();}/*接受键盘输入*/fk_down(); /*方块自动下落*/}//m_sound(350,500); /*块落下的声音*/ check_line(); /*检查有没有可消去的行*/if (be_lined)m_sound(250,1000);elsem_sound(350,500);}return0;}/*------------------------------------*/void init(){int i,j;for (i=0;i<20;i++)for (j=0;j<10;j++)background[i][j]=0;/*背景数组赋初值0*/next_shape=(get_random(7)+5)/7;next_dir=(get_random(4)+2)/4;/*预先产生一个方块*/display_interface();/*画界面*/}void display_interface(){clscreen();setxy(40,5);printf("The Next: ");setxy(1,1);}/*-----------------------------------------*/void display_back()/*显示背景*/{int i,j;for (i=0;i<20;i++){for (j=0;j<10;j++){setxy(2*(j+1),i+2); /*数组下标到屏幕坐标的变换*/if (!background[i][j])/*背景数组中值为0*/printf(" ");elseprintf("[]");}}}/*---------------------------------------*/void display_fk(int x,int y,int shape,int dir)/*显示方块*/{int i,j;for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]){setxy((x+2*j),(y+i));/*结合现在方块的位置*/printf("[]");}}}}/*-----------------------------------*/void getinput(){if(GetAsyncKeyState(VK_LEFT)){if (!is_illegal(now_position.x-2,now_position.y,dir)){eras_fk(now_position.x,now_position.y,shape,dir);now_position.x=now_position.x-2;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}elsem_sound(440,500);/*如果没有遇阻,方块位置左移一格*/}else if(GetAsyncKeyState(VK_RIGHT)){if (!is_illegal(now_position.x+2,now_position.y,dir)){eras_fk(now_position.x,now_position.y,shape,dir);now_position.x=now_position.x+2;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}elsem_sound(440,500);/*如果没有遇阻,方块位置右移一格*/}else if(GetAsyncKeyState(VK_UP)){if (!is_illegal(now_position.x,now_position.y,(dir+1)%4)){eras_fk(now_position.x,now_position.y,shape,dir);dir=(dir+1)%4;display_fk(now_position.x,now_position.y,shape,dir);Sleep(1000);}}else if(GetAsyncKeyState(VK_DOWN)){fk_down(true);}else if(GetAsyncKeyState(VK_SPACE)){game_over();}}/*------------------------------------*/void m_sound(int freq,int time){Beep(freq,time);}/*--------------------------------*/void eras_fk(int x,int y,int shape,int dir)/*擦除方块*/{int i,j;for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]){setxy((x+2*j),(y+i));/*结合现在方块的位置*/printf(" ");}}}}/*----------------------------------------------------*/ void fk_down(bool quickly) /*方块下落*/{int i,j,x,y;if (!is_illegal(now_position.x,now_position.y+1,dir))/*下落没有阻碍*/{eras_fk(now_position.x,now_position.y,shape,dir);now_position.y=now_position.y+1;display_fk(now_position.x,now_position.y,shape,dir);if(quickly){Sleep(10);}else{Sleep(1000);}}else/*不可再下落了*/{/*方块并入背景*/x=now_position.x;y=now_position.y; /*x,y表示方便*/for (i=0;i<4;i++){for (j=0;j<4;j++){if (fang_kuai[shape][dir][i][j]==1) background[(y-2+i)][(x/2-1+j)]=1;}}fall_to_land=1; /*告诉主程序方块着地*/}}/*-----------------------------------------------------*/ bool is_illegal(int x,int y,int changed_dir){int i,j;bool illegal=false;/*先判断有没有出界,如果有x,y在界外并且此x,y处方块数组为1,就返回1*/for (i=0;i<4;i++)for (j=0;j<4;j++)if (fang_kuai[shape][changed_dir][i][j]==1&&((x+j*2)>21 || (x+j*2)<2 || (y+i)>21 || (y+i)<2))illegal=true;/*再判断是否有原方块阻碍*/if (!illegal){for (i=0;i<4;i++)for (j=0;j<4;j++)if (fang_kuai[shape][changed_dir][i][j]==1&&background[(y-2+i)][(x/2-1+j)]==1)illegal=true;/*有阻碍返回一*/}return illegal;}/*-----------------------------------------------------*/int get_random(int n){int x;Sleep(500);/*randomize();x=random(n);*/srand( (unsigned)time(NULL));x=rand()%n;return(x);}/*--------------------------------------------------------------*/void check_line() /*待修改*/{/*检查背景数组*/int i,j,k;int line,n;for (i=19;i>=0;i--){k=1; /*开始默认成行*/for (j=9;j>=0;j-- ){if (background[i][j]==0) /*不成行的条件*/k=0;}if (k==1) /*如果成行*/{be_lined=1; /*成行标志*/for (line=i;line>0;line--)for (n=9;n>=0;n--)background[line][n]=background[line-1][n];/*逐次下移一行*/i=i+1; /*把下一次待检的行重新设定*/}}}/*--------------------------------------------------------------*/void game_over(){clscreen();setxy(35,1);printf("GAME OVER");exit(0);}void clscreen(){system("cls");}void setxy(int x,int y){HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);COORD place;place.X = x;place.Y = y;SetConsoleCursorPosition(hConsole, place);}/* Colors defined for SetColor(int) */enum {BLACK = 0,DARK_BLUE = 1,DARK_GREEN = 2,TEAL = 3,DARK_RED = 4,DARK_PURPLE = 5,GOLD = 6,GREY = 7,DARK_WHITE = 8,BLUE = 9,GREEN = 10,CYAN = 11,RED = 12,PURPLE = 13,YELLOW = 14,WHITE = 15};void SetColor(const int foreground, const int background) {int Color = foreground + (background * 16);HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);}你把这段拿回去看哈吧,这是一个俄罗斯方块的程序,就是在控制台运行的,就是用你所说的纯数字和字符所运行,你现在只能在dos 下显示那些纯数字的东西,是因为你很多技术性的手法,你还不会,但你学习到一定程度后,你就会有所领悟,也不要太心急,当你练好内功后,修炼招数,应该会很快的!希望对你有帮助。

俄罗斯方块c++源代码

俄罗斯方块c++源代码

#include <conio.h>#include <stdlib.h>#include<stdio.h>#include <windows.h>#include <mmsystem.h>#pragma comment(lib,"winmm.lib") //播放背景音乐的头文件#include "colorConsole.h"#include<time.h>#define SQUARE_COLOR BACKGROUD_BLUE|BACKGROUD_RED| BACKGROUD_INTENSITY //背景颜色#define SQUARE_COLOR FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY //方块的颜色#define up 72#define down 80#define left 75#define right 77#define esc 27#define MAPW 15 //地图的宽度#define MAPH 25 //地图的高度void initiate1();int * build(); //创建方块//初始化工作BOOL isavailable(int a[],int x,int y,int w,int h); //判定是否能放下void drawblocks(int a[],int w,int h,int x,int y,WORD wColors[],int nColors);void delete_cache(); //清除键盘缓冲区void revolve(int a[][4],int w,int h,int *x,int y); //转动方块void pro();void end();void delete_blocks(int *a,int w,int h,int x,int y);void gameover();void deletefull_line(int m[][MAPW],int row,int w,int h); //消除一行int dx=30,dy=5; //屏幕上的偏移量int score=0,level=0;int map[MAPH][MAPW];int a1[4][4]={{1},{1,1,1}};int a2[4][4]={{0,1},{1,1,1}};int a3[4][4]={{1,1},{0,1,1}};int a4[4][4]={{0,0,1},{1,1,1}};int a5[4][4]={{0,1,1},{1,1}};int a6[4][4]={{1,1,1,1}};int a7[4][4]={{1,1},{1,1}};int main(){HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_BLUE| FOREGROUND_GREEN|FOREGROUND_INTENSITY };while(1){sndPlaySound("Resource\\Just Dance.wav",SND_LOOP|SND_ASYNC);//用异步方式播放音乐,PlaySound函数在开始播放后立即返回system("CLS");int n=0;printf("目录\n1.开始游戏\n2.退出游戏\n\n\n");scanf("%d",&n);switch(n){case 1:system("CLS");textout(handle,22,6,wColors+2,1,"请选择游戏等级:");textout(handle,32,8,wColors+2,1,"1.初级");textout(handle,32,10,wColors+2,1,"2.中级");textout(handle,32,12,wColors+2,1,"3.高级");while(1){char choice;choice=_getch();if(choice=='1'){textout(handle,22,6,wColors+2,1,"开始游戏,初级");textout(handle,32,8,wColors+2,1," ");textout(handle,32,10,wColors+2,1," ");textout(handle,32,12,wColors+2,1," ");level=0,score=0;Sleep(2000);textout(handle,22,6,wColors+2,1," ");break;}else if(choice=='2'){textout(handle,22,6,wColors+2,1,"开始游戏,中级");textout(handle,32,8,wColors+2,1," ");textout(handle,32,10,wColors+2,1," ");textout(handle,32,12,wColors+2,1," ");level=2,score=20;Sleep(2000);textout(handle,22,6,wColors+2,1," ");break;}else if(choice=='3'){textout(handle,22,6,wColors+2,1,"开始游戏,高级");textout(handle,32,8,wColors+2,1," ");textout(handle,32,10,wColors+2,1," ");textout(handle,32,12,wColors+2,1," ");level=4,score=40;Sleep(2000);textout(handle,22,6,wColors+2,1," ");break;}else if(choice!='1'&&choice!='2'&&choice!='3')continue;}pro();break;case 2:return 0;default:printf("错误,按键继续");while(!_kbhit());}}}void pro() //游戏主题{initiate1();int *b=NULL;b=build(); //创建方块int sign,blank,x,y;while(1){for(int i=0;i<4;i++) //复制方块for(int j=0;j<4;j++)if(a[i][j]=*(b+i*4+j)) blank=i;y=1-blank;x=4;delete_blocks(&a[0][0],4,4,16,10);b=build();HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_BLUE| FOREGROUND_GREEN|FOREGROUND_INTENSITY };drawblocks(b,4,4,16,10,wColors,1);wColors[0]=SQUARE_COLOR;drawblocks(&a[0][0],4,4,x,y,wColors,1);delete_cache();char string[5];wColors[0]=FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_INTENSITY;textout(handle,dx-10,8+dy,wColors,1,itoa(score,string,10));textout(handle,dx-10,14+dy,wColors,1,itoa(level,string,10));sign=1;while(sign){int delay=0,max_delay=100-10*level; //延迟量while(delay<max_delay){if(_kbhit()) //用if避免按住键使方块卡住{int draw=0;int key=_getch();switch (key){case up:delete_blocks(&a[0][0],4,4,x,y);revolve(a,4,4,&x,y);draw=1;break;case down:delay=max_delay;break;case left:if(isavailable(&a[0][0],x-1,y,4,4)){delete_blocks(&a[0][0],4,4,x,y);x--;draw=1;}break;case right:if(isavailable(&a[0][0],x+1,y,4,4)){delete_blocks(&a[0][0],4,4,x,y);x++;draw=1;}break;case 32://32 是空格键的ASCII码,按空格键暂停while(1){textout(handle,dx,-2+dy,wColors,1,"Press any key to continue");Sleep(200);textout(handle,dx,-2+dy,wColors,1,"");Sleep(200);if(_kbhit()){draw=1;break;}}break;case esc://按键退出游戏exit(EXIT_SUCCESS);}if(draw){HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};drawblocks(&a[0][0],4,4,x,y,wColors,1);draw=0;}}_sleep(5);delay++;}if(isavailable(&a[0][0],x,y+1,4,4)) //是否能下移{delete_blocks(&a[0][0],4,4,x,y);y++;HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};drawblocks(&a[0][0],4,4,x,y,wColors,1);}else{sign=0; //标记,使跳出while(sign) 循环,产生新方块if(y<=1){system("CLS");HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_RED| FOREGROUND_GREEN};textout(handle,4+dx,6+dy,wColors,1,"GAME OVER!!!");textout(handle,4+dx,8+dy,wColors,1,"分数:");textout(handle,10+dx,8+dy,wColors,1,itoa(score,string,10));textout(handle,4+dx,10+dy,wColors,1,"制作者:***");delete_cache();exit(EXIT_SUCCESS);} //是否结束for(int i=0;i<4;i++) //放下方块for(int j=0;j<4;j++)if(a[i][j]&&((i+y)<MAPH-1)&&((j+x)<MAPW-1))map[i+y][j+x]=a[i][j];int full,k=0;for( i=y;i<min(y+4,MAPH-1);i++){full=1;for(int j=1;j<14;j++)if(!map[i][j]) full=0;if(full) //消掉一行{deletefull_line(map,i,MAPW,MAPH);k++;score=score+k;level=min(score/10,9);}}}}}}void initiate1() //初始化{int i;for(i=0;i<25;i++){map[i][0]=-2;map[i][14]=-2;}for(i=0;i<15;i++){map[0][i]=-1;map[24][i]=-1;}map[0][0]=-3;map[0][14]=-3;map[24][0]=-3;map[24][14]=-3;HANDLE handle;handle=initiate();WORD wColors[1]={FOREGROUND_GREEN| FOREGROUND_BLUE|FOREGROUND_INTENSITY};textout(handle,dx-10,6+dy,wColors,1,"SCORE");textout(handle,dx-10,12+dy,wColors,1,"LEVEL");textout(handle,32+dx,8+dy,wColors,1,"NEXT");wColors[0]=FOREGROUND_RED|FOREGROUND_BLUE|FOREGROUND_INTENSITY;drawblocks(&map[0][0],15,25,0,0,wColors,1);textout(handle,dx,dy,wColors,1,"◎═════════════◎");wColors[0]=FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY;textout(handle,dx+8,dy+5,wColors,1,"按任意键开始");wColors[0]=FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY ;textout(handle,dx+7,dy-3,wColors,1,"制作者:***");int x=_getch();srand(time(NULL));textout(handle,dx+8,dy+5,wColors,1," ");}int * build() //创建方块{int * a=NULL;int c=rand()%7;switch(c){case 0:a=&a1[0][0];break;case 1:a=&a2[0][0];break;case 2:a=&a3[0][0];break;case 3:a=&a4[0][0];break;case 4:a=&a5[0][0];break;case 5:a=&a6[0][0];break;case 6:a=&a7[0][0];break;}return a;}void drawblocks(int a[],int w,int h,int x,int y,WORD wColors[],int nColors) //画出方块{HANDLE handle;handle = initiate();int temp;for(int i=0;i<h;i++)for(int j=0;j<w;j++)if((temp=a[i*w+j])&&y+i>0){if(temp==-3){textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"◎");_sleep(30);}else if(temp==-2){textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"║");_sleep(30);}else if(temp==1)textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"◎");else if(temp==-1){textout(handle,2*(x+j)+dx,y+i+dy,wColors,nColors,"═");_sleep(30);}}}void delete_cache() //清除缓冲区{while(_kbhit()){_getch();}}void delete_blocks(int *a,int w,int h,int x,int y) //覆盖方块{HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};for(int i=0;i<h;i++)for(int j=0;j<w;j++)if(a[i*w+j]&&i+y>0)textout(handle,2*(x+j)+dx,y+i+dy,wColors,1," ");}void revolve(int a[][4],int w,int h,int *x,int y) //转动方块{int b[4][4]={{0,0,0,0},{0,0,0,0},{0,0,0,0},{0,0,0,0}};int sign=0,line=0;for(int i=h-1;i>=0;i--){for(int j=0;j<w;j++)if(a[i][j]){b[j][line]=a[i][j];sign=1;}if(sign){line++;sign=0;}}for(i=0;i<4;i++)if(isavailable(&b[0][0],*x-i,y,w,h)){*x-=i;for(int k=0;k<h;k++)for(int j=0;j<w;j++)a[k][j]=b[k][j];break;}}void deletefull_line(int m[][MAPW],int row,int w,int h) //消除满行的方块{HANDLE handle;handle=initiate();WORD wColors[1]={SQUARE_COLOR};textout(handle,2+dx,row+dy,wColors,1,"﹌﹌﹌﹌﹌﹌﹌﹌﹌﹌");_sleep(100);int i;for(i=row;i>1;i--){delete_blocks(&m[i][1],MAPW-2,1,1,i);for(int j=1;j<MAPW-1;j++)m[i][j]=m[i-1][j];drawblocks(&m[i][1],MAPW-2,1,1,i,wColors,1);}for(i=1;i<MAPW-1;i++)m[1][i]=0;}BOOL isavailable(int a[],int x,int y,int w,int h){for(int i=max(y,1);i<y+h;i++)for(int j=x;j<x+w;j++)if(map[i][j]&&a[w*(i-y)+j-x])return 0;return 1;}第二个cpp:#include "colorConsole.h"HANDLE initiate(){HANDLE hOutput;hOutput = GetStdHandle(STD_OUTPUT_HANDLE);return hOutput;}BOOL textout(HANDLE hOutput,int x,int y,WORD wColors[],int nColors,LPTSTR lpszString) {DWORD cWritten;BOOL fSuccess;COORD coord;coord.X = x; // start at first cellcoord.Y = y; // of first rowfSuccess = WriteConsoleOutputCharacter(hOutput, // screen buffer handlelpszString, // pointer to source stringlstrlen(lpszString), // length of stringcoord, // first cell to write to&cWritten); // actual number writtenif (! fSuccess)cout<<"error:WriteConsoleOutputCharacter"<<endl;for (;fSuccess && coord.X < lstrlen(lpszString)+x; coord.X += nColors){fSuccess = WriteConsoleOutputAttribute(hOutput, // screen buffer handlewColors, // pointer to source stringnColors, // length of stringcoord, // first cell to write to&cWritten); // actual number written}if (! fSuccess)cout<<"error:WriteConsoleOutputAttribute"<<endl;return 0;}二很经典的游戏.简单又让人着迷.今天就用mfc来实现个自己的俄罗斯方块.运行截图如下:看起来还行吧..网上有很多版本的实现代码.但是看了几个都是用一个很大的数组记录这些下落的物体的形状.然后写一个很大的switch case来实现变形.感觉真麻烦.今天提出一个容易的实现方法.下面切入正题思路是这样的:一:随机生成物体二:控制1.变形围绕一个方块向右旋转90度.以变形2.左右下移动1>物体左右移动的时候不要过界.2>物体落定后.(1).设定它落下的位置.(2).看是否满了一行.满了一行消去(3).看是否方块垒到顶了.到了game over三:重复以上步骤约定:下落的会变形的那个小东东,我们叫物体Object (--!!.大家忍受下这个名字.我是想不出其他的名字了.)左侧那个物体在里面移动的区域叫游戏区域Block实现这个游戏的思路跟玩这个游戏一样简单...1,随机生成一个物体.2,响应键盘的输入,做左右下移动和变形3,物体落到底部,判断是否满一行,物块垒满一行消除之.垒到顶部game over但是实现起来貌似又不是那么简单了.首先看起来随机生成一个不同形状的物体就是挑战怎么在视图上画一个个的不同形状的物体呢?我们看下这个游戏.每个物体都是由更小的方块组成.这些基本的小方块没有什么不同,再看看这个二维的游戏界面,左边的游戏区域,一个个的小方块合在一起是否就是我们所熟悉的二维数组?假如我们把这个游戏区域映射到一个二维数组,当这个数组元素有物体占据的时候就在上面涂颜色,没有则涂背景色.不就实现了么?.好了可以定义游戏的区域的数据结构了.这个游戏中由于要画不同的颜色,因此数据结构可以如下定义:2struct tagBlock3{4bSet;5COLORREF color;6}block[18][10]; // 我们将这个游戏区域格式化为18*10 (row*col);那么画一个物体又该如何画呢?假如我们先用数组定义好物体的形状,然后移动变化,那就太麻烦了.可以看到这些物体都是更小的方块组成的.(我们用四个小方块组成一个大的物体).用四个小方块,通过相对位置的不同可以变化成各种各样的不同形状.我们最终是要在那个二维数组中画不同形状的物体.那么在画的时候就要直到当前的物体应该画到哪儿.假如我们对二维数组的每个元素再抽象出来一个数据结构.在这个数据结构中保存当前它在二维数组中的位置(行列值).那就容易多了.7typedef struct tagPane9int row; // 在block[18][10]的行10int col; // 列11}Pane;这是一个小方格的定义,那每个物体要四个小方格,于是12struct tagObject13{14Pane object[4];15COLORREF color; // 每个物体有自己的颜色16int t; // 对应于最上面的一个方块的行值row17int b; // 对应于最下面一个方块行值18int l; // 对应于最左面一个方块的列值col19int r; // 对应于最右面一个方块列值20};由于我们要在画一个当前的下落的物体和一个下次将出现的物体.因此定义两个物体的对象21tagObject Object,NextObject;每个物体都是有边界的(把四个小方格全部盛下的最小矩形边界),我们把这个物体的四个小方块当前在block中的行列值,记录下来作为边界,放置在 tblr中.下面很多地方是用到这几个值的我们规定每个小方块的实际大小是 (24*24)像素那这个游戏区域实际上就是 height = 18*24 ,width = 10*24大小的矩形内(要注意数组的行列和矩形宽高的对应,col 对应的是width, row 对应的是height)22// 定义方格大小和游戏区域的矩形23const int PANE_WIDTH = 24; // 每个方格大小时24 * 24 pixel24const CRect BLOCK_RECT = CRect(29,31,271,463); // 游戏区域矩形现在的问题是,你怎么知道具体应该在视图的哪个地方画这些小方块呢?太简单了.我们可以由行列值(row,col)立即得到它在视图中所对应的矩形区域CRect(col*PANE_WIDTH,row*PANE_WIDTH,(col+1)*PANE_WIDTH,(row+1)*PANE_WIDTH); 假如我们要画一个物体,物体的四个方块的行列值都知道的.比如是在二维数组中(<0,0> <0,1> <1,0> <1,1>) 那<0,0>对应的视图的坐标矩形是(0,0,24,24)<0,1> -----(24,0,48,24)....自己那么对比几下就明白了.可以写一个函数专门获取小方块对应的实际视图中的矩形区域(实际上,我们的游戏区域不是从视图的0,0开始画的,而是上和左都有空白,左边空白LEFT_MARGIN个像素,上边空白是TOP_MARGIN个像素,因此是以(LEFT_MARGIN,TOP_MARGIN)点处作为游戏区域的左上角 .方块的长和宽相等,定义为PANE_WIDTH = 24)25// 根据坐标取得客户区矩形26CRect CRBlock::GetPaneRect(int row, int col)27{28if (row < 0 || col < 0)29{30return CRect(0,0,0,0);32returnCRect(col*PANE_WIDTH+LEFT_MARGIN,row*PANE_WIDTH+TOP_MARGIN,33(col+1)*PANE_WIDTH+LEFT_MARGIN,(row+1)*PANE_WIDTH+TOP_MARGIN);34}35//为方便.给出另一个重载的版本36// 由Pane的坐标取得对应的客户区的矩形37CRect CRBlock::GetPaneRect(Pane *p)38{39return GetPaneRect(p->row,p->col);40}现在再绘制一个物体还难么???张飞吃豆芽.!41#define RANDOM_COLOR RGB(rand()%256,rand()%256,rand()%256)42// 绘制当前下落的物体43void CRBlock::DrawFallingObject(CDC *pDC)44{45CBrush brush(Object.color);46CBrush brBorder(RANDOM_COLOR);47CBrush *pOld = pDC->SelectObject(&brush);48for (int i = 0; i < 4; i++)49{50CRect rc = GetPaneRect(&(Object.object[i]));51if (!rc.IsRectNull()) //这个组成物体的小方块还未出现在游戏区域内52{53pDC->Rectangle(&rc);54pDC->FrameRect(&rc,&brBorder); // 绘制边界,看起来会漂亮点哦.55}56}57pDC->SelectObject(pOld);58}咦.郁闷了...吃豆芽的时候遇到点problem.....需要绘制下一个将出现的物体.这个物体不是绘制在游戏区域内的.而是在游戏区域的右侧.没关系.假如我们在游戏区域和这下个物体绘制的区域之间隔一个方块的宽度.所有的问题都又解决了,原来的函数还照样可以用......继续吃豆芽59const CRect RECT_NEXTOBJECT = CRect(294,30,438,174); // 在这个矩形局域画下一个物体4*6 *PANE_WIDTH 大小60//294 = LEFT_MARGIN + 10 * PANE_WIDTH + 1*PANE_WIDTH;61现在这个4*6的区域的左上角,即是第一个方格的列坐标就是10+1 = 11 了.至于行坐标,由于这个区域是和原来的游戏区域上对齐的,所以依然是0;62// 绘制下一个将出现的物体63void CRBlock::DrawNextObject(CDC *pDC)64{65int l = NextObject.l;66int t = NextObject.t;67int r = NextObject.r;68int b = NextObject.b;6970// 把NextObject 的行列映射到要画在的矩形中71int offsetRow = (0+(6-(b-t+1))/2)-t; /// 这只是要把物体画到这个区域的中心72int offsetCol = (11+(6-(r-l+1))/2)-l; //7374// 这一段只是美化75CBrush brBkgnd(COLOR_BKGND);76CBrush *pOld = pDC->SelectObject(&brBkgnd);77CPen pen;78pen.CreatePen(PS_SOLID,1,RANDOM_COLOR);79CPen *pOldPen = pDC->SelectObject(&pen);80pDC->Rectangle(&RECT_NEXTOBJECT);81pDC->SelectObject(pOldPen);82pDC->SelectObject(pOld);8384CBrush brush(NextObject.color);85CBrush brBorder(RANDOM_COLOR);86pDC->SelectObject(&brush);87// 画下一个物体88for (int i = 0; i < 4; i++)89{90int row = NextObject.object[i].row;91int col = NextObject.object[i].col;92CRect rc = GetPaneRect(row+offsetRow,col+offsetCol);93if (!rc.IsRectNull())94{95pDC->Rectangle(&rc);96pDC->FrameRect(&rc,&brBorder);97}98}99}1>生成物体大家想的都过于复杂了.生成物体只是为几个小方块生成几个行列值,当然这个行列值不是随意的.而是有限制的.假如我们让第一个方块的行列值为 <-1,4> 然后依据这个方块在它的上下左右四个方向随机生成第二个方块,然后再根据第二个生成第三....根据第三个生成第四个.每个方块都是上一个方块的上下左右四个方向中非上一个方块的地方,那这个生成的物体正是我们要的!!!不信在纸上画一下! 根据这个思路进行改变.可以生成任何你要的形状!! 但是这样生成的却没有 T 形状的...(下面给出的是可以生成这个形状的代码)知道了上一个方块的位置,我们只要一个相对于上一个方块位置的偏移就好了(0,1) ---- 右(-1,0) ---- 上(1,0) ---- 下(0,-1) -- 左我们随机在这四个偏移量中拿出一个,生成下一个物体,但是又不能和上一个物体重叠 ,其实这次生成的偏移量不等于上一次生成偏移量的取反就满足要求.(在纸上画一下.任何时候你在纸上画画都能很快想明白一些问题,有时会得到不同的灵感)1// 随机的产生物体2void CRBlock::GenerateObject(struct tagObject &obj)3{4obj.object[0].row = obj.object[3].row = -1;5obj.object[0].col = obj.object[3].col = 4;6int x = -2,y = -2; // x,y 为偏移量7for (int c = 1; c <= 2; c++)8{9MakeRandomOffset(x,y); // 每次产生的位移不能是上一个方块的位置10obj.object[c].row = obj.object[c-1].row + x;11obj.object[c].col = obj.object[c-1].col + y;12x=-x,y=-y; // 上次生成的偏移量的取反13}14UpdateLimit(obj);15MakeRandomOffset(x,y);16/// 这个只是为了要得到一个T 形状的物体而做的.否则把下面的代码写到上面的循环中就完成任务了17if (obj.r-obj.l == 2 || obj.b-obj.t == 2)18{19obj.object[c].row = obj.object[1].row + x;20obj.object[c].col = obj.object[1].col + y;21}22else23{24obj.object[c].row = obj.object[2].row + x;25obj.object[c].col = obj.object[2].col + y;26}27obj.color = RANDOM_COLOR;28UpdateLimit(obj);29}3031// 随即产生一个偏移量.这个偏移量不能是参数x和y相同的32// 随即值只有4种可取,即是x和y的绝对值不相同的.(0,0) (+-1,+-1) 的偏移都是不合法的.33void CRBlock::MakeRandomOffset(int &offsetX, int &offsetY)34{35static const int offset[] = {-1,0, 1,0, 0,-1, 0,1};36int oldX = offsetX;37int oldY = offsetY;38do39{40int _i = (rand()%4)*2;41offsetX = offset[_i];42offsetY = offset[_i+1];43} while (offsetX == oldX && offsetY == offsetY);44}4546上面有一个函数还没有定义下面就是:4748// 更新物体的上下左右边界49// 左和上取最小50// 右和下取最大51void CRBlock::UpdateLimit(struct tagObject &obj)52{53obj.l = obj.object[0].col;54obj.r = obj.object[0].col;55obj.t = obj.object[0].row;56obj.b = obj.object[0].row;57for (int i = 1; i <= 3; i++)58{59if (obj.l > obj.object[i].col)60{61obj.l = obj.object[i].col;62}63if (obj.r < obj.object[i].col)64{65obj.r = obj.object[i].col;66}67if (obj.t > obj.object[i].row)68{69obj.t = obj.object[i].row;70}71if (obj.b < obj.object[i].row)72{73obj.b = obj.object[i].row;74}75}76}假如你不想要这样的形状,你可以调整生成的四个小方块的相对位置.就这样简单几步你就可以生成任何你想要的形状.爽否?三>变形上面是吃豆芽,下面就是啃骨头了.这是本程序的第二个难点真的那么难么?你认为变形会如何解决?说出来真让人失望.但又不得不说.这个骨头如此的脆弱,以至于当初摩拳擦掌准备下一翻苦功夫,栽几个大跟头的决心后备都用不上了,像是下了老劲而一拳打在了棉花上.用钱钟书在<围城>里形容李梓梅见到"情敌"方鸿渐的时候的话说:这是快意的失望!(最近在看<围城>,钱钟书真是人才.写的书太好了.)假如我们先找出这四个小方块最中间的一个,让它保持位置不变.而让其余的三个方块围着他向右做90度的旋转.是不是就是变形了?估计有人在这个时候该骂 "他妈的" 了...我当时就是.在纸上坐标啊.角啊,余弦啊,比划了半天.结果就是这样就变形了. 真 "他妈的".但是我想用三角函数和角在一个 x轴向右为正方向,y轴向下为正方向的坐标象限内(二维数组的逻辑)进行变形.就只是套用几个三角函数的公式就能完成了.这样程序将会简洁许多了.谁数学好,可以做一下,做好别忘了告诉我啊.(恨当初不该花那么多的时间跑出去玩通宵,数学没学好,真是后悔的我肠子都青了.童鞋们引以为戒).现在是0点48分.每这个时候大脑都会脱离我的精神独立控制四肢,因此废话多了些.说话意识流了点儿.不要介意.--!!下面是变形的代码:变形的过程中要注意的事情是:变形后不能覆盖住原来已经存在的方块位置.不能超出游戏区域边界.因此一旦变形失败就重建到原来的状态.77// 方块变形78// 变形的实现步骤:79// 找出4个方块的中心方块..80// 其他3个方块围绕这个方块向右旋转90度.81// 其他3个方块相对于这个中心方块的位置只可能时8中情况,82// 即是它的八个方向(包括对角线上的和水平垂直)83// 这个算法对物体变形的同时可能会造成物体左移,因此规定连续两次变形就右移一列84void CRBlock::Transform()85{86// 假如变形后失败,则重建到原来状态87struct tagObject objTemp = Object;88// 以(row,col)为中心旋转89int l = Object.l;90int ri = Object.r;91int t = Object.t;92int b = Object.b;93if (ri-l == b-t) // 正方形方块不变形,这个判断依据是,只有正方形的长和宽是相等的94{95return;96}97const int r = (t + b)/2;98const int c = (l + ri)/2;99// 变形实现,对4个小方块依次判断重新设定位置100 for (int i = 0; i < 4; i++)101 {102103 int &row = Object.object[i].row;104 int &col = Object.object[i].col;105 if ( row== r && col == c) // 中心方块不旋转106 continue;107 int offsetX = col - c;108 int offsetY = row - r;109 // 分八种情况分别变化110 if (offsetX > 0) // 在中心方块右边111 {112 if (offsetY == 0) // 正右方113 { // 到正下方114 row = r + offsetX;115 col = c;116 }117 else if (offsetY > 0) // 在右下方118 { // 到左下方119 col = c - offsetX;120 }121 else // 右上方122 { // 到右下方123 // 列不变124 row = r - offsetY;125 }126 }127 else if (offsetX == 0) // 和中心点在同一列,offsetY有正负号,恰好可以写成一个式子128 {129 row = r;130 col = c - offsetY;131 }132 else // 在中心方块左边133 {134 if (offsetY > 0) // 左下135 {// 到左上136 //列不变137 row = r - offsetY;138 }139 else if (offsetY == 0)// 正左方140 {// 到正上方141 row = r + offsetX;142 col = c;143 }144 else // 左上145 {// 到右上146 // 行不变147 col = c - offsetX;148 }149 }150 if (col < 0 || col >= 10 || (row > 0 && block[row][col].bSet)) // 变形失败151 {152 Object = objTemp;153 return;154 }155 }156 UpdateLimit(Object); // 更新方块的边界157 if (m_nTimesTransform == 2) // 连续变形了两次158 {159 Move(RIGHT); // 右移一个单位160 m_nTimesTransform = 0;161 }162 }3> 控制控制程序比控制我自己的意识要容易多了. 响应键盘的上下左右键就万事大吉enum {TRANSFORM = 0,DOWN = 2,LEFT = -1,RIGHT = 1,FASTTOBOTOOM = 3};先定义好变形和移动代码,在switch case中用到.FASTTOBOTOOM = 3 是什么意思咧? 先它是说不要一格一格的移动而要立即落到底部滴干活.每按一下向下的方向键它就下移动一行,但是要按空格键它就会立即下落到底部了.(对急性子和需要炫耀自己反应灵敏的人来说这个定义尤其爽!我属于有时候会炫耀自己反应敏捷的急性子的人!每次按空格键浑身都舒畅无比)....需要很多代码么?不需要.需要的是一点编码技巧1// 移动2// 左右下3void CRBlock::Move(int to)4{5int i;6switch (to)7{8case TRANSFORM: // 方向键向上是变形9m_nTimesTransform++; // 连续变形的次数10Transform();11break;12case LEFT:13case RIGHT:14if (IsBorder(to)) // 到最左或最右边或者物体下面有物体阻挡15{16return;17}18for (i = 0; i < 4; i++)19{20Object.object[i].col += to;21}22Object.r += to;23Object.l += to;24break;25case DOWN: // 一行26MoveDown(FALSE);27break;28case FASTTOBOTOOM: // 到底儿29MoveDown(TRUE);30break;31}32}技巧在这儿,do while 循环配合BOOL参数加上break.不需要额外的判断,顺溜的就向<梦想照进现实>中的那男人喝的好酒:冰爪子,从这儿下去到胃里成火线了.冰火两重天,你来试试!33// 向下移动bContinue 代表是一次到底还是移动一行34void CRBlock::MoveDown(BOOL bContinue)35{36do37{38if (IsBottom()) // 到底了39{40SetBlockFlag();41IsLineFull(); // 是否一行满?42if (Object.t < 0) // 组成当前物体的最上面的方块在游戏区域外43GameOver();44Object = NextObject;45GenerateObject(NextObject);// 产生下一个46m_nTimesTransform = 0; // 新产生的方块还未变形47break;48}49for (int i = 0; i < 4; i++)50{51Object.object[i].row += 1; // 方块下移一行52}53Object.b += 1; // 方块边界变了54Object.t += 1;55} while (bContinue);56}在移动物体的时候要注意的事项:1>不能过界吧2>不能覆盖已有物体吧57// 检测正在下落的物体下面是否已经存在物体了58// 或者到了最下面59BOOL CRBlock::IsBottom()60{61if (Object.b >= 17) // 游戏区域时10 * 18 转换到数组是9 17 ,9 是最右,17 是最下62{63return TRUE;64}65for (int c = 0; c < 4; c++) // 找出每一个物体的4个方块的位置然后判断66{67int i = Object.object[c].row;68int j = Object.object[c].col;69if ((i >= 0 && j >= 0) && block[i+1][j].bSet) // 此处已经有物体了70{71return TRUE;72}73}74return FALSE;75}物体落下后要干什么?当然是保存它落下的位置了?76// 检查现在在游戏区域中最上面的一个物体所在row (0 ~ 17)77// 在物体落下的位置标志为true.表示应该在这个地方画图形78void CRBlock::SetBlockFlag(BOOL bSet)79{80if (m_topLine > Object.t)81{82m_topLine = Object.t;83}84// 检测组成物体的4个方块的位置85for (int c = 0; c < 4; c++)86{87int i = Object.object[c].row;88int j = Object.object[c].col;89block[i][j].bSet = TRUE; // 设置此处已经被物体占据90block[i][j].color = Object.color;91}92}m_topLine 又是什么东东? 是当前垒的最高的物体所在二维数组的行值.这个值变成小于0 就算是game over了.....希望你垒的最后一块砖不是长条.....因为那样就像是囧到极点的老坟! ----- 装上了避雷针的埃及金字塔! <猜火车>中屎霸对马克说:That's fucking nightmare! 物体落下后光记录它落在的位置还不够,还得判断是否一行满了.93// 看一行是否满了,假如某一行都被标记为TRUE就时满了94BOOL CRBlock::IsLineFull()95{96int s = Object.t; // 最上97int topLine = m_topLine;98for (int e = Object.b; e >= s;) // e 和s都有被改变的可能99{100 int k = 0;101 for (k; k < 10; k++)102 {103 if (!block[e][k].bSet) // 未满104 {105 break;106 }107 }108 if (k == 10) // 满了就得删除这一行,并且自这行向上的行都要下移一行109 {110 for (int i = e; i >= m_topLine; i--)111 {112 for (int j = 0; j < 10; j++)113 {114 block[i][j].bSet = block[i-1][j].bSet;115 }116 }117 for (i = 0; i < 10; i++)118 {119 block[m_topLine][i].bSet = FALSE;120 }121 m_score += 100;122 m_topLine++; // 删除一行,则最高行向下移动一行123 s++; // Object所占的位置最上的一行要下移一行124 }125 else // 没有满126 {127 e--; // 则从object所占的位置行自下向上依次检测128 }129 }130 return FALSE; 131 }。

《俄罗斯方块》程序编写超详细解释

《俄罗斯方块》程序编写超详细解释

《俄罗斯方块》程序编写超详细解释Tc2.0 编写俄罗斯方块游戏很多编程爱好者都编写过俄罗斯方块的游戏程序。

很久以前,我用Tc2.0也做过一个;最近有好些朋友看见我以前的俄罗斯方块的程序后,问我是怎么做的。

我一直想把这个程序的整个过程写一份详细的东西,与各位编程爱好者分享,一直没空。

正好现在放假了,而且离回家还有几天。

于是我就把这个程序重新写了一遍,尽量使程序的结构比较清晰好懂一些。

同时写了下面的这份东西。

俄罗斯方块游戏的程序中用到了一些方法。

为了比较容易理解这些方法,我在讲述的同时写了些专门针对这些方法的示例程序。

这些示例程序力求短小,目的是用最小的代码能够清楚的示例所用的方法。

这些示例程序都经过tc2.0测试。

最后还附了完整的俄罗斯方块游戏的源代码,和最终的可执行程序。

如果你看了这份东东,有什么意见和想法,请发电子邮件告诉我。

我将会继续更新这分东东,最新的版本可以在我的个人主页上下载。

下面的问题是有关俄罗斯方块程序的,其中有些是朋友问我的,有些是我认为可能会被问到的。

我尽量按问题从易到难排列这些问题。

关于俄罗斯方块程序的一些问题:******************************************************Tc2.0中怎么样设置图形显示?Tc2.0中常用图形函数的用法?怎样获取鍵盘输入?怎样控制方块的移动?怎样控制时间间隔(用于游戏中控制形状的下落)?游戏中的各种形状及整个游戏空间怎么用数据表示?游戏中怎么判断左右及向下移动的可能性?游戏中怎么判断某一形状旋转的可能性?按向下方向键时加速某一形状下落速度的处理?怎么判断某一形状已经到底?怎么判断某一已经被填满?怎么消去已经被填满的一行?怎么消去某一形状落到底后能够消去的所有的行?(如长条最多可以消去四行)怎样修改游戏板的状态?怎样统计分数?怎样处理升级后的加速问题?怎样判断游戏结束?关于计分板设计的问题。

关于“下一个”形状取法的问题。

俄罗斯方块详解

俄罗斯方块详解

QQ: 120173389
Mail:tlp.totop@ 空间 /tlptotop单片机 俄罗斯方块 详解
-2-
就像这个 U 字形的容器装满了无法消行的方块,即生成新的方块失败,则游戏结束。流程 图如下:
主程序流程图
开始 执行初始化 产生一个新方块 不成功 上 旋转 游戏结束 下 向下 移动 成功 检测按键 左 向左 移动 右 向右 移动 超时 向下 移动
QQ: 120173389
Mail:tlp.totop@ 空间 /tlptotop单片机 俄罗斯方块 详解
-5{ 0xff,0xff,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10, 0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10,0x80,0x10, 0x80,0x10, };
点阵 16*16 显示缓冲区共需 32 字节(BYTE) ,而数组 map 却有 34 字节(BYTE) ,那是因为 有 2 个字节(BYTE)0xff,用作游戏地图的下界,消行的时候此行也不消行。我们把这段代码 也保存到 block.h 文件中。缓冲区数据与点阵的对应关系渐下图:
方块的属性有方块的类型(type 7 种) 、状态(state 4 种) 、对应的图形区(*pPic) 、位 置坐标(x,y) ,所以我们定义一个结构体类型,包含这几个成员。并且定义 2 个结构体变 量,分别表示当前方块 this 和下个方块 next。代码如下:
/***************************************************** 定义结构体类型 *****************************************************/ typedef struct { uchar type;//方块的类型(LJITOSZ) uchar state;//方块的状态(0、90、180、270°旋转) uchar code *pPic;//对应图形区指针 uchar x,y;//方块的坐标

俄罗斯方块游戏原代码

俄罗斯方块游戏原代码

#include<stdio.h>#include<stdlib.h>#include<dos.h>#include<graphics.h> /*系统提供的头文件*/#define TIMER 0x1c /*定义时钟中断的中断号*/#define VK_LEFT 0x4b00/*左移键*/#define VK_RIGHT 0x4d00/*右移键*/#define VK_DOWN 0x5000 /*加速键*/#define VK_UP 0x4800 /*变形键*/#define VK_SPACE 0x3920 /*变形键*/#define VK_END 0x4f00 /*暂停键*/#define VK_ESC 0x011b#define VK_ENTER 0x1c0d#define BSIZE 16 /*方块的边长是16个象素*/#define MAX_SHAPE 19 /*总共有19种各形态的方块*/#define BOARD_WIDTH 10 /*游戏面板的宽度,以方块的宽度为单位*/#define BOARD_HEIGHT 20/*游戏面板的高度,以方块的宽度为单位*/#define BGCOLOR BLACK /*背景色*/#define FORECOLOR WHITE /*前景色*/#define FALSE 0#define TRUE 1#define EMPTY 0#define FILLED 1#define BOARD_LEFT_X 10 /*游戏面板左上角的横坐标*/#define BOARD_LEFT_Y 5 /*游戏面板左上角的纵坐标*//*定义全局变量*/extern int Gameboard[BOARD_WIDTH+2][BOARD_HEIGHT+2];extern int nCurrent_block_index ; /*当前下落的方块的索引号*/ extern int nNext_block_index ; /*下一个方块的索引号*/extern int nSpeed, nScore; /*速度和得分*/extern int nSpeedUpScore; /*第一次要加速需达到的分数*/extern int bAccel, bOver;extern int nOriginX, nOriginY;/*某一形状的原点的绝对坐标*/ extern unsigned int TimerCounter; /* 计时变量,每秒钟增加18 */struct block{int arrXY[8];int nColor;int nNext;}; /*保存某一形状信息的结构体*/typedef struct block BLOCK;extern BLOCK arrayBlock[19];void interrupt newtimer(void);void SetTimer(void interrupt(*IntProc)(void));void KillTimer();void InitializeGraph();void InitializeGameboard() ;void DrawSquare(int x, int y);void DrawBlock(int BlockIndex, int sx, int sy,int color); int IsConflict(int BlockIndex, int x, int y);void HandleLeft(int BlockIndex,int *x, int *y);void HandleRight(int BlockIndex,int *x, int *y);void HandleUp(int *BlockIndex,int *x, int *y);int HandleDown(int BlockIndex,int *x, int *y);int IsLineFull(int y);void KillLine(int y);int KillLines(int y);int IsGameOver();int GameOver();void StartGame();void ProcessInGame();void game();void win();void help();void design();void show_win();void main(){win();menu();}void help(){clrscr();help();textcolor(WHITE);gotoxy(20,4);cprintf("\xDB\xDB\xDB\xDB\xB2 HELP ABOUT THE Game \xB2\xDB\xDB\xDB\xDB"); gotoxy(4,6);cprintf(" [ 1 ] - Metamorphose : Press the left key square moves left "); gotoxy(30,8);cprintf("Press the left key square move to the right");gotoxy(30,10);cprintf("Press down key square accelerate whereabouts");gotoxy(4,12);cprintf(" [ 2 ] - Speed up : Press the button oblong rotating ");gotoxy(4,14);cprintf(" [ 3 ] - Game Start : Press Enter to button to start the game"); gotoxy(4,16);cprintf(" [ 4 ] - Game Over : Press the ESC key to quit the game");gotoxy(30,18);cprintf("YOU WANT TO BE HELPFUL");gotoxy(6,23);printf("Press any key to go to the MAIN MENU ........");getche();}menu(){int x;do{{clrscr();design();textcolor(WHITE);cprintf("\xDB\xDB\xDB\xDB\xB2 Tetris Game \xB2\xDB\xDB\xDB\xDB");gotoxy(3,4);cprintf("--------------------------------------------------------------------------");gotoxy(35,5);cprintf("MAIN MENU");gotoxy(26,8);cprintf(" 1 - New Game ");gotoxy(26,9);cprintf(" 2 - Rank ");gotoxy(26,10);cprintf(" 3 - HELP ");gotoxy(26,11);cprintf(" 4 - The Game Explain ");gotoxy(26,12);cprintf(" 5 - EXIT ");x=toupper(getch());switch(x){case '1':game();break;case '2':cprintf("At present there is no ranking");break;case '3':help();break;case '4':cprintf("This game by LuWenJun,ChenLong,QiWei jointly compiled,Deficiencies still please forgive me");break;case '5':exit(0);break;default:clrscr();design();gotoxy(17,12);printf("\a\xDB\xB2 WRONG ENTRY : PRESS ANY KEY AND TRY AGAIN"); getche();}}}while(x!='5');return x;}void win(){int i,graphdriver,graphmode,size,page;char s1[30],s2[30];graphdriver=DETECT;initgraph(&graphdriver,&graphmode,"c:\\turboc2");cleardevice();setbkcolor(BLUE);setviewport(40,40,600,440,1);setfillstyle(1,2);setcolor(YELLOW);rectangle(0,0,560,400);floodfill(50,50,14);rectangle(20,20,540,380);setfillstyle(1,13);floodfill(21,300,14);setcolor(BLACK);settextstyle(1,0,6);outtextxy(100,60,"Welcom You");setviewport(100,200,540,380,0);setcolor(14);setfillstyle(1,12);rectangle(20,20,420,120);settextstyle(2,0,9);floodfill(21,100,14);sprintf(s1,"Let's our play Tetris Game!");setcolor(YELLOW);outtextxy(60,40,s1);sprintf(s2,"Press any key to play....");setcolor(1);settextstyle(4,0,3);outtextxy(110,80,s2);getch();closegraph();}void design(){int i;clrscr();textcolor(14);gotoxy(2,2);cprintf("\xC9");gotoxy(3,2);for(i=1;i<=74;i++)cprintf("\xCD");gotoxy(77,2);cprintf("\xBB");gotoxy(2,3);cprintf("\xBA");gotoxy(2,4);cprintf("\xBA");gotoxy(2,5);cprintf("\xBA");gotoxy(2,6);cprintf("\xBA");gotoxy(2,7);cprintf("\xBA");gotoxy(2,8);cprintf("\xB A");gotoxy(2,9);cprintf("\xBA");gotoxy(2,10);cprintf("\xBA");gotoxy(2,11);cprintf("\ xBA");gotoxy(2,12);cprintf("\xBA");gotoxy(2,13);cprintf("\xBA");gotoxy(2,14);cprintf("\xBA");gotoxy(2,15);cprintf(" \xBA");gotoxy(2,16);cprintf("\xBA");gotoxy(2,17);cprintf("\xBA");gotoxy(2,18);cprintf("\xBA");gotoxy(2,22);cprintf(" \xCC");gotoxy(2,19);cprintf("\xBA");gotoxy(2,20);cprintf("\xBA");gotoxy(2,21);cprintf(" \xBA");gotoxy(2,24);cprintf("\xC8");gotoxy(2,23);cprintf("\xBA");gotoxy(3,24);for(i=1;i<=74;i++)cprintf("\xCD");gotoxy(77,18);cprintf("\xBA");gotoxy(77,19);cprintf("\xBA");gotoxy(77,20);cprint f("\xBA");gotoxy(77,21);cprintf("\xBA");gotoxy(77,24);cprintf("\xBC");gotoxy(77,23);cprintf("\xBA");gotoxy(3,22);for(i=1;i<=74;i++)cprintf("\xCD");gotoxy(77,22);cprintf("\xB9");gotoxy(77,3);cprintf("\xBA");gotoxy(77,4);cprintf("\xBA");gotoxy(77,5);cprintf("\xBA");gotoxy(77,6);cprintf("\xBA");gotoxy(77,7);cprintf("\xBA");gotoxy(77,8);cprintf(" \xBA");gotoxy(77,9);cprintf("\xBA");gotoxy(77,10);cprintf("\xBA");gotoxy(77,11);cprintf ("\xBA");gotoxy(77,12);cprintf("\xBA");gotoxy(77,13);cprintf("\xBA");gotoxy(77,14);cprintf("\xBA");gotoxy(77,15);cprint f("\xBA");gotoxy(77,16);cprintf("\xBA");gotoxy(77,17);cprintf("\xBA");textcolor(RED);}void show_win(void){union REGS in, out;in.x.ax = 0x1;int86(0x33, &in, &out);}/*********************************************************** 函数原型:void InitializeGraph() * * 传入参数:无 ** 返回值:无 ** 函数功能:初始化进入图形模式***********************************************************/void InitializeGraph(){int gdriver = VGA, gmode=VGAHI, errorcode;/* 初始化图形模式*/initgraph(&gdriver, &gmode, "c:\\turboc2");/* 读取初始化结果 */errorcode = graphresult();if (errorcode != grOk) /* 错误发生 */{printf("Graphics error: %s\n", grapherrormsg(errorcode));printf("Press any key to halt:");getch();exit(1); /* 返回错误码 */}}/*********************************************************** 函数原型:void InitializeGameboard() ** 传入参数:无** 返回值:无** 函数功能:初始化游戏面板以及下一形状提示框、计分框和难度框 ***********************************************************/void InitializeGameboard(){/* 绘制游戏面板(即游戏区域)*/setfillstyle(SOLID_FILL,BGCOLOR);bar(BSIZE*BOARD_LEFT_X,BSIZE*BOARD_LEFT_Y,BSIZE*(BOARD_LEFT_X+BOARD_WIDTH),BSIZE*(BOARD_LEFT_Y+BOARD_HEIGHT));setcolor(WHITE);rectangle(BSIZE*BOARD_LEFT_X,BSIZE*BOARD_LEFT_Y,BSIZE*(BOARD_LEFT_X+BOARD_WIDTH),BSIZE*(BOARD_LEFT_Y+BOARD_HEIGHT));/*绘制下一形状提示框*/setcolor(BLUE);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(5+1), "next");setfillstyle(SOLID_FILL, BGCOLOR);bar(BSIZE*(24.5+2), BSIZE*6, BSIZE*(24.5+2+5), BSIZE*(6+5));setcolor(YELLOW);rectangle(BSIZE*(24.5+2), BSIZE*6, BSIZE*(24.5+2+5), BSIZE*(6+5));/*绘制速度框*/setcolor(BLUE);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(12+1), "level");setfillstyle(SOLID_FILL, BGCOLOR);bar(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1)); setcolor(RED);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(13+1), "0");/*绘制计分框*/setcolor(BLUE);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(19+1), "score");setfillstyle(SOLID_FILL, BGCOLOR);bar(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1)); setcolor(RED);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(20+1), "0");}int Gameboard[BOARD_WIDTH+2][BOARD_HEIGHT+2];int nCurrent_block_index;/* 当前下落的方块的索引号*/int nNext_block_index ; /*下一个方块的索引号*/int nSpeed, nScore; /*速度和得分*/int nSpeedUpScore = 1000; /*第一次要加速需达到的分数*/int bAccel, bOver;int nOriginX=5, nOriginY=1;/*某一形状的原点的绝对坐标*/ BLOCK arrayBlock[19]={/*x1,y1,x2,y2,x3,y3,x4,y4, color, next*/{ 0,-2, 0,-1, 0, 0, 1, 0, CYAN, 1}, /* */{-1, 0, 0, 0, 1,-1, 1, 0, CYAN, 2}, /* # */{ 0,-2, 1,-2, 1,-1, 1, 0, CYAN, 3}, /* # */{-1,-1,-1, 0, 0,-1, 1,-1, CYAN, 0}, /* ## */{ 0,-2, 0,-1, 0, 0, 1,-2,MAGENTA, 5}, /* */{-1,-1,-1, 0, 0, 0, 1, 0,MAGENTA, 6}, /* ## */{ 0, 0, 1,-2, 1,-1, 1, 0,MAGENTA, 7}, /* # */{-1,-1, 0,-1, 1,-1, 1, 0,MAGENTA, 4}, /* # */{-1, 0, 0,-1, 0, 0, 1, 0,YELLOW, 9}, /* */{-1,-1, 0,-2, 0,-1, 0, 0,YELLOW, 10}, /* */{-1,-1, 0,-1, 0, 0, 1,-1,YELLOW, 11}, /* # */{ 0,-2, 0,-1, 0, 0, 1,-1,YELLOW, 8}, /* ### */{-1, 0, 0,-1, 0, 0, 1,-1, BROWN, 13}, /* ## */{ 0,-2, 0,-1, 1,-1, 1, 0, BROWN, 12}, /* ## */{-1,-1, 0,-1, 0, 0, 1, 0, WHITE, 15}, /* ## */{ 0,-1, 0, 0, 1,-2, 1,-1, WHITE, 14}, /* ## */{ 0,-3, 0,-2, 0,-1, 0, 0, RED, 17},/* # */{-1, 0, 0, 0, 1, 0, 2, 0, RED, 16},/* # *//* # *//* # */{ 0,-1, 0, 0, 1,-1, 1, 0, BLUE, 18},/* ## *//* ## */};/*********************************************************** 函数原型:void StartGame () ** 传入参数:无** 返回值:无 ** 函数功能:游戏开始时调用的函数,其中绘制界面需调用函数 ** InitializeGameboard(), 接下来需初始化游戏面板的 ** 各个方块和一些全局变量的初值 ***********************************************************/void StartGame(){int i,j;/*设置游戏面板中每个方块的初始值*/for(j=0;j<=BOARD_HEIGHT;j++)for(i=0;i<BOARD_WIDTH+2;i++){if(i==0 || i==BOARD_WIDTH+1)Gameboard[i][j] = FILLED;elseGameboard[i][j] = EMPTY;}for(i=0;i<BOARD_WIDTH+2;i++)Gameboard[i][BOARD_HEIGHT+1] = FILLED;InitializeGameboard();/*设置游戏变量的初值*/nNext_block_index = -1; /*游戏初始,没有下一个形状的索引号*/nSpeed = 0;nScore = 0;}/*********************************************************** 函数原型:void ProcessInGame() ** 传入参数:无** 返回值:无** 函数功能:核心函数,主要用于处理在游戏中的各种事件(如按下各种按键) ***********************************************************/void ProcessInGame(){int key;bioskey(0);randomize();while(1){if(nNext_block_index==-1){nCurrent_block_index = rand()%19;nNext_block_index = rand()%19;/*绘制下一个提示形状*/DrawBlock(nNext_block_index,19,6,arrayBlock[nNext_block_index].nColor );}else{nCurrent_block_index = nNext_block_index;DrawBlock(nNext_block_index, 19,6,BGCOLOR ); /* 消除原来的提示形状 */nNext_block_index = rand()%19;DrawBlock(nNext_block_index,19,6,arrayBlock[nNext_block_index].nColor ); /*绘制下一个提示形状 */}nOriginX=5, nOriginY=1;TimerCounter = 0;DrawBlock(nCurrent_block_index, nOriginX,nOriginY, arrayBlock[nCurrent_block_index].nColor );/*在面板内绘制当前形状*/while(1){if (bioskey(1))key=bioskey(0);else key=0;bAccel = FALSE;switch(key){case VK_LEFT: /* 左移 */HandleLeft(nCurrent_block_index,&nOriginX,&nOriginY );break;case VK_RIGHT: /* 右移 */HandleRight(nCurrent_block_index,&nOriginX,&nOriginY );break;case VK_UP: /* 旋转 */case VK_SPACE:HandleUp(&nCurrent_block_index, &nOriginX,&nOriginY);break;case VK_DOWN: /* 下落加速键 */bAccel=TRUE;break;case VK_END: /* 暂停*/bioskey(0);break;case VK_ESC: /* 退出游戏 */bOver=TRUE;return;}if(bAccel || TimerCounter>(20-nSpeed*2))if(HandleDown(nCurrent_block_index,&nOriginX,&nOriginY))break;if(bOver)return;}}}/*********************************************************** 函数原型:void main() ** 传入参数:无 ** 返回值:无 ** 函数功能:入口函数,包含俄罗斯方块程序的主流程 ***********************************************************/void game(){InitializeGraph();SetTimer(newtimer); /*设置新的时钟中断*/while(1){StartGame();ProcessInGame();if(GameOver())break;bOver = FALSE;}KillTimer();closegraph();}unsigned int TimerCounter=0; /* 计时变量,每秒钟增加18 *//*********************************************************** 函数原型:void interrupt (*oldtimer)(void) ** 传入参数:无** 返回值:无** 函数功能:指向原来时钟中断处理过程入口的中断处理函数指针(句柄) ***********************************************************/void interrupt (*oldtimer)(void);/*********************************************************** 函数原型:void interrupt newtimer(void) ** 传入参数:无 ** 返回值:无 ** 函数功能:新的时钟中断处理函数 ***********************************************************/void interrupt newtimer(void){(*oldtimer)();TimerCounter++;}/*********************************************************** 函数原型:void SetTimer(void interrupt(*)(void)) ** 传入参数:无 ** 返回值:无 ** 函数功能:设置新的时钟中断处理函数 ***********************************************************/void SetTimer(void interrupt(*IntProc)(void)){oldtimer=getvect(TIMER);disable();setvect(TIMER,IntProc);enable();}/*********************************************************** 函数原型:void KillTimer() ** 传入参数:无 ** 返回值:无 ** 函数功能:恢复原先的时钟中断处理函数 ***********************************************************/void KillTimer(){disable();setvect(TIMER,oldtimer);enable();}/*********************************************************** 函数原型:void DrawSquare(int x, int y) ** 传入参数:游戏面板中的横坐标x,纵坐标y ** 返回值:无 ** 函数功能:在坐标(x, y)处绘制方块 ***********************************************************/void DrawSquare(int x, int y){if(y<1)return;bar(BSIZE*(x+9)+1,BSIZE*(y+4)+1,BSIZE*(x+10)-1,BSIZE*(y+5)-1);}/*********************************************************** 函数原型:void DrawBlock(int BlockIndex, int sx, int sy,int color) ** 传入参数:形状的索引BlockIndex,绝对横坐标x,绝对纵坐标y,颜色color ** 返回值:无** 函数功能:在坐标(sx, sy)处绘制颜色为color的形状***********************************************************/void DrawBlock(int BlockIndex, int sx, int sy,int color){int i,c;setfillstyle(SOLID_FILL, color);for(i=0;i<7;i+=2)DrawSquare(arrayBlock[BlockIndex].arrXY[i]+sx,arrayBlock[BlockIndex].arrXY[i+1]+sy);}/*********************************************************** 函数原型:int IsConflict(int BlockIndex, int x, int y) ** 传入参数:形状的索引BlockIndex,绝对横坐标x,绝对纵坐标y ** 返回值:无冲突返回0,有冲突返回1 ** 函数功能:判断形状是否能存在于坐标(x, y)处 * **********************************************************/int IsConflict(int BlockIndex, int x, int y){int i;for (i=0;i<=7;i++,i++){if (arrayBlock[BlockIndex].arrXY[i]+x<1 || arrayBlock[BlockIndex].arrXY[i]+x>10)return TRUE;if (arrayBlock[BlockIndex].arrXY[i+1]+y<1)continue;if(Gameboard[arrayBlock[BlockIndex].arrXY[i]+x][arrayBlock[BlockIndex].arrXY[i+1]+ y])return TRUE;}return FALSE;}/*********************************************************** 函数原型:int HandleLeft(int BlockIndex,int *x, int *y) * * 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:无** 函数功能:按下左方向键时的处理函数***********************************************************/void HandleLeft(int BlockIndex,int *x, int *y) /*按下左方向键时的处理函数*/{if(!IsConflict(BlockIndex,*x-1,*y)){DrawBlock(BlockIndex,*x,*y,BGCOLOR); /*擦除原先的形状*/(*x)--;DrawBlock(BlockIndex, *x, *y, arrayBlock[BlockIndex].nColor); /*绘制当前形状*/}}/*********************************************************** 函数原型:int HandleRight(int BlockIndex,int *x, int *y) ** 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:无** 函数功能:按下右方向键时的处理函数***********************************************************/void HandleRight(int BlockIndex,int *x, int *y)/*按下右方向键时的处理函数*/{if(!IsConflict(BlockIndex,*x+1,*y)){DrawBlock(BlockIndex,*x,*y,BGCOLOR); /*擦除原先的形状*/(*x)++;DrawBlock(BlockIndex, *x, *y, arrayBlock[BlockIndex].nColor); /*绘制当前形状*/}}/*********************************************************** 函数原型:int HandleUp(int BlockIndex,int *x, int *y) ** 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:无** 函数功能:按下上方向键(旋转键)时的处理函数***********************************************************/void HandleUp(int *BlockIndex,int *x, int *y) /*按下旋转键时的处理函数*/{int NextBlockIndex, i;static int arrayOffset[5]={0,-1,1,-2,2};NextBlockIndex = arrayBlock[*BlockIndex].nNext;for(i=0;i<5;i++)if(!IsConflict(NextBlockIndex, *x+arrayOffset[i],*y)){DrawBlock(*BlockIndex, *x, *y, BGCOLOR); /*擦除原先的形状*/*BlockIndex = arrayBlock[*BlockIndex].nNext;(*x) += arrayOffset[i];DrawBlock(*BlockIndex, *x, *y, arrayBlock[*BlockIndex].nColor); /*绘制当前形状*/}}/*********************************************************** 函数原型:int HandleDown(int BlockIndex,int *x, int *y) * * 传入参数:形状的索引BlockIndex,绝对横坐标的指针*x,绝对纵坐标的 ** 指针*y ** 返回值:仍在自由下落返回0,无法下落了返回1 ** 函数功能:按下向下方向键或自由下落时的处理函数***********************************************************/int HandleDown(int BlockIndex,int *x, int *y)/*按下下方向键或自由下落时的处理函数*/{char ScoreBuffer[10]={0},SpeedBuffer[10]={0};int i;int NumLinesKilled=0;/*if(TimerCounter>(20-nSpeed*2))*/{TimerCounter = 0; /*重置时钟中断*/if(!IsConflict(BlockIndex,*x,*y+1)) /*仍在下落*/{DrawBlock(BlockIndex,*x,*y,BGCOLOR); /*擦除原先的形状*/(*y)++;DrawBlock(BlockIndex, *x, *y, arrayBlock[BlockIndex].nColor); /*绘制当前形状*/return FALSE;/*仍在下落返回FALSE*/}else /*无法再下落了*/{DrawBlock(BlockIndex,*x,*y,FORECOLOR);for (i=0;i<=7;i++,i++){if ((*y)+arrayBlock[BlockIndex].arrXY[i+1]<1)continue;Gameboard[(*x)+arrayBlock[BlockIndex].arrXY[i]][(*y)+arrayBlock[BlockIndex].arrX Y[i+1]]=1;}NumLinesKilled = KillLines(*y);if(NumLinesKilled>0){switch(NumLinesKilled){case 1:nScore+=100;case 2:nScore+=300;case 3:nScore+=500;case 4:nScore+=800;}/*重绘计分框*/setfillstyle(SOLID_FILL,BLACK);bar(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*20, BSIZE*(25+8), BSIZE*(20+1));itoa(nScore,ScoreBuffer, 10);setcolor(RED);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(20+1), ScoreBuffer);if(nScore > nSpeedUpScore){nSpeed++;nSpeedUpScore+= nSpeed*1000;/*重绘速度框*/setfillstyle(SOLID_FILL,BLACK);bar(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1));setcolor(YELLOW);rectangle(BSIZE*25,BSIZE*13, BSIZE*(25+8), BSIZE*(13+1)); itoa(nSpeed,SpeedBuffer,10);setcolor(YELLOW);settextjustify(CENTER_TEXT, BOTTOM_TEXT);outtextxy(BSIZE*(25+4), BSIZE*(13+1), SpeedBuffer);}if(IsGameOver())bOver = TRUE;return TRUE; /*下落到底返回TRUE*/}}}/*********************************************************** 函数原型:int IsLineFull(int y) ** 传入参数:纵坐标y ** 返回值:填满返回1,否则返回0 ** 函数功能:判断第y行是否已被填满***********************************************************/int IsLineFull(int y){int i;for(i=1;i<=10;i++)if(!Gameboard[i][y])return FALSE;return TRUE;}/*********************************************************** void KillLine(int y) ** 传入参数:纵坐标y ** 返回值:无 ** 函数功能:消去第y行***********************************************************/void KillLine(int y){int i,j;for(j=y;j>=2;j--)for(i=1;i<=10;i++){if(Gameboard[i][j]==Gameboard[i][j-1])continue;if(Gameboard[i][j-1]==FILLED){Gameboard[i][j]=FILLED;setfillstyle(SOLID_FILL,FORECOLOR);}else /*Gameboard[i][j-1]==EMPTY*/Gameboard[i][j] = EMPTY;setfillstyle(SOLID_FILL,BGCOLOR);}DrawSquare(i,j);}}/*********************************************************** 函数原型:int KillLines(int y) ** 传入参数:纵坐标y ** 返回值:消去的行数 ** 函数功能:消去第y行以及与第y行连续的上面被填满的行 ***********************************************************/int KillLines(int y){int i, j, LinesKilled=0;for(i=0;i<4;i++){while(IsLineFull(y)){KillLine(y);LinesKilled++;i++;}y--;if(y<1)break;}return LinesKilled;}/*********************************************************** 函数原型:int IsGameOver() ** 传入参数:无 ** 返回值:游戏结束返回1,否则返回0 ** 函数功能:判断游戏是否结束***********************************************************/int IsGameOver(){int i;for(i=1;i<=10;i++)if(Gameboard[i][1])return TRUE;return FALSE;}/*********************************************************** 函数原型:int GameOver() ** 传入参数:无** 返回值:退出游戏返回1,否则返回0 ** 函数功能:在界面上输出游戏结束信息,并根据用户按键选择决定是否退出游戏***********************************************************/int GameOver(){int key;settextjustify(CENTER_TEXT,TOP_TEXT);/* 输出游戏结束信息 */setcolor(RED);outtextxy(BSIZE*15,BSIZE*12,"Game Over");setcolor(GREEN);outtextxy(BSIZE*15,BSIZE*14,"Enter : New Game");outtextxy(BSIZE*15,BSIZE*15,"Esc : Exit");for(;;){while(!bioskey(1));key=bioskey(0);if (key==VK_ENTER)return FALSE; /* 按下回车键,重新开始游戏 */if (key==VK_ESC)return TRUE; /* 按下ESC键,退出游戏 */}}。

俄罗斯方块代码

俄罗斯方块代码
int rotate();
int getW();
int getH();
void clearOldBox();
void putNewBox();
int collisionRotate(int box[][4]);
void getMessage();
void dispatchMessage();
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x20,0x00,0x01,0x00,0x70,0x00,
0x01,0x00,0x30,0x00,0x01,0x00,0x30,0x00,
0x00,0xF4,0x00,0xE0,0x0F,0x86,0x00,0xC0,
0x00,0x03,0x83,0x00,0x00,0x00,0x3C,0x00,
0x00,0x00,0x70,0x00,0x00,0x03,0xC0,0x00,
0x00,0x7E,0x00,0x00,0x3F,0xF0,0x00,0x00,
#define WINY 470
#define GAP 6
#define AREAX (WINX+GAP)
#define AREAY (WINY-GAP)
#define BOXW 15
int oldarea[MAXY+1][MAXX];
0x00,0xE0,0x06,0x00,0x03,0xC0,0x06,0x00,
0x0F,0x80,0x0C,0x00,0x3E,0x04,0x38,0x00,

C语言小游戏源代《俄罗斯方块》

C语言小游戏源代《俄罗斯方块》

C语言小游戏源代码《俄罗斯方块》#include <stdlib.h>#include <stdio.h>#include <graphics.h>#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 112void 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;int Act,Staus;int i,j,k;int Wid=10;int NoPass=CAN;float Delays=15000;int BeginH=250,BeginS=7;float Seconds=0;int Scores=0;int flag=1;int Sounds=CAN;int PreAct,NextAct;int a[8][4][4][4]={{{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0}, {1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,0,0,0,1,0,0,0,1,0,0,0},{1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0}},{{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0}},{{1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0},{0,1,0,0,1,1,0,0,0,1,0,0,0,0,0,0},{0,1,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,1,0,0,1,0,0,0,0,0,0,0}},{{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0},{0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0},{1,0,0,0,1,1,0,0,0,1,0,0,0,0,0,0},{0,1,1,0,1,1,0,0,0,0,0,0,0,0,0,0}},{{0,1,0,0,1,1,0,0,1,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,0,0,1,1,0,0,1,0,0,0,0,0,0,0},{1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0}},{{1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0},{1,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0},{1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,0}, {0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0}}, {{0,0,1,0,1,1,1,0,0,0,0,0,0,0,0,0}, {1,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0}, {1,1,1,0,1,0,0,0,0,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,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}}}; int b[4][4];main(int argc,char *argv[]){if (argc!=1){if (argv[1]!="")Heng=atoi(argv[1]);if (argv[2]!="")Shu=atoi(argv[2]);}Init(); /*初始化界面*/PreAct=random(8); /*取得当前的方块*/ for(;;) /*以下是游戏流程*/{NextAct=random(8); /*取得下一个方块*/ DrawNext(1); /*画出下一个方块*/Act=PreAct;if (Heng%2==0) ActH=Heng/2;else ActH=(Heng-1)/2;ActS=0; /*方块开始从游戏空间的中间下落*/Staus=0; /*取开始的状态*/NoPass=CAN; /*物体可以下落*/Give(); /*取得当前的方块*/Display(Act+1); /*显示当前的方块,每种方块的颜色不同*/ GoOn(); /*游戏的算法精髓所在*/PreAct=NextAct; /*方块下落完毕,取得下一个方块*/ DrawNext(0);}}void Init(){int GraphDriver=DETECT,GraphMode;registerbgidriver(EGAVGA_driver);initgraph(&GraphDriver,&GraphMode,"");if (kbhit()) Sounds=CANNOT;setcolor(1);OutTextXY(10,10,"Tetris");OutTextXY(30,30,"Version 2.0");OutTextXY(10,120,"Help:");OutTextXY(20,140,"+ :Faster");OutTextXY(20,160,"- :Slower");OutTextXY(20,180,"Esc :Quit");OutTextXY(20,200,"F1 :Help");OutTextXY(10,310,"Copyright(c) 1998.2.22");OutTextXY(10,320,"By Mr. Unique");outtextxy(10,250,"Score: 00000");rectangle(BeginH-3,BeginS-3,BeginH+Heng*(Wid+2)+2,BeginS+Shu*(Wid+2)+2);rectangle(BeginH-5,BeginS-5,BeginH+Heng*(Wid+2)+4,BeginS+Shu*(Wid+2)+4);rectangle(BeginH+(Heng+4)*(Wid+2)-2,BeginS+10,BeginH+(Heng+8)*(Wid+2)+2,BeginS+12+4*( Wid+2));for (i=0;i<MAX;i++)for (j=0;j<MAX;j++){Position[i][j]=1;middle[i][j]=-1;}for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)Position[i][j]=0;for (i=0;i<Heng;i++)for (j=0;j<Shu;j++)DrawBox(i,j,0);randomize();}void GoOn(){for(;;){Seconds+=0.2; /*控制方块的下落速度*/if (Seconds>=Delays){Down();Seconds=0;if (NoPass==BOTTOM){DetectFill();middle[ActH][ActS]=Act;if (ActS==0)Fail();return;}}if (kbhit())Select();}}void Down() /*方块下降*/{Display(0);if (Touch(ActH,ActS,0,1)==CAN) ActS++;elsemiddle[ActH][ActS]=Act; Display(Staus+1);}int Touch(int x,int y,int dx,int dy) {NoPass=CAN;for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+dx+i][y+dy+j]+=b[i][j];for (i=0;i<MAX;i++)for (j=0;j<MAX;j++)if (Position[i][j]>1)NoPass=CANNOT;for (i=0;i<4;i++)for (j=0;j<4;j++){Position[x+dx+i][y+dy+j]-=b[i][j]; middle[x+dx+i][y+dy+j]=Act;}if (NoPass==CANNOT && dx==0 && dy==1) {for (i=0;i<4;i++)for (j=0;j<4;j++)Position[x+i][y+j]+=b[i][j];NoPass=BOTTOM;}return NoPass;}int GetKey(void){int Ch,Low,Hig;Ch=bioskey(0);Low=Ch&0x00ff;Hig=(Ch&0xff00)>>8;return(Low==0?Hig+256:Low);}void Select(){int OldStaus,acts=ActS;switch(GetKey()){case ESC :Quit();break;case DOWN :Seconds+=14500;break;case LEFT :Display(0);if (ActH>0 && Touch(ActH,ActS,-1,0)==CAN) { ActH--;}Display(Act+1);break;case RIGHT :Display(0);if (ActH<Heng && Touch(ActH,ActS,1,0)==CAN) { ActH++;}Display(Act+1);break;case BLANK : Display(0);ksdown();Display(Act+1);break;case F1 :Help();break;case EQUAL :case ADD :if (Delays>300) Delays-=100;break; case DEC :if (Delays<3000) Delays+=100;break; case PAUSEP :case PAUSEp :getch();break;case SOUNDS :case SOUNDs :if (Sounds==CAN)Sounds=CANNOT;elseSounds=CAN;break;case UP :if(Act==7){while(acts<Shu-1&&Position[ActH][acts]!=1) acts++;Position[ActH][acts]=0;DrawBox(ActH,acts,0);acts=ActS;break;}else{Display(0);OldStaus=Staus;switch(Act){case 0:case 3:case 4:if (Staus==1) Staus=0;else Staus=1;break; case 1:break;case 2:case 5:case 6:if (Staus==3) Staus=0;else Staus++;break; }Give();if (Touch(ActH,ActS,0,0)==CANNOT){Staus=OldStaus;Give();}Display(Act+1);break;}}}void ksdown(){while(flag){if(Touch(ActH,ActS,0,0)==CAN){ActS++;}else {ActS--;flag=0;}}flag=1;}void Quit(){int ch,TopScore;FILE *fp;if ((fp=fopen("Russian.scr","r+"))!=NULL) {fscanf(fp,"%d",&TopScore);if (Scores>TopScore){setcolor(1);outtextxy(470,80,"Hello !");outtextxy(470,100,"In all the players,"); outtextxy(470,120,"You are the First !"); outtextxy(470,140,"And your score will"); outtextxy(470,160,"be the NEW RECORD !"); fseek(fp,0L,0);fprintf(fp,"%d",Scores);}fclose(fp);}setcolor(1);OutTextXY(470,220,"Are You Sure (Yes/no)?");ch=getch();if (ch=='y'||ch=='Y'){closegraph();delay(20);exit(0);}setcolor(0);outtextxy(470,220,"Are You Sure (Yes/no)?"); }void OutTextXY(int x,int y,char *String) {int i=0;char a[2];moveto(x,y);a[1]='\0';while (*(String+i)!='\0'){a[0]=*(String+i);outtext(a);if (Sounds==CAN && a[0]!=' '){sound(3000);delay(50);nosound();}i++;}}void Help(){unsigned Save;void *Buf;Save=imagesize(160,120,500,360);Buf=malloc(Save);getimage(160,120,500,360,Buf);setfillstyle(1,1);bar(160,120,500,280);setcolor(0);OutTextXY(170,130," About & Help");OutTextXY(170,150," # # # ########## # # # "); OutTextXY(170,160," # ## # # # # # # ###### ### "); OutTextXY(170,170," ########## ########## ## # # "); OutTextXY(170,180," # # # # # # # ## #### "); OutTextXY(170,190," # ## # #### ## # # # "); OutTextXY(170,200," # ## # # # # # ## # # # "); OutTextXY(170,210," # # # ## ## # ###### # # # "); OutTextXY(170,220," ## # ## # ## # # # # "); OutTextXY(170,230," # ## # #### # ## # "); OutTextXY(170,260," Good Luckly to You !!! ");getch();putimage(160,120,Buf,0);free(Buf);}void GetScores(){int Sec10000,Sec1000,Sec100,Sec10,Sec1; setfillstyle(0,1);bar(60,250,109,260);Sec1=Scores%10;Sec10=(Scores%100-Scores%10)/10;Sec100=(Scores%1000-Scores%100)/100;Sec1000=(Scores%10000-Scores%1000)/1000; Sec10000=(Scores%100000-Scores%10000)/10000; DispScore(60,250,'0'+Sec10000);DispScore(70,250,'0'+Sec1000);DispScore(80,250,'0'+Sec100);DispScore(90,250,'0'+Sec10);DispScore(100,250,'0'+Sec1);DispScore(110,250,'0');DispScore(120,250,'0');}void DispScore(int x,int y,char Ch){char a[2];a[1]='\0';a[0]=Ch;outtextxy(x,y,a);void Give(){for (i=0;i<4;i++)for (j=0;j<4;j++)b[i][j]=a[Act][Staus][i][j];}void Display(int color){for (i=0;i<4;i++)for (j=0;j<4;j++)if (b[i][j]==1) DrawBox(ActH+i,ActS+j,color); }void DrawBox(int x,int y,int Color){x=BeginH+x*(Wid+2);y=BeginS+y*(Wid+2);setfillstyle(1,Color);bar(x+2,y+2,x+Wid-1,y+Wid-1);if (Color==0)setcolor(9);elsesetcolor(Act+1);rectangle(x+4,y+4,x+Wid-4,y+Wid-4);}void DrawNext(int Color)for (i=0;i<4;i++)for (j=0;j<4;j++)if (a[NextAct][0][i][j]==1) DrawBox(Heng+4+i,1+j,Color); }void DetectFill(){int Number,Fall,FallTime=0;for (i=Shu-1;i>=0;i--){Number=0;for (j=0;j<Heng;j++)if (Position[j][i]==1) Number++;if (Number==Heng){FallTime++;if (Sounds==CAN){sound(500);delay(500);nosound();}for (Fall=i;Fall>0;Fall--)for (j=0;j<Heng;j++){Position[j][Fall]=Position[j][Fall-1];middle[j][Fall]=middle[j][Fall-1];if (Position[j][Fall]==0) DrawBox(j,Fall,0); else DrawBox(j,Fall,middle[j][Fall]+1);}i++;}}switch(FallTime){case 0:break;case 1:Scores+=1;break;case 2:Scores+=3;break;case 3:Scores+=6;break;case 4:Scores+=10;break;}if (FallTime!=0){GetScores();if (Scores%100==0) Delays-=100;}}void Fail(){if (Sounds==CAN){for (k=0;k<3;k++){sound(300);delay(200);nosound();}}setcolor(1);OutTextXY(440,200,"Game over!"); Quit();closegraph();exit(0);}。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

俄罗斯方块3.0版本
一、采用的技术方法
(1)编程方法采用的MFC;
(2)运用编程技术:Windows图形编程技术(基本的绘图CDC/HDC, GDI对象(笔、刷子、字体)、图形(线、矩形、圆形);
(2)菜单、工具条设计与使用;
(3)对话框设计与使用;
(4)系统通用对话框的使用;
(6)基本控件(按钮、静态文本框、文本编辑框、下拉框、列表框等);
(7)实现系统数据的可持久化:要求使用数据库或文件或MFC文档串行化技术实现这一点;
二、达到目标
在我的俄罗斯方块2.0版本基础上,完善游戏功能(如背景音乐和游戏音效的播放,游戏结束,排行榜等),完善游戏的运行规则(确定输赢的准则,积分的获得方式等)。

三、主要步骤
1、添加游戏背景音乐,音效资源;
2、添加两个对话框类即排行榜对话框类和打破记录者更改的对话框类;
3、添加响应排行榜对话框IDD_DIALOG_NEWRECORD和IDD_DIALOG_PH;
4、添加结束菜单ID_VIEW_END和排行榜菜单ID_VIEW_PHB;
5、主要代码说明;
mciSendString("play music\\4.mp3 repeat",NULL,0,NULL); //背景音乐是mp3格式循环播放
mciSendString("stop music\\4.mp3",NULL,0,NULL); //停止播放背景音乐
case VK_LEFT: //左移
russia.Move(1);
PlaySound("music\\btn.wav",NULL,SND_FILENAME|SND_ASYNC); //播放左移音效
break;
case VK_RIGHT: //右移
russia.Move(2);
PlaySound("music\\btn.wav",NULL,SND_FILENAME|SND_ASYNC); //播放右移音效
break;
case VK_DOWN: //下移
russia.Move(3);
PlaySound("music\\btn.wav",NULL,SND_FILENAME|SND_ASYNC); //播放下移音效
break;
case VK_UP: //变换
russia.Move(4);
PlaySound("music\\transform.wav",NULL,SND_FILENAME|SND_ASYNC);
//播放变换方块音效
PlaySound("music\\fadelayer.wav",NULL,SND_FILENAME|SND_ASYNC); //消方块时的音效
PlaySound("music\\lost.wav",NULL,SND_FILENAME|SND_ASYNC); //游戏结束时的音效
响应结束菜单函数
void CMBlockView::OnViewEnd()
{
if(AfxMessageBox("是否结束游戏?",MB_OKCANCEL)==IDOK)
{
russia.end = true; //将结束标志设为真
IfGoon = false; //将继续游戏标志为假
mciSendString("close music\\4.mp3",NULL,0,NULL); //关闭背景音乐
KillTimer(1);
//移除定时器1
}
NewRecord(); //是否破纪录函数
}
响应结束菜单流程图
排行榜功能实现函数
//...........显示排行榜对话框................
void CMBlockView::OnViewPhb()
{
LoadConfig(); //装载配置
CPaihang ph; //排行榜对话框
ph.SetBRecord(m_uPrimary); //显示冠军分数
ph.SetBHolder(m_szPrimary); //显示冠军姓名
ph.DoModal(); //为模态对话框
SaveConfig(); //保存ini信息
}
/............载入配置...............
void CMBlockView::LoadConfig()
{ //----------获取本地目录-------------*/
char
exeFullPath[MAX_PATH]; //MAX_PATH在API 中有定义,为128
CString
strPath; //存储执行程序路径
GetModuleFileName(NULL, exeFullPath, MAX_PATH); //应用程序全路径存放地址
strPath = CString(exeFullPath);
strPath = strPath.Left(strPath.ReverseFind('\\'));
//-----------------------------------*/
strPath += "\\config.ini"; //配置文件名
char strPrimary[80];
GetPrivateProfileString("HOLDER","PrimaryHolder", "匿名
",strPrimary,80,strPath); //从私有初始化文件获取冠军姓名字符串
m_szPrimary=strPrimary; //初始话冠军姓

m_uPrimary = GetPrivateProfileInt("SCORE","Primary",
0,strPath); //从私有初始化文件获取整型分数值
}
//............是否打破记录函数...............
void CMBlockView::NewRecord()
{
int uRecord = m_uPrimary;
if (uRecord < russia.m_score)
{
CDlgNewRecord dlg;
dlg.DoModal(); //显示新冠军记录的模态对话框LoadConfig(); //装载配置
CPaihang ph; //排行榜对话框
m_uPrimary = russia.m_score; //将新分数记录
m_szPrimary = dlg.m_szName; //将新的姓名记录
ph.SetBRecord(m_uPrimary); //显示冠军分数
ph.SetBHolder(m_szPrimary); //显示冠军姓名
ph.DoModal();
SaveConfig();}
}
//..............保存配置................
void CMBlockView::SaveConfig()
{ //----------获取本地目录-------------*/
char exeFullPath[MAX_PATH];
CString strPath;
GetModuleFileName(NULL, exeFullPath, MAX_PATH);
strPath = CString(exeFullPath);
strPath = strPath.Left(strPath.ReverseFind('\\'));
//-----------------------------------*/
strPath += "\\config.ini";
//记录保持分数
CString strPrimary;
//记录保持者
CString strPrimaryHolder;
//写配置文件
strPrimary.Format("%u",m_uPrimary);
strPrimaryHolder.Format("%s",m_szPrimary);
WritePrivateProfileString("SCORE","Primary", strPrimary,strPath);
WritePrivateProfileString("HOLDER","PrimaryHolder", strPrimaryHolder,strPath);
}
排行榜流程图
这个版本完成了双缓存
CDC BkDc,BlockDc,MemDc; //背景设备,方块前景设备,内存设备
CBitmap BpMem; //创建内存背景位图
MemDc.CreateCompatibleDC(pDC); //这个设备兼容当前DC
BpMem.CreateCompatibleBitmap(pDC,700,600); //创建一个位图对象,该位图对象的大小,决定了兼容设备上下文的大小
BkDc.CreateCompatibleDC(pDC); //这个设备兼容当前DC。

相关文档
最新文档