文章目录

前言

一、关于点阵屏

二、俄罗斯方块代码部分

1.main主函数

2.按键扫描

3.方块生成

4.方块显示

5.方块下降

6.固定的方块显示

7.方块的左右移动

8.键值的判断与执行

9.方块的旋转

10.总代码

总结


前言

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


一、关于点阵屏

行选值默认是低电平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 02.
0 0 0 0
0 0 0 0
0 2 2 2
0 2 0 03.
0 0 0 0
0 2 2 0
0 0 2 0
0 0 2 04.
0 0 0 0
0 0 0 0
0 0 2 0
2 2 2 05.
0 0 0 0
0 0 2 0
0 0 2 0
0 2 2 06.
0 0 0 0
0 0 0 0
0 2 0 0
0 2 2 27.
0 0 0 0
0 2 2 0
0 2 0 0
0 2 0 08.
0 0 0 0
0 0 0 0
2 2 2 0
0 0 2 09.
0 0 0 0
0 0 0 0
0 0 2 0
0 2 2 210.
0 0 0 0
0 2 0 0
0 2 2 0
0 2 0 011.
0 0 0 0
0 0 0 0
2 2 2 0
0 2 0 012.
0 0 0 0
0 0 2 0
0 2 2 0
0 0 2 013.
0 0 0 0
0 0 0 0
2 2 0 0
0 2 2 014.
0 0 0 0
0 0 2 0
0 2 2 0
0 2 0 015.
0 0 0 0
0 2 0 0
0 2 2 0
0 0 2 016.
0 0 0 0
0 0 0 0
0 2 2 0
2 2 0 017.
0 0 0 0
0 0 0 0
0 0 0 0
2 2 2 218.
0 2 0 0
0 2 0 0
0 2 0 0
0 2 0 019.
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;elseDIO = 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 charsbit 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;elseDIO = 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();//对于已经固定的图形显示
}

总结

希望对你们有所帮助,如有不足还望指正。

51单片机点阵屏实现俄罗斯方块相关推荐

  1. 51单片机8*8点阵屏、取模软件的使用

    取模软件网盘提取 链接:https://pan.baidu.com/s/1YYQo_tZNCXlo9uWVbtsNdg 提取码:jfbr 74HC595芯片原理图: 两片595芯片级联驱动点阵屏只需要 ...

  2. 【51单片机快速入门指南】2.4:74HC595、LED点阵屏及其SPI控制

    目录 硬知识 IO 口扩展方式-串转并 74HC595 芯片介绍 硬件设计 测试源码 HC74595.c HC74595.h main.h 实验现象 SPI控制 普中51-单核-A2 STC89C52 ...

  3. 单片机汉字点阵c语言程序,51单片机C语言多种点阵屏驱动程序(开发软件为keil C...

    51单片机C语言多种点阵屏驱动程序(开发软件为keil C 2016-08-23 1 0 0 暂无评分 其他 1 积分下载 如何获取积分? 51单片机C语言多种点阵屏驱动程序(开发软件为keil C ...

  4. 51单片机学习笔记-7LED点阵屏

    7 点阵屏 [toc] 注:笔记主要参考B站江科大自化协教学视频"51单片机入门教程-2020版 程序全程纯手打 从零开始入门". 注:工程及代码文件放在了本人的Github仓库. ...

  5. 51单片机学习笔记(串口通信 LED点阵屏 DS1302)

    四.串口通信 1.基本概念 通信中最重要的两个方面: 信息表示和解析方法: 信息的传输方法. 通信双方事先需要约定好信息的表示方法和解析方法,做到一致,否则信息不能有效传递. 信号的传输方法是指经过编 ...

  6. 51单片机仿真例程-led点阵屏

    用51单片机驱动led点阵屏 #include <reg51.h> unsigned char hang[10]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0 ...

  7. 51单片机8×8LED点阵屏动态显示取模汉字+ Proteus仿真

    51单片机8×8LED点阵屏动态显示取模汉字+ Proteus仿真 Proteus仿真 取模软件:pctolcd2002 程序代码 #include<reg52.h>unsigned ch ...

  8. 51单片机+LCD12864液晶显示的俄罗斯方块游戏,Proteus仿真、AD原理图、代码、论文等

    设计要求 (1)利用51单片机,设计一款俄罗斯方块游戏,完成硬件电路的开发和程序的编写调试: (2)采用LCD12864液晶作为游戏运行界面: (3)利用按键输入灵活控制方块的移动与变形: (4)能够 ...

  9. 51单片机LED点阵屏逐帧显示和流动显示图像

    上一篇逐帧显示用的是定时和中断控制,碰到了一些麻烦,我觉得也是一种不错的办法,因为Delay的时间更短,而且如果不那么介意亮度的情况甚至可以不用Delay()函数,这里采用将要显示的图像按顺序存储在数 ...

最新文章

  1. 程序员接活利器,dataTable组件带你快速开发,摆脱CRUD
  2. python操作excel和txt文件
  3. 腾讯云实时音视频技术发展简史 — 从编解码器容错优化到云端决策系统
  4. UltraEdit 使用操作
  5. 【Tensorflow】TF中的字符串tf.string
  6. mysql5.7安装完成后密码是多少_安装了mysql5.7后,如何进行配置(密码等)初始化...
  7. ubuntu 串口调试工具推荐_串口调试能有多便捷?——FUR组件的应用
  8. Ubuntu学习(应用集合、命令行以及遇到的问题)
  9. Javascript浏览器事件(上)
  10. Android Studio的Project有某个项目,Build Variants却没有,如何添加物已有项目?
  11. github windows系统监控_windows快速制作U盘启动工具Rufus
  12. c语言char a什么意思,C语言中char *a[ ]什么意思,他和char (*)a[ ]有什么什么区别?...
  13. 找回excel工作表保护密码
  14. 如何建立个人网站:从搭建到运营再到盈利
  15. 订单信息表和订单明细表
  16. 微型计算机增刊2016,科幻世界·2016年增刊
  17. java doc转图片_使用Java实现word文档转图片 在线预览
  18. 史上最长最全!围绕故障管理谈SRE体系建设
  19. 11.js的new操作符做了哪些事情?
  20. 电子计算机应用是啥,第二代电子计算机使用的电子元件是什么

热门文章

  1. 怎样提取网页视频中的音频文件
  2. 外卖 webpp2---hesdar组件
  3. 牛客小白月赛21 I I love you(dp的优化)
  4. 魅族6支持html吗,不知道你们发现了么,魅族Flyme6 超好用的隐藏功能
  5. 杂谈:倘若flash支持JPEG XR格式?
  6. python随机生成邮箱、自我介绍、地址、时间等
  7. 盛世昊通董车长2.0,数字化整合行业产业链变革
  8. 电子设计竞赛学习msp430单片机(msp430g2553,msp430f5529,tmec123G)
  9. 常用Pandas读取excel(或txt)部分行列并输出
  10. [树莓派 PICO(基于MicroPython)]基础教程02-按键测试、按键控制外设LED开关