Welcome 微信登录

首页 / 移动开发 / Android / Android实现2048小游戏

本文实例介绍了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() {@Overridepublic 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()函数,这个在程序打开的时候运行一次,通过他来动态设计卡片大小,并且添加卡片和开始游戏.

@Overrideprotected 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() {@Overridepublic void onAnimationStart(Animation animation) {}@Overridepublic void onAnimationRepeat(Animation animation) {}@Overridepublic 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"><LinearLayoutandroid:layout_marginTop="15dp"android:orientation="horizontal"android:gravity="center"android:layout_width="match_parent"android:layout_height="wrap_content"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#ff776e65"android:text="@string/title"android:textSize="50sp"/></LinearLayout><LinearLayoutandroid:layout_width="match_parent"android:orientation="horizontal"android:layout_marginTop="10dp"android:layout_height="wrap_content"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:textColor="#ff776e65"android:layout_marginLeft="30dp"android:textSize="35sp"android:text="@string/Score"/><TextViewandroid:id="@+id/tvscore"android:layout_marginLeft="20dp"android:textSize="25sp"android:textColor="#ff776e65"android:layout_width="70dp"android:layout_height="37dp"/><Buttonandroid: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><FrameLayoutandroid:id="@+id/gameContainer"android:layout_width="fill_parent"android:layout_height="0dp"android:layout_weight="1"><develop.niuli.com.game.GameViewandroid: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.AnimLayerandroid:id="@+id/animLayer"android:layout_width="match_parent"android:layout_height="match_parent"></develop.niuli.com.game.AnimLayer></FrameLayout></LinearLayout>
以上就是本文的全部内容,希望对大家的学习有所帮助。