游戏2048的实现

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>
				
时间: 2024-08-10 23:15:49

游戏2048的实现的相关文章

【Qt点滴】游戏2048

看到了挺火的2048,就想用Qt实现一下,游戏逻辑倒是不复杂,稍微推敲就能搞定,倒是动画和各种细节前前后后参考了很多,也想了很久. 一个月前把功能都实现了,因为考试等各种琐事,这几天才想到整理下.真正编写的时间也并不久,一周左右吧. 这次是用Qt5开发,一个QWidget窗口,添加一个restart按钮,一个最高分label,一个当前分label.然后16宫格的游戏面板部分继承自QGLWidget类,面板监听鼠标按下和放开坐标来识别四个方向的移动. 逻辑部分不复杂,每次计算更新当前面板的分数后,

游戏2048源代码 - C语言控制台界面版

完整源代码如下,敬请读者批评指正: 1 /* 2 * Copyright (C) Judge Young 3 * E-mail: [email protected] 4 * Version: 1.0 5 */ 6 7 #include <stdio.h> 8 #include <time.h> /* 包含设定随机数种子所需要的time()函数 */ 9 #include <conio.h> /* 包含Windows平台上完成输入字符不带回显和回车确认的getch()函数

Android 带你玩转实现游戏2048 其实2048只是个普通的控件

1.概述 博主本想踏入游戏开放行业,无奈水太深,不会游泳:于是乎,只能继续开发应用,但是 原生Android也能开发游戏么,2048.像素鸟.别踩什么来着:今天给大家带来一篇2048的开发篇,别怕不分上下文,或者1.2.3.4,一篇包 你能玩happy~虽然我从来没有玩到过2048!!!其实大家也可以当作自定义控件来看~~~ 特别说明一下,游戏2048里面的方块各种颜色来源于:http://download.csdn.net/detail/qq1121674367/7155467,这个2048的

[小游戏]2048

益智小游戏2048    玩法:    该游戏使用方向键让方块上下左右移动.如果两个带有相同数字的方块在移动中碰撞,则它们会合并为一个方块,且所带数字变为两者之和.每次移动时,会有一个值为2或者4的新方块出现.    可能不好理解,你玩几下就知道了.    这款游戏玩起来会让你”根本停不下来“,很有意思的.通关截图: 游戏官网:http://gabrielecirulli.github.io/2048/ date:2014-10-26

Android 带你玩转实现游戏2048 其实2048只是个普通的控件(转)

1.概述 博主本想踏入游戏开放行业,无奈水太深,不会游泳:于是乎,只能继续开发应用,但是原生Android也能开发游戏么,2048.像素鸟.别踩什么来着:今天给大家带来一篇2048的开发篇,别怕不分上下文,或者1.2.3.4,一篇包你能玩happy~虽然我从来没有玩到过2048!!!其实大家也可以当作自定义控件来看~~~ 特别说明一下,游戏2048里面的方块各种颜色来源于:http://download.csdn.net/detail/qq1121674367/7155467,这个2048的代码

Andorid游戏2048开发(一)

最近有一款Android平台下的游戏很是火爆----2048.下面记录一下开发过程.由于笔者是Android开发的初学者,所以希望借以此文熟悉整个Android开发的流程. 首先创建Game2048的游戏项目.我们选择最低平台为Android4.0(API 14),最高支持平台Android4.4(API 19),然后一路Next,创建完成之后,我们修改activity_main.xml文件.修改默认的布局方式为LinearLayout布局方式.然后我们在嵌套一个Linearyout布局,用户游

180行ruby代码搞定游戏2048

最今在玩2048这款小游戏,游戏逻辑简单,非常适合我这种对于游戏新入行的人来实现逻辑.于是选择了最拿手的ruby语言来实现这款小游戏的主要逻辑.还是挺简单的,加起来4小时左右搞定. 上代码: require 'optparse' module Help HELP_TEXT =<<HELP press buttons for move l => move to left r => move to right t => move to top b => move to bo

简易游戏 2048 制作

// Matrix.h #ifndef MATRIX_H #define MATRIX_H #include<iostream> #include<time.h> #include<stdlib.h> #define rows 4 #define cols 4 #define L 6 using std::ostream; classMatrix{ friend ostream&operator<<(ostream& out,constMat

JavaScript小游戏--2048(PC端)

1.初始化棋局 $(document).ready(function() { prepare_for_mobile(); //适配移动端 new_game(); }); 2.开始新游戏 function new_game() { back = []; //初始化棋盘 init(); //在随机两个格子生成数字 generate_one_number(); generate_one_number(); } 3.初始化 function init() { for (var i = 0; i < 4;

结对编程小游戏2048

作业要求: 自选题目(不少于500行代码),进行结对编程 轮流担任领航员和驾驶员 记录结对编程的过程,写成结对博客 1.结对题目,写清需求 2.上传代码(截图),两人合作的合影 3.约定的规范 4.记录时间 5.心得和体会 Deadline 9月18日 23:59:59 小组成员 019任帅昌 020禹继跃 1.结对题目:2048小游戏 需求分析:在人们学习工作之余,小游戏成为了人们打发时间做的必不可少的事情了,而2048这款小游戏它不仅能在你工作学习疲惫之后使你身心放松,还能益智 2.游戏代码