android开发日志之2048安卓版
2015-10-31 21:03
513 查看
之前是在eclipse上写的,后面换成了android sudio。
2048游戏的UI整体可以采用线性布局,即LinearLayout,其中嵌套一个线性布局和一个GridLayout,内嵌的线性布局填充文本框,以显示分数,GridLayout中填充4x4的继承自FrameLayout的card类作为主要的游戏界面。由于大部分操作都在GridLayout中进行,可以自定义一个继承自GridLayout的类GameView,类中定义判定上下左右滑动的方法和每次滑动后自动添加一个随机数字的方法以及每次滑动后判断游戏是否可以继续进行的方法。
主布局activity_main.xml代码如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/container" //match_parent表示布局充满整个屏幕 android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.example.administractor.game2048.MainActivity" //里面的组件垂直放置 android:orientation="vertical" tools:ignore="MergeRootFrame"> <LinearLayout //宽度充满整个屏幕,高度自适应。 android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="horizontal" > //显示当前分数的文本框 <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Your Score:"/> <TextView android:id="@+id/tvScore" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </LinearLayout> //使用自定义的GridLayout <com.example.administractor.game2048.GameView android:layout_width="fill_parent" android:layout_height="0dp" android:layout_weight="1" android:id="@+id/GameView" > </com.example.administractor.game2048.GameView> </LinearLayout>GameView.java:
package com.example.administrator.game2048; import java.util.ArrayList; import java.util.List; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.graphics.Point; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.widget.GridLayout; public class GameView extends GridLayout { //调用类构造方法 public GameView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); //初始化游戏 InitGameView(); } public GameView(Context context, AttributeSet attrs) { super(context, attrs); InitGameView(); } public GameView(Context context) { super(context); InitGameView(); } private void InitGameView(){ //设置为4x4个方格 setColumnCount(4); //设置背景颜色 setBackgroundColor(0xffeee4da); //判定滑动方向 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)){ if(offsetx<-5){ swipeLeft(); }else if(offsetx>5){ swipeRight(); } }else{ if(offsety<-5){ swipeUp(); }else if(offsetx>3){ 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(h, w))/4; addCards(cardWidth,cardWidth); startGame(); } //在4x4的方格上添加满卡片 public 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); cardmap[x][y]=c; } } } //游戏开始时每个卡片默认值设为0,并随机添加两张带数字的卡片 private void startGame(){ MainActivity.getMainActivity().clearScore(); for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { cardmap[x][y].setNum(0); } } addRandomNum(); addRandomNum(); } private void addRandomNum() { //使用emptypoints将数字为0的card提取出来,并随即选择一个空card赋值 emptyPoints.clear(); for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { if(cardmap[x][y].getNum()<=0){ emptyPoints.add(new Point(x,y)); } } } Point p=emptyPoints.remove((int)(Math.random()*emptyPoints.size())); //2和4出现的概率控制在1:9 cardmap[p.x][p.y].setNum(Math.random()>0.1?2:4); } //左滑方法 private void swipeLeft(){ //merge作为判断能否滑动的flag 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(cardmap[x1][y].getNum()>0){ if(cardmap[x][y].getNum()<=0){ cardmap[x][y].setNum(cardmap[x1][y].getNum()); cardmap[x1][y].setNum(0); merge=true; x--; }else if(cardmap[x][y].equal(cardmap[x1][y])){ cardmap[x][y].setNum(cardmap[x][y].getNum()*2); cardmap[x1][y].setNum(0); MainActivity.getMainActivity().addScore(cardmap[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 (cardmap[x][y1].getNum()>0) { if (cardmap[x][y].getNum()<=0) { cardmap[x][y].setNum(cardmap[x][y1].getNum()); cardmap[x][y1].setNum(0); y++; merge = true; }else if (cardmap[x][y].equal(cardmap[x][y1])) { cardmap[x][y].setNum(cardmap[x][y].getNum()*2); cardmap[x][y1].setNum(0); MainActivity.getMainActivity().addScore(cardmap[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 (cardmap[x][y1].getNum()>0) { if (cardmap[x][y].getNum()<=0) { cardmap[x][y].setNum(cardmap[x][y1].getNum()); cardmap[x][y1].setNum(0); y--; merge = true; }else if (cardmap[x][y].equal(cardmap[x][y1])) { cardmap[x][y].setNum(cardmap[x][y].getNum()*2); cardmap[x][y1].setNum(0); MainActivity.getMainActivity().addScore(cardmap[x][y].getNum()); merge = true; ae48 } 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(cardmap[x1][y].getNum()>0){ if(cardmap[x][y].getNum()<=0){ cardmap[x][y].setNum(cardmap[x1][y].getNum()); cardmap[x1][y].setNum(0); x++; merge=true; }else if(cardmap[x][y].equal(cardmap[x1][y])){ cardmap[x][y].setNum(cardmap[x][y].getNum()*2); cardmap[x1][y].setNum(0); MainActivity.getMainActivity().addScore(cardmap[x][y].getNum()); merge=true; } break; } } } } if(merge){ addRandomNum(); checkComplete(); } } //如果有空卡片或者相邻的值相同卡片则游戏还能进行 public void checkComplete(){ 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].equal(cardmap[x-1][y])|| x<3&&cardmap[x][y].equal(cardmap[x+1][y])|| y>0&&cardmap[x][y].equal(cardmap[x][y-1])|| y<3&&cardmap[x][y].equal(cardmap[x][y+1])){ complete=false; break ALL; } } } //游戏结束弹出alert提示窗口 if(complete){ new AlertDialog.Builder(getContext()).setTitle("大林哥温馨提示").setMessage("游戏结束").setPositiveButton("重来",new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface arg0, int arg1) { startGame(); } }).show(); } } private Card[][] cardmap=new Card[4][4]; private List<Point> emptyPoints=new ArrayList<Point>(); }主类MainActivity.java:
package com.example.administrator.game2048;
import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;
public class MainActivity extends Activity {
public MainActivity(){
mainActivity=this;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvscore = (TextView) findViewById(R.id.tvScore);
}
public void clearScore(){
score=0;
showScore();
}
public void showScore(){
tvscore.setText(score+"");
}
public void addScore(int s){
score+=s;
showScore();
}
private TextView tvscore;
private int score=0;
public static MainActivity mainActivity=null;
public static MainActivity getMainActivity() {
return mainActivity;
}
}
Card.java:
package com.example.administrator.game2048;
import android.content.Context;
import android.view.Gravity;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.TextView;
public class Card extends FrameLayout {
public Card(Context context) {
super(context);
LayoutParams lp = null;
View background = new View(getContext());
//参数-1表示layoutparams填充满整个父容器
lp = new LayoutParams(-1, -1);
//设置卡片之间有10像素的间隔
lp.setMargins(10, 10, 0, 0);
background.setBackgroundColor(0x33ffffff);
addView(background, lp);
label = new TextView(getContext());
label.setTextSize(28);
label.setGravity(Gravity.CENTER);
lp = new LayoutParams(-1, -1);
lp.setMargins(10, 10, 0, 0);
addView(label, lp);
setNum(0);
}
private int n=0;
public int getNum(){
return n;
}
//设置数字及对应的背景颜色
public void setNum(int n){
this.n=n;
if(n<=0){
label.setText("");
}else{
label.setText(n+"");
}
switch (n) {
case 0:
label.setBackgroundColor(0x00000000);
break;
case 2:
label.setBackgroundColor(0xffeee4da);
break;
case 4:
label.setBackgroundColor(0xffede0c8);
break;
case 8:
label.setBackgroundColor(0xfff2b179);
break;
case 16:
label.setBackgroundColor(0xfff59563);
break;
case 32:
label.setBackgroundColor(0xfff67c5f);
break;
case 64:
label.setBackgroundColor(0xfff65e3b);
break;
case 128:
label.setBackgroundColor(0xffedcf72);
break;
case 256:
label.setBackgroundColor(0xffedcc61);
break;
case 512:
label.setBackgroundColor(0xffedc850);
break;
case 1024:
label.setBackgroundColor(0xffedc53f);
break;
case 2048:
label.setBackgroundColor(0xffedc22e);
break;
default:
label.setBackgroundColor(0xff3c3a32);
break;
}
}
//判断卡片是否相等
public boolean equal(Card o){
return getNum()==o.getNum();
}
private TextView label;
}
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- Android IPC进程间通讯机制
- Android Manifest 用法
- [转载]Activity中ConfigChanges属性的用法
- Android之获取手机上的图片和视频缩略图thumbnails
- Android之使用Http协议实现文件上传功能
- Android学习笔记(二九):嵌入浏览器
- android string.xml文件中的整型和string型代替
- i-jetty环境搭配与编译
- android之定时器AlarmManager
- android wifi 无线调试
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- android 代码实现控件之间的间距
- android FragmentPagerAdapter的“标准”配置
- Android"解决"onTouch和onClick的冲突问题
- android:installLocation简析
- android searchView的关闭事件