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

来源:互联网 发布:win7流量监控软件 编辑:程序博客网 时间:2024/05/07 03:35
没玩过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.游戏效果截图:
                  

0 0