必威体育Betway必威体育官网
当前位置:首页 > IT技术

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

时间:2019-07-30 09:44:18来源:IT技术作者:seo实验室小编阅读:67次「手机版」
 

android游戏开发

没玩过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.游戏效果截图:

相关阅读

游戏UI制作归纳

原则:制作方便,使用简单 管理层面 逻辑管理、界面加载,显示,隐藏,关闭,根据标示获得相应界面实例、层级深度、分组、导航、动画、样式

Android--SQLite数据库实现增删改查

SQLite–轻量级数据库 一般常见于安卓客户端。用于存储一些重要数据,因其操作容易、使用简单的好处博得一大批迷妹。今天就来说一

专业显卡能玩游戏吗?

游戏显卡和专业显卡有什么区别?专业显卡能玩游戏吗?这是很多网友会问到的一个问题,也是一个电脑爱好者老生常谈的一个问题。有过研究

一键分析Android的BugReport

在Android系统测试中,经常要抓取log,而内置的BugReport功能无异是最方便全面的。那么问题来了,BugReport包含的信息虽多,但分析起来就

Android8.0 图形引擎的心跳 - Vsync信号

VSync是Android4.1黄油计划引入的三大核心元素之一,主要为解决用户交互体验差的问题。Android通过VSync机制来提高显示效果,通常这

分享到:

栏目导航

推荐阅读

热门阅读