Android游戏开发之2048游戏简单实现

时间:2021-02-07 03:24:36
没玩过2048的可以自己下一个玩玩,挺有趣的益智游戏。
本文实现了其简单的游戏逻辑,能够进行记分,游戏结束判断功能。重新开始以及保存游戏模块还没有写好,后边
会一一进行完善。
代码都有详细的注释,相信大家都能够看懂。
 
1.MainActivity:
 
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    private TextView tvScore;
    private static MainActivity mainActivity=null;
    private Button restart,saveGame,quitGame;


    public MainActivity(){  //可以在外界访问MainActivity的实例  mainActivity=this;  //MainActivity一旦被构建,就给mainActivity静态变量赋值,就可以从外界进行访问它  }
    public static MainActivity getMainActivity(){
        return mainActivity;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tvScore=(TextView)findViewById(R.id.tvScore);
        quitGame=(Button)findViewById(R.id.quit);
        restart=(Button)findViewById(R.id.restart);
        restart.setOnClickListener(this);
        quitGame.setOnClickListener(this);
    }
    @Override
    public void onClick(View v) {
        try {
            switch (v.getId()){
                case R.id.quit:
                    System.exit(0);
                    break;
                case R.id.restart:
                    //new GameView(this,attrs,defStyleAttr).startGame(); //调用方法不成功  Toast.makeText(this, "Not complete", Toast.LENGTH_SHORT).show();
                    break;
            }
        }catch (NullPointerException e){  //空指针异常, 用一个null对象调用了它的某一个方法导致java.lang.NullPointerException错误  e.printStackTrace();
        }

    }

    //记分的实现:  public void clearScore(){
        score=0;
        showScore();
    }
    public void showScore(){
        tvScore.setText(score+"");
    }
    public void addScore(int s){
        score+=s;
        showScore();

    }
    private int score=0;

}

2.新建GameView类:

public class GameView extends GridLayout {

    public GameView(Context context, AttributeSet attrs, int defStyleAttr) {   //构造方法  super(context, attrs, defStyleAttr);
        initGameView();
    }
    public GameView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initGameView();
    }
    public GameView(Context context) {
        super(context);
        initGameView();

    }


    private void initGameView(){      //初始化  setColumnCount(4);//指定为4列  setBackgroundColor(0xffF0FFF0);

        setOnTouchListener(new OnTouchListener() {  //触摸监听  private float startX,startY,offsetX,offsetY;
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        startX=event.getX();
                        startY=event.getY();
                        break;
                    case MotionEvent.ACTION_UP:
                        offsetX=event.getX()-startX; //偏移量  offsetY=event.getY()-startY;

                        if(Math.abs(offsetX)>Math.abs(offsetY)){  //如果用户斜着滑动,X的偏移量大于Y的偏移量,说明用户为向X方向移动的意图  if(offsetX<-5){  //理论上是小于0,由于可能存在误差,故选择-5  swipeLeft();
                            }else if(offsetX>5){
                                swipeRight();
                            }
                        }else {
                            if (offsetY < -5) {
                                swipeUp();
                            }else if(offsetY>5){
                                swipeDown();
                            }
                        }
                        break;
                }
                return true;
            }
        });

    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {  //适应手机屏幕,设定卡片宽高  super.onSizeChanged(w, h, oldw, oldh);
        int cardWidth=(Math.min(w,h)-15)/4;
        addCards(cardWidth,cardWidth);
        startGame();
    }
    private void addCards(int cardWidth,int cardHeight){
        Card c;
        for (int y=0;y<4;y++){
            for (int x=0;x<4;x++){
                c=new Card(getContext());
                c.setNum(0);
                addView(c,cardWidth,cardHeight);

                cardsMap[x][y]=c; //把16张卡片全部添加进这个二维数组中,方便使用  }
        }
    }
    public void startGame(){ //开始游戏模块  MainActivity.getMainActivity().clearScore(); //分数清0   for (int y=0;y<4;y++){
            for(int x=0;x<4;x++){
                cardsMap[x][y].setNum(0);  //清0  }
            }
        addRandomNum();  //调用  addRandomNum();
        }

    private void addRandomNum(){  //添加随机数模块  emptyPoints.clear(); //清0  for (int y=0;y<4;y++){
            for(int x=0;x<4;x++){
                if(cardsMap[x][y].getNum()<=0){  //只有当卡片上没有数字时才会在其上添加  emptyPoints.add(new Point(x,y));
                }
            }
        }
        Point p=emptyPoints.remove((int)(Math.random()*emptyPoints.size())); //Math.random()随机获取0-1之间的数  cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4); //2和4出现的概率为9:1   }

    private void swipeLeft(){  //向左滑动模块  boolean merge=false;

        for(int y=0;y<4;y++){   //向右遍历  for(int x=0;x<4;x++){

                for(int x1=x+1;x1<4;x1++){
                    if(cardsMap[x1][y].getNum()>0){

                        if (cardsMap[x][y].getNum()<=0){
                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
                            cardsMap[x1][y].setNum(0);

                            x--;
                            merge=true;
                        }else if (cardsMap[x][y].equals(cardsMap[x1][y])){  //合并  cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
                            cardsMap[x1][y].setNum(0);

                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());  //记分的方式  merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){   //判断是否合并,若合并了,则添加一个随机数  addRandomNum();
            checkComplete();
        }

    }
    private void swipeRight(){
        boolean merge=false;

        for(int y=0;y<4;y++){   //向左遍历  for(int x=3;x>=0;x--){

                for(int x1=x-1;x1>=0;x1--){
                    if(cardsMap[x1][y].getNum()>0){

                        if (cardsMap[x][y].getNum()<=0){
                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
                            cardsMap[x1][y].setNum(0);

                            x++;
                            merge=true;
                        }else if (cardsMap[x][y].equals(cardsMap[x1][y])){
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
                            cardsMap[x1][y].setNum(0);

                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
                            merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            addRandomNum();
            checkComplete();
        }
    }
    private void swipeUp(){
        boolean merge=false;

        for(int x=0;x<4;x++){
            for(int y=0;y<4;y++){

                for(int y1=y+1;y1<4;y1++){
                    if(cardsMap[x][y1].getNum()>0){

                        if (cardsMap[x][y].getNum()<=0){
                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
                            cardsMap[x][y1].setNum(0);

                            y--;
                            merge=true;
                        }else if (cardsMap[x][y].equals(cardsMap[x][y1])){
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
                            cardsMap[x][y1].setNum(0);

                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
                            merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            addRandomNum();
            checkComplete();
        }
    }
    private void swipeDown(){
        boolean merge=false;

        for(int x=0;x<4;x++){
            for(int y=3;y>=0;y--){

                for(int y1=y-1;y1>=0;y1--){
                    if(cardsMap[x][y1].getNum()>0){

                        if (cardsMap[x][y].getNum()<=0){
                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
                            cardsMap[x][y1].setNum(0);

                            y++;
                            merge=true;
                        }else if (cardsMap[x][y].equals(cardsMap[x][y1])){
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
                            cardsMap[x][y1].setNum(0);

                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
                            merge=true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            addRandomNum();
            checkComplete();
        }
    }
    private void checkComplete(){  //判断游戏是否结束模块,当16个卡片填满数字且相邻之间没有相同的数字,则认为游戏结束。  boolean complete=true;

        ALL: //添加一个标签,其后为冒号  for (int y=0;y<4;y++){
            for (int x=0;x<4;x++){
                if(cardsMap[x][y].getNum()==0||
                        (x>0 && cardsMap[x][y].equals(cardsMap[x-1][y]))||
                        (x<3 && cardsMap[x][y].equals(cardsMap[x+1][y]))||
                        (y>0 && cardsMap[x][y].equals(cardsMap[x][y-1]))||
                        (y<3 && cardsMap[x][y].equals(cardsMap[x][y+1]))){
                    complete=false;
                    break ALL;  //使其跳出这个大循环   }
            }
        }
        //游戏结束时弹窗  if(complete){
            new AlertDialog.Builder(getContext()).setTitle("Hello!").setMessage("The game is over !")
                    .setNegativeButton("Restart", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    startGame();
                }
            }).setPositiveButton("Quit", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    System.exit(0);  //直接退出游戏  }
            }).show();
        }
    }
    private Card[][] cardsMap=new Card[4][4];
    private List<Point> emptyPoints=new ArrayList<Point>();
}
3.新建Card类:
package com.example.administrator.game2048;

import android.content.Context;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;

/**  * Created by Administrator on 2016/9/17.  */ public class Card extends FrameLayout {
    private int num=0;
    private TextView label;

    public Card(Context context) {
        super(context);

        label=new TextView(getContext());
        label.setTextSize(32);
        label.setBackgroundColor(0x335F9EA0);
        label.setGravity(Gravity.CENTER); //卡片在中心显示   LayoutParams lp=new LayoutParams(-1,-1); // (-1,-1)表示填充满整个父级容器  lp.setMargins(15,15,0,0); //设置每个卡片的间隔  addView(label,lp);
    }
    public int getNum() {
        return num;
    }

    public void setNum(int num) {
        this.num = num;
        if(num<=0){
            label.setText("");
        }else{
            label.setText(num+"");
        }

    }
    public boolean equals(Card o) {
        return getNum()==o.getNum();
    }

}
4.xml:


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  xmlns:tools="http://schemas.android.com/tools"  android:layout_width="match_parent"  android:layout_height="match_parent"  android:orientation="vertical"  tools:context="com.example.administrator.game2048.MainActivity">

    <LinearLayout  android:layout_width="match_parent"  android:layout_height="wrap_content"  android:orientation="horizontal">
    <TextView  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:text="Score :"  android:textSize="25dp"/>

        <TextView  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:id="@+id/tvScore"  android:textSize="25dp"/>

    </LinearLayout>
    <Space  android:layout_width="match_parent"  android:layout_height="15dp" />

        <com.example.administrator.game2048.GameView  android:layout_width="match_parent"  android:layout_height="0dp"  android:layout_weight="0.8"  android:id="@+id/gameView">

        </com.example.administrator.game2048.GameView>
        <LinearLayout  android:layout_width="match_parent"  android:layout_height="0dp"  android:layout_weight="0.1"  android:orientation="horizontal">
            <Button  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_weight="1"  android:id="@+id/restart"  android:text="Restart"  android:textAllCaps="false"  android:background="#2bb"  android:textSize="15dp"  android:textColor="#159"  />
            <Button  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_weight="1"  android:id="@+id/save"  android:text="Save"  android:textAllCaps="false"  android:background="#2cc"  android:textSize="15dp"  android:textColor="#159"  />
            <Button  android:layout_width="wrap_content"  android:layout_height="wrap_content"  android:layout_weight="1"  android:id="@+id/quit"  android:text="Quit"  android:textAllCaps="false"  android:background="#2dd"  android:textSize="15dp"  android:textColor="#159"  />

        </LinearLayout>


</LinearLayout>
5.游戏效果截图: