可以用Proteus仿真的KeilC俄罗斯方块程序
2012-11-13
徐文军

//--------------------------------------------------------------------------//

//源程序大公开//

//(c) Copyright 2001-2005 xuwenjun//

//All Rights Reserved//

//V1.00//

//--------------------------------------------------------------------------//

//标 题: 俄罗斯方块程序?//

//文件名: xwj_fk.c//

//版 本: V1.00//

//修改人: 徐文军E-mail:xuwenjun@21cn.com//

//日 期: 05-05-13//

//描 述: 俄罗斯方块程序?//

//声 明://

//以下代码仅免费提供给学习用途,但引用或修改后必须在文件中声明出处. //

//如用于商业用途请与作者联系.E-mail:xuwenjun@21cn.com//

//有问题请mailto xuwenjun@21cn.com欢迎与我交流!//

//--------------------------------------------------------------------------//

//老版本: 无老版本文件名://

//创建人: 徐文军E-mail:xuwenjun@21cn.com//

//日 期: 05-05-13//

//描 述://

//1、功能完整,直接使用//

//2、模块独立性强,移植方便,外部仅init和move函数,修改显示和输入即可 //

//3、对减少内存占用、尽量减少屏幕操作进行适当优化//

//4、新方块生成高度随机,绝对无规律//

//5、仿真环境为Keil7.5+Proteus6.5,可以联机也可脱机运行//

//code SIZE=1845----//

//constANT SIZE=326----//

//data SIZE=1619//

//idata SIZE=50----//

//bit SIZE=11//

//--------------------------------------------------------------------------//

#include

#include "xwj_lcd16.h"// 字符液晶控制函数声明//

#include "xwj_lcd6963.h"// T6963C 公用函数

#include "xwj_hlkey.h"// P1口行列式键盘 //

#include "xwj_serial.h"//串口函数集

#include "change.h"//数制转换

#include "xwj_fk.h"//俄罗斯方块程序

#define ulongunsigned long

#define uintunsigned int

#define ucharunsigned char

extern void delay(unsigned int x);

//----------------俄罗斯方块内部函数----------------------------------------//

void fk_dot(uchar x,uchar y);//显示1个方块点

void fk_cldot(uchar x,uchar y);//清除1个方块点

void fk_show(void);//显示分数

void fk_reffk(void);//刷新方块

void fk_refnew(void);//刷新预览方块

void fk_refline(yy);//刷新1行背景

bit fk_chk(void);//冲突检查

void fk_new(void);//产生新方块

void fk_add(void);//方块合并

/*

//-----------------俄罗斯方块公用函数--------------------------------------//

void fk_init(void);//方块初始化

void fk_move(unsigned char mode);//移动方块

*/

//-------------------------------------------------------------------------//

#define FULLMAP0x0fff/*掩码*/

#define LINEGUAN20/*20行过一关*/

#define NEWX15/*预览方块X位置*/

#define NEWY12/*预览方块Y位置*/

#define LINEMAX21/*屏幕最高21行*/

uint idata fk_map[LINEMAX+4];//背景映象

uchar fk_x,fk_y,fk_r;//方块左右、高度、方向

uchar fk_type;//方块形状

uchar fk_oldx,fk_oldy,fk_oldr;//方块上次左右、高度、方向

uchar fk_newtype,fk_newr;//新方块形状、方向

uint score;//总分

uint line;//总行数

uchar speed;//速度

uchar moven;//速度相关计数器

uchar automapn;//随机方块的行数

bit fk_run;//俄罗斯方坑蜗吩诵?

uchar code fk_mod[][4][4]={//方块模型号,4个方向,4行

0,0,7,2,0,1,3,1,0,0,2,7,0,2,3,2,//_|_

0,0,6,3,0,1,3,2,0,0,6,3,0,1,3,2,//_|~

0,0,3,6,0,2,3,1,0,0,3,6,0,2,3,1,//~|_

0,0,7,4,0,3,1,1,0,0,1,7,0,2,2,3,//|__

0,0,7,1,0,1,1,3,0,0,4,7,0,3,2,2,//__|

0,0,0,15,1,1,1,1,0,0,0,15,1,1,1,1,//____

0,0,3,3,0,0,3,3,0,0,3,3,0,0,3,3,//田字

};

uchar code strmap[4][9]={

"不错! ","真棒! ","好极啦!","太棒了!",

};

//--------------------------------------------------------------------------//

void fk_dot(uchar x,uchar y)//显示1个方块点

{

printat(x*3+1, 241-(y-4)*12,"■");

}

//--------------------------------------------------------------------------//

void fk_cldot(uchar x,uchar y)//清除1个方块点

{

//printat(x*3+1, 241-(y-4)*12,"□");

printat(x*3+1, 241-(y-4)*12,"┘");

}

//--------------------------------------------------------------------------//

void fk_show(void)//显示分数

{

printat(50, 12,chnint(score,1));

printat(60, 12,"00");

printat(40, 12,"得分:");

printat(54,36,chnint(line,1));

printat(40, 36,"行数:");

printat(54,60,chnchar(speed,1));

printat(40,60,"速度:");

printat(54,84,chnchar(automapn,1));

printat(40,84,"关数:");

}

//--------------------------------------------------------------------------//

void fk_reffk(void)//刷新方块

{

uchar i,j;

uchar temp;

//----------------------------------------------//清除原来的方块

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

{

temp=(fk_mod[fk_type][fk_oldr][i]);

for (j=fk_oldx;j

{

if(temp&0x01)

{

fk_cldot(j,fk_oldy+i);

}

temp>>=1;

}

}

//----------------------------------------------//显示新的方块

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

{

temp=(fk_mod[fk_type][fk_r][i]);

for (j=fk_x;j

{

if(temp&0x01)

{

fk_dot(j,fk_y+i);

}

temp>>=1;

}

}

fk_oldx=fk_x;fk_oldy=fk_y;fk_oldr=fk_r;//保存新方块位置

}

//--------------------------------------------------------------------------//

void fk_refnew(void)//刷新预览方块

{

uchar i,j;

uchar temp;

//----------------------------------------------//预览方块

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

{

temp=(fk_mod[fk_newtype][fk_newr][i]);

for (j=NEWX;j

{

if(temp&0x01)

{

fk_dot(j,NEWY+i);

}

else

{

fk_cldot(j,NEWY+i);

}

temp>>=1;

}

}

}

//--------------------------------------------------------------------------//

void fk_refline(yy)//刷新1行背景

{

uchar i;

uint temp;

if (yy>=4)

{

temp=fk_map[yy];

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

{

if ((temp&0x01) !=0)

fk_dot(i,yy);

else

fk_cldot(i,yy);

temp >>= 1;

}

}

}

//--------------------------------------------------------------------------//

bit fk_chk(void)//冲突检查

{

uchar i;

bit neq=0;

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

{

if ( (((fk_mod[fk_type][fk_r][i])<

neq=1;

}

return(neq);

}

//--------------------------------------------------------------------------//

void fk_new(void)//产生新方块

{

srand(rand()+fk_x+fk_y+fk_r);

fk_oldx=fk_x=5;

fk_oldy=fk_y=LINEMAX;

fk_type = fk_newtype;

fk_oldr=fk_newr;

fk_newtype = rand()%7;

fk_newr=rand()%4;

fk_refnew();//刷新预览方块

if (fk_run)

fk_reffk();//刷新显示

}

//--------------------------------------------------------------------------//

void fk_add(void)//方块合并

{

uchar i,j;

uchar full=0x00;

uchar fulltemp;

uchar fullline=0x00;

for (i=0;i<4;i++)//方块合并

{

fk_map[fk_y+i] |= (fk_mod[fk_type][fk_r][i])<

full <<= 1;

if ((fk_y+i >= 4) && (fk_map[fk_y+i] == 0xffff))//满行

{

full |= 0x01;

}

}

if (full != 0)//有满行

{

for (j=0;j<3;j++)//消行闪烁3次

{

delay(300);

fulltemp=full;

for (i=0;i<4;i++)//4行

{

if ((fulltemp&0x08) != 0)

{

fk_map[fk_y+i] ^= FULLMAP;

}

fk_refline(fk_y+i);

fulltemp <<= 1;

}

}

fulltemp=full;

for (i=fk_y;i

{

if ((i < LINEMAX+4)&&(fk_map[i-fullline]!=fk_map[i]))

{

fk_map[i-fullline]=fk_map[i];

fk_refline(i-fullline);

}

if ((i >= LINEMAX+4)&&(fk_map[i-fullline]!=~FULLMAP))

{

fk_map[i-fullline]=~FULLMAP;//背景映象

fk_refline(i-fullline);

}

if ((fulltemp&0x08) != 0)

{

fullline++;

}

fulltemp <<= 1;

}

if (((line+fullline)/LINEGUAN) != (line/LINEGUAN))//每20行速度+1

speed ++;

line += fullline;//更新分数、行数

score += (1<

printat(46,180,strmap[fullline-1]);//夸奖

fk_show();//显示分数

fk_new();//产生新方块

}

else

{

if (fk_y > LINEMAX-10)//在最高位置碰撞且不能消行则游戏结束

printat(46,180,"加油啊!");//加油啊

if (fk_y > LINEMAX-6)//在最高位置碰撞且不能消行则游戏结束

printat(46,180,"糟糕了!");//糟糕了

if (fk_y==LINEMAX)//在最高位置碰撞且不能消行则游戏结束

fk_run=0;//方块初始化

else

fk_new();//产生新方块

}

}

//--------------------------------------------------------------------------//

void fk_init(void)//方块初始化

{

uchar i;

fk_run = 0;

moven=0;

Lcd6963Cls();

Lcd6963Rec(0,0,152,255);

Lcd6963ChHz(0);//切换到16X16点阵

printat(2, 16,"欢迎光临文君阁");

printat(2, 48,"请按键选择:");

printat(2, 80,"-----------------");

printat(2, 96,"7左旋 8右旋 9右旋");

printat(2, 112,"4左移 5右旋 6右移");

printat(2, 128,"4速度 5开始 6关数");

printat(2, 144,"1左移 2下移 3右移");

printat(2, 160,"-----------------");

Lcd6963ChHz(1);//切换到12X12点阵

printat(46,180,"欢迎使用");

fk_show();//显示分数

while (~fk_run)

{

fk_move();//等待设置速度关数开始

delay(10);

}

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

{

fk_map[i]=0xffff;//背景映象

}delay(3000);

for (i=4;i

{

if (i<(automapn+4))

fk_map[i]=rand()-1|~FULLMAP; //背景映象

else

fk_map[i]=~FULLMAP;//背景映象

fk_refline(i);//刷新1行背景

}

fk_show();//显示分数

//fk_new();//产生新方块

}

//--------------------------------------------------------------------------//

void fk_move(void)//移动方块

{

unsigned char temp;

if(KeyTest())//检查有无按键

{

putinbuf(KeyGetcode());//按键码输入接收缓冲区

}

if (checkin())

{

temp=getbyte();

if (temp!=0) Lcd16Wrcharhh(12,0,temp);

if (temp!=0) Lcd16Wrchar(15,0,temp);

putchar(temp);

}

else

temp=0xff;//无键设为无效键用于下移方块

temp -= '0';

switch(temp)

{

default:

if (--moven)//游戏难度

break;

else

{

moven=(252>>speed)+2;

}

case 2://下移

if (fk_run)//游戏中下移

{

if(fk_y>0)

{

fk_y--;

if(fk_chk())

{

fk_y++;//有冲突取消操作,执行碰撞组合

fk_add();//方块合并//产生新方块

}

}

else//方块到底也执行碰撞组合

{

fk_add();//方块合并

}

}

else//初始化时

{

fk_new();//产生新方块

}

break;

case 0://下移到底

while((fk_y>0)&&~(fk_chk())) //一直下移直到冲突

{

fk_y--;

}

moven=1;

fk_y++;//恢复到未冲突位置

break;

case 3://右移

case 6://右移

if (fk_run)//游戏中右移

{

if(fk_x<12)

{

fk_x++;

if(fk_chk())

fk_x--;//有冲突取消操作

}

}

else//初始化时

{

automapn++;

automapn &= 0x0f;

fk_show();//显示分数

}

break;

case 1://左移

case 4://移

if (fk_run)//游戏中左移

{

if(fk_x>0)

{

fk_x--;

if(fk_chk())

fk_x++;//有冲突取消操作

}

}

else//初始化时

{

speed++;

speed &= 0x07;

fk_show();//显示分数

}

break;

case 9://右转

case 8://右转

case 5://右转

if (fk_run)//游戏中右转

{

fk_r++;

if(fk_chk())

fk_r--;//有冲突取消操作

fk_r &= 0x03;

}

else//初始化时

{

fk_run = 1;

}

break;

case 7://左转

if (fk_run)//游戏中右转

{

fk_r--;

if(fk_chk())

fk_r++;//有冲突取消操作

fk_r &= 0x03;

}

else//初始化时

{

fk_run = 1;

}

break;

}

if((fk_run)&& ((fk_x!=fk_oldx)||(fk_y!=fk_oldy)||(fk_r!=fk_oldr)) )

{

fk_reffk();//刷新显示

}

rand();

}

/*

// ---------------------------------------------- //32字节

void delay(uint x)

{

uint i,j;

for (i=0; i

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

}

}

//--------------------------------------------------------------------------//

void main(void)// 测试用

{

serial_init();

Lcd6963Init();//Lcd6963复位

Lcd16Reset();//Lcd16复位

Serial_main();//串口测试用主函数

Lcd16main();//Lcd16临时测试主程序

Lcd6963main();//Lcd6963测试用

fk_init();//方块初始化

while(1)

{

if (~fk_run)

fk_init();//方块初始化

fk_move();//移动方块

delay(10);

}

}

可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号