C++借助curses库实现俄罗斯方块
主要要实现如下几个功能:方块的移动控制、方块变形、判定方块是否接触边界和进行方块堆积、对方块进行消除。
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库实现俄罗斯方块的更多相关文章
- 编程利用利用curses库编程开始
时间紧张,先记一笔,后续优化与完善. curses库常用函数: 注意编译时要用这样的格式:gcc xxx.c -l curses -o xxx 第一个小例子: include <stdio.h& ...
- [C++]基于Curses库的实时系统监测可视化系统-2017-12-09 15-07-42
Congratulations 0.0 技术记录 [1] [C++]Linux之Ubuntu下编译C程序出现错误:“ stray ‘\302'或者'\240' in program”的解决方案 [2 ...
- [C++]Linux之图形界面编程库[curses库]之入门教程
1. 安装 //方法一 sudo apt-get install libncurses5-dev [ ubuntu 16.04:亲测有效] //方法二 sudo apt-get install ncu ...
- python安装curses库
windows系统在安装curses库时,如果直接使用conda或者pip安装,总是失败,到如下网址直接下载.whl文件,然后再用pip安装即可. https://www.lfd.uci.edu/~g ...
- Windows下使用Python的Curses库时 No module named _curses问题
这个问题产生的 根本原因 是 curses 库不支持 windows.所以我们在下载完成python后(python 是自带 curses 库的),虽然在 python目录\Lib 中可以看到 c ...
- curses库--libncurses5-dev--游标移动及屏幕的显示
curses是一个在Linux/Unix下广泛应用的图形函数库.,作用是可以绘制在DOS下的用户界面和漂亮的图形. curses的名字起源于"cursor optimization" ...
- Linux下的Curses库的源码下载与安装
curses库是可以在linux终端中写出字符用户界面的一个库,现在较新的版本应该是ncurses库,现在已经很少有人再去使用他了,所以想拥有这个库并且在linux下写出自己用户界面的可以参考一下本博 ...
- Linux curses库使用
相信您在网路上一定用过如 tin,elm 等工具, 这些软体有项共同的特色, 即他们能利用上下左右等方向键来控制游标的位置. 除此之外, 这些程式的画面也较为美观. 对Programming 有兴趣 ...
- Linux学习笔记13——使用curses函数库
一 安装curses库 如果你的Linux系统中curses库,直接敲入命令sudo apt-get install libncurses5-dev,然后就会自动安装curses库,安装好之后敲入命令 ...
随机推荐
- Java 8 ThreadLocal 源码解析
Java 中的 ThreadLocal是线程内的局部变量, 它为每个线程保存变量的一个副本.ThreadLocal 对象可以在多个线程中共享, 但每个线程只能读写其中自己的副本. 目录: 代码示例 源 ...
- shell脚本示例:计算毫秒级、微秒级时间差
bash&shell系列文章:http://www.cnblogs.com/f-ck-need-u/p/7048359.html 有时候需要计算命令的执行时间长度,可以使用time命令,虽然t ...
- SpringBoot学习(三)-->Spring的Java配置方式之读取外部的资源配置文件并配置数据库连接池
三.读取外部的资源配置文件并配置数据库连接池 1.读取外部的资源配置文件 通过@PropertySource可以指定读取的配置文件,通过@Value注解获取值,具体用法: @Configuration ...
- Scala(一) —— 基础
一.输出 println("Hello World") 二.变量与常量 1.变量用var表示,常量使用val表示 2.变量类型声明 var variableName : DateT ...
- 业务开发(六)—— MyBatis框架
0x01.元素内容必须由格式正确的字符数据或标记组成. Caused by: org.apache.ibatis.builder.BuilderException: Error creating do ...
- C# 显式转换关键字 explicit
不同于隐式转换,显式转换运算符必须通过转换的方式来调用. 如果转换操作会导致异常或丢失信息,则应将其标记为 explicit. 这可阻止编译器静默调用可能产生意外后果的转换操作. 省略转换将导致编译时 ...
- WPF window 子窗口反馈效果(抖动/阴影渐变)
当设置了owner的子窗口显示后,点击子窗口外部,需要一种反馈机制(反馈动画). 实现: 1.触发源 每次点击子窗口外部,即母窗口时,事件捕捉如下 HwndSource hwndSource = Pr ...
- [angularjs] angularjs系列笔记(六)http
读取服务器json数据,get方式 <body> <div ng-app="Home"> <div ng-controller="httpT ...
- Java 数组声明的几种方式
Java数组定义声明的几种方法: 1. 类型名称[] 变量名=new 类型名称[length]; 2.类型名称[] 变量名={?,?,?}; 3.类型名称[] 变量名=new 类型名称[]{?,?,? ...
- 【Java每日一题】20170117
20170116问题解析请点击今日问题下方的“[Java每日一题]20170117”查看(问题解析在公众号首发,公众号ID:weknow619) package Jan2017; import jav ...