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下载:

时间: 2024-11-08 23:26:34

android 2048游戏实现的相关文章

Android 2048游戏开发

根据教程写的简单的2048游戏. 极客学院教程地址:http://www.jikexueyuan.com/course/43.html 我的源代码地址:https://github.com/myCodingTrip/2048Game 项目有3个类. Card extends FrameLayout{ private int num; private TextView label; public Card(Context context) public int getNum() public vo

个人android 2048的玩耍

个人android 2048的玩耍 个人信息:就读于燕大本科软件工程专业 目前大四; 本人博客:google搜索"cqs_2012"即可; 个人爱好:酷爱数据结构和算法,希望将来从事算法工作为人民作出自己的贡献; 编程语言:java ; 编程坏境:Windows 7 专业版 x64; 编程工具:jdk,eclipse; 制图工具:office 2010 powerpoint; 硬件信息:7G-3 笔记本; 这篇文章意义: 这篇文章是主要记录和讲解开发android 2048游戏的一个过

Android项目开发实战-2048游戏

<2048>是一款比较流行的数字游戏,最早于2014年3月20日发行.原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台.这款游戏是基于<1024>和<小3传奇>的玩法开发而成的新型数字游戏.游戏源地址:http://gabrielecirulli.github.io/2048/ 1.新建android项目game2048 修改activity_main.xml文件 <LinearLayout xmlns:andro

Android手机中的2048游戏Demo开发

Android中正火的2048游戏开发,赶紧开发一个自己的2048吧 1.游戏中的几个关键点 1)界面 2048游戏的操作界面就是一个4X4的方格.如下图所示: 游戏首先要绘制出该界面. @1 界面布局文件 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:

极客学院Android之2048游戏开发全过程

2048完整开发 课1.游戏2048玩法介绍 同一条线上的相同数字折叠 课2.创建2048游戏项目 修改布局 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:lay

2048游戏回顾一:使用SurfaceView创建游戏启动动画

SurfaceView有个很大的好处,就是可以在子线程中绘制UI,其他的View只能在主线程中更新UI,这或多或少给编程增加了些不便.而SurfaceVIew在子线程中可以绘制UI的特性,再加上其可以直接从内存或者DMA等硬件接口取得图像数据,这使得它适合2d游戏的开发. SurfaceView使用步骤 SurfaceView的使用比较简单,可以总结为如下几个步骤: 1.继承SurfaceView并实现 SurfaceHolder.Callback方法 譬如: public class Star

是男人就下100层【第五层】——2048游戏

前言: 在"阳光小强"的实战系列博文<是男人就下100层>的上一层我们一起从零开始完成了我们自己的贪吃蛇游戏--CrazySnake,可能很多朋友还不过瘾,那么我们今天就来玩一玩最近一直比较火的2048游戏,让大家再过一把瘾.由于"阳光小强"目前并没有从事Android的游戏开发工作,所以这些游戏的实现并不需要很专业的游戏开发知识,如果你有Android的基础就可以一起来参与进来共同完成这个游戏.有些朋友可能就会说"这些小游戏,会不会有点简单,

是男人就下100层【第五层】——2048游戏从源码到发布市场

上一篇<是男人就下100层[第五层]--换肤版2048游戏>中阳光小强对2048游戏用自己的方式进行了实现,并分享了核心源码,这一篇阳光小强打算将该项目的所有源代码公开并结合这个实例在这篇文章中介绍一下如何添加广告和实现分享功能. 最终运行效果如下(更多运行效果请看<是男人就下100层[第五层]--换肤版2048游戏>): 一.如何实现换肤 换肤的思路其实很简单,在ActionBar中添加菜单,当用户选择某一个皮肤后就将当前的皮肤状态修改并保存到SharedPreference中,

分享一下自己写的2048游戏(3*3,4*4,5*5,6*6多种玩法,可反悔)

2048是一款非常常见的小游戏,所以我也想自己尝试着写一款,给自己练练手.说道练手,这里需要交代一下:我从事Android的工作刚刚一年,平时的工作主要是客制化UI和修改Bug,也就是这里改改,那里改改,因此,完整的开发项目的机会比较少,所以,对我而言,想要提高自己的编程水平,抽出时间自己做一些小项目是有意义的.虽然平时的工作主要是客制化UI和修改bug,但并不意味这我的工作是简单枯燥的,我时常会遇到系统中的一些bug,这样我有机会阅读android系统的源码,并从中分析问题出现的原因,这份工作