如何用链表实现俄罗斯方块

1,考虑如何存储俄罗斯方块

俄罗斯方块形状有19种,如果用数组表示可能会浪费空间(网上有很多实现代码)。

考虑到每个正方形形状都是一个范围为4 *4的小正方形,所以以字体点阵的形式存储,即设置一个4行4列的数组,元素设置为1,表示这个位置小。

Box,元素设置为0,表示这个位置没有小盒子。这整个4*4的阵列形成了俄罗斯方块的形状。

1000

1000

1100

0000

上面的4*4代表一个L型的正方形。

4*4 =16位是短类型,所以每个块可以用一个短类型的数据来表示。我们将俄罗斯方块点阵的数字存储在rockArray中,可以预先将这19个方块的字体点阵转换成十六进制,然后在初始化rockArray时进行赋值。

然而,这种方法不具有可扩展性,并且需要在每次有新的方块时进行改变。

所以你可以写一个配置文件来表示19种方块。(RockShape.ini)

@###@###@@######1234

从配置文件中读取块类型的代码在下面3中解释(在Init.h的ReadRock函数中)。

2如何画正方形?

您可以使用EasyX库来绘制简单的图形。

EasyX库是在VC下实现TC简单绘图功能的库,简单易学(直接百度EasyX库,里面有详细教程)。

那么怎么画一个盒子呢?这个盒子以短式储存。

从short读取,可以用mask mask = 1与short的每一位进行相位,如果结果是1,则画一个小方块;

函数声明:

void DisplayRock(int rockIdx,RockLocation_t* LocatePtr,bool displayed)1

参数1:表示数组中的下标,取出短类型的盒子表示数据。

参数2:表示当前坐标,即盒子左上角的坐标x和y。

参数3: true表示画方框,false表示擦除方框。

//图形窗口中框的位置(即4*4块左上角的坐标)typedef struct LOCATE。

{ int leftint top

} rock location _ t;123456

3如何翻转同类型的盒子,

按↑的时候应该会翻转同类型的盒子。

例如下横杆和垂直杆。

@###@###@###@###@@@@############****1234567891011

typedef结构岩石

{//用来表示一个盒子的形状(每个字节8位,每4位表示盒子中的一行)。

无符号短rockShapeBitsint nextRockIndex//下一个框,下标}数组中的RockType123456

定义一个RockType类型的数组来存储19种正方形。

rock type rock array[19]= {(0,0)};

当我们按“↑”时,可以将传入的绘图框函数中的rockIndex改为当前框结构中的nextRockIndex。

简单解释一下ReadRock函数的实现:当读取一个空行时,表示已经读取了一个类型的box,当读取一个* * *行时,表示已经读取了同类型的box,具体取决于代码实现和代码中的具体注释。

4.主游戏实现逻辑

贴个预告。

注:上面预览的游戏控制区和游戏显示区是通过Draw.h的DrawGameWindow()函数实现的

(1)在初始位置画一个正方形,在预览区画下一个正方形。

(2)盒子有两种行为:响应键盘命令UserHitKeyBoard()和自由下落。

如果你敲击键盘(w,a,s,d,),空格表示暂停。如果在规定时间内没有敲击键盘,盒子自由下落一个单位。

If (kbhit()) //如果敲击键盘,处理按键。

{

user hit = getch();

用户点击键盘(用户点击& ampcurRockIndex & amp;curRockLocation);

}//如果不是,自动下移一个单位:else不能用,因为键可能不是上、下、左、右。

DWORD new time = GetTickCount();if(new time-old time & gt;=(无符号整数)(300)amp;& ampmoveAbled == TRUE)

{

oldtime = newtime

display rock(curRockIndex & amp;curRockLocation,false);

currocklocation . top+= ROCK _ SQUARE _ WIDTH;//删除一个网格

}1234567891011121314

(3)方块落地时(即不能下移),判断是否满,满则淘汰,然后判断游戏是否结束。如果游戏结束,直接退出游戏。

判断FullLine: fullline()函数,从底线开始判断,直到遇到空行。

而(数!= xROCK_SQUARE_NUM) //遇到空行14。

{

linefull = truecount = 0;for(int I = 1;我& lt= xROCK _ SQUARE _ NUM++i)

{ if (game_board[idx][i] == 0)

{

linefull = falsecount++;

}

} if (linefull) //全行,消除当前行,更新分数。

{

DelCurLine(idx);//消除整行

game _ socres+= 3;

update socres(game _ socres);

idx++;//因为下面会减1。

}

idx-;

}123456789101112131415161718192021

(4)消除满线

擦除要删除的整行:即块成与背景同色,代码为黑色。

然后把上面一行往下移,移一行删一行,直到遇到空行。

具体实现见代码game.h

void DelCurLine(int rowIdx)

(4)判断箱子是否可以移动。

在game.h中实现

bool mobilable(int rock index,rock location _ t * currentlocatoptr,int f_direction)1

* *对比当前位置(左上角)的坐标,可以放下rockIndex框吗?

注意:如果f_direction是↑,则传入的rockIndex是下一个框* *。

如果不能移动,为game_board设置一个标志,表示位置被占用。

//游戏棋盘的全局变量状态描述(即表示当前界面中哪里有方块)//0表示否,1表示是(多加两行两列形成栅栏,方便判断方块是否可以移动)int game _ board[y rock _ square _ num+2][x rock _ square _ num+2]= { 123

实施过程中遇到的一些问题

(1)急速下落时,方块可能会落在围栏范围之外。

快速下落是让箱子一次下落2个单位距离。

当判断不能落下时,从当前坐标的顶端减去一个单位的距离,即y。

(2)多线满时,不能消除。

判断满行时,循环寻找满行,找到一个满行,再排除一行,然后继续判断是否满,直到遇到一个空行。

具体源代码的实现:俄罗斯方块的C语言源代码。

也可以直接从GitHub下载C语言的俄罗斯方块源代码。

注意:可能还是会有一些问题。欢迎指正。

版权声明:本文为文强1208原创文章,遵循CC 4.0 BY-SA版权协议。转载请附上原出处链接和本声明。

本文链接:/wenqiang 1208/article/details/71244843