如何用链表实现俄罗斯方块
俄罗斯方块形状有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