打造一个属于你自己的Android版2048

今天写的博客是2048,说实话我是开始要写2048的时候才下一个来玩一下,之前是不懂的,玩了之后发现简单易入迷。下面直入主题,  

一开始,首先要熟悉2048这个游戏,最好写一下规则说明书,这里我就不列出来了。  

效果图展示:开始界面——>功能选择界面——>游戏界面

 

 

功能介绍:

开始界面:五秒之后进入功能选择界面

功能选择界面:根据不同的按钮来选择游戏的模式,可以选择不同模式,对应会有不同的图片进入游戏界面就开始播放背景音乐

游戏界面:1.记录分数;2.保留最高分;3.游戏区域符合游戏规则;4.背景音乐的播放开始暂停和停止;5.移动合并的声音 ; 6.游戏重来; 7.赢或者输跳出对话框

核心思想:(可以看完代码再来体会,或者体会完能有所启发后自己写)

做完这个2048后,给我最大的感觉就是把游戏界面当做一个自定义组件来实现,就像是系统自给的组件,比如按钮,按钮有自己的颜色大小外观,你点击按钮会有点击事件(切换图片显示下按效果),那么一个游戏界面也是这样的,有自己的颜色大小外观,和响应事件,那么这些内容就要我们自己来实现。

  其次就是2048的游戏逻辑,移动、合并、判断输赢,这些都要好好思考算法。经典地用到了二维数组来存储卡片位置,便于增删的链表来记录空位置。

再然后,如何打造个性化的2048,就是把数字变成自己喜欢的图片咯~数字逻辑转换为图像逻辑时,运用到了数组,算是比较笨的方法,但也是最容易想到的。

最后是传参问题,一是方式,activity之间的跳转用intent来传参;一般的用getxx,setxx来传参;自定义组件上下文context不用传构造函数里有。二是先后顺序,一开始我把获取参数放在GameView的构造函数里,这样GameView在初始化时已经执行了获取参数,参数来不及传过来的。

实现流程:

java代码:

 

</pre><pre name="code" class="java">/**
 * @author Clark Xu
 * 
 * 五秒之后跳转到功能选择界面
 *
 */
public class WelcomeActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
		setContentView(R.layout.welcome);
		skip();
	}
	// 5秒之后跳转到第二个页面
	// time计时器
	public void skip() {
		final Intent it = new Intent(WelcomeActivity.this, ChooseActivity.class); // 你要转向的Activity
		Timer timer = new Timer();
		TimerTask task = new TimerTask() {
			@Override
			public void run() {
				startActivity(it); // 执行
			}
		};
		timer.schedule(task, 1000 * 5);
	}
}
/**
 * @author Clark Xu
 * 
 * 功能选择界面:根据不同的按钮来选择游戏的模式,进入游戏界面就开始播放对应的背景音乐
 *
 */
public class ChooseActivity extends Activity {
	private int row = 4, column = 4;
	private int model = 1;
	private Button Btn3x3;
	private Button Btn4x4;
	private Button Btn5x5;
	private Button Btn6x6;
	private Button NormalBtn;
	private Button DigitBtn;
	private Button QilongzhuBtn;
	private Button HuoyinBtn;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		requestWindowFeature(Window.FEATURE_NO_TITLE);// 去掉标题栏
		setContentView(R.layout.choose);
		getView();
		setListeners();
	}

	public void getView() {
		Btn3x3 = (Button) findViewById(R.id.Btn3x3);
		Btn4x4 = (Button) findViewById(R.id.Btn4x4);
		Btn5x5 = (Button) findViewById(R.id.Btn5x5);
		Btn6x6 = (Button) findViewById(R.id.Btn6x6);
		NormalBtn = (Button) findViewById(R.id.NormalBtn);
		DigitBtn = (Button) findViewById(R.id.DigitBtn);
		QilongzhuBtn = (Button) findViewById(R.id.QilongzhuBtn);
		HuoyinBtn = (Button) findViewById(R.id.HuoyinBtn);
	}

	//多个按钮添加监听事件用这种格式简洁明了
	public void setListeners() {
		Button button[] = { Btn3x3, Btn4x4, Btn5x5, Btn6x6, NormalBtn,
				DigitBtn, QilongzhuBtn, HuoyinBtn };
		// 创一个事件处理类
		ButtonListener bl = new ButtonListener();
		for (int i = 0; i < 8; i++) {
			button[i].setOnClickListener(bl);
		}
	}
	
	class ButtonListener implements OnClickListener{
		//他们都要发生跳转,然后各自传不同的参数
		@Override
		public void onClick(View v) {
			if(v instanceof Button){
				//发生跳转
				Intent intent =new Intent(ChooseActivity.this,MainActivity.class);
				//传不同参
				int btnId=v.getId();
				switch (btnId) {
				case R.id.Btn3x3:
					column = 3;
					row = 3;
					break;
				case R.id.Btn4x4:
					column = 4;
					row = 4;
					break;			
				case R.id.Btn5x5:
					column = 5;
					row = 5;
					break;
				case R.id.Btn6x6:
					column = 6;
					row = 6;
					break;
				case R.id.NormalBtn:
					model = 1;
					break;
				case R.id.DigitBtn:
					model = 2;
					break;
				case R.id.QilongzhuBtn:
					model = 3;
					break;
				case R.id.HuoyinBtn:
					model = 4;
					break;
				default:			
					break;			
				}
				intent.putExtra("column", column);
				intent.putExtra("row", row);
				intent.putExtra("model", model);
				intent.putExtra("music", true);
				startActivity(intent);				
			}		
		}	
	}
}
/**
 * @author Clark Xu
 * 把自定义组件GameView添加到这上面,
 * 获取传过来的各种参数,执行不同的模式
 *
 */
public class MainActivity extends Activity {

	private int score = 0;
	private TextView tvScore;
	private TextView tvBestScore;
	private int column = 4;
	private int row = 4;
	private int model = 1;
	private MediaPlayer mp;
	private boolean music = false;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		Button resbtn = (Button) findViewById(R.id.resbtn);
		tvScore = (TextView) findViewById(R.id.scoreView2);
		tvBestScore = (TextView) findViewById(R.id.scoreView4);

		Intent intent = this.getIntent();
		row = intent.getIntExtra("row", 4);
		column = intent.getIntExtra("column", 4);
		model = intent.getIntExtra("model", 1);
		switch (model) {
		case 1:// 数字版
			mp = MediaPlayer.create(this, R.raw.infectious);
			break;
		case 2:// 数码版
			mp = MediaPlayer.create(this, R.raw.braveheart);
			break;
		case 3:// 七龙珠版
			mp = MediaPlayer.create(this, R.raw.qilongzhu);
			break;
		case 4:// 火影版
			mp = MediaPlayer.create(this, R.raw.huoyin);
			break;
		}

		try {
			mp.prepare();// 让mp对象准备
		} catch (Exception e) {
			e.printStackTrace();
		}

		// 一进来就播放音乐
		music = intent.getBooleanExtra("music", false);
		if (music && (null != mp)) {
			mp.start();
			mp.setLooping(true);
		}
		// 开始游戏的逻辑
		GameView.getGameView().initGameView();

		// 获取三个按钮
		Button butStart = (Button) this.findViewById(R.id.startBtn);
		Button butPause = (Button) this.findViewById(R.id.pauseBtn);
		Button butStop = (Button) this.findViewById(R.id.stopBtn);

		// 实例化事件处理类
		MusicListener ml = new MusicListener();

		// 给事件源添加动作监听方法,指定事件处理类对象ml
		butStart.setOnClickListener(ml);
		butPause.setOnClickListener(ml);
		butStop.setOnClickListener(ml);
		resbtn.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// TODO Auto-generated method stub
				GameView.getGameView().startGame();
				clearScore();
			}
		});
	}

	class MusicListener implements OnClickListener {

		@Override
		public void onClick(View v) {
			Button btn = (Button) v;
			String text = btn.getText().toString();
			if (text.equals("START")) {
				if (null != mp)
					mp.start();
				mp.setLooping(true);
			} else if (text.equals("PAUSE")) {
				if (null != mp)
					mp.pause();
			} else if (text.equals("STOP")) {
				// stop的话就完全结束了,还不如用pause,再调用seekTo时间调为0
				try {
					mp.pause();
					mp.seekTo(0);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
	}

	public int getColumn() {
		return column;
	}

	public int getRow() {
		return row;
	}

	public int getModel() {
		return model;
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.main, menu);
		return true;
	}

	public void clearScore() {
		score = 0;
		showScore();
	}

	public void showScore() {
		tvScore.setText(score + "");
	}

	public void addScore(int s) {
		score += s;
		showScore();
		int maxScore = Math.max(score, getBestScore());
		saveBestScore(maxScore);
		showBestScore(maxScore);
	}

	// 保存分数
	public void saveBestScore(int s) {
		Editor e = getPreferences(MODE_PRIVATE).edit();
		e.putInt("bestScore", s);
		e.commit();
	}

	public int getBestScore() {
		return getPreferences(MODE_PRIVATE).getInt("bestScore", 0);
	}

	public void showBestScore(int s) {
		tvBestScore.setText(s + "");
	}

	// 销毁Activity时执行的,重写此方法表示Activity的生命周期结束不要一直播放占用资源
	protected void onDestroy() {
		super.onDestroy();
		if (null != mp)
			try {
				mp.release();
			} catch (Exception e) {
				e.getStackTrace();
			}
	}
}
/**
 * @author Clark Xu
 * 游戏自定义组件:设置大小颜色模式,
 * 根据响应实现游戏逻辑
 *  继承表格布局更合适
 */
public class GameView extends GridLayout {
	private float startX, startY, endX, endY, offX, offY;
	private int row = 4, colunm = 4;// 行row对应y,列colunm对应x,默认开始都为4
	private CardView[][] cardsMap = new CardView[10][10];// 用一个二维数组来存
	private List<Point> emptyPoints = new ArrayList<Point>();// 链表方便增加删除
	private static GameView gview = null;
	private MainActivity my2048;
	private CardAnim ca = new CardAnim();
	private int cw;

	// 在xml中能够访问则要添加构造方法
	// 以防万一三个构造方法都要写:对应参分别为上下文,属性,样式
	public GameView(Context context) {
		super(context);
		gview = this;
	}

	public GameView(Context context, AttributeSet attrs) {
		super(context, attrs);
		gview = this;
	}

	public GameView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		gview = this;
	}

	public static GameView getGameView() {
		return gview;
	}

	// 由于手机可能不同,我们需要动态地获取卡片的宽高,所以要重写下面这个方法获取当前布局的宽高,
	// 为了让手机不会因倒过来改变宽高,要去mainifest里配置
	// 只会在手机里第一次运行的时候执行,之后不会改变
	protected void onSizeChanged(int w, int h, int oldw, int oldh) {
		super.onSizeChanged(w, h, oldw, oldh);

		int cardWidth = (Math.min(w, h) - 10) / colunm;

		addCards(cardWidth, cardWidth);// 把参数传过去

		startGame();
	}

	public void startGame() {
		for (int y = 0; y < row; y++) {
			for (int x = 0; x < colunm; x++) {
				cardsMap[x][y].setNum(0);
			}
		}
		my2048.addScore(0);
		my2048.clearScore();
		addRandomNum();
		addRandomNum();
	}

	private void addCards(int cardWidth, int cardHeigth) {
		CardView c;
		cw = cardWidth;

		for (int y = 0; y < row; y++) {
			for (int x = 0; x < colunm; x++) {
				// 并不知道getContext是什么意思
				c = new CardView(getContext());
				// 先都初始画0号图片
				c.setNum(0);
				addView(c, cardWidth, cardHeigth);
				// 把所有的卡片都记录下来
				cardsMap[x][y] = c;
			}
		}
	}

	// 添加随机数的时候要先遍历
	private void addRandomNum() {

		emptyPoints.clear();
		for (int y = 0; y < row; y++) {
			for (int x = 0; x < colunm; x++) {
				if (cardsMap[x][y].getNum() <= 0) {
					emptyPoints.add(new Point(x, y));// 把空位给emptypoints链表
				}
			}
		}
		// 随机把emptyPoints中的一个赋值,生成2的概率为9,4为1
		Point p = emptyPoints
				.remove((int) (Math.random() * emptyPoints.size()));
		// 2号图片和4号图片
		cardsMap[p.x][p.y].setNum(Math.random() > 0.1 ? 2 : 4);
        //动画生成效果
		ca.createScaleTo1(cardsMap[p.x][p.y]);
	}

	// GameView实现的功能
	public void initGameView() {
		my2048 = (MainActivity) this.getContext();
		colunm = my2048.getColumn();
		row = my2048.getRow();

		setColumnCount(colunm);// 设置表格为4列
		setBackgroundColor(Color.BLUE);
		setOnTouchListener(new OnTouchListener() {

			public boolean onTouch(View v, MotionEvent event) {
				int action = event.getAction();// 获取触屏的动作
				switch (action) {
				// 按下获取起始点
				case MotionEvent.ACTION_DOWN:
					startX = event.getX();
					startY = event.getY();
					break;
				// 松开获取终止点,通过比较位移来判断滑动方向
				// 要处理一下滑动偏的,看offx和offy哪个绝对值大就按照哪个来
				case MotionEvent.ACTION_UP:
					endX = event.getX();
					endY = event.getY();
					offX = startX - endX;
					offY = startY - endY;
					if (Math.abs(offX) >= Math.abs(offY)) {
						if (offX >= 5)
							moveLeft();// System.out.println("左");
						else if (offX < -5)
							moveRight();// System.out.println("右");
					} else if (Math.abs(offX) <= Math.abs(offY)) {
						if (offY >= 5)
							moveUp();// System.out.println("上");
						else if (offY < -5)
							moveDown();// System.out.println("下");
					}
					break;
				}
				// !!!要改为true,否则ACTION_UP不会执行
				return true;
			}
		});
	}

	private void moveLeft() {
		boolean merge = false;
		for (int y = 0; y < row; y++) {
			for (int x = 0; x < colunm; x++) {
				// 遍历当前位置的右边,如果有数字,如果当前位置没有数字,则合并到当前位置
				for (int x1 = x + 1; x1 < colunm; 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;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_MOVE);
							break;
						} else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x1][y].setNum(0);
							my2048.addScore(cardsMap[x][y].getNum());
							merge = true;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_CANCEL);

							break;
						}
						break;
					}
				}
			}
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}
	}

	private void moveRight() {
		boolean merge = false;
		for (int y = 0; y < row; y++) {
			for (int x = colunm - 1; 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;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_MOVE);

							break;
						} else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x1][y].setNum(0);
							my2048.addScore(cardsMap[x][y].getNum());
							merge = true;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_CANCEL);

							break;
						}

						break;
					}
				}
			}
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}

	}

	private void moveUp() {
		boolean merge = false;
		for (int x = 0; x < colunm; x++) {
			for (int y = 0; y < row; y++) {
				// 遍历当前位置的右边,如果有数字,如果当前位置没有数字,则合并到当前位置
				for (int y1 = y + 1; y1 < row; 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;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_MOVE);

							break;
						} else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x][y1].setNum(0);
							my2048.addScore(cardsMap[x][y].getNum());
							merge = true;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_CANCEL);

							break;
						}
						break;
					}
				}
			}
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}

	}

	private void moveDown() {
		boolean merge = false;
		for (int x = 0; x < colunm; x++) {
			for (int y = row - 1; 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;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_MOVE);
							break;
						} else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x][y1].setNum(0);
							my2048.addScore(cardsMap[x][y].getNum());
							merge = true;
							MyPlayer.playTone(getContext(),
									MyPlayer.INDEX_SONG_CANCEL);

							break;
						}
						break;
					}
				}
			}
		}
		if (merge) {
			addRandomNum();
			checkComplete();
		}

	}

	// 判断结束
	private void checkComplete() {

		boolean complete = true;
		for (int y = 0; y < row; y++) {
			for (int x = 0; x < colunm; x++) {
				if (cardsMap[x][y].getNum() == 2048)
					new AlertDialog.Builder(getContext())
							.setTitle("你好")
							.setMessage("游戏胜利")
							.setPositiveButton("重来",
									new DialogInterface.OnClickListener() {

										@Override
										public void onClick(
												DialogInterface dialog,
												int which) {
											startGame();
										}
									}).show();
			}
		}

		ALL: for (int y = 0; y < row; y++) {
			for (int x = 0; x < colunm; 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;// 如果出现这种情况,跳出双重循环,只写一个break只能跳出当前循环
				}
			}
		}

		if (complete) {
			new AlertDialog.Builder(getContext())
					.setTitle("你好")
					.setMessage("游戏结束")
					.setPositiveButton("重来",
							new DialogInterface.OnClickListener() {

								@Override
								public void onClick(DialogInterface dialog,
										int which) {
									startGame();
								}
							}).show();
		}
	}
}
/**
 * @author Clark Xu
 * 卡片自定义组件,添加到GameView上
 *
 */
public class CardView extends FrameLayout {

	private int num = 0;
	// 只显示数字的话可以用Textview,要是用图片的话要用imview
	private TextView label;
	private ImageView pic;
	private int[] picArray = new int[3000];
	private MainActivity my2048;
	private int model = 1;
	private LayoutParams lp;

	public CardView(Context context) {
		super(context);
		putPic();
		pic = new ImageView(getContext());
		lp = new LayoutParams(-1, -1);// -1,-1就是填充完父类容器的意思
		lp.setMargins(10, 10, 0, 0);// 用来设置边框很管用
		addView(pic, lp);// 把imageView加到CardView上
		setNum(0);
	}
    //把数字逻辑实现的2048转化为图片逻辑,只需要把数字定位数组序数,数字对应图片,并保持一一对应关系
	public void putPic() {
		picArray[0] = R.drawable.num0;
		picArray[2] = R.drawable.pic2;
		picArray[4] = R.drawable.pic4;
		picArray[8] = R.drawable.pic8;
		picArray[16] = R.drawable.pic16;
		picArray[32] = R.drawable.pic32;
		picArray[64] = R.drawable.pic64;
		picArray[128] = R.drawable.pic128;
		picArray[256] = R.drawable.pic256;
		picArray[512] = R.drawable.pic512;
		picArray[1024] = R.drawable.pic1024;
		picArray[2048] = R.drawable.pic2048;
		// 数字版+7
		picArray[7] = R.drawable.num0;
		picArray[9] = R.drawable.num2;
		picArray[11] = R.drawable.num4;
		picArray[15] = R.drawable.num8;
		picArray[23] = R.drawable.num16;
		picArray[39] = R.drawable.num32;
		picArray[71] = R.drawable.num64;
		picArray[135] = R.drawable.num128;
		picArray[263] = R.drawable.num256;
		picArray[519] = R.drawable.num512;
		picArray[1031] = R.drawable.num1024;
		picArray[2055] = R.drawable.num2048;
		// 七龙珠版+10
		picArray[10] = R.drawable.num0;
		picArray[12] = R.drawable.wk1;
		picArray[14] = R.drawable.wk2;
		picArray[18] = R.drawable.wk3;
		picArray[26] = R.drawable.wk4;
		picArray[42] = R.drawable.wk5;
		picArray[74] = R.drawable.wk6;
		picArray[128] = R.drawable.wk7;
		picArray[266] = R.drawable.wk8;
		picArray[522] = R.drawable.wk9;
		picArray[1034] = R.drawable.wk10;
		picArray[2058] = R.drawable.wk11;
		// 其他版+17
		picArray[17] = R.drawable.num0;
		picArray[19] = R.drawable.hy1;
		picArray[21] = R.drawable.hy2;
		picArray[25] = R.drawable.hy3;
		picArray[33] = R.drawable.hy4;
		picArray[49] = R.drawable.hy5;
		picArray[81] = R.drawable.hy6;
		picArray[145] = R.drawable.hy7;
		picArray[273] = R.drawable.hy8;
		picArray[529] = R.drawable.hy9;
		picArray[1041] = R.drawable.hy10;
		picArray[2065] = R.drawable.hy11;
	}

	// 数字:数字相当于图片id
	public int getNum() {
		return num;
	}

	public void setNum(int num) {
		this.num = num;

		my2048 = (MainActivity) this.getContext();
		model = my2048.getModel();
		System.out.println(">>>>>>>>>>" + model);
		switch (model) {
		case 1:// 普通模式
			pic.setBackgroundResource(picArray[num + 7]);
			break;
		case 2:// 数码模式
			pic.setBackgroundResource(picArray[num]);
			break;
		case 3:// 七龙珠模式
			pic.setBackgroundResource(picArray[num + 10]);
			break;
		case 4:// 火影模式
			pic.setBackgroundResource(picArray[num + 17]);
			break;
		}
	}

	// 判断数字是否相同
	public boolean equals(CardView cv) {
		return getNum() == cv.getNum();
	}
}
/**
 * @author Clark Xu
 * 音效播放类MyPlayer,
 * 因为是放在asset目录下读取方式有所不同
 *
 */
public class MyPlayer {
	public final static int INDEX_SONG_MOVE = 0;
	public final static int INDEX_SONG_CANCEL = 1;
	public final static int INDEX_SONG_BEGIN = 2;

	private final static String[] SONG_NAMES = { "cancel.mp3", "move.mp3",
			"braveheart.mp3" };
	// 音效播放
	private static MediaPlayer[] mToneMediaPlayer = new MediaPlayer[SONG_NAMES.length];

	/*
	 * 播放声音效果 cancel move
	 */
	public static void playTone(Context context, int index) {
		// 加载声音
		AssetManager assetManager = context.getAssets();
		if (mToneMediaPlayer[index] == null) {
			mToneMediaPlayer[index] = new MediaPlayer();
			try {
				AssetFileDescriptor fileDescriptor = assetManager
						.openFd(SONG_NAMES[index]);
				mToneMediaPlayer[index].setDataSource(
						fileDescriptor.getFileDescriptor(),
						fileDescriptor.getStartOffset(),
						fileDescriptor.getLength());
				mToneMediaPlayer[index].prepare();

			} catch (Exception e) {
				// TODO: handle exception
				e.printStackTrace();
			}
		}
		mToneMediaPlayer[index].start();
	}
}
<?xml version="1.0" encoding="utf-8"?>


<!-- 主界面的布局方式 -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_weight="0.65"
        android:orientation="horizontal" >


        <TextView
            android:id="@+id/scoreView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/score"
            android:textSize="22sp" />


        <TextView
            android:id="@+id/scoreView2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="22sp" />
        <TextView
            android:id="@+id/scoreView3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/bestscore"
            android:textSize="22sp" />


        <TextView
            android:id="@+id/scoreView4"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="22sp" />
    </LinearLayout>


    <!-- 把自定义组件的全路径写下来 -->


    <com.lanjie.game2048.GameView
        android:id="@+id/GameView"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="10" />
  


    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal" >


        <Button
            android:id="@+id/startBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/startBtn" />


        <Button
            android:id="@+id/pauseBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/pauseBtn" />


        <Button
            android:id="@+id/stopBtn"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:text="@string/stopBtn" />
        
    </LinearLayout>


    <Button
        android:id="@+id/resbtn"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/restart" />


</LinearLayout>

over

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值