51单片机点阵屏实现俄罗斯方块

这篇具有很好参考价值的文章主要介绍了51单片机点阵屏实现俄罗斯方块。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

文章目录

前言

一、关于点阵屏

二、俄罗斯方块代码部分

1.main主函数

2.按键扫描

3.方块生成

4.方块显示 

5.方块下降 

 6.固定的方块显示

7.方块的左右移动

8.键值的判断与执行 

9.方块的旋转 

 10.总代码

总结


前言

这里采用的是清翔51单片机,通过独立键盘实现左右移动和旋转,通过8×8点阵屏显示


一、关于点阵屏

51单片机点阵屏实现俄罗斯方块

 51单片机点阵屏实现俄罗斯方块

 行选值默认是低电平0,列选值默认是高电平1,通过74HC595芯片可以将数据进行串入并出输入然后就可以显示了。

二、俄罗斯方块代码部分

1.main主函数

从主函数开始看会清晰很多。

void main()
{
	uchar j, k, i;
	for (j = 0; j < 8; j++)
		for (k = 0; k < 9; k++)
			axis[j][k] = 1;//8×8点阵屏上面的每一个点都初始化为1(1代表点亮,0代表熄灭),这样便于后面显示
	timer0Init();//定时器0初始化
	while (1)
	{
		scan();//判断键值,并通过键值执行相应指令
		if (a)
		{
			Random();//生成一个随机图形(仅生成一次)
			a = 0;
		}
		if (m == 40)
		{
			down();//定时器没定时一次m++,m到40的时候图形下降一格
			m = 0;
		}
		Clear();//判断有没有一行全部点亮,有就消除
		for (i = 0; i < 8; i++)
		{
			if (axis[i][8] == 0)//判断游戏结束
				return;
		}
	}
}

首先定义了一个二维数组用来存放点阵屏64个点的状态,通过0,1的方式存储,这样存储的好处是在显示图像的时候可以通过运算把每一行的值给算出来并通过74HC595这个芯片传给点阵屏。这个二维数组设置为[8][9]是因为最上面要有一行用来判断游戏是否结束的,最上面一行一旦出现0,那么游戏结束 。

uchar axis[8][9] = { 0 };

 通过下面这种方式算出其行值

axis[0][i] * 128 + axis[1][i] * 64 + axis[2][i] * 32 + axis[3][i] * 16 + axis[4][i] * 8 + axis[5][i] * 4 + axis[6][i] * 2 + axis[7][i] * 1

 接下来是定时器中断的配置以及内容

void timer0Init()
{
	EA = 1;
	ET0 = 1;
	TR0 = 1;
	TMOD = 0X01;
	TH0 = 0XDD;
	TL0 = 0XFF;
}
void timer0() interrupt 1
{
	TH0 = 0XDD;
	TL0 = 0XFF;
	m++;
	KeyScan();//按键扫描
	for (d = 0; d < 4; d++)
	{
		if (yy[d] <= 8 && yy[d] >= 1)
			displaymove(coorx[xx[d] - 1], coory[yy[d] - 1]);//对于活动的图形的显示
	}
	displayfixed();//对于已经固定的图形显示
}

 这里也可以看出来我把显示图像分成了两部分

2.按键扫描

要想实现方块的左右移动以及图形旋转就要用到键盘,所以这里先展示键盘部分代码,键盘为了保证单片机能立刻反应,最好放在定时器中断里面,我只用到了3个按键,第一个是左移,第二个是顺时针旋转,第四个是右移,第三个按键可以自己设计,比如加速下落,逆时针旋转之类的。

void KeyScan()
{
	if (key_s2 == 0)
	{
		delay(10);
		if (key_s2 == 0)
		{
			key = 1;
		}
	}
	if (key_s3 == 0)
	{
		delay(10);
		if (key_s3 == 0)
		{
			key = 2;
		}
	}
	if (key_s4 == 0)//这一个按键其实没用到
	{
		delay(10);
		if (key_s4 == 0)
		{
			key = 3;
		}
	}
	if (key_s5 == 0)
	{
		delay(10);
		if (key_s5 == 0)
		{
			key = 4;
		}
	}
}

3.方块生成

方块生成就要用到随机函数了由于每个方块都是由4个小方块组成的,所以我这里又定义了2个数组分别代表每个方块的坐标,关于坐标, x轴是1到8,y轴是1到12,因为生成的图形要慢慢显示出来所以在最上方留了4行,所以下面坐标会出现9到12。我的代码比较繁琐,我把每一种情况都列了出来,没想到什么更好的方法。.

uchar xx[4];
uchar yy[4];
void Random()
{
	ran = rand() % 19 + 1;
	switch (ran)
	{
	case 1:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 4; yy[2] = 10; xx[3] = 4; yy[3] = 11; break;
	case 2:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 6; yy[3] = 10; break;
	case 3:xx[0] = 5; yy[0] = 9; xx[1] = 5; yy[1] = 10; xx[2] = 4; yy[2] = 11; xx[3] = 5; yy[3] = 11; break;
	case 4:xx[0] = 3; yy[0] = 9; xx[1] = 4; yy[1] = 9; xx[2] = 5; yy[2] = 9; xx[3] = 5; yy[3] = 10; break;
	case 5:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 5; yy[2] = 10; xx[3] = 5; yy[3] = 11; break;
	case 6:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 6; yy[2] = 9; xx[3] = 4; yy[3] = 10; break;
	case 7:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 4; yy[2] = 11; xx[3] = 5; yy[3] = 11; break;
	case 8:xx[0] = 5; yy[0] = 9; xx[1] = 3; yy[1] = 10; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	case 9:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 6; yy[2] = 9; xx[3] = 5; yy[3] = 10; break;
	case 10:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 4; yy[3] = 11; break;
	case 11:xx[0] = 4; yy[0] = 9; xx[1] = 3; yy[1] = 10; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	case 12:xx[0] = 5; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 5; yy[3] = 11; break;
	case 13:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 3; yy[2] = 10; xx[3] = 4; yy[3] = 10; break;
	case 14:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 5; yy[3] = 11; break;
	case 15:xx[0] = 5; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 4; yy[3] = 11; break;
	case 16:xx[0] = 3; yy[0] = 9; xx[1] = 4; yy[1] = 9; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	case 17:xx[0] = 3; yy[0] = 9; xx[1] = 4; yy[1] = 9; xx[2] = 5; yy[2] = 9; xx[3] = 6; yy[3] = 9; break;
	case 18:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 4; yy[2] = 11; xx[3] = 4; yy[3] = 12; break;
	case 19:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	}
}

然后我把每一个ran值对应的图形给出来

1.
0 0 0 0
0 2 0 0
0 2 0 0
0 2 2 0

2.
0 0 0 0
0 0 0 0
0 2 2 2
0 2 0 0

3.
0 0 0 0
0 2 2 0
0 0 2 0
0 0 2 0

4.
0 0 0 0
0 0 0 0
0 0 2 0
2 2 2 0

5.
0 0 0 0
0 0 2 0
0 0 2 0
0 2 2 0

6.
0 0 0 0
0 0 0 0
0 2 0 0
0 2 2 2

7.
0 0 0 0
0 2 2 0
0 2 0 0
0 2 0 0

8.
0 0 0 0
0 0 0 0
2 2 2 0
0 0 2 0

9.
0 0 0 0
0 0 0 0
0 0 2 0
0 2 2 2

10.
0 0 0 0 
0 2 0 0
0 2 2 0
0 2 0 0

11.
0 0 0 0
0 0 0 0
2 2 2 0
0 2 0 0

12.
0 0 0 0
0 0 2 0
0 2 2 0
0 0 2 0

13.
0 0 0 0
0 0 0 0
2 2 0 0
0 2 2 0

14.
0 0 0 0
0 0 2 0
0 2 2 0
0 2 0 0

15.
0 0 0 0
0 2 0 0
0 2 2 0
0 0 2 0

16.
0 0 0 0
0 0 0 0
0 2 2 0
2 2 0 0

17.
0 0 0 0
0 0 0 0
0 0 0 0
2 2 2 2

18.
0 2 0 0
0 2 0 0
0 2 0 0
0 2 0 0

19.
0 0 0 0
0 0 0 0
0 2 2 0
0 2 2 0

4.方块显示 

方块既然生成了,总得让他显示吧,而这个显示是实时的所以放在中断里面,而这个方块坐标的数据是不能传给点阵屏的,所以需要将坐标转化,于是就引入了这两个数组。举个例子,坐标是(1,1)那么就把coorx[1-1],coory[1-1]传进去这样(1, 1)这个点就能显示了。同样的道理,对四个点进行扫描,就可以显示出方块了

uchar coorx[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
uchar coory[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
void SendByte(uchar dat)
{
	uchar i;
	S_CLK = 0;
	R_CLK = 0;
	for (i = 0; i < 8; i++)
	{
		if (dat & 0x01)
			DIO = 1;
		else
			DIO = 0;
		S_CLK = 1;
		S_CLK = 0;
		dat >>= 1;
	}
}

void displaymove(uchar dat1, uchar dat2)
{
	SendByte(dat1);
	SendByte(dat2);
	R_CLK = 1;
	R_CLK = 0;
}

 这里if说一下,由于坐标设置的是9到12行的地方,超出了点阵屏的范围,所以要设置一个范围约束一下,等到下降的时候就可以显示了。

for (d = 0; d < 4; d++)
	{
		if (yy[d] <= 8 && yy[d] >= 1)
			displaymove(coorx[xx[d] - 1], coory[yy[d] - 1]);//对于活动的图形的显示
	}

5.方块下降 

这一步挺麻烦的,要考虑很多东西,这里补充一下,对于方块的生成,我对每一个小方块是按次序编号的,按从左往右,从下往上的次序,所以这里判定是否到达下边界的代码中我直接使用了if (yy[0] <= 1)yy[0]肯定是最下面的那个方块,如果最下面那个碰到下边界就停止了。

void down()
{
	uchar n;
	if (yy[0] <= 1)
	{
		for (n = 0; n < 4; n++)
		{
			axis[xx[n] - 1][yy[n] - 1] = 0;//碰到边界了,此时这四个点的状态置为0,之后会将这个方块显示出来
		}
		Random();//方块停止了,需要重新生成方块
	}
	else
	{
		if (yy[0] <= 9 && yy[1] <= 9 && yy[2] <= 9 && yy[3] <= 9)//约束范围,防止越界
		{
			if (axis[xx[0] - 1][yy[0] - 2] == 1 && axis[xx[1] - 1][yy[1] - 2] == 1 && axis[xx[2] - 1][yy[2] - 2] == 1 && axis[xx[3] - 1][yy[3] - 2] == 1)//判断下一个方块下移过程中是否碰到了已经被固定了的方块,如果碰到就不下降了
			{
				for (n = 0; n < 4; n++)
				{
					yy[n]--;
				}
			}
			else
			{
				for (n = 0; n < 4; n++)
				{
					axis[xx[n] - 1][yy[n] - 1] = 0;//如果方块被固定了,那么这个方块所在的位置的状态就会被赋给axis,便于后续的显示
				}
				Random();
			}
		}
		else
		{
			for (n = 0; n < 4; n++)
			{
				yy[n]--;
			}
		}
	}
}

 6.固定的方块显示

由于xx,yy只能代表一个方块,而且在重新生成方块时他们又会被重新赋值,所以已经被固定的方块可以通过axis代表状态的这个数组显示出来,在上面的代码中,已经被固定的方块被固定的那几个位置的状态0被赋值到了axis,问题就是我们要如何通过这个数组显示出那些被固定住的方块。这就体现我把状态设为1和0的原因了。

我们通常传给单片机的数据都是16进制,原因是方便简单,这里我要传的是10进制的数。

这里我们又需要定义一个数组trans[8]用来存放col值

uchar trans[8] = { 0 };
void displayfixed()
{
	uchar i;
	for (i = 0; i < 8; i++)
	{
		trans[i] = axis[0][i] * 128 + axis[1][i] * 64 + axis[2][i] * 32 + axis[3][i] * 16 + axis[4][i] * 8 + axis[5][i] * 4 + axis[6][i] * 2 + axis[7][i] * 1;//将col值运算出来存入trans中,并传给点阵屏
		SendByte(trans[i]);
		SendByte(coory[i]);
		R_CLK = 1;
		R_CLK = 0;
	}
}

这边其实又用到了coory[],这里代表的是row的值,这样行选值和列选值都传进去了,只要把函数再放进中断里面就行了。 

7.方块的左右移动

这个要注意不能越界,也就是左右边界,所以需要加下面的if判断

void left()
{
	uchar i;
	if (xx[0] >= 2 && xx[1] >= 2 && xx[2] >= 2 && xx[3] >= 2)
		for (i = 0; i < 4; i++)
		{
			xx[i]--;
		}
}

void right()
{
	uchar i;
	if (xx[0] <= 7 && xx[1] <= 7 && xx[2] <= 7 && xx[3] <= 7)
		for (i = 0; i < 4; i++)
		{
			xx[i]++;
		}
}

8.键值的判断与执行 

void scan()
{
	if (key == 1)
	{
		left();
		key = 5;
	}
	if (key == 2)
	{
		Dextrorotary();
		key = 5;
	}
	if (key == 4)
	{
		right();
		key = 5;
	}
}

9.方块的旋转 

这个我想不出更好的办法了,只能一个个写,挺费时间的,而且代码也很繁琐,这里用的办法就是一个一个分析我以第一个L形为例。加了if是因为如果在右边界,这个方块是不能转的,一转方块的一个脚就会出界,下面的if也是同样的道理,所以加了来限制一下,原理就是把第一个图形的样子通过坐标平移,一顿操作将第一个图形的样子变成第二个图形的样子,然后由于样子变了,所以ran也要变,因为ran的每一个值都代表一个图形。这里可以根据上面的那些图形编程。

void Dextrorotary()
{
	switch (ran)
	{
	case 1:if (xx[0] + 2 <= 8)xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] + 1; xx[3] = xx[3] + 2; yy[3] = yy[3] - 1; ran = 2; break;
	case 2:xx[0] = xx[0] + 1; xx[1] = xx[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 3; break;
	case 3:if (xx[0] - 2 >= 1)xx[0] = xx[0] - 2; xx[1] = xx[1] - 1; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[2] = yy[2] - 2; yy[3] = yy[3] - 1; ran = 4; break;
	case 4:xx[0] = xx[0] + 1; xx[1] = xx[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 1; break;
	case 5:if (xx[0] + 2 <= 8)xx[2] = xx[2] + 1; yy[2] = yy[2] - 1; xx[3] = xx[3] - 1; yy[3] = yy[3] - 1; ran = 6; break;
	case 6:xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] - 2; yy[2] = yy[2] + 2; xx[3] = xx[3] + 1; yy[3] = yy[3] + 1; ran = 7; break;
	case 7:if (xx[0] - 1 >= 1)xx[0] = xx[0] + 1; xx[1] = xx[1] - 1; yy[2] = yy[2] - 1; yy[3] = yy[3] - 1; ran = 8; break;
	case 8:xx[0] = xx[0] - 1; xx[1] = xx[1] + 2; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[3] = yy[3] + 1; ran = 5; break;
	case 9:xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 10; break;
	case 10:if (xx[0] - 1 >= 1)xx[1] = xx[1] - 1; xx[2] = xx[2] - 1; xx[3] = xx[3] + 1; yy[3] = yy[3] - 1; ran = 11; break;
	case 11:xx[0] = xx[0] + 1; xx[1] = xx[1] + 1; xx[2] = xx[2] + 1; yy[3] = yy[3] + 1; ran = 12; break;
	case 12:xx[0] = xx[0] - 1; xx[1] = xx[1] + 1; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[2] = yy[2] - 1; yy[3] = yy[3] - 1; ran = 9; break;
	case 13:xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] + 2; xx[3] = xx[3] + 1; yy[3] = yy[3] + 1; ran = 14; break;
	case 14:if (xx[0] - 1 >= 1)xx[1] = xx[1] + 1; yy[1] = yy[1] - 1; xx[2] = xx[2] - 2; xx[3] = xx[3] - 1; yy[3] = yy[3] - 1; ran = 13; break;
	case 15:xx[0] = xx[0] + 2; xx[1] = xx[1] + 1; yy[1] = yy[1] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 16; break;
	case 16:xx[0] = xx[0] + 2; yy[1] = yy[1] + 1; xx[2] = xx[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 15; break;
	case 17:xx[0] = xx[0] + 1; yy[1] = yy[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 2; xx[3] = xx[3] - 2; yy[3] = yy[3] + 3; ran = 18; break;
	case 18:if (xx[0] - 1 >= 1 && xx[0] + 2 <= 8)xx[0] = xx[0] - 1; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[2] = yy[2] - 2; xx[3] = xx[3] + 2; yy[3] = yy[3] - 3; ran = 17; break;
	}
}

 10.总代码

#include <reg52.h>
#include <stdlib.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char

sbit key_s2 = P3 ^ 0;
sbit key_s3 = P3 ^ 1;
sbit key_s4 = P3 ^ 2;
sbit key_s5 = P3 ^ 3;
sbit DIO = P3 ^ 4;
sbit S_CLK = P3 ^ 5;
sbit R_CLK = P3 ^ 6;

uchar key;
uchar d;
uchar ran;
uchar a = 1;
uchar m = 0;
uchar xx[4];
uchar yy[4];
uchar axis[8][9] = { 0 };
uchar trans[8] = { 0 };
uchar coorx[8] = { 0x7f, 0xbf, 0xdf, 0xef, 0xf7, 0xfb, 0xfd, 0xfe };
uchar coory[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };

void delay(uint z)
{
	uint x, y;
	for (x = z; x > 0; x--)
		for (y = 114; y > 0; y--);
}

void KeyScan()
{
	if (key_s2 == 0)
	{
		delay(10);
		if (key_s2 == 0)
		{
			key = 1;
		}
	}
	if (key_s3 == 0)
	{
		delay(10);
		if (key_s3 == 0)
		{
			key = 2;
		}
	}
	if (key_s4 == 0)//这一个按键其实没用到
	{
		delay(10);
		if (key_s4 == 0)
		{
			key = 3;
		}
	}
	if (key_s5 == 0)
	{
		delay(10);
		if (key_s5 == 0)
		{
			key = 4;
		}
	}
}

void SendByte(uchar dat)
{
	uchar i;
	S_CLK = 0;
	R_CLK = 0;
	for (i = 0; i < 8; i++)
	{
		if (dat & 0x01)
			DIO = 1;
		else
			DIO = 0;
		S_CLK = 1;
		S_CLK = 0;
		dat >>= 1;
	}
}

void displaymove(uchar dat1, uchar dat2)
{
	SendByte(dat1);
	SendByte(dat2);
	R_CLK = 1;
	R_CLK = 0;
}

void displayfixed()
{
	uchar i;
	for (i = 0; i < 8; i++)
	{
		trans[i] = axis[0][i] * 128 + axis[1][i] * 64 + axis[2][i] * 32 + axis[3][i] * 16 + axis[4][i] * 8 + axis[5][i] * 4 + axis[6][i] * 2 + axis[7][i] * 1;//将col值运算出来存入trans中,并传给点阵屏
		SendByte(trans[i]);
		SendByte(coory[i]);
		R_CLK = 1;
		R_CLK = 0;
	}
}

void Random()
{
	ran = rand() % 19 + 1;
	switch (ran)
	{
	case 1:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 4; yy[2] = 10; xx[3] = 4; yy[3] = 11; break;
	case 2:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 6; yy[3] = 10; break;
	case 3:xx[0] = 5; yy[0] = 9; xx[1] = 5; yy[1] = 10; xx[2] = 4; yy[2] = 11; xx[3] = 5; yy[3] = 11; break;
	case 4:xx[0] = 3; yy[0] = 9; xx[1] = 4; yy[1] = 9; xx[2] = 5; yy[2] = 9; xx[3] = 5; yy[3] = 10; break;
	case 5:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 5; yy[2] = 10; xx[3] = 5; yy[3] = 11; break;
	case 6:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 6; yy[2] = 9; xx[3] = 4; yy[3] = 10; break;
	case 7:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 4; yy[2] = 11; xx[3] = 5; yy[3] = 11; break;
	case 8:xx[0] = 5; yy[0] = 9; xx[1] = 3; yy[1] = 10; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	case 9:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 6; yy[2] = 9; xx[3] = 5; yy[3] = 10; break;
	case 10:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 4; yy[3] = 11; break;
	case 11:xx[0] = 4; yy[0] = 9; xx[1] = 3; yy[1] = 10; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	case 12:xx[0] = 5; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 5; yy[3] = 11; break;
	case 13:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 3; yy[2] = 10; xx[3] = 4; yy[3] = 10; break;
	case 14:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 5; yy[3] = 11; break;
	case 15:xx[0] = 5; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 5; yy[2] = 10; xx[3] = 4; yy[3] = 11; break;
	case 16:xx[0] = 3; yy[0] = 9; xx[1] = 4; yy[1] = 9; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	case 17:xx[0] = 3; yy[0] = 9; xx[1] = 4; yy[1] = 9; xx[2] = 5; yy[2] = 9; xx[3] = 6; yy[3] = 9; break;
	case 18:xx[0] = 4; yy[0] = 9; xx[1] = 4; yy[1] = 10; xx[2] = 4; yy[2] = 11; xx[3] = 4; yy[3] = 12; break;
	case 19:xx[0] = 4; yy[0] = 9; xx[1] = 5; yy[1] = 9; xx[2] = 4; yy[2] = 10; xx[3] = 5; yy[3] = 10; break;
	}
}

void down()
{
	uchar n;
	if (yy[0] <= 1)
	{
		for (n = 0; n < 4; n++)
		{
			axis[xx[n] - 1][yy[n] - 1] = 0;//碰到边界了,此时这四个点的状态置为0,之后会将这个方块显示出来
		}
		Random();//方块停止了,需要重新生成方块
	}
	else
	{
		if (yy[0] <= 9 && yy[1] <= 9 && yy[2] <= 9 && yy[3] <= 9)//约束范围,防止越界
		{
			if (axis[xx[0] - 1][yy[0] - 2] == 1 && axis[xx[1] - 1][yy[1] - 2] == 1 && axis[xx[2] - 1][yy[2] - 2] == 1 && axis[xx[3] - 1][yy[3] - 2] == 1)//判断下一个方块下移过程中是否碰到了已经被固定了的方块,如果碰到就不下降了
			{
				for (n = 0; n < 4; n++)
				{
					yy[n]--;
				}
			}
			else
			{
				for (n = 0; n < 4; n++)
				{
					axis[xx[n] - 1][yy[n] - 1] = 0;//如果方块被固定了,那么这个方块所在的位置的状态就会被赋给axis,便于后续的显示
				}
				Random();
			}
		}
		else
		{
			for (n = 0; n < 4; n++)
			{
				yy[n]--;
			}
		}
	}
}

void left()
{
	uchar i;
	if (xx[0] >= 2 && xx[1] >= 2 && xx[2] >= 2 && xx[3] >= 2)
		for (i = 0; i < 4; i++)
		{
			xx[i]--;
		}
}

void right()
{
	uchar i;
	if (xx[0] <= 7 && xx[1] <= 7 && xx[2] <= 7 && xx[3] <= 7)
		for (i = 0; i < 4; i++)
		{
			xx[i]++;
		}
}

void Dextrorotary()
{
	switch (ran)
	{
	case 1:if (xx[0] + 2 <= 8)xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] + 1; xx[3] = xx[3] + 2; yy[3] = yy[3] - 1; ran = 2; break;
	case 2:xx[0] = xx[0] + 1; xx[1] = xx[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 3; break;
	case 3:if (xx[0] - 2 >= 1)xx[0] = xx[0] - 2; xx[1] = xx[1] - 1; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[2] = yy[2] - 2; yy[3] = yy[3] - 1; ran = 4; break;
	case 4:xx[0] = xx[0] + 1; xx[1] = xx[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 1; break;
	case 5:if (xx[0] + 2 <= 8)xx[2] = xx[2] + 1; yy[2] = yy[2] - 1; xx[3] = xx[3] - 1; yy[3] = yy[3] - 1; ran = 6; break;
	case 6:xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] - 2; yy[2] = yy[2] + 2; xx[3] = xx[3] + 1; yy[3] = yy[3] + 1; ran = 7; break;
	case 7:if (xx[0] - 1 >= 1)xx[0] = xx[0] + 1; xx[1] = xx[1] - 1; yy[2] = yy[2] - 1; yy[3] = yy[3] - 1; ran = 8; break;
	case 8:xx[0] = xx[0] - 1; xx[1] = xx[1] + 2; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[3] = yy[3] + 1; ran = 5; break;
	case 9:xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 10; break;
	case 10:if (xx[0] - 1 >= 1)xx[1] = xx[1] - 1; xx[2] = xx[2] - 1; xx[3] = xx[3] + 1; yy[3] = yy[3] - 1; ran = 11; break;
	case 11:xx[0] = xx[0] + 1; xx[1] = xx[1] + 1; xx[2] = xx[2] + 1; yy[3] = yy[3] + 1; ran = 12; break;
	case 12:xx[0] = xx[0] - 1; xx[1] = xx[1] + 1; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[2] = yy[2] - 1; yy[3] = yy[3] - 1; ran = 9; break;
	case 13:xx[1] = xx[1] - 1; yy[1] = yy[1] + 1; xx[2] = xx[2] + 2; xx[3] = xx[3] + 1; yy[3] = yy[3] + 1; ran = 14; break;
	case 14:if (xx[0] - 1 >= 1)xx[1] = xx[1] + 1; yy[1] = yy[1] - 1; xx[2] = xx[2] - 2; xx[3] = xx[3] - 1; yy[3] = yy[3] - 1; ran = 13; break;
	case 15:xx[0] = xx[0] + 2; xx[1] = xx[1] + 1; yy[1] = yy[1] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 16; break;
	case 16:xx[0] = xx[0] + 2; yy[1] = yy[1] + 1; xx[2] = xx[2] + 1; xx[3] = xx[3] - 1; yy[3] = yy[3] + 1; ran = 15; break;
	case 17:xx[0] = xx[0] + 1; yy[1] = yy[1] + 1; xx[2] = xx[2] - 1; yy[2] = yy[2] + 2; xx[3] = xx[3] - 2; yy[3] = yy[3] + 3; ran = 18; break;
	case 18:if (xx[0] - 1 >= 1 && xx[0] + 2 <= 8)xx[0] = xx[0] - 1; yy[1] = yy[1] - 1; xx[2] = xx[2] + 1; yy[2] = yy[2] - 2; xx[3] = xx[3] + 2; yy[3] = yy[3] - 3; ran = 17; break;
	}
}

void Clear()
{
	uchar i;
	for (i = 0; i < 8; i++)
	{
		if (axis[0][i] + axis[1][i] + axis[2][i] + axis[3][i] + axis[4][i] + axis[5][i] + axis[6][i] + axis[7][i] == 0)
		{
			uchar j, k;
			for (j = i; j < 8; j++)
			{
				for (k = 0; k < 8; k++)
				{
					axis[k][j] = axis[k][j + 1];
				}
			}
		}
	}
}

void scan()
{
	if (key == 1)
	{
		left();
		key = 5;
	}
	if (key == 2)
	{
		Dextrorotary();
		key = 5;
	}
	if (key == 4)
	{
		right();
		key = 5;
	}
}

void timer0Init()
{
	EA = 1;
	ET0 = 1;
	TR0 = 1;
	TMOD = 0X01;
	TH0 = 0XDD;
	TL0 = 0XFF;
}

void main()
{
	uchar j, k, i;
	for (j = 0; j < 8; j++)
		for (k = 0; k < 9; k++)
			axis[j][k] = 1;//8×8点阵屏上面的每一个点都初始化为1(1代表点亮,0代表熄灭),这样便于后面显示
	timer0Init();//定时器0初始化
	while (1)
	{
		scan();//判断键值,并通过键值执行相应指令
		if (a)
		{
			Random();//生成一个随机图形(仅生成一次)
			a = 0;
		}
		if (m == 40)
		{
			down();//定时器没定时一次m++,m到40的时候图形下降一格
			m = 0;
		}
		Clear();//判断有没有一行全部点亮,有就消除
		for (i = 0; i < 8; i++)
		{
			if (axis[i][8] == 0)//判断游戏结束
				return;
		}
	}
}

void timer0() interrupt 1
{
	TH0 = 0XDD;
	TL0 = 0XFF;
	m++;
	KeyScan();//按键扫描
	for (d = 0; d < 4; d++)
	{
		if (yy[d] <= 8 && yy[d] >= 1)
			displaymove(coorx[xx[d] - 1], coory[yy[d] - 1]);//对于活动的图形的显示
	}
	displayfixed();//对于已经固定的图形显示
}

总结

希望对你们有所帮助,如有不足还望指正。文章来源地址https://www.toymoban.com/news/detail-500851.html

到了这里,关于51单片机点阵屏实现俄罗斯方块的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 51单片机驱动点阵屏

    目录 1设计目的 2设计方案 2.1材料选择 2.2电源设计 2.3控制设计 3焊接调试 3.1焊接 3.2调试 4程序 此次设计的东西是一个点阵屏,通过点阵屏实现电梯屏幕功能。显示内容包括向上运行箭头和向下运行箭头,以及1-12的楼层。 点阵屏采用3*4=12块点阵屏拼接而成,采用串联方式。

    2024年01月22日
    浏览(46)
  • 51单片机8*8点阵屏

    8*8点阵屏是一种LED显示屏,它由8行和8列的LED灯组成。每个LED灯的开闭状态都可以独立控制,从而可以显示出数字、字母、符号、图形等信息。 8*8点阵屏的原理是通过行列扫描的方式,控制LED灯的亮灭,从而显示出所需的图案或信息。通过逐行逐列地控制LED的亮灭,就可以在

    2024年01月21日
    浏览(39)
  • 【51单片机】LED点阵屏

    🎊专栏【51单片机】 🍔喜欢的诗句:更喜岷山千里雪 三军过后尽开颜。 🎆音乐分享【Waiting For Love】 大一同学小吉,欢迎并且感谢大家指出我的问题🥰 目录 🍔74HC595图片 🍔74HC595原理 🍔”上升沿“是什么意思 🎆LED点阵屏显示图形  🎈现象  🎈代码(三部分) main.c  Del

    2024年02月02日
    浏览(43)
  • 51单片机LED点阵屏

    LED点阵屏是一种由许多小型LED灯组成的矩阵式显示屏。这些LED灯可以是单色、双色或全彩的,它们排列成行和列的网格,可以根据需要点亮来显示图像、文字或动画等内容。LED点阵屏广泛应用于户外广告牌、室内显示、交通信号灯、电子价格标签和其他需要显示信息的场合。

    2024年01月23日
    浏览(51)
  • 51单片机 点阵矩阵 坤坤代码

    2024年02月05日
    浏览(91)
  • 51单片机 8*8LED点阵(入门教学)

    LED 点阵介绍 LED 点阵是由发光二极管排列组成的显示器件,在我们日常生活的电器中随 处可见,被广泛应用于汽车报站器,广告屏等。 通常应用较多的是 8*8 点阵,然后使用多个 8*8 点阵可组成不同分辨率的 LED 点阵显示屏,比如16*16 点阵可以使用 4 个 8*8 点阵构成。因此理解

    2024年02月02日
    浏览(46)
  • 51单片机——LED点阵屏(显示滚动画面)

    目录   一、关于数码管、LED点阵屏显示的注意点 二、功能介绍 三、主要模块的介绍 3.1 74HC595模块和点阵屏显示函数 3.1.1 74HC595介绍 3.1.2 点阵屏显示函数MatrixLED() 3.2定时器中断模块 四、程序实现 五、效果展示   一定要消影,不然显示的画面有重影。不管是数码管还是LED点阵

    2023年04月17日
    浏览(41)
  • 基于51单片机点阵汉字显示程序设计

    本次实践是用51单片机最小系统为核心,并使用4块8×8LED点阵组成的16×16LED点阵、2块74HC595位移寄存器芯片作为16×16LED点阵的行驱动、2块74HC138译码器芯片作为16×16LED点阵的列驱动、和8个独立按键组成的51单片机系统,实现汉字在LED点阵屏幕上进行多种功能的显示:实现静态显

    2024年02月05日
    浏览(45)
  • 51单片机学习--LED点阵屏显示图形&动画

    为了通用性考虑,需要把用到的几个口用特殊位声明来重新命名,由于RCLK在头文件中已有定义,所以这里把P3^5声明成RCK吧。。这样的做法可以提高可读性 接下来编写74HC595的输入函数 执行完八次循环后数据就会存到移位寄存器里面了,接下来要输出只需要给RCLK一个高电平即

    2024年02月14日
    浏览(41)
  • 51单片机——LED 点阵点亮一个点,小白详解

    LED点阵介绍:        LED点阵是由发光二极管排列组成的显示器件,在我们生活中的电器中随处可见,被广泛用于汽车报站器,广告屏等。         通常用用较多的是8*8点阵,然后使用多个8*8点阵组成不同分辨率的LED点阵显示屏,比如16*16点阵可以使用4个8*8点阵构成。因

    2024年02月09日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包