安卓开发实现俄罗斯方块游戏

1.实现方式

*使用安卓开发实现
*使用开发工具:AndroidStudio

2.样例展示

1.游戏开始样例

在这里插入图片描述

2.游戏进行中

在这里插入图片描述

3.游戏暂停

在这里插入图片描述

4.游戏结束

在这里插入图片描述

3.代码展示

 * 1.结构说明:控制显示的xml文件和逻辑控制的java代码组成
 * 2.布局说明:主要是三部分布局:游戏部分,底部的button部分,以及右侧的状态显示部分和开始、暂停按钮部分
 * 3.游戏窗口的线的绘制、游戏方格的绘制均由java代码实现
 * 4.游戏方块的生成是创建相应的对象
 * 5.不同方块的下落利用随机数实现

1.页面布局xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="#67C6F1">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:padding="10dp"
        android:orientation="horizontal">
            <FrameLayout
                android:id="@+id/layoutGame"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content">

            </FrameLayout>
            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="bottom"
                android:orientation="vertical">

                <Button
                    android:id="@+id/btnStart"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Start"/>

                <Button
                    android:id="@+id/btnPause"
                    android:layout_width="match_parent"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:text="Pause"/>
            </LinearLayout>

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <Button
            android:id="@+id/btnLeft"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="左"
            android:textSize="25dp"/>

        <Button
            android:id="@+id/btnTop"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="上"
            android:textSize="25dp"/>

        <Button
            android:id="@+id/btnRight"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="右"
            android:textSize="25dp"/>

        <Button
            android:id="@+id/btnBottom"
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:text="下"
            android:textSize="25dp"/>



    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="60dp"
        android:orientation="horizontal">

        <TextView
            android:layout_width="0dp"
            android:layout_height="match_parent"
            android:layout_weight="1"
            android:textStyle="bold"
            android:text="power by android"
            android:textSize="18dp"
            android:gravity="center"
          />

    </LinearLayout>

</LinearLayout>

2.后台逻辑

package com.example.i;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.Toast;

import java.util.Random;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    //声明一个游戏区域控件
    View view;
    //游戏区域长宽
    int xWidth,xHight;
    //地图画笔
    Paint mapPaint;

    //初始化辅助线画笔
    Paint linepaint;

    //方块画笔
    Paint boxPaint;

    //状态画笔
    Paint startPaint;

    //地图
    boolean [][]maps;
    //方块
    Point[] boxs;

    //方块的种类
    final int TYPE = 7;

    //方块类型
    int boxType;
    //方块大小
    int boxSize;

    //自动下落线程
    public  Thread downThread;

    //
    public Handler handler=new Handler(){
        public void handleMessage(android.os.Message msg){
            //刷新重绘view
            view.invalidate();
        };
    };

    //暂停状态
    public boolean isPause;

    //游戏结束状态

    public boolean isOver;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //去掉标题栏
        getSupportActionBar().hide();
        setContentView(R.layout.activity_main);
        intData();
        newBoxs();
        initView();
        intLister();
    }
    //初始化数据
    public void intData(){
        //获得屏幕宽度
        int width=getScreeWidth(this);
        //设置游戏区域宽度=屏幕宽度*2/3
        xWidth=width * 2/3;
        //游戏区域的高度=宽度 * 2
        xHight=2 * xWidth;
        //初始化地图
        maps=new boolean[10][20];

        //初始化方块大小:游戏宽度/10
        boxSize=xWidth/maps.length;
    }
    /*新的方块*/
    public  void newBoxs(){
        //随机数生成一个新的方块
        Random random=new Random();
        boxType=random.nextInt(7);
        switch (boxType){
            //田字形
            case 0:
                boxs=new Point[]{new Point(4,0),new Point(5,0),new Point(4,1),new Point(5,1)};
                break;
            //L
            case 1:
                boxs=new Point[]{new Point(4,1),new Point(5,0),new Point(3,1),new Point(5,1)};
                break;
            //反L
            case 2:
                boxs=new Point[]{new Point(4,1),new Point(3,0),new Point(3,1),new Point(5,1)};
                break;
            //横条
            case 3:
                boxs=new Point[]{new Point(3,0),new Point(4,0),new Point(5,0),new Point(6,0)};
                break;
            //凸字形
           case 4:
            boxs=new Point[]{new Point(4,1),new Point(5,0),new Point(5,1),new Point(6,1)};
                break;
            case 5:
                boxs=new Point[]{new Point(4,0),new Point(5,0),new Point(5,1),new Point(5,2)};
                break;
            case 6:
                boxs=new Point[]{new Point(5,0),new Point(6,0),new Point(4,1),new Point(5,1)};
                break;

        }


    }
    //初始化视图
    @SuppressLint("ResourceAsColor")
    public void initView(){
        //初始化画笔
        mapPaint=new Paint();
        mapPaint.setColor(0x50000000);
        mapPaint.setAntiAlias(true);

        linepaint =new Paint();
        linepaint.setColor(R.color.paint1);
        //一般会打开抗锯齿
        linepaint.setAntiAlias(true);

        //初始化方块画笔
        boxPaint=new Paint();
        boxPaint.setColor(0xff000000);
        boxPaint.setAntiAlias(true);

        startPaint=new Paint();
        startPaint.setColor(R.color.tools);
        startPaint.setAntiAlias(true);
        startPaint.setTextSize(100);

        //1.得到父容器
        FrameLayout layoutGame=findViewById(R.id.layoutGame);
        //2.实例化游戏区域
        view = new View(this){
            //重写游戏区域绘制
            @Override
            protected void onDraw(Canvas canvas) {
                super.onDraw(canvas);
                //绘制地图
                for(int x=0;x<maps.length;x++){
                    for(int y=0;y<maps[x].length;y++){
                        if(maps[x][y] == true)
                            canvas.drawRect(x*boxSize,y*boxSize,x*boxSize+boxSize,y*boxSize+boxSize,mapPaint);
                    }
                }

                //方块绘制
                for(int i=0;i<boxs.length;i++){
                    //矩形绘制
                    canvas.drawRect(
                            boxs[i].x*boxSize,
                            boxs[i].y*boxSize,
                            boxs[i].x*boxSize+boxSize,
                            boxs[i].y*boxSize+boxSize,boxPaint);
                }

                //地图辅助线绘制
                for(int x=0;x<maps.length;x++){
                    canvas.drawLine(x*boxSize,0,x*boxSize,view.getHeight(),linepaint);
                }
                for(int y=0;y<maps[0].length;y++){
                    canvas.drawLine(0,y*boxSize,view.getWidth(),y*boxSize,linepaint);
                }
                //游戏结束提示
                if(isOver){
                    canvas.drawText("游戏结束",view.getWidth()/2-startPaint.measureText("游戏结束")/2,view.getHeight()/2,startPaint);
                }


                //画暂停状态
                if(isPause && !isOver){
                    canvas.drawText("暂停",view.getWidth()/2-startPaint.measureText("暂停")/2,view.getHeight()/2,startPaint);
                }
            }
        };
        //3.设置游戏区域大小
        view.setLayoutParams(new FrameLayout.LayoutParams(xWidth,xHight));
        //设置背景颜色
        view.setBackgroundColor(R.color.gamabg11);
        //4.添加到父容器里面
        layoutGame.addView(view);


    }
   /* 初始化监听*/
    public  void intLister(){
        findViewById(R.id.btnLeft).setOnClickListener(this);
        findViewById(R.id.btnRight).setOnClickListener(this);
        findViewById(R.id.btnTop).setOnClickListener(this);
        findViewById(R.id.btnRight).setOnClickListener(this);
        findViewById(R.id.btnBottom).setOnClickListener(this);
        findViewById(R.id.btnStart).setOnClickListener(this);
        findViewById(R.id.btnPause).setOnClickListener(this);
    }
    //获得屏幕宽度
    public static  int getScreeWidth(Context context){
        WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        DisplayMetrics outMetrice = new DisplayMetrics();
        wm.getDefaultDisplay().getMetrics(outMetrice);
        return  outMetrice.widthPixels;
    }
    /*捕捉点击事件*/
    @Override
    public void onClick(View v) {
        switch (v.getId()){
            //左
            case R.id.btnLeft:
                if (isPause)
                    return;
                move(-1,0);
                break;
            //上
            case R.id.btnTop:
                if (isPause)
                    return;
               rotate();
                break;
            //右
            case R.id.btnRight:
                if (isPause)
                    return;
                move(1,0);
                break;
            //下
            case R.id.btnBottom:
                if (isPause)
                    return;
                //快速下落
                while (true){
                    //如果下落失败 结束循环
                    if(!moveBottom()){
                        break;
                    }

                }
                break;
            //开始
            case R.id.btnStart:

                startGame();
                break;
            //暂停
            case R.id.btnPause:
                setPause();
                break;
        }
        //调用重新绘制view
        view.invalidate();
    }


    /*设置暂停状态*/
    public void setPause(){
        if(isPause)
            isPause=false;
        else
            isPause=true;
    }
    /*开始游戏*/
    public void startGame(){

        if(downThread==null){
            downThread=new Thread(){
                @Override
                public void run() {
                    super.run();
                    while(true){
                        try{
                            //休眠500毫秒
                            sleep(500);
                        }catch (InterruptedException e){
                            e.printStackTrace();
                        }

                        //判断游戏是否处于结束状态
                        //判断是否属于暂停状态
                        if(isOver||isPause)
                            //继续循环
                            continue;
                        //执行一次下落
                        moveBottom();
                        //通知主线程刷新
                        handler.sendEmptyMessage(0);
                    }
                }
            };
            downThread.start();
        }
        //清除地图
        for(int x=0;x<maps.length;x++){
            for(int y = 0;y<maps[0].length;y++){
                maps[x][y]=false;
            }
        }

        //游戏结束主观题设为false
        isOver=false;
        //暂停状态设为false
        isPause=false;

        //生成新的方块
        newBoxs();

    }

    /*下落*/
    public  boolean moveBottom(){
        //1.移动成功不做处理
        if(move(0,1))
            return true;
        //2.移动失败,堆积处理
        for(int i=0;i<boxs.length;i++)
            maps[boxs[i].x][boxs[i].y] = true;
        //3.消行处理
        cleaneLine();
        //4.生成新的方块
        newBoxs();
        //5.游戏结束判断
        isOver=checkOver();
        return false;
    }
    /*消行处理*/
    public void cleaneLine(){
        for(int y=maps[0].length-1;y>0;y--){
                //执行判断
               if(checkLine(y)) {
                   //执行消行
                   deleteLine(y);
                   //消掉的那一行开始重新遍历
                   y++;
               }
        }
    }
    /*消行判断*/
    public boolean checkLine(int y){
        for(int x=0;x<maps.length;x++){
            //如果有一个不为true,则这一行不能消除
            if(!maps[x][y])
                return  false;
        }
        return true;
    }
    /*执行消行*/
     public void deleteLine(int dy){
         for(int y=maps[0].length-1;y>0; y--){
             for(int x=0;x<maps.length;x++){
                 maps[x][y]=maps[x][y-1];
             }
         }
     }
    /*游戏结束判断*/
    public  boolean checkOver(){
        for(int i=0;i<boxs.length;i++){
            if(maps[boxs[i].x][boxs[i].y]){
                return true;
            }
        }
        return false;
    }


    /*移动*/
    public boolean move(int x,int y){
        for(int i=0;i<boxs.length;i++) {
            //把方块预移动的点传入边界判断
            if(cheakBoundary(boxs[i].x +x, boxs[i].y +y)){
                //如果出界 返回false
                return false;
            }
        }


        //遍历方块数组每一个都加上偏移量
        for(int i=0;i<boxs.length;i++) {
            boxs[i].x += x;
            boxs[i].y += y;
        }
        return  true;
    }
    /*旋转*/
    public boolean rotate(){
        //如果当前方块为田字形,旋转失败
        if(boxType==0){
            return  false;
        }
        //遍历方块数组,每一个都绕着中心店点旋转90度
        for(int i=0;i<boxs.length;i++){
            //旋转算法(笛卡尔公式)顺时针旋转90度
            int checkX=-boxs[i].y+boxs[0].y+boxs[0].x;
            int checkY=boxs[i].x-boxs[0].x+boxs[0].y;

            //将预旋转的点传入边界判断是否出界
            if(cheakBoundary(checkX,checkY))
                //如果出界false,旋转失败
                return false;
        }
        //遍历方块数组,每一个都绕着中心店点旋转90度
        for(int i=0;i<boxs.length;i++){
            //旋转算法(笛卡尔公式)顺时针旋转90度
            int checkX=-boxs[i].y+boxs[0].y+boxs[0].x;
            int checkY=boxs[i].x-boxs[0].x+boxs[0].y;
            boxs[i].x=checkX;
            boxs[i].y=checkY;
        }
        return true;
    }
    /**
     * 出界判断
     * 传入x,y,判断是否在边界外
     * return ture说出界
     * */
    public  boolean cheakBoundary(int x,int y){
        return (x<0 ||y<0||x>=maps.length||y>=maps[0].length||maps[x][y] == true);
    }
}

3.部分样式

在这里插入图片描述

4.功能说明:

 * 1.底部的上下左右四个按钮实现游戏的方块的旋转和左右移动和快速下落。
* 2.右侧的“开始”按钮完成游戏的开始,“暂停”按钮实现游戏的暂停,并在游戏窗口显示暂停字样。
发布了43 篇原创文章 · 获赞 45 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/mzc_love/article/details/102535579