- 单臂大回旋(风车)式旋转
- 支持自定义方块
- 支持修改棋盘大小
- 暴肝一晚,码风混乱,欢迎拍砖/fad
###还有些bug
1判定问题:
一直旋转可能产生原力(卡过下落时间)…减缓掉落
2积分加速还没有严格测试,手太残了,没测出来
食用方式
编译生成.exe
同文件夹下放1.txt,并输入方块信息
4.23更新:下键加速下落
4.25更新:双缓存防闪屏
4.25更新1:修复结束不显示:Game over
参考资料:https://blog.csdn.net/oHanTanYanYing/article/details/72179593
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <ctime>
#include <cmath>
#include <windows.h>
#include <algorithm>
using namespace std;
#define Col 14 //1,2,3,4最小公倍数 列 +2框
#define Row 20 //10层 行 +2
#define min_col 0
#define min_row 0
#define max_col Col-1
#define max_row Row-1
#define edge 3
#define Max_long 5 //长
#define Max_width 5 //宽
#define Max_score_len 10
struct Shape
{
int shape[Max_width][Max_long];
int ture_long;
int ture_width;
int xx;
int yy;
int xx1; //旋转定位点
int yy1;
int fig; //1,2,3,4 分别从初始逆时针
};
//0---
//---1
class Russia
{
private:
int score;
int speed; //系统毫秒%speed=0时下落一节, speed =2000 - 200*(score%3) ||1000
int map[Row][Col]; //0未占用,1已占用 2下落块 edge画边界
int sum_shapes; //形状总数
HANDLE h[2];
COORD coord;
DWORD bytes;
CONSOLE_CURSOR_INFO cci;
int now_h;
char *version;
public:
Shape *list;
Russia();
~Russia();
void play(); //开始游戏
int work(Shape); //回合运行 -1 game over
void In_shapes(string); //输入形状
void display(); //展现棋盘
void check(int,int); //检查并修理
void draw(Shape &,int); //0清空,1填充
void draw2(Shape &,int); //填充2
int judge(Shape &,int ,int ,int); //新的中心位置,新的姿态
void new_display();
void turn_char(char *);
};
Russia::Russia():version("修改信息:2020.4.25 by ssy9")
{
CONSOLE_CURSOR_INFO cci = {1, 0};
h[0] = CreateConsoleScreenBuffer(
GENERIC_WRITE,//定义进程可以往缓冲区写数据
FILE_SHARE_WRITE,//定义缓冲区可共享写权限
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
h[1] = CreateConsoleScreenBuffer(
GENERIC_WRITE,//定义进程可以往缓冲区写数据
FILE_SHARE_WRITE,//定义缓冲区可共享写权限
NULL,
CONSOLE_TEXTMODE_BUFFER,
NULL
);
cci.bVisible = 0;
cci.dwSize = 1;
SetConsoleCursorInfo(h[0], &cci);
SetConsoleCursorInfo(h[1], &cci);
coord.Y = 0;
coord.X = 0;
bytes = 0;
now_h = 0;
memset(map,0,sizeof(map));
for(int i=0;i<Row;i++)
{
for(int j=0;j<Col;j++)
{
if(i==0||j==0||i==Row-1||j==Col-1)
{
map[i][j] = edge;
}
}
}
score = 0;
}
Russia::~Russia()
{
free(list);
}
void Russia::In_shapes(string fn)
{
fn +='\0';
ifstream file;
file.open(fn.c_str(),ios::in);
file>>this->sum_shapes;
list = (Shape *)malloc(sizeof(Shape)*sum_shapes);
for(int i=0;i<sum_shapes;i++)
{
file>>(list[i].ture_long)>>(list[i].ture_width);
for(int j=0;j<list[i].ture_width;j++)
{
for(int k=0;k<list[i].ture_long;k++)
{
file>>list[i].shape[j][k];
}
}
}
file.close();
}
void Russia::display()
{
for(int i=0;i<Row;i++)
{
for(int j=0;j<Col;j++)
{
switch(map[i][j])
{
case 0:
cout<<" ";
break;
case 1:
case 2:
cout<<"█";
break;
case edge:
cout<<"※";
break;
}
//cout<<map[i][j];
}
cout<<endl;
}
cout<<"-------------------------------------------"<<endl;
cout<<"你的分数为:"<<score<<endl;
}
void Russia::turn_char(char *p)
{
int len = 1,tem=1;
while(this->score/tem!=0)
{
tem*=10;
len++;
}
int top = 0;
int tem_score = this->score;
while(len--)
{
tem/=10;
if(tem==0)
tem=1;
p[top++]='0'+tem_score/tem;
tem_score%=tem;
}
}
void Russia::new_display()
{
coord.X = 0;
coord.Y = 0;
for(int i=0;i<Row;i++)
{
char tem[(Col+5)*2];
int tail = 0;
memset(tem,0,sizeof(tem));
for(int j=0;j<Col;j++)
{
switch(map[i][j])
{
case 0:
strcat(&tem[tail]," ");
tail+=2;
break;
case 1:
case 2:
strcat(&tem[tail],"█");
tail+=2;
break;
case edge:
strcat(&tem[tail],"※");
tail+=2;
break;
}
//cout<<map[i][j];
}
coord.Y=i;
WriteConsoleOutputCharacterA(h[now_h],&tem[0],strlen(tem),coord,&bytes);
}
//system("cls");
//system("mode con cols=30 lines=26");
SetConsoleActiveScreenBuffer(h[now_h]);
coord.Y++;
WriteConsoleOutputCharacterA(h[now_h],"--------------------",20,coord,&bytes);
coord.Y++;
char name[Max_score_len+10] = "score: ";
turn_char(&name[7]);
WriteConsoleOutputCharacterA(h[now_h],name,strlen(name),coord,&bytes);
coord.Y+=3;
WriteConsoleOutputCharacterA(h[now_h],version,strlen(version),coord,&bytes);
Sleep(100);
now_h=(now_h+1)%2;
}
void Russia::play()
{
while(1)
{
//计算速度
speed = 1000 - 100*(score/2);
if(speed<30)
speed = 30; //此处修改速度
int rand_shape = rand()%sum_shapes;
if(work(list[rand_shape])==-1)
{
coord.Y=1;
coord.X=Col*2+3;
WriteConsoleOutputCharacterA(h[(now_h+1)%2],"Game over",9,coord,&bytes);
//cout<<"score:"<<score<<endl;
//cout<<"Game over"<<endl;
system("pause");
return;
}
}
}
void Russia::check(int top,int bottom) //top<=bottom
{
for(int i=top;i<=bottom;i++)
{
int jud = 1;
for(int j=1;j<=Col-2;j++)
{
if(map[i][j]==0)
{
jud = 0; //不能清理
}
}
if(jud == 1)
{
score++;
for(int j=i-1;j>=1;j--)
{
int jud1=0; //全0标记
for(int k=1;k<=Col-2;k++)
{
map[j+1][k] = map[j][k];
jud1=(jud1|map[j+1][k]);
}
if(jud == 0) //全是0 复制完毕
{
break;
}
}
}
}
}
void Russia::draw(Shape &now_shape,int tar)
{
switch(now_shape.fig)
{
case 1:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(map[now_shape.yy+j][now_shape.xx+i]!=1)
map[now_shape.yy+j][now_shape.xx+i] = ((now_shape.shape[j][i]&tar));
}
}
break;
case 2:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(map[now_shape.yy-i][now_shape.xx+j]!=1)
map[now_shape.yy-i][now_shape.xx+j] = ((now_shape.shape[j][i]&tar));
}
}
break;
case 3:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(map[now_shape.yy-j][now_shape.xx-i]!=1)
map[now_shape.yy-j][now_shape.xx-i] = ((now_shape.shape[j][i]&tar)); //
}
}
break;
case 4:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(map[now_shape.yy+i][now_shape.xx-j]!=1)
map[now_shape.yy+i][now_shape.xx-j] = ((now_shape.shape[j][i]&tar));
}
}
break;
}
}
void Russia::draw2(Shape &now_shape,int tar)
{
switch(now_shape.fig)
{
case 1:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(tar==0)
{
if(map[now_shape.yy+j][now_shape.xx+i]==2)
map[now_shape.yy+j][now_shape.xx+i]=0;
}
if(tar==1)
{
if(map[now_shape.yy+j][now_shape.xx+i]==0)
map[now_shape.yy+j][now_shape.xx+i] = ((now_shape.shape[j][i]&tar)<<1);
}
}
}
break;
case 2:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(tar==1)
if(map[now_shape.yy-i][now_shape.xx+j]==0)
map[now_shape.yy-i][now_shape.xx+j] = ((now_shape.shape[j][i]&tar)<<1);
if(tar==0)
if(map[now_shape.yy-i][now_shape.xx+j]==2)
map[now_shape.yy-i][now_shape.xx+j]=0;
}
}
break;
case 3:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(tar==1)
if(map[now_shape.yy-j][now_shape.xx-i]==0)
map[now_shape.yy-j][now_shape.xx-i] = ((now_shape.shape[j][i]&tar)<<1); //
if(tar==0)
if(map[now_shape.yy-j][now_shape.xx-i]==2)
map[now_shape.yy-j][now_shape.xx-i]=0;
}
}
break;
case 4:
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(tar==1)
if(map[now_shape.yy+i][now_shape.xx-j]==0)
map[now_shape.yy+i][now_shape.xx-j] = ((now_shape.shape[j][i]&tar)<<1);
if(tar==0)
if(map[now_shape.yy+i][now_shape.xx-j]==2)
map[now_shape.yy+i][now_shape.xx-j]=0;
}
}
break;
}
}
int Russia::judge(Shape &now_shape,int new_x,int new_y,int new_fig)
{
switch(new_fig)
{
case 1:
if(new_x<=0||new_x>=Col-1||new_y<=0||new_y>=Row-1)
return 0; //是否越界
if((new_x+now_shape.ture_long-1>=max_col)||(new_y+now_shape.ture_width-1>=max_row))
return 0;
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(map[new_y+j][new_x+i]&now_shape.shape[j][i]) //是否重合
return 0;
}
}
return 1;
break;
case 2:
if(new_x<=0||new_x>=Col-1||new_y<=0||new_y>=Row-1)
return 0;
if((new_x+now_shape.ture_width-1>=max_col)||(new_y-now_shape.ture_long+1<=min_row))
return 0;
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
//cout<<(map[new_y-i][new_x+j]&now_shape.shape[j][i])<<endl;
if((map[new_y-i][new_x+j]&now_shape.shape[j][i])==1)
return 0;
}
}
return 1;
break;
case 3:
if(new_x<=0||new_x>=Col-1||new_y<=0||new_y>=Row-1)
return 0;
if((new_x-now_shape.ture_long+1<=min_col)||(new_y-now_shape.ture_width+1<=min_row))
return 0;
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(map[new_y-j][new_x-i]&now_shape.shape[j][i]) //
return 0;
}
}
return 1;
break;
case 4:
if(new_x<=0||new_x>=Col-1||new_y<=0||new_y>=Row-1)
return 0;
if((new_x-now_shape.ture_width+1<=min_col)||(new_y+now_shape.ture_long-1>=max_row))
return 0;
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if(map[new_y+i][new_x-j]&now_shape.shape[j][i])
return 0;
}
}
return 1;
break;
}
}
int Russia::work(Shape now_shape)
{
//初始化位置
now_shape.yy=1;
now_shape.xx=1+rand()%(Col-2-now_shape.ture_long);
now_shape.yy1=now_shape.ture_width;
now_shape.xx1=now_shape.xx+now_shape.ture_long-1;
now_shape.fig=1;
//检查该位置是否重合
for(int i=0;i<now_shape.ture_long;i++)
{
for(int j=0;j<now_shape.ture_width;j++)
{
if((map[j+now_shape.yy][i+now_shape.xx]&now_shape.shape[j][i])==1) //重合不合法
{
/*
system("cls");
cout<<"score:"<<score<<endl;
cout<<"Game over"<<endl;
system("pause");
*/
return -1;
}
}
}
while(clock()%speed!=0){}//基准时间
while(clock()%speed==0){}
draw2(now_shape,1);
//system("cls");
new_display();
//开始下落
int drop_faster = 0;
int last_clock=0;
while(1)
{
if((clock()%speed<=50&&last_clock==1)||drop_faster==1) //下落
{
drop_faster = 0;
//判断能不能落
if(judge(now_shape,now_shape.xx,now_shape.yy+1,now_shape.fig)==1)//能落
{
draw2(now_shape,0); //清空
now_shape.yy++; //下降
draw2(now_shape,1); //填补
//system("cls");
new_display();
}
else
{
draw(now_shape,0);
draw(now_shape,1);
//system("cls");
new_display();
break;
}
}
else //显示并读取键盘状态
{
if(clock()%speed!=0)
{
last_clock = 1; //更新flag
}
int last_state = 0;
if(GetKeyState(38)<0&&last_state==0) //逆时针旋转
{
last_state = 1; //更新状态
int ttem=now_shape.fig%4+1;
if(judge(now_shape,now_shape.xx,now_shape.yy,ttem)==1)
{
draw2(now_shape,0); //清空
now_shape.fig=ttem;
draw2(now_shape,1); //填补
//system("cls");
new_display();
}
}
if(GetKeyState(37)<0&&last_state==0) //左
{
last_state = 1; //更新状态
if(judge(now_shape,now_shape.xx-1,now_shape.yy,now_shape.fig)==1)
{
draw2(now_shape,0); //清空
now_shape.xx--;
draw2(now_shape,1); //填补
//system("cls");
new_display();
}
}
if(GetKeyState(39)<0&&last_state==0) //右
{
last_state = 1; //更新状态
if(judge(now_shape,now_shape.xx+1,now_shape.yy,now_shape.fig)==1)
{
draw2(now_shape,0); //清空
now_shape.xx++;
draw2(now_shape,1); //填补
//system("cls");
new_display();
}
}
if(GetKeyState(40)<0&&last_state==0)
{
last_state=1;
drop_faster = 1;
}
}
}
check(min_row+1,max_row-1);
return 1;
}
Russia russia;
int main()
{
//system("mode con cols=30 lines=26");
//SetConsoleTitle("俄罗斯方块 by ssy9");
srand(time(0));
russia.In_shapes("1.txt");
russia.play();
return 0;
}
补充说明:
从1.txt里读取方块数据
一个方块数
每个方块长 宽
1,0表示占位
例:可以直接拷贝进1.txt食用:
10
4 2
1 1 1 1
1 0 0 1
4 1
1 1 1 1
4 2
1 1 1 1
0 0 0 1
3 2
1 1 0
0 1 1
2 2
1 1
0 1
2 2
1 0
1 1
2 2
1 1
1 1
3 3
1 1 0
0 1 1
0 0 1
3 3
1 1 1
1 0 1
1 1 1
3 3
1 1 1
1 1 0
1 0 0
其余内容见:https://www.jianshu.com/p/6d9732872d0b