这个作业属于哪个课程 | <2020面向对象程序设计> |
---|---|
这个作业要求在哪里 | <我罗斯方块> |
这个作业的目标 | 进行第一次汇报,报告进展及遇到的问题 |
成员 | 魏兴晟031903124 |
陈天武031903105 | |
邓泽纪031903109 |
目前进度及目标
目前已将方块类和玩家类写得比较详细,其中比较重大的困难如砖块的碰撞判定及消行和涨行都经过了测试
接下来的目的是在游戏类中进行操作的输入控制方块,以及加入计时器功能使方块能够随时间下落
在渲染类中要能够即时地将场地和砖块显示在屏幕上
当前代码还需要让每次运行时随机到的方块不同
方块类
方块类遇到的困难是要返回四个格子的坐标来进行碰撞判断,这里最好使用穷举法
这是id=1,state=0的方块,转轴坐标为(x,y),左上角为坐标原点,因为数组特性的原因y要写在前面,四个格子的坐标分别为
(y,x)(y,x-1)(y,x+1)(y-1,x-1)
玩家类
在玩家类中有方块对象now和next,分别是当前操控的方块和接下来会出现的方块
二维数组wall[26][16]用来存储场地中所有砖的位置
变量refuse用来存储将要上涨的垃圾行数,在放置下一个方块的瞬间上涨
采用这种设计的原因是考虑到砖块离地面1格时若突然涨4格垃圾行会很难处理,而事实上现代方块也确实是采用存储垃圾行的方式
玩家类中有操控方块的方法,碰撞的判定是通过方块对象test进行测试,判断左右移动是否会导致方块和场地重合,如未重合则操作合法
若旋转导致了重合将会测试旋转后方块右侧1格和左侧2格的位置能否移动,因此靠墙的竖直方块能够旋转成横向
对玩家类一些方法的测试
砖块的碰撞判定及踢墙
int main() {
Player p;
int i;
for (i = 0; i < 10; i++) p.Rmove(); //进行10次右移操作,Z砖未出墙
for (i = 0; i < 20; i++)p.drop();//进行20次下落,Z砖落地,J砖产生,初始形状为 ∟
p.rotate();//J砖顺时针旋转,形状为 「
for (i = 0; i < 10; i++)p.Lmove();//J砖左移,竖直面贴墙
p.rotate();//此旋转会导致J砖和墙重合,因此J砖测试了右侧1格的位置,形状为┐
for (i = 0; i < 120; i++)p.drop();//J砖及其他各砖块正常产生及落地
p.display();
}
垃圾行上涨
int main() {
Player p;
p.add_refuse(10);//refuse+=10
p.rise();//上涨
p.display();
}
目前方块类和玩家类的代码
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
class Block {
private:
int x, y;//转轴坐标
int id;//0=I青,1=J蓝,2=L橙,3=O黄,4=S绿,5=T紫,6=Z红
int state;//旋转状态
public:
Block(Block&b) {
x = b.x;
y = b.y;
id = b.id;
state = b.state;
}
Block(int y1,int x1,int id1,int state1=0):y(y1),x(x1),id(id1),state(state1){}
int** coordinate() {
int** i=new int*[4];
for (int j = 0; j < 4; j++)i[j] = new int[2];
i[0][0] = y;
i[0][1] = x;
if (id == 0) {
if (state == 0 || state == 2) {
i[1][0] = y;
i[1][1] = x - 1;
i[2][0] = y;
i[2][1] = x + 1;
i[3][0] = y;
i[3][1] = x + 2;
}
else if (state == 1 || state == 3) {
i[1][0] = y + 1;
i[1][1] = x;
i[2][0] = y - 1;
i[2][1] = x;
i[3][0] = y - 2;
i[3][1] = x;
}
}
else if (id == 1) {
if (state == 0) {
i[1][0] = y;
i[1][1] = x - 1;
i[2][0] = y - 1;
i[2][1] = x - 1;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (state == 1) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y - 1;
i[2][1] = x + 1;
i[3][0] = y + 1;
i[3][1] = x;
}
if (state == 2) {
i[1][0] = y;
i[1][1] = x - 1;
i[2][0] = y + 1;
i[2][1] = x + 1;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (state == 3) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y + 1;
i[2][1] = x - 1;
i[3][0] = y + 1;
i[3][1] = x;
}
}
else if (id == 2) {
if (state == 0) {
i[1][0] = y;
i[1][1] = x - 1;
i[2][0] = y - 1;
i[2][1] = x + 1;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (state == 1) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y + 1;
i[2][1] = x + 1;
i[3][0] = y + 1;
i[3][1] = x;
}
if (state == 2) {
i[1][0] = y;
i[1][1] = x - 1;
i[2][0] = y + 1;
i[2][1] = x - 1;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (state == 3) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y - 1;
i[2][1] = x - 1;
i[3][0] = y + 1;
i[3][1] = x;
}
}
else if (id == 3) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y - 1;
i[2][1] = x + 1;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (id == 4) {
if (state == 0||state==2) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y;
i[2][1] = x - 1;
i[3][0] = y - 1;
i[3][1] = x + 1;
}
else if (state == 1||state==3) {
i[1][0] = y-1;
i[1][1] = x;
i[2][0] = y;
i[2][1] = x+1;
i[3][0] = y+1;
i[3][1] = x + 1;
}
}
else if (id == 5) {
if (state == 0) {
i[1][0] = y;
i[1][1] = x - 1;
i[2][0] = y - 1;
i[2][1] = x;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (state == 1) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y;
i[2][1] = x + 1;
i[3][0] = y + 1;
i[3][1] = x;
}
if (state == 2) {
i[1][0] = y;
i[1][1] = x - 1;
i[2][0] = y + 1;
i[2][1] = x;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (state == 3) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y;
i[2][1] = x - 1;
i[3][0] = y + 1;
i[3][1] = x;
}
}
else if (id == 6) {
if (state == 0 || state == 2) {
i[1][0] = y - 1;
i[1][1] = x;
i[2][0] = y - 1;
i[2][1] = x - 1;
i[3][0] = y;
i[3][1] = x + 1;
}
else if (state == 1 || state == 3) {
i[1][0] = y - 1;
i[1][1] = x + 1;
i[2][0] = y;
i[2][1] = x + 1;
i[3][0] = y + 1;
i[3][1] = x;
}
}
return i;
}//根据私有变量返回方块四个格子的坐标
void rotate() {
if (state < 3)state++;
else state = 0;
}
void Lmove() { x--; }
void Rmove() { x++; }
void drop() { y++; }
};
class Player {
private:
int refuse;//积攒垃圾行数,放置下一个方块的瞬间上涨
int wall[26][16];//边界及所有屏幕内存在方块的位置
Block now, next;//目前方块及下一方块
public:
Player():refuse(0),now(*(new Block(2,7,rand()%7))),next(*(new Block(2,7, rand() % 7))){
for (int i = 0; i < 26; i++)
for (int j = 0; j < 16; j++)
wall[i][j] = 0;
for (int i = 0; i < 23; i++)
wall[i][2] = wall[i][13] = 1;
for (int j = 3; j <=12; j++)
wall[22][j] = 1;
}
void produce() {
now = next;
next =Block(2, 7, rand() % 7);
}//产生新方块,设置now和next对象
int clear() {
int sum = 0,t;
int i, j,k;
for (i = 2; i < 22; i++) {
t = 0;
for (j = 3; j <= 12; j++) {
if (wall[i][j] == 0) {
t++;
}
}
if (t == 0) {
sum++;
for (j = i; j >= 2; j--) {
for (k = 3; k <= 12; k++) {
wall[j][k] = wall[j - 1][k];
}
}
}
}
return sum;
}//消行,返回消除行数
void add_refuse(int x) {refuse += x;}
void rise() {
int i, j;
if (height() + refuse <= 20&&refuse!=0) {
for (i = 2; i < 22 - refuse;i++ ) {
for (j = 3; j <= 12; j++) {
wall[i][j] = wall[i + 1][j];
}
}
for (i =22-refuse; i <22; i++) {
for (j = 3; j <= 12; j++) {
wall[i][j] = 1;
}
}
for (i = 22 - refuse; i < 22; i++) {
wall[i][rand() % 10 + 3] = 0;
}
refuse = 0;
}
}//根据refuse数值上涨垃圾行,refuse归零
int height() {
for (int i = 2; i < 22; i++) {
for (int j = 3; j <= 12; j++) {
if (wall[i][j] == 1)
return 22 - i;
}
}
return 0;
}//返回屏幕内方块高度
bool judge_fail() {
for (int i = 0; i <= 1; i++)
for (int j = 3; j <= 12; j++)
if (wall[i][j] == 1)
return true;
if (height() + refuse > 20)
return true;
return false;
}//3<=x<=12,0<=y<=1内有方块或height+refuse>20时判定失败
bool judge_coincide(Block test) {
int** i = test.coordinate();
for(int j=0;j<4;j++)
if (wall[i[j][0]][i[j][1]] == 1)return true;
return false;
}//判断测试砖块与墙是否重合
void rotate() {
Block test = now;
test.rotate();
if (judge_coincide(test) == false)
now.rotate();
else {
test.Rmove();
if (judge_coincide(test) == false) {
now.rotate();
now.Rmove();
}
else {
test.Lmove();
test.Lmove();
if (judge_coincide(test) == false) {
now.rotate();
now.Lmove();
}
else {
test.Lmove();
if (judge_coincide(test) == false) {
now.rotate();
now.Lmove();
now.Lmove();
}
}
}
}
}//旋转并判断合法性以及踢墙
void Lmove() {
Block test = now;
test.Lmove();
if (judge_coincide(test) == false)
now.Lmove();
}//左移
void Rmove() {
Block test = now;
test.Rmove();
if (judge_coincide(test) == false)
now.Rmove();
}//右移
void drop() {
Block test = now;
test.drop();
if (judge_coincide(test) == false)
now.drop();
else {
set();
}
}//下降
void set() {
int** i = now.coordinate();
for (int j = 0; j < 4; j++)
wall[i[j][0]][i[j][1]] = 1;
produce();
}//放置方块
void display() {
for (int i = 0; i < 26; i++) {
for (int j = 0; j < 16; j++) {
if (wall[i][j] == 0)cout << " ";
else cout << "■";
}
cout << endl;
}
}
};