android 2048游戏实现
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下载: