码迷,mamicode.com
首页 > 其他好文 > 详细

游戏2048的实现

时间:2015-04-19 13:17:35      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:

package com.ccg.mygame2048;

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;

/**
 * 
 * @author chencangui 
 * 游戏界面类,继承GridLayout GameView 类,继承自GridLayout
 */
public class GameView extends GridLayout {

	/**
	 * 三个构造方法
	 */
	public GameView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);

		gameView = this;
		initGameView();
	}

	public GameView(Context context) {
		super(context);
		gameView = this;
		initGameView();
	}

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

	
	private void initGameView() {
		// 设置这个界面有多少列
		setColumnCount(4);

		// 设置界面的背景颜色
		setBackgroundColor(0xffbbada0);
		// 设置触摸监听事件
		setOnTouchListener(new View.OnTouchListener() {
			/*
			 * startX: 起始的位置的X坐标            startY: 起始位置的Y坐标 
			 * offsetX: X坐标偏移量                     offsetY:Y坐标偏移量
			 * 
			 */
			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;
					// 看一下是X的偏移量大还是Y的偏移量大,
					if (Math.abs(offsetX) > Math.abs(offsetY)) {
						// 设置为5是考虑到可能存在误差
						if (offsetX < -5) {
							swipeLeft();
						} else if (offsetX > 5) {
							swipeRight();
						}
					} else {
						if (offsetY < -5) {
							swipeUp();
						} else if (offsetY > 5) {
							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(w, h) - 10) / 4;

		// 添加卡片
		addCards(cardWidth, cardWidth);

		startGame();
	}

	// 添加卡片方法
	private 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);

				cardsMap[x][y] = c;
			}
		}
	}

	// 开始游戏方法
	public void startGame() {

		// 将分数清零
		MainActivity.getMainActivity().clearScore();

		// 初始化,cardsMap的值首先都是零
		for (int y = 0; y < 4; y++) {
			for (int x = 0; x < 4; x++) {
				cardsMap[x][y].setNum(0);
			}
		}

		addRandomNum();
		addRandomNum();
	}

	// 添加随机数方法
	private void addRandomNum() {

		//
		emptyPoints.clear();
		// 对所有的卡片的值进行遍历,将空的存进来
		for (int y = 0; y < 4; y++) {
			for (int x = 0; x < 4; x++) {
				if (cardsMap[x][y].getNum() <= 0) {
					emptyPoints.add(new Point(x, y));
				}
			}
		}

		// 随机移除一个点
		Point p = emptyPoints
				.remove((int) (Math.random() * emptyPoints.size()));

		// 设置这个点的数字,2出现的概率是0.9,4的是0.1
		cardsMap[p.x][p.y].setNum(Math.random() > 0.1 ? 2 : 4);
	}

	// 左移方法实现,游戏实现逻辑
	private void swipeLeft() {

		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++) {
					// 如果x1不空
					if (cardsMap[x1][y].getNum() > 0) {
						// 如果当前是空的
						if (cardsMap[x][y].getNum() <= 0) {
							// 将当前的数字设为右边的数字
							cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
							// 右边的数字设为0
							cardsMap[x1][y].setNum(0);
							// 重新遍历一次
							x--;
							// 交换了
							merge = true;
						} else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
							// 如果数字相等的话那么久相加,存回左边,然后右边的设为零
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x1][y].setNum(0);
							// 更新分数
							MainActivity.getMainActivity().addScore(
									cardsMap[x][y].getNum());
							merge = true;
						}
						// 执行完毕则跳出循环
						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 (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;
						} else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x1][y].setNum(0);
							MainActivity.getMainActivity().addScore(
									cardsMap[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 (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;
						} else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x][y1].setNum(0);
							MainActivity.getMainActivity().addScore(
									cardsMap[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 (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;
						} else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
							cardsMap[x][y].setNum(cardsMap[x][y].getNum() * 2);
							cardsMap[x][y1].setNum(0);
							MainActivity.getMainActivity().addScore(
									cardsMap[x][y].getNum());
							merge = true;
						}

						break;
					}
				}
			}
		}

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

	// 监听游戏是否已经结束
	private void checkComplete() {

		boolean complete = true;

		// 添加一个All标签,如果符合任意一种就跳出循环
		ALL: for (int y = 0; y < 4; y++) {
			/*
			 * 只要下面任意一个条件成立就跳出循环: 有空余位置 四个方向上的位置有相同的数字
			 */
			for (int x = 0; x < 4; 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; // 跳出整个循环
				}
			}
		}

		// 如果已经结束的话跳出一个提示框
		if (complete) {
			new AlertDialog.Builder(getContext())
					.setTitle("你好")
					.setMessage("游戏结束")
					.setPositiveButton("重来",
							new DialogInterface.OnClickListener() {

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

	}

	
	private static GameView gameView = null;
	public static GameView getGameView(){
		
		return gameView;
	}  
	
	// 初始化一个4x4的卡片变量,用于记录每次添加的卡片
	private Card[][] cardsMap = new Card[4][4];
	// 存储空点的对象
	private List<Point> emptyPoints = new ArrayList<Point>();
}
<pre name="code" class="java">package com.ccg.mygame2048;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
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);
		button = (Button) findViewById(R.id.startNewGame);
		button.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {

				GameView.getGameView().startGame();
				// TODO Auto-generated method stub

			}
		});
	}


	private static MainActivity mainActivity = null;

	// 让外界可以访问到MainActivity
	public static MainActivity getMainActivity() {
		return mainActivity;

	}

	// 显示分数
	public void showScore() {
		tvScore.setText(score + "");

	}

	// 清空分数
	public void clearScore() {

		score = 0;
		showScore();

	}

	// 更新分数
	public void addScore(int s) {
		score += s;

		showScore();
	}

	private int score = 0;
	private TextView tvScore;
	private Button button;

}

package com.ccg.mygame2048;

import android.content.Context;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;

/**
 * 
 * @author chencangui
 * 卡片类,用于添加卡片,继承自FrameLayout
 */
public class Card extends FrameLayout {

	public Card(Context context) {
		super(context);
		//初始化
		label = new TextView(getContext());
		//设置文字大小
		label.setTextSize(32);
		//设置文字的文职
		label.setGravity(Gravity.CENTER);
		//设置文字颜色
		label.setBackgroundColor(0x33ffffff);
		//布局参数,宽高都是-1-1,充满布局容器
		LayoutParams lp = new LayoutParams(-1, -1);
		//设置与父容器之间的间距
		lp.setMargins(10, 10, 0, 0);
		//将label添加进去
		addView(label, lp);
		//初始化时卡片都是空的
		setNum(0);
	}
	//卡片里面应该有一个数字
	private int num = 0;
	//取得数字
	public int getNum() {
		return num;
	}
	//设置数字
	public void setNum(int num) {
		this.num = num;
		//如果数字是零,则显示应为空
		if (num<=0) {
			label.setText("");
		}else{
			label.setText(num+"");
		}
	}
	//判断卡片里面的文字是否相同
	public boolean equals(Card o) {
		return getNum()==o.getNum();
	}

	private TextView label;
}



XML代码:
<pre name="code" class="html"><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

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

        <TextView
            android:textSize="30sp"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="@string/score" />

        <TextView
            android:textSize="30sp"
            android:id="@+id/tvScore"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_weight="1" />

        <Button
            android:id="@+id/startNewGame"
            android:textSize="20sp"
            android:layout_width="150dp"
            android:layout_height="wrap_content"
            android:text="开始新游戏" />
    </LinearLayout>

    <com.ccg.mygame2048.GameView
        android:id="@+id/gameview"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_weight="1" >
    </com.ccg.mygame2048.GameView>

</LinearLayout>




游戏2048的实现

标签:

原文地址:http://blog.csdn.net/chencangui/article/details/45127929

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!