1. 程式人生 > >android 2048遊戲實現

android 2048遊戲實現

2048小遊戲 post gettext grid total put slide ram swa

android 的2048小遊戲完整實現:GridLayout布局(android 4.0及以上)。

曾經做過一個2048的算法題,學了幾天android,認為能夠實現個安卓版的。也就動手寫了個。

包括的東西:

GridLayout布局

在activity中動態加入view組件

推斷用戶在屏幕滑動的的方向

2048算法(參考之前用C++寫的,寫的還算通俗易懂吧,http://blog.csdn.net/liang5630/article/details/39895087)。

不多說,先上圖:

技術分享


package com.example.y2048;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.y2048.map.Direction;
import com.example.y2048.map.Maps;

public class MainActivity extends Activity {
	private String tag = "GridLayoutActivity";
	GridLayout gridLayout;
	float startX = 0, startY = 0, endX, endY;
	Maps maps = new Maps();
	private TextView score;
	private TextView best;

	@SuppressLint("NewApi")
	void init() {
		// 獲取View對象
		gridLayout = (GridLayout) findViewById(R.id.root);

		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				Button bn = new Button(this);
				bn.setClickable(false);
				bn.setText("");
				// 設置該button的字號大小
				bn.setTextSize(30);
				bn.setWidth(120);
				bn.setHeight(120);
				// 指定該組件所在的行
				GridLayout.Spec rowSpec = GridLayout.spec(i + 2);
				// 指定該組件所在的列
				GridLayout.Spec columnSpec = GridLayout.spec(j);
				String msg = "rowSpec:" + (i + 2) + " - columnSpec:" + (j);
				Log.d(tag, msg);
				GridLayout.LayoutParams params = new GridLayout.LayoutParams(
						rowSpec, columnSpec);
				// 指定該組件占滿容器
				// params.setGravity(Gravity.FILL);
				gridLayout.addView(bn, params);
				maps.addButton(i, j, bn);
			}
		}
		score = (TextView) findViewById(R.id.score);
		score.setText("0");
		best = (TextView) findViewById(R.id.best);
		maps.setScore(score);
		maps.setBest(best);
		maps.init();
	}

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

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {

		// System.out.println("觸摸");
		int action = event.getAction();
		if (action == MotionEvent.ACTION_DOWN) {
			startX = event.getX();
			startY = event.getY();
		} else if (action == MotionEvent.ACTION_UP) {
			endX = event.getX();
			endY = event.getY();
			int direction = GetSlideDirection(startX, startY, endX, endY);
			// System.out.println(startX+","+startY+"|"+endX+","+endY+"  "+direction);
			// Toast.makeText(this, direction+"", Toast.LENGTH_LONG).show();
			boolean gameOver = maps.Slide(direction);
			if (gameOver) {
				if(maps.getScore()>maps.getBestScore()){
					Toast.makeText(this, "恭喜超過最佳記錄!。!", Toast.LENGTH_SHORT).show();
					maps.setBestScore(maps.getScore());
					best.setText(maps.getScore()+"");
				}else{
					Toast.makeText(this, "GameOver", Toast.LENGTH_SHORT).show();
				}
			
			}
		}
		return super.dispatchTouchEvent(event);
	}

	// 返回角度
	private double GetSlideAngle(float dx, float dy) {
		return Math.atan2(dy, dx) * 180 / Math.PI;
	}

	// 依據起點和終點返回方向 1:向上。2:向下,3:向左,4:向右,0:未滑動
	private int GetSlideDirection(float startX, float startY, float endX,
			float endY) {
		float dy = startY - endY;
		float dx = endX - startX;
		int result = Direction.NONE;
		// 假設滑動距離太短
		if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {
			return result;
		}
		double angle = GetSlideAngle(dx, dy);
		if (angle >= -45 && angle < 45) {
			return Direction.RIGHT;
		} else if (angle >= 45 && angle < 135) {
			return Direction.UP;
		} else if (angle >= -135 && angle < -45) {
			return Direction.DOWN;
		} else if ((angle >= 135 && angle <= 180)
				|| (angle >= -180 && angle < -135)) {
			return Direction.LEFT;
		}
		return result;
	}

	public void reset(View view) {
		maps.init();
	}

}


package com.example.y2048.map;

public interface Direction {
	//1:向上,2:向下,3:向左,4:向右,0:未滑動
		static final int LEFT=3;
		static final int RIGHT=4;
		static final int UP=1;
		static final int DOWN=2;
		static final int NONE=0;
}

package com.example.y2048.map;

import java.util.Random;

import android.content.Context;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class Maps {
	private TextView score;
	private TextView best;
	private Button[][] maps = new Button[4][4];

	public void addButton(int i, int j, Button btn) {
		maps[i][j] = btn;
	}

	private void swapText(Button btn1, Button btn2) {
		CharSequence text = btn1.getText();
		btn1.setText(btn2.getText());
		btn2.setText(text);
	}

	void up_remove_blank() {
		int i, j, k;
		for (j = 0; j < 4; j++) {
			for (i = 1; i < 4; i++) {
				k = i;
				while (k - 1 >= 0
						&& maps[k - 1][j].getText().toString().length() == 0) {// 上面的那個為空
					swapText(maps[k][j], maps[k - 1][j]);
					k--;

				}
			}
		}
	}

	void down_remove_blank() {
		int i, j, k;
		for (j = 0; j < 4; j++) {
			for (i = 2; i >= 0; i--) {
				k = i;
				while (k + 1 <= 3
						&& maps[k + 1][j].getText().toString().length() == 0) {// 上面的那個為空
					swapText(maps[k][j], maps[k + 1][j]);
					k++;
				}
			}
		}
	}

	void left_remove_blank() {
		int i, j, k;
		for (i = 0; i < 4; i++) {
			for (j = 1; j < 4; j++) {
				k = j;
				while (k - 1 >= 0
						&& maps[i][k - 1].getText().toString().length() == 0) {// 上面的那個為空
					swapText(maps[i][k], maps[i][k - 1]);
					k--;
				}
			}
		}
	}

	void right_remove_blank() {
		int i, j, k;
		for (i = 0; i < 4; i++) {
			for (j = 2; j >= 0; j--) {
				k = j;
				while (k + 1 <= 3
						&& maps[i][k + 1].getText().toString().length() == 0) {// 上面的那個為空
					swapText(maps[i][k], maps[i][k + 1]);
					k++;
				}
			}
		}
	}

	void left() {
		int i, j;
		for (i = 0; i < 4; i++) {
			for (j = 0; j < 3; j++) {
				String s1 = maps[i][j].getText().toString();
				String s2 = maps[i][j + 1].getText().toString();

				if (s1.equals(s2) && !s1.equals("")) {
					// maps[i][j]+=maps[i][j+1];
					Integer sum = Integer.valueOf(maps[i][j].getText()
							.toString());
					sum += Integer.valueOf(maps[i][j + 1].getText().toString());

					int total = Integer.valueOf(score.getText().toString());
					score.setText(String.valueOf(sum + total));
					maps[i][j].setText(sum.toString());
					maps[i][j + 1].setText("");
					left_remove_blank();
				}
			}
		}
	}

	void right() {
		int i, j;
		for (i = 0; i < 4; i++) {
			for (j = 3; j >= 1; j--) {
				String s1 = maps[i][j].getText().toString();
				String s2 = maps[i][j - 1].getText().toString();
				if (s1.equals(s2) && !s1.equals("")) {
					// maps[i][j]+=maps[i][j-1];
					// maps[i][j-1]=0;
					Integer sum = Integer.valueOf(maps[i][j].getText()
							.toString());
					sum += Integer.valueOf(maps[i][j - 1].getText().toString());
					int total = Integer.valueOf(score.getText().toString());
					score.setText(String.valueOf(sum + total));
					maps[i][j].setText(sum.toString());
					maps[i][j - 1].setText("");
					right_remove_blank();
				}
			}
		}
	}

	void up() {
		int i, j;
		for (j = 0; j < 4; j++) {// 每一列
			for (i = 0; i < 3; i++) {
				String s1 = maps[i][j].getText().toString();
				String s2 = maps[i + 1][j].getText().toString();
				if (s1.equals(s2) && !s1.equals("")) {
					// maps[i][j]=maps[i][j]+maps[i+1][j];
					// maps[i+1][j]=0;
					Integer sum = Integer.valueOf(maps[i][j].getText()
							.toString());
					sum += Integer.valueOf(maps[i + 1][j].getText().toString());
					int total = Integer.valueOf(score.getText().toString());
					score.setText(String.valueOf(sum + total));
					maps[i][j].setText(sum.toString());
					maps[i + 1][j].setText("");
					// 移除空格
					up_remove_blank();
				}
			}
		}
	}

	void down() {
		int i, j;
		for (j = 0; j < 4; j++) {// 每一列
			for (i = 3; i >= 1; i--) {
				String s1 = maps[i][j].getText().toString();
				String s2 = maps[i - 1][j].getText().toString();
				if (s1.equals(s2) && !s1.equals("")) {
					// maps[i][j]=maps[i][j]+maps[i-1][j];
					// maps[i-1][j]=0;
					Integer sum = Integer.valueOf(maps[i][j].getText()
							.toString());
					sum += Integer.valueOf(maps[i - 1][j].getText().toString());
					int total = Integer.valueOf(score.getText().toString());
					score.setText(String.valueOf(sum + total));
					maps[i][j].setText(sum.toString());
					maps[i - 1][j].setText("");
					// 移除空格
					down_remove_blank();
				}
			}
		}
	}

	private void addNumber() {
		Random random = new Random();
		int x = random.nextInt(4);
		int y = random.nextInt(4);
		int number = random.nextInt(20);//出現2的概率為95% 4的概率5%
		if(number==0) number=4;
		else number=2;
		while (maps[x][y].getText().toString().length() != 0) {
			x = random.nextInt(4);
			y = random.nextInt(4);
		}
		maps[x][y].setText(number + "");
	}

	public void init() {
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				maps[i][j].setText("");
			}
		}
		score.setText("0");
		addNumber();
		addNumber();
	}

	private boolean isFull() {
		for (int i = 0; i < 4; i++) {
			for (int j = 0; j < 4; j++) {
				if (maps[i][j].getText().toString().length() == 0) {
					return false;
				}
			}
		}
		return true;
	}

	public boolean Slide(int direction) {
		if (direction == Direction.LEFT) {
			left_remove_blank();
			left();
			if (isFull())
				return true;
			else {
				addNumber();
			}
		} else if (direction == Direction.RIGHT) {
			right_remove_blank();
			right();
			if (isFull())
				return true;
			else {
				addNumber();
			}
		} else if (direction == Direction.UP) {
			up_remove_blank();
			up();
			if (isFull())
				return true;
			else {
				addNumber();
			}
		} else if (direction == Direction.DOWN) {
			down_remove_blank();
			down();
			if (isFull())
				return true;
			else {
				addNumber();
			}
		}
		return false;
	}

	public void setScore(TextView score) {
		this.score = score;
	}

	public void setBest(TextView best) {
		this.best = best;
		best.setText(getBestScore()+"");
	}
	public int getScore(){
		return Integer.valueOf(score.getText().toString());
	}
	public int getBestScore(){
		SharedPreferences sp = best.getContext().getSharedPreferences("bestScore.txt", Context.MODE_PRIVATE);
		int bestScore=sp.getInt("bestScore", 0);
		return bestScore;
	}
	public void setBestScore(int score){
		SharedPreferences sp = best.getContext().getSharedPreferences("bestScore.txt", Context.MODE_PRIVATE);
		Editor edit = sp.edit();
		edit.putInt("bestScore", score);
		edit.commit();
	}

}

<GridLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/root"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:columnCount="4"
    android:rowCount="6"
    tools:ignore="NewApi" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:gravity="center"
        android:text="Score:" />

    <TextView
        android:id="@+id/score"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:layout_marginLeft="4dp"
        android:layout_marginRight="4dp"
        android:gravity="center"
        android:text="Score:" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center"
        android:text="Best:" />

    <TextView
        android:id="@+id/best"
        android:layout_width="wrap_content"
        android:layout_height="50dp"
        android:gravity="center" />

    <Button
        android:layout_width="wrap_content"
        android:layout_height="40dp"
        android:layout_columnSpan="4"
        android:onClick="reset"
        android:text="reset" />

</GridLayout>


轉載請註明出處:http://blog.csdn.net/liang5630/article/details/41251549

源代碼及apk下載:








android 2048遊戲實現