首页 > 系统 > Android > 正文

Android实现2048小游戏

2020-04-11 10:54:59
字体:
来源:转载
供稿:网友

本文实例介绍了Android实现2048小游戏的相关代码,分享给大家供大家参考,具体内容如下

根据界面,主要实现4*4的格子方块比较麻烦,其他的都挺简单的.总体为实现4*4的格子,自定义GridLayout,并在其中添加触摸监听事件,进行一系列的操作,从而实现游戏的逻辑,最后再添加动画效果即可完成.
下面是设计思路:

一.GameView的设计

首先自定义一个类,继承GridLayout,添加两个构造方法

public class GameView extends GridLayout {  //两个必要的构造方法  public GameView(Context context) {    super(context);    initView();  }  public GameView(Context context, AttributeSet attrs) {    super(context, attrs);    initView();  }  }

接下来在initView()中实现设置GridLayout为四列,并且添加触摸事件监听.(监听方法还可以重写onTouchEvent(),返回值为true即可),判断触摸方向,主要是通过x轴和y轴的偏移量的比较

 //初始化变量的方法  public void initView(){    //设置只有四列    setColumnCount(4);    //设置监听事件    setOnTouchListener(new OnTouchListener() {      @Override      public boolean onTouch(View v, MotionEvent event) {        switch (event.getAction()) {          case MotionEvent.ACTION_DOWN:            setX = event.getX();            setY = event.getY();            break;          case MotionEvent.ACTION_UP:            offsetX = event.getX() - setX;            offsetY = event.getY() - setY;            //判断滑动方向            if (Math.abs(offsetX) >= Math.abs(offsetY)) {              if (offsetX > 0) {                swipright();              } else if (offsetX < 0) {                swipleft();              }            } else {              if (offsetY > 0) {                swipdown();              } else if (offsetY < 0) {                swipup();              }            }            break;        }        return true;      }    });  }

监听事件实现后先放在那里,接下来把4*4的里面每个小格子设计成小卡片,每个卡片就是一个TextView,卡片设计很简单,需要什么就添加什么,默认数字为0,这个时候代表是空值,也就是空卡片.

public class Card extends FrameLayout {  public Card(Context context) {    super(context);    tvCard = new TextView(getContext());    tvCard.setTextSize(40f);    tvCard.setGravity(Gravity.CENTER);    LayoutParams lp = new LayoutParams(-1,-1);    lp.setMargins(15,15,0,0);    addView(tvCard, lp);  }  //卡片上的数字  private int num;  private boolean is2048 = true;  private void judgeIs2048(int num){    if (is2048){      if (2048==num){        Toast.makeText(getContext(),"恭喜赵莹达到2048",Toast.LENGTH_LONG).show();        is2048 = false;      }    }  }  public int getNum() {    return num;  }  public void setNum(int num) {    this.num = num;    if (num<=0){      tvCard.setText("");    }else {    //这里传进去的是字符串因此需要加上空字符      tvCard.setText(num+"");    }    switch (num) {      case 0:        tvCard.setBackgroundColor(0x33ffffff);        break;      case 2:        tvCard.setBackgroundColor(0xffeee4da);        break;      case 4:        tvCard.setBackgroundColor(0xffede0c8);        break;      case 8:        tvCard.setBackgroundColor(0xfff2b179);        break;      case 16:        tvCard.setBackgroundColor(0xfff59563);        break;      case 32:        tvCard.setBackgroundColor(0xfff67c5f);        break;      case 64:        tvCard.setBackgroundColor(0xfff65e3b);        break;      case 128:        tvCard.setBackgroundColor(0xffedcf72);        break;      case 256:        tvCard.setBackgroundColor(0xffedcc61);        break;      case 512:        tvCard.setBackgroundColor(0xffedc850);        break;      case 1024:        tvCard.setBackgroundColor(0xffedc53f);        break;      case 2048:        tvCard.setBackgroundColor(0xffedc22e);        break;      default:        tvCard.setBackgroundColor(0xff3c3a32);        break;    }    judgeIs2048(num);  }  //判断是否相等,用于合并  public boolean equals(Card o) {    return getNum()==o.getNum();  }  //用于显示数字  private TextView tvCard;  public TextView getTvCard() {    return tvCard;  }}

卡片设计就需要添加到GameView里面,这个时候重写onSizeChanged()函数,这个在程序打开的时候运行一次,通过他来动态设计卡片大小,并且添加卡片和开始游戏.

@Override  protected void onSizeChanged(int w, int h, int oldw, int oldh) {    super.onSizeChanged(w, w, oldw, oldh);    Config.CARD_WIDTH = (Math.min(w,h)-10)/4;    AddCard(Config.CARD_WIDTH);    StartGame();  }

添加卡片,一开始全设置为0,也就是全部添加空卡片

 //添加卡片  private void AddCard(int CARD_WIDTH){    Card c;    for (int x = 0;x<4;x++){      for (int y = 0;y<4;y++){        c = new Card(getContext());        c.setNum(0);        addView(c, CARD_WIDTH, CARD_WIDTH);        cardMap[y][x] = c;      }    }  }

游戏开始需要随机添加两张卡片,数值2或者4,出现比率9:1

//开始游戏  public void StartGame(){    for (int y = 0;y<4;y++){      for (int x = 0;x<4;x++){        cardMap[y][x].setNum(0);      }    }    AddRandomCard();    AddRandomCard();  }

随机添加卡片设计

//添加随机卡片  private void AddRandomCard(){    CardPoint.clear();    for (int y = 0;y<4;y++){      for (int x = 0;x<4;x++){        if (cardMap[x][y].getNum()<=0){          CardPoint.add(new Point(x,y));        }      }    }    //把一张空卡片换成带数字的    Point p = CardPoint.remove((int)(Math.random()*CardPoint.size()));    cardMap[p.x][p.y].setNum(Math.random()>0.1?2:4);    MainActivity.getMainActivity().getAnimLayer().createScaleTo1(cardMap[p.x][p.y]);}

这样大体框架就设计好了
接下来是滑动事件,这里只举例左滑

private void swipleft(){    boolean status = false;    for (int y = 0; y < 4; y++) {      for (int x = 0; x < 4; x++) {        for (int x1 = x+1; x1 < 4; x1++) {          if (cardMap[x1][y].getNum()>0) {            if (cardMap[x][y].getNum()<=0) {              MainActivity.getMainActivity().getAnimLayer().createMoveAnim(cardMap[x1][y],cardMap[x][y], x1, x, y, y);              cardMap[x][y].setNum(cardMap[x1][y].getNum());              cardMap[x1][y].setNum(0);              x--;              status = true;            }else if (cardMap[x][y].equals(cardMap[x1][y])) {              MainActivity.getMainActivity().getAnimLayer().createMoveAnim(cardMap[x1][y], cardMap[x][y],x1, x, y, y);              cardMap[x][y].setNum(cardMap[x][y].getNum() * 2);              cardMap[x1][y].setNum(0);              MainActivity.getMainActivity().addScore(cardMap[x][y].getNum());              status = true;            }            break;          }        }      }    }    if (status){      AddRandomCard();      checkGame();    }  }

每次添加卡片还需要判断是否结束游戏

//结束游戏  private void checkGame(){    boolean complete = true;    ALL:    for (int y = 0; y < 4; y++) {      for (int x = 0; x < 4; x++) {        if (cardMap[x][y].getNum()==0||            (x>0&&cardMap[x][y].equals(cardMap[x-1][y]))||            (x<3&&cardMap[x][y].equals(cardMap[x+1][y]))||            (y>0&&cardMap[x][y].equals(cardMap[x][y-1]))||            (y<3&&cardMap[x][y].equals(cardMap[x][y+1]))) {          complete = false;          break ALL;        }      }    }    if (complete) {      Toast.makeText(getContext(), "游戏结束" + MainActivity.getMainActivity().getScore(), Toast.LENGTH_LONG).show();    }  }

设计总体上框架就是上面说的那些.

二.动画效果

动画效果主要是创建,移动,合并这三个效果,因此重写个继承FrameLayout的class,覆盖到游戏界面上,这样的目的可以通过MainActivity中实例化当前这个类,然后可以操作其方法,然后通过滑动来设置动画

public class AnimLayer extends FrameLayout {  public AnimLayer(Context context, AttributeSet attrs, int defStyle) {    super(context, attrs, defStyle);  }  public AnimLayer(Context context, AttributeSet attrs) {    super(context, attrs);  }  public AnimLayer(Context context) {    super(context);  }  public void createMoveAnim(final Card from,final Card to,int fromX,int toX,int fromY,int toY){    final Card c = getCard(from.getNum());    LayoutParams lp = new LayoutParams(Config.CARD_WIDTH, Config.CARD_WIDTH);    lp.leftMargin = fromX*Config.CARD_WIDTH;    lp.topMargin = fromY*Config.CARD_WIDTH;    c.setLayoutParams(lp);    if (to.getNum()<=0) {      to.getTvCard().setVisibility(View.INVISIBLE);    }    TranslateAnimation ta = new TranslateAnimation(0, Config.CARD_WIDTH*(toX-fromX), 0, Config.CARD_WIDTH*(toY-fromY));    ta.setDuration(100);    ta.setAnimationListener(new Animation.AnimationListener() {      @Override      public void onAnimationStart(Animation animation) {}      @Override      public void onAnimationRepeat(Animation animation) {}      @Override      public void onAnimationEnd(Animation animation) {        to.getTvCard().setVisibility(View.VISIBLE);        recycleCard(c);      }    });    c.startAnimation(ta);  }  private Card getCard(int num){    Card c;    if (cards.size()>0) {      c = cards.remove(0);    }else{      c = new Card(getContext());      addView(c);    }    c.setVisibility(View.VISIBLE);    c.setNum(num);    return c;  }  private void recycleCard(Card c){    c.setVisibility(View.INVISIBLE);    c.setAnimation(null);    cards.add(c);  }  private List<Card> cards = new ArrayList<Card>();  public void createScaleTo1(Card target){    ScaleAnimation sa = new ScaleAnimation(0.1f, 1, 0.1f, 1, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);    sa.setDuration(100);    target.setAnimation(null);    target.getTvCard().startAnimation(sa);  }}

最后主布局文件如下

<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:background="#fffaf8ef"  android:orientation="vertical"  android:paddingBottom="@dimen/activity_vertical_margin"  android:paddingLeft="@dimen/activity_horizontal_margin"  android:paddingRight="@dimen/activity_horizontal_margin"  android:paddingTop="@dimen/activity_vertical_margin"  tools:context=".MainActivity">  <LinearLayout    android:layout_marginTop="15dp"    android:orientation="horizontal"    android:gravity="center"    android:layout_width="match_parent"    android:layout_height="wrap_content">    <TextView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:textColor="#ff776e65"      android:text="@string/title"      android:textSize="50sp"/>  </LinearLayout>  <LinearLayout    android:layout_width="match_parent"    android:orientation="horizontal"    android:layout_marginTop="10dp"    android:layout_height="wrap_content">    <TextView      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:textColor="#ff776e65"      android:layout_marginLeft="30dp"      android:textSize="35sp"      android:text="@string/Score"/>    <TextView      android:id="@+id/tvscore"      android:layout_marginLeft="20dp"      android:textSize="25sp"      android:textColor="#ff776e65"      android:layout_width="70dp"      android:layout_height="37dp"      />    <Button      android:layout_width="wrap_content"      android:layout_height="wrap_content"      android:id="@+id/startgame"      android:layout_marginLeft="40dp"      android:background="#ffbbada0"      android:textSize="15sp"      android:text="@string/start"/>  </LinearLayout>  <FrameLayout    android:id="@+id/gameContainer"    android:layout_width="fill_parent"    android:layout_height="0dp"    android:layout_weight="1">  <develop.niuli.com.game.GameView    android:layout_marginTop="40dp"    android:id="@+id/Gridlayout"    android:layout_width="match_parent"    android:background="#ffbbada0"    android:layout_height="350dp">  </develop.niuli.com.game.GameView>  <develop.niuli.com.game.AnimLayer    android:id="@+id/animLayer"    android:layout_width="match_parent"    android:layout_height="match_parent">  </develop.niuli.com.game.AnimLayer>  </FrameLayout></LinearLayout>

以上就是本文的全部内容,希望对大家的学习有所帮助。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表