俄罗斯方块的程序编写

来源:本站
导读:目前正在解读《俄罗斯方块的程序编写》的相关信息,《俄罗斯方块的程序编写》是由用户自行发布的知识型内容!下面请观看由(电工技术网 - www.9ddd.net)用户发布《俄罗斯方块的程序编写》的详细说明。
简介:本文章是关于俄罗斯方块的程序编写。

/************************************************************************************

*标题: *******************俄罗斯方块游戏*******************************************

* 连接方法:无需跳线。需要插上,12864(控制器st7920)液晶屏。 *

* *

* 1.进阶,游戏程序,感兴趣的朋友可以看看代码,自己理解。 *

* 2.游戏,按键功能说明; 1 号键盘(设置) :暂停/开始 *

* 2 号键盘(确认) :翻转 *

* 3 号键盘(时间-) :左移 *

* 4 号键盘(时间-) :右移 *

* *

* 第二功能键 ;当 1 号键盘(设置) :暂停/开始 按下后 *

* 3,4号键是设置游戏难度的。 *

* *

* *

* Easy board 出品 *

*

*************************************************************************************/

//12864并行接口参考程序,控制器st7920

#include "reg52.h"

#include "Lcd12864.h"

#include "Key.h"

#include "boardinit.h"

#define uchar unsigned char

#define uint unsigned int

static unsigned long Seed = 1;

#define A 48271L

#define M 2147483647L

#define Q (M / A)

#define R (M % A)

/************************************

伪随机数发生器

*************************************/

double Random(void)

{

long TmpSeed;

TmpSeed=A*(Seed%Q)-R*(Seed/Q);

if(TmpSeed>=0)

Seed=TmpSeed;

else

Seed=TmpSeed+M;

return (double)Seed/M;

}

/**************************************

为伪随机数发生器播种

***************************************/

void InitRandom(unsigned long InitVal)

{

Seed=InitVal;

}

//延时子程序

void Delay(unsigned int t)

{

unsigned int i,j;

for(i=0;i<t;i++)

for(j=0;j<10;j++);

}

#define LGOU 0

#define RGOU 1

#define RZ 2

#define LZ 3

#define T 4

#define GUN 5

#define BOX 6

unsigned int idata num[19+2]={

0xfff,//第1行,最下面

0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,

0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,0x801,//第2行到第20行共19行

0xfff//第21行,最上面

};//定义共21行,其中num[0]为下墙壁行,num[20]为上墙壁行,每行12格,最左一格为左墙壁列,最右一格为右墙壁列

unsigned char code Block[28][2]={

/*

* 口 口口口 口口

* 口 口 口 口

* 口口 口口口口

*/

{0x88,0xc0},{0xe8,0x00},{0x62,0x20},{0x02,0xe0},

/*

* 口 口口 口口口

* 口 口 口 口

* 口口 口口口 口

*/

{0x22,0x60},{0x08,0xe0},{0xc8,0x80},{0xe2,0x00},

/*

* 口

* 口口 口口

* 口 口口

*/

{0x8c,0x40},{0x6c,0x00},{0x8c,0x40},{0x6c,0x00},

/*

* 口 口口

* 口口 口口

* 口

*/

{0x4c,0x80},{0xc6,0x00},{0x4c,0x80},{0xc6,0x00},

/*

* 口 口

* 口 口口 口口口 口口

* 口口口 口 口 口

*/

{0x04,0xe0},{0x8c,0x80},{0xe4,0x00},{0x26,0x20},

/*口

* 口

* 口 口口口口

* 口

*/

{0x44,0x44},{0x0f,0x00},{0x44,0x44},{0x0f,0x00},

/*

* 口口

* 口口

*/

{0x06,0x60},{0x06,0x60},{0x06,0x60},{0x06,0x60}

};

#define PASSSCORE 20

struct Jimu

{

unsigned int dat;

char x;

unsigned char y;

unsigned char type;

unsigned char change;

}Sign[3];//积木结构体

unsigned char SysFlag=0;

#define NEWSIGNFLAG 0

#define DEADFLAG 1

#define PAUSEFLAG 2

unsigned char Score=0;

unsigned char Level=1;

unsigned char DelayCnt=5;

unsigned char KeyBuffer=0;

#define RESEVER 1

#define CHANGE 2

#define DOWN 3

#define LEFT 4

#define RIGHT 5

#define PAUSE 6

/*********************************

初始化MPU

**********************************/

void InitCpu(void)

{

TMOD=0x0;

TH0=0;

TL0=0;

TR0=1;

ET0=1;

EA=1;

}

/*****************************

定时中断服务子程序

******************************/

void Timer0Int(void) interrupt 1

{

switch(OSReadKey())

{

case 9:

KeyBuffer=PAUSE;

break;

case 13:

KeyBuffer=CHANGE;

break;

case 17:

KeyBuffer=DOWN;

break;

case 21:

KeyBuffer=RIGHT;

break;

case 25:

KeyBuffer=LEFT;

break;

default:

break;

}

}

/******************************

画墙壁,初始化界面

*******************************/

void DrawBoard(void)

{

unsigned char n;

for(n=0;n<12;n++)

{

Lcd_Rectangle(3*n,0,3*n+2,2,1);

Lcd_Rectangle(3*n,60,3*n+2,62,1);

}

for(n=0;n<20;n++)

{

Lcd_Rectangle(0,3*n,2,3*n+2,1);

Lcd_Rectangle(33,3*n,35,3*n+2,1);

}

Lcd_WriteStr(4,0,"Easy出品");

Lcd_WriteStr(3,2,"Score:");

Lcd_WriteStr(3,3,"Level:");

}

/***********************************

游戏结束处理

************************************/

void GameOver(void)

{

if((SysFlag&(1<<DEADFLAG))!=0)

Lcd_WriteStr(3,1,"You Fail");

else

Lcd_WriteStr(3,1,"You Pass");

}

unsigned int code MaskTab[16]={

0x0001,0x0002,0x0004,0x0008,0x0010,0x0020,0x0040,0x0080,

0x0100,0x0200,0x0400,0x0800,0x1000,0x2000,0x4000,0x8000

};

/**********************************

根据积木图标左下坐标X,Y来画出积木图标

***********************************/

void DrawSign(struct Jimu Temp,unsigned char DrawMode)

{

unsigned char m,n;

for(m=0;m<4;m++)

for(n=0;n<4;n++)

{

if((Temp.dat&MaskTab[4*m+n])!=0)

Lcd_Rectangle(Temp.x+n*3,Temp.y-2-3*m,Temp.x+n*3+2,Temp.y-3*m,DrawMode);

}

}

/********************************

将积木图标值融入num数据中

也即把积木图标固定,无法再下降

*********************************/

FixSign(void)

{

unsigned char m,n;

for(m=0;m<4;m++)//行循环

for(n=0;n<4;n++)//列循环

{

if((Sign[0].dat&MaskTab[4*m+n])!=0)

{

num[20-(Sign[0].y-2)/3+m]|=MaskTab[11-Sign[0].x/3-n];

}

}

}

/********************************

判断积木图标中方块是否与障碍方块重合

*********************************/

unsigned char CheckIf(void)

{

unsigned char m,n;

for(m=0;m<4;m++)//行循环

for(n=0;n<4;n++)//列循环

{

if((Sign[1].dat&MaskTab[4*m+n])!=0)

{

if((num[20-(Sign[1].y-2)/3+m]&MaskTab[11-Sign[1].x/3-n])!=0)

return 0;

}

}

return 1;

}

/********************************

判断积木图标是否可以继续下降一格

********************************/

unsigned char CheckIfDown(void)

{

Sign[1]=Sign[0];//

Sign[1].y+=3;//假设下降一格

return CheckIf();

}

/********************************

判断积木图标是否可以向左移动

*********************************/

unsigned char CheckIfLeft(void)

{

Sign[1]=Sign[0];

Sign[1].x-=3;

return CheckIf();

}

/********************************

判断积木图标是否可以向右移动

*********************************/

unsigned char CheckIfRight(void)

{

Sign[1]=Sign[0];

Sign[1].x+=3;

return CheckIf();

}

/********************************

判断是否可以旋转

*********************************/

unsigned char CheckIfRoll(void)

{

unsigned char i;

unsigned int Temp;

Sign[1]=Sign[0];

if(++Sign[1].change>3)

Sign[1].change=0;

i=Sign[1].type*4+Sign[1].change;

Temp=(unsigned int)Block[0]<<8;

Temp=Temp|Block[1];

Sign[1].dat=Temp;

return CheckIf();

}

/********************************

寻找满格的行并做消除处理

最多寻找4个满行并做消除

*********************************/

void DelFull(void)

{

unsigned char m,n;

unsigned char Temp;

unsigned char Flag=0;

Temp=(Sign[0].y-2)/3;

if(Temp>=20)//防止越过了下边界

Temp=1;

else

Temp=20-Temp;

for(n=Temp+3;n>=Temp;n--)//积木图标的最顶行开始寻找满行比较有利于运算

{

if(num[n]==0xfff)

{

Flag=1;

for(m=n+1;m<=19;m++)

{

num[m-1]=num[m];

}

num[m]=0x801;

Score++;//每找到一个满行,则分数加1

}

}

if(Flag)//为加速而设置并判断的标志,有已固定的积木有满格消行变化则重画积木界面

{

for(m=Temp;m<=19;m++)//为加速,不必要重第一行重画起,只需要从积木图标最下行开始往上的重画

for(n=1;n<=10;n++)

{

if((num[m]&MaskTab[n])==0)

{

if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)!=0)//为加速而做的读象素操作

{

Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,0);

}

}

else

{

if(Lcd_ReadPixel(30-(n-1)*3,57-(m-1)*3)==0)//为加速而做的读象素操作

{

Lcd_Rectangle(30-(n-1)*3,57-(m-1)*3,30-(n-1)*3+2,57-(m-1)*3+2,1);

}

}

}

}

}

/*******************************

随机产生一个积木图标放到预产生区域并显示出来

********************************/

void CreatSign(void)

{

unsigned char n;

unsigned int Temp;

DrawSign(Sign[2],0);//先清除

n=Random()*28;

Temp=(unsigned int)Block[n][0]<<8;

Temp=Temp|Block[n][1];

Sign[2].dat=Temp;

Sign[2].x=45;

Sign[2].y=4*3+2;

Sign[2].type=n/4;

Sign[2].change=n%4;

DrawSign(Sign[2],1);//后画出

}

void PrintScore(void)

{

unsigned char Str[3];

Str[0]=(Score/10)|0x30;

Str[1]=(Score%10)|0x30;

Str[2]=0;

Lcd_WriteStr(6,2,Str);

}

void PrintLevel(void)

{

unsigned char Str[3];

Str[0]=(Level/10)|0x30;

Str[1]=(Level%10)|0x30;

Str[2]=0;

Lcd_WriteStr(6,3,Str);

}

/********************************

游戏的具体过程,也是贪吃蛇算法的关键部分

*********************************/

void GamePlay(void)

{

unsigned char m,n;

unsigned int Temp;

SysFlag|=1<<NEWSIGNFLAG;//刚开始初始化为需要产生新的积木图标

InitRandom(TL0);

Lcd_WriteStr(3,1,"Playing");

PrintScore();

PrintLevel();

CreatSign();

while(1)

{

if((SysFlag&(1<<NEWSIGNFLAG))==1)//判是否需要产生新的积木图标

{

SysFlag&=~(1<<NEWSIGNFLAG);

Sign[0]=Sign[2];

CreatSign();

Sign[0].x=12;

Sign[0].y=14;

for(m=0;m<4;m++)//行循环

{

for(n=0;n<4;n++)//列循环

{

if((Sign[0].dat&MaskTab[15-m*4-n])==0)

break;

}

if(n==4)

Sign[0].y-=3;

}//将积木图标出现置顶

for(m=0;m<4;m++)//行循环

for(n=0;n<4;n++)//列循环

{

if((Sign[0].dat&MaskTab[4*m+n])!=0)

{

if((num[20-(Sign[0].y-2)/3+m]&MaskTab[11-Sign[0].x/3-n])!=0)

SysFlag|=1<<DEADFLAG;

}

}

if((SysFlag&(1<<DEADFLAG))!=0)

break;//如果产生新的积木图标中的方块与已固定好的方块重合,则死亡。游戏结束

DrawSign(Sign[0],1);

}

switch(KeyBuffer)

{

case LEFT:

KeyBuffer=0;

if((SysFlag&(1<<PAUSEFLAG))==0)

{

if(CheckIfLeft())

{

DrawSign(Sign[0],0);

Sign[0].x-=3;

DrawSign(Sign[0],1);

}

}

else

{

if(++Level>=10)

Level=1;

PrintLevel();

}

break;

case RIGHT:

KeyBuffer=0;

if((SysFlag&(1<<PAUSEFLAG))==0)

{

if(CheckIfRight())

{

DrawSign(Sign[0],0);

Sign[0].x+=3;

DrawSign(Sign[0],1);

}

}

else

{

if(++Level>=10)

Level=1;

PrintLevel();

}

break;

case DOWN:

KeyBuffer=0;

if((SysFlag&(1<<PAUSEFLAG))==0)

{

if(CheckIfDown())//判断是否能继续下降一格

{

DrawSign(Sign[0],0);

Sign[0].y+=3;

DrawSign(Sign[0],1);

}

}

break;

case CHANGE:

KeyBuffer=0;

if((SysFlag&(1<<PAUSEFLAG))==0)

{

if(CheckIfRoll())

{

DrawSign(Sign[0],0);

if(++Sign[0].change>3)

Sign[0].change=0;

m=Sign[0].type*4+Sign[0].change;

Temp=(unsigned int)Block[m][0]<<8;

Temp=Temp|Block[m][1];

Sign[0].dat=Temp;

DrawSign(Sign[0],1);

}

}

break;

case PAUSE:

KeyBuffer=0;

SysFlag^=1<<PAUSEFLAG;

if((SysFlag&(1<<PAUSEFLAG))==0)

{

Lcd_WriteStr(3,1," ");

Lcd_WriteStr(3,1,"Playing");

}

else

{

Lcd_WriteStr(3,1," ");

Lcd_WriteStr(3,1,"Pause");

}

break;

default:

break;

}

if((SysFlag&(1<<PAUSEFLAG))!=0)

continue;

Delay(500);

if(++DelayCnt>=2*(11-Level))

{

DelayCnt=0;

if(CheckIfDown())//判断是否能继续下降一格

{

DrawSign(Sign[0],0);

Sign[0].y+=3;

DrawSign(Sign[0],1);

}

else

{

FixSign();

DelFull();

PrintScore();

if(Score>=PASSSCORE)

{

SysFlag&=~(1<<DEADFLAG);

break;//跳出玩游戏过程

}

SysFlag|=1<<NEWSIGNFLAG;//新的积木图标产生标志置1

}

}

}

}

void Main()

{

InitCpu();//初始化CPU

boardinit();

Lcd_Reset(); //初始化LCD屏

Lcd_Clear(0);//清屏

DrawBoard();//画界面

GamePlay();//玩游戏

GameOver();//游戏结束

while(1);//要想重玩,只能重启,可继续完善该游戏

}

提醒:《俄罗斯方块的程序编写》最后刷新时间 2024-03-14 00:55:56,本站为公益型个人网站,仅供个人学习和记录信息,不进行任何商业性质的盈利。如果内容、图片资源失效或内容涉及侵权,请反馈至,我们会及时处理。本站只保证内容的可读性,无法保证真实性,《俄罗斯方块的程序编写》该内容的真实性请自行鉴别。