一、实验简介
1.1 实验内容
本节实验我们将实现俄罗斯方块主要函数的设计,完成基本功能并运行。
1.2 实验知识点
窗口的绘制
方块类的设计
旋转算法
移动、消除函数
1.3 实验环境
xface 终端
g++ 编译器
ncurses 库
1.4 编译程序
编译命令要加上 -l 选项引入 ncurses 库:
g++ main.c -l ncurses
1.5 运行程序
./a.out
1.6 运行结果
二、实验步骤
2.1 头文件
首先包含头文件以及定义一个交换函数和随机数函数,后面用到(交换函数用来做方块的旋转,随机数用来设置方块的形状)
#include#include #include #include #include #include void swap(int &a, int &b){ int t=a; a = b; b = t; } int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) shape[i][j]=0; switch(cshape) { case 0: size_h=1; size_w=4; shape[0][0]=1; shape[0][1]=1; shape[0][2]=1; shape[0][3]=1; break; case 1: size_h=2; size_w=3; shape[0][0]=1; shape[1][0]=1; shape[1][1]=1; shape[1][2]=1; break; case 2: size_h=2; size_w=3; shape[0][2]=1; shape[1][0]=1; shape[1][1]=1; shape[1][2]=1; break; case 3: size_h=2; size_w=3; shape[0][1]=1; shape[0][2]=1; shape[1][0]=1; shape[1][1]=1; break; case 4: size_h=2; size_w=3; shape[0][0]=1; shape[0][1]=1; shape[1][1]=1; shape[1][2]=1; break; case 5: size_h=2; size_w=2; shape[0][0]=1; shape[0][1]=1; shape[1][0]=1; shape[1][1]=1; break; case 6: size_h=2; size_w=3; shape[0][1]=1; shape[1][0]=1; shape[1][1]=1; shape[1][2]=1; break; } //设置完形状以后初始化方块的起始位置 head_x=game_win_width/2; head_y=1; //如果刚初始化就重合了,游戏结束~ if(isaggin()) game_over=true; }
2.4 旋转函数
这里用了一个比较简单的算法对方块进行旋转,类似于矩阵的旋转,先将 shape 数组进行斜对角线对称化,再进行左右对称,便完成了旋转,需要注意的是要判断旋转后方块是否出界或重合,如果是,则取消本次旋转。
void Piece::rotate()
{
int temp[4][4]={0}; //临时变量
int temp_piece[4][4]={0}; //备份用的数组
int i,j,tmp_size_h,tmp_size_w;
tmp_size_w=size_w;
tmp_size_h=size_h;
for(int i=0; i<4;i++)
for(int j=0;j<4;j++)
temp_piece[i][j]=box_shape[i][j]; //备份一下当前的方块,如果旋转失败则返回到当前的形状
for(i=0;i<4;i++)
for(j=0;j<4;j++)
temp[j][i]=box_shape[i][j]; //斜对角线对称
i=size_h;
size_h=size_w;
size_w=i;
for(i=0;ibox_shape[i][j]==1){
mvwaddch(game_win,head_y+i,head_x+j,'#');
wrefresh(game_win);
}
}
}
}
2.5 移动函数
如果玩家没有按下任何按键,方块需要慢速下落,所以我们不能够因为等待按键输入而阻塞在 getch() ,这里用到了 select() 来取消阻塞。
struct timeval timeout; timeout.tv_sec = 0; timeout.tv_usec= 500000; if (select(1, &set, NULL, NULL, &timeout) == 0)
timeout 就是我们最多等待按键的时间,这里设置了 500000us,超过这个时间就不再等待 getch() 的输入,直接进行下一步。
如果在 timeout 时间内检测到按键,则下面的 if 语句为真,得到输入的 key 值,通过判断不同的 key 值进行向左、右、下、旋转等操作。
if (FD_ISSET(0, &set))
while ((key = getch()) == -1) ;
向左、右、下移动的函数处理方式基本相同,这里只拿向下移动的函数进行说明
if(key==KEY_DOWN){
head_y++; //方块的y坐标+1
if(isaggin()){ //如果重合或出界,则取消这次移动
head_y--;
if(line!=0){
for(i=game_win_height-2;i>=2;i--){
int s=i;
if(exsqr(i)==0){
while(s>1 && exsqr(--s)==0); //查找存在方块的行,将其下移
for(j=1;j
三、实验总结
到这里几个关键函数的介绍也就完成了,搞明白这些函数的功能并实现,再参考源码补全其他函数以及main函数就可以运行啦!当然俄罗斯方块的实现方法还有很多,每个人的思路和方法可能会不一样,或许你写出来的俄罗斯方块更简洁、更流畅! Enjoy it !:)



