一个简单的用C语言写的俄罗斯方块程序?

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结构定位

{ int leftint top

} rock location _ t;123456

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

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

例如下横杆和垂直杆。

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

你能想象一个静态循环链表这样实现吗?

循环相同类型的块,

正方形由struct结构表示。

typedef结构岩石

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

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

定义一个RockType类型的数组存储19种方块?

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

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

简单解释一下ReadRock函数的实现:当读取一个空行时,表示已经读取了一个框,而当读取* * *?行表示已经读取了相同类型的框,这取决于代码实现和代码中的特定注释。

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 MoveAble(int rockIndex,rock location _ t * currentlocatoptr,int f_direction)1

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

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

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

//全局变量——游戏棋盘的状态描述(即表示当前界面哪里有方块)?//0表示否,1表示是(多加两行两列形成栅栏,方便判断盒子是否可以移动)?int game _ board[yROCK _ SQUARE _ NUM+2][xROCK _ SQUARE _ NUM+2]= { 0 };123

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

(1)快速下落时,箱子可能会落在围栏范围之外。

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

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

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

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