主要要实现如下几个功能:方块的移动控制、方块变形、判定方块是否接触边界和进行方块堆积、对方块进行消除。

1.方块的移动控制
上下左右四个方向
上-->变形,下-->加速下落,左-->向左移动,右-->向右移动
注意在移动的时候,还要判定是否接触边界,特别是向下移动,除了需要确定是否接触底部边界外,还要注意是否发生方块堆积。

 void Piece::show(){
fd_set set;
FD_ZERO(&set);
FD_SET(, &set);
struct timeval timeout;
timeout.tv_sec = ;
timeout.tv_usec= ;
if (select(, &set, NULL, NULL, &timeout) == ){
//mvwprintw(game_win,21,20,"+");
pos_x++;
if(reachBottom()){
pos_x--;
int x=;
for(int i=;i<shape_x;i++){
for(int j=;j<shape_y;j++){
if(shape[i][j]==){
map[pos_x+i+][pos_y+j+]=;
mvwaddch(game_win,pos_x+i+,pos_y+j+,'#');
}
}
}
pos_x=;
srand((int)time());
pos_y=rand()%(map_y-);
while(pos_y==){
pos_y=rand()%(map_y-);
}
next_shape_id=rand()%;
//shape_id=3;
nextShape();
wrefresh(game_win);
int flag=;
int lines=;
if(flag==){
for(int i=map_x-;i>=;i--){
while(fullLine(i)){
lines++;
int k=i-;
while(fullLine(k)){
k--;
lines++;
}
for(int j=;j<(map_y-);j++){
map[k+][j+]=;
mvwaddch(game_win,k+,j+,' ');
}
int kk=k+;
for(;kk>=;kk--){
for(int jj=;jj<(map_y-);jj++){
if(map[kk][jj+]==){
map[kk+][jj+]=;
mvwaddch(game_win,kk+,jj+,'#');
}else{
map[kk+][jj+]=;
mvwaddch(game_win,kk+,jj+,' ');
}
}
}
score+=(lines*);
std::string tempS;
std::ostringstream ex_msg;
ex_msg<<"score: "<<score;
tempS=ex_msg.str();
mvwprintw(score_win,,,tempS.c_str());
wrefresh(score_win);
//mvwaddch(game_win,k+1,j,' ');
wrefresh(game_win);
}
}
}
}else{
//mvwprintw(game_win,21,20,"-");
for(int i=;i>=;i--){
for(int j=;j>=;j--){
if(shape[i][j]==){
int x=;
mvwaddch(game_win,pos_x+i,pos_y++j,' ');
mvwaddch(game_win,pos_x+i+,pos_y++j,'#');
}
}
}
wrefresh(game_win);
}
}
if(FD_ISSET(,&set)){
while((key=getch())==-); if(key==KEY_RIGHT){
//clearShape();
pos_y++;
if(reachBottom()){
pos_y--;
}else{
for(int i=;i<=;i++){
for(int j=;j>=;j--){
if(shape[i][j]==){
//列上的移动
mvwaddch(game_win,pos_x+i+,pos_y+j,' ');
mvwaddch(game_win,pos_x+i+,pos_y+j+,'#');
}
}
}
wrefresh(game_win);
}
} if(key==KEY_LEFT){
//clearShape();
pos_y--;
if(reachBottom()){
pos_y++;
}else{
for(int i=;i<=;i++){
for(int j=;j<=;j++){
if(shape[i][j]==){
//列上的移动
mvwaddch(game_win,pos_x+i+,pos_y+j+,' ');
mvwaddch(game_win,pos_x+i+,pos_y+j+,'#');
}
}
}
wrefresh(game_win);
}
} if(key==KEY_UP){
changeShape();
}
if(key==KEY_DOWN){
pos_x++;
if(reachBottom()){
pos_x--;
}else{
for(int i=;i>=;i--){
for(int j=;j>=;j--){
if(shape[i][j]==){
int x=;
mvwaddch(game_win,pos_x+i,pos_y++j,' ');
mvwaddch(game_win,pos_x+i+,pos_y++j,'#');
}
}
}
wrefresh(game_win);
}
}
}
}

2.方块变形
做法很简单,首先,4x4整体按左右对称,再交换方块实际长和宽的值,在实际的长和宽这个范围内再进行左右对称。
同样这里要注意是否发生了越界和方块堆积,如果发生了,就恢复原形状。

 void Piece::changeShape(){
int temp[][]={};
int temp1[][]={};
int temp2[][]={};
for(int i=;i<;i++){
for(int j=;j<;j++){
temp[j][i]=shape[i][j];
temp2[i][j]=shape[i][j];//保存shape数组
}
}
for(int i=;i<;i++){
for(int j=;j<;j++)
shape[i][j]=;
}
int temp3=shape_x;
shape_x=shape_y;
shape_y=temp3;
for(int i=;i<shape_x;i++){
for(int j=;j<shape_y;j++){
temp1[i][shape_y--j]=temp[i][j];
}
}
for(int i=;i<;i++){
for(int j=;j<;j++)
shape[i][j]=temp1[i][j];
}
if(reachBottom()){
for(int i=;i<;i++){
for(int j=;j<;j++)
shape[i][j]=temp2[i][j];
}
int temp3=shape_x;
shape_x=shape_y;
shape_y=temp3;
}else{
for(int i=;i<;i++){
for(int j=;j<;j++){
if(temp2[i][j]==){
mvwaddch(game_win,pos_x+i+,pos_y++j,' ');
}
}
}
wrefresh(game_win);
for(int i=;i>=;i--){
for(int j=;j>=;j--){
if(shape[i][j]==){
mvwaddch(game_win,pos_x+i+,pos_y++j,'#');
wrefresh(game_win);
}
}
}
}
}

3.判定方块是否接触边界和进行方块堆积
这里主要是要考虑到,左右上下类似装饰条的行。方块堆积就是判定下一行方块要占据的位置是否已经有其他方块占据了。

 bool Piece::reachBottom(){
for(int i=;i<shape_x;i++){
for(int j=;j<shape_y;j++){
if(shape[i][j]==){
if(pos_x+i>(map_x-)){
return true;
}
if(pos_y+j>(map_y-)||pos_y+j<){
return true;
}
if(map[pos_x+i+][pos_y+j+]==){
return true;
}
}
}
}
return false;
}

4.对方块进行消除
从最后一行放置方块的行号开始,依次判定此行是否需要消除,消除后还要继续判定本行的情况(应对连续消除多行的情况)。

 for(int i=map_x-;i>=;i--){
while(fullLine(i)){
lines++;
int k=i-;
while(fullLine(k)){
k--;
lines++;
}
for(int j=;j<(map_y-);j++){
map[k+][j+]=;
mvwaddch(game_win,k+,j+,' ');
}
int kk=k+;
for(;kk>=;kk--){
for(int jj=;jj<(map_y-);jj++){
if(map[kk][jj+]==){
map[kk+][jj+]=;
mvwaddch(game_win,kk+,jj+,'#');
}else{
map[kk+][jj+]=;
mvwaddch(game_win,kk+,jj+,' ');
}
}
}
score+=(lines*);
std::string tempS;
std::ostringstream ex_msg;
ex_msg<<"score: "<<score;
tempS=ex_msg.str();
mvwprintw(score_win,,,tempS.c_str());
wrefresh(score_win);
//mvwaddch(game_win,k+1,j,' ');
wrefresh(game_win);
}
}

完整代码:https://github.com/JsonZhangAA/shiyanlou/tree/master/C%2B%2B_%E4%BF%84%E7%BD%97%E6%96%AF%E6%96%B9%E5%9D%97

C++借助curses库实现俄罗斯方块的更多相关文章

  1. 编程利用利用curses库编程开始

    时间紧张,先记一笔,后续优化与完善. curses库常用函数: 注意编译时要用这样的格式:gcc xxx.c -l curses -o xxx 第一个小例子: include <stdio.h& ...

  2. [C++]基于Curses库的实时系统监测可视化系统-2017-12-09 15-07-42

    Congratulations 0.0 技术记录 [1]  [C++]Linux之Ubuntu下编译C程序出现错误:“ stray ‘\302'或者'\240' in program”的解决方案 [2 ...

  3. [C++]Linux之图形界面编程库[curses库]之入门教程

    1. 安装 //方法一 sudo apt-get install libncurses5-dev [ ubuntu 16.04:亲测有效] //方法二 sudo apt-get install ncu ...

  4. python安装curses库

    windows系统在安装curses库时,如果直接使用conda或者pip安装,总是失败,到如下网址直接下载.whl文件,然后再用pip安装即可. https://www.lfd.uci.edu/~g ...

  5. Windows下使用Python的Curses库时 No module named _curses问题

    这个问题产生的 根本原因 是 curses 库不支持 windows.所以我们在下载完成python后(python 是自带 curses 库的),虽然在  python目录\Lib  中可以看到 c ...

  6. curses库--libncurses5-dev--游标移动及屏幕的显示

    curses是一个在Linux/Unix下广泛应用的图形函数库.,作用是可以绘制在DOS下的用户界面和漂亮的图形. curses的名字起源于"cursor optimization" ...

  7. Linux下的Curses库的源码下载与安装

    curses库是可以在linux终端中写出字符用户界面的一个库,现在较新的版本应该是ncurses库,现在已经很少有人再去使用他了,所以想拥有这个库并且在linux下写出自己用户界面的可以参考一下本博 ...

  8. Linux curses库使用

     相信您在网路上一定用过如 tin,elm 等工具, 这些软体有项共同的特色, 即他们能利用上下左右等方向键来控制游标的位置. 除此之外, 这些程式的画面也较为美观. 对Programming 有兴趣 ...

  9. Linux学习笔记13——使用curses函数库

    一 安装curses库 如果你的Linux系统中curses库,直接敲入命令sudo apt-get install libncurses5-dev,然后就会自动安装curses库,安装好之后敲入命令 ...

随机推荐

  1. 基于SpringMVC+Spring+MyBatis实现秒杀系统【概况】

    前言 本教程使用SpringMVC+Spring+MyBatis+MySQL实现一个秒杀系统.教程素材来自慕课网视频教程[https://www.imooc.com/learn/631].有感兴趣的可 ...

  2. Raft 基础

    目录 三个状态 什么是任期 节点之间的通信 1. 三个状态 Raft 设计了 3 个状态,用于表示节点的状态,分别是跟随者,候选者,领导者. 领导者:通常只有一个领导人,并且其他节点都是跟随者. 跟随 ...

  3. Java并发(一)—— 使用多线程

    Java的线程机制是抢占式的,所谓的抢占式指的是每一个线程都会被分配一个指定大小的时间片,一旦这个时间片用完,就会通过上下文切换到另一个线程上去. 并发是主要是为了提高单处理器的性能.创建一个线程会有 ...

  4. 怎么使用小程序的data-*属性?

    参考文档:小程序事件 怎么使用小程序的data-*属性?[data-type,data-num,……] dataset 在组件中可以定义数据,这些数据将会通过事件传递给 SERVICE. 书写方式: ...

  5. echarts tab 切换问题整理

    一.bootstrap tabs 解决方案 方式一 tab切换echarts无法正常显示 https://blog.csdn.net/cjs68/article/details/78072382 ta ...

  6. 事件处理程序 (DOM0级)

    DOM0事件处理程序 每个元素都有自己的事件处理程序属性,那么直接获取对象,然后在对象上设置事件处理程序属性. 1:获取节点对象引用 2:在事件成员上设置处理函数,这时函数内部this指向节点对象. ...

  7. 06-HTML-表格标签

    <html> <head>  <title>表格标签学习</title>  <meta charset="utf-8"/> ...

  8. select2 插件加载后端数据

    //html <select class="form-group form-control" name="roomId" id="roomLis ...

  9. 洛谷P2470 [SCOI2007]压缩(区间dp)

    题意 题目链接 Sol 神仙题Orz 考虑区间dp,如果我们只设\(f[l][r]\)表示\(s_{lr}\)被压缩的最小长度,而不去关心内部\(M\)分布的话,可能在转移的时候转移出非法状态 因此考 ...

  10. ionic APP二维码插件 地址

     二维码插件地址第一个   https://github.com/kyocn/BarcodeScanner git网址 下载网址  https://github.com/kyocn/BarcodeSc ...