综合练习——简易俄罗斯方块
2017-11-20 本文已影响33人
孙浩j
需求分析:类1.图形类(父类图形和子类的具体图形)2.屏幕类
- 图形类,这个类可以被具体的图形所继承
- 图形是由多个点组成的,每个点有它的位置,点的位置决定了图形位置
- 所以建立点类,把点放到数组中,用多点的组合位置表示图形
- 图形类具有的功能
- 1.左移
- 2.右移
- 3.下移
- 4.顺时针旋转
- 5.判断是否越界
*屏幕类核心功能
*1.消行
*(1)判断最后一行是不是满的
*(2)消除最后一行
*2.保存图形
*(1)保存正在移动的图形
*(2)保存已经到底不能再移动的图形
*3.打印图形
*(1)打印的图形包括正在移动的图形和被存的图形
*4.判断正在移动的图形和被存的图形坐标是否冲和
*/
点类
public class Spot {
private int row; //定义行坐标
private int col; //定义列坐标
public Spot(int row, int col) {
super();
this.row = row;
this.col = col;
}
public Spot() {
super();
}
public int getRow() {
return row;
}
public void setRow(int row) {
this.row = row;
}
public int getCol() {
return col;
}
public void setCol(int col) {
this.col = col;
}
//图形的移动功能是根据点移动的
public void left(){
col=col-1;
}
public void right(){
col=col+1;
}
public void bottom(){
row=row+1;
}
}
public abstract class Graph {
private Spot[]sp=new Spot[4]; //建立一个用于构成图形的数组
public Graph(){
}
public Spot[] getSp() {
return sp;
}
public void setSp(Spot[] sp) {
this.sp = sp;
}
public void leftG(){ //图形左移,将数组里每一个点左边都进行改变
for(int i=0;i<sp.length;i++){
sp[i].setCol(sp[i].getCol()-1);
}
}
public void rightG(){ //图形右移
for(int i=0;i<sp.length;i++){
sp[i].setCol(sp[i].getCol()+1);
}
}
public void bottomG(){ //图形下移
for(int i=0;i<sp.length;i++){
sp[i].setRow(sp[i].getRow()+1);
}
}
public void topG(){ //图形上移
for(int i=0;i<sp.length;i++){
sp[i].setRow(sp[i].getRow()-1);
}
}
public boolean judgeLeft(){ //判断左侧是否越界,越界为true
for(int i=0;i<sp.length;i++){
if(sp[i].getCol()<1){
return true;
}
}
return false;
}
public boolean judgeRight(){ //判断右侧是否越界,越界为true
for(int i=0;i<sp.length;i++){
if(sp[i].getCol()>12){
return true;
}
}
return false;
}
public boolean judgeBottom(){ //判断下侧是否越界,越界为true
for(int i=0;i<sp.length;i++){
if(sp[i].getRow()>15){
return true;
}
}
return false;
}
public abstract void rotate();//y-q+p, p-x+q
//定义一个抽象的旋转的方法,由子类决定怎么旋转
}
具体图形类T型(该类继承了抽象类图形,自动具备了非抽象方法)
public class T extends Graph {
public T(int row,int col){ //子类调用父类方法要使用super.方法
super.getSp()[0]=new Spot(row,col-1); //通过确定中心点坐标找到其它点和其关系,确定了图形形状
super.getSp()[1]=new Spot(row,col);
super.getSp()[2]=new Spot(row,col+1);
super.getSp()[3]=new Spot(row+1,col);
}
public void rotate() {//y-q+p, p-x+q
Spot[] sp=new Spot[4];
//建一个新数组用于接收旋转后的图形,用原数组,旋转后坐标和原坐标有影响
for(int i=0;i<super.getSp().length;i++){
sp[i]=new Spot(super.getSp()[i].getCol()
-super.getSp()[1].getCol()
+super.getSp()[1].getRow(),
super.getSp()[1].getRow()
-super.getSp()[i].getRow()
+super.getSp()[1].getCol());
}
super.setSp(sp); //把这个旋转后的坐标位置传给图形
}
public void rotate1() {//y-q+p, p-x+q //逆时针旋转
Spot[] sp=new Spot[4];
for(int i=0;i<super.getSp().length;i++){
sp[i]=new Spot(-super.getSp()[i].getCol()
+super.getSp()[1].getCol()
+super.getSp()[1].getRow(),
-super.getSp()[1].getRow()
+super.getSp()[i].getRow()
+super.getSp()[1].getCol());
}
super.setSp(sp);
}
}
屏幕类
public class Screen {
private String[][] s=new String[15][12];//保存当前图形
private String[][] s1=new String[15][12]; //用于存已有图形
public Screen(){
for(int i=0;i<s1.length;i++){
for(int j=0;j<s1[i].length;j++){
s1[i][j]="*";
}
}
}
public void setS(Graph g){
//把图形存到屏幕中图形坐标的位置里。
for(int i=0;i<s.length;i++){ //屏幕的行
for(int j=0;j<s[i].length;j++){ //屏幕的列
boolean b=false;
for(int k=0;k<g.getSp().length;k++){ //
if((g.getSp()[k].getRow()==(i+1)&&
g.getSp()[k].getCol()==(j+1))){
b=true;
}
}
if(b){
s[i][j]="~";
}else{
s[i][j]="*"; //在不满足的地方存星,是为了防止图形位置改变时,原有位置还存在
}
}
}
}
public void setS1(){ // 用于存不再受控制移动的图形
for(int i=0;i<s.length;i++){
for(int j=0;j<s[i].length;j++){
if(s[i][j]=="~"){
s1[i][j]=s[i][j];
}
}
}
}
public void print(){ //打印出的屏幕是不受控制的图形+正在受控制移动的图形
for(int i=0;i<s.length;i++){
for(int j=0;j<s[i].length;j++){
if(s1[i][j]=="~"){
System.out.print(s1[i][j]);
}else{
System.out.print(s[i][j]);
}
}
System.out.println();
}
}
public String[][] getS() {
return s;
}
public boolean have(){ //判断正在移动的图形和已经被存起来的图形是否重合
for(int i=0;i<s.length;i++){
for(int j=0;j<s[i].length;j++){
if(s[i][j]==s1[i][j]&&s[i][j]=="~"){ //在相同的且等于~就是图形重合
return true;
}
}
}
return false;
}
public boolean full(){//判断最后一行是不是满的
boolean a=true;
for(int i=0;i<s1[14].length;i++){
if(s1[14][i]=="*"){
a=false;
break;
}else{
a=true;
}
}
return a;
}
public void delete(){ //删除最后一行
for(int i=s1.length-1;i>0;i--){
for(int j=0;j<s1[i].length;j++){
s1[i][j]=s1[i-1][j];
}
}
}
}
测试类
import java.util.*;
public class Demo1 {
public static void main(String[]args) throws InterruptedException{
Scanner in=new Scanner(System.in);
Screen s=new Screen();
while(true){
T t=new T(3,3);
s.setS(t);
//s.print();
out:while(true){ //不断移动
System.out.println("1表示左移,2表示右移,3表示下移,4表示旋转");
int a=in.nextInt();
if(a==1){
if(!t.judgeLeft()){ //如何没到达左侧边界,图形左移。
t.leftG();
s.setS(t);} //存到屏幕对象的正在移动图形的数组里
if(t.judgeLeft()){
t.rightG(); //但是左移后不一定到没到边界,这时要判断一下,到了边界之外右移回来
s.setS(t);
}
s.print(); //打印屏幕
}else if(a==2){ //如何没到达右侧边界,图形左移被存到屏幕对象的正在移动图形的数组里
if(!t.judgeRight()){
t.rightG();
s.setS(t);}
if(t.judgeRight()){
t.leftG();
s.setS(t);
}
s.print();//打印屏幕
}else if(a==3){
if(!t.judgeBottom()&&!s.have()){ //没到底边界,并且没跟已有图形重合,下移
t.bottomG();
s.setS(t);}
if(t.judgeBottom()||s.have()){ //如果下移后出了底边界,就上上移一下
t.topG(); //并且把上移后的图形存到 到达地步的屏幕数组里
s.setS(t);
s.setS1();
while(true){
if(s.full()){ //如果最后一行满了
s.delete(); //消除最后一行
}else{
s.print(); //打印出屏幕
break out; //这时不断移动的循环接收,重新进入一个图形开始移动
}
}
}
s.print();
}else if(a==4){
if(!t.judgeBottom()&&!t.judgeLeft()&&!t.judgeRight())//没到边界进行顺时针旋转
{
t.rotate();
s.setS(t);
}
if(t.judgeBottom()||t.judgeLeft()||t.judgeRight()){ //旋转后出了边界进行逆时针旋转
t.rotate1();
s.setS(t);
}
s.print(); 打印屏幕
}
}
}
}
}