整个页面分为三个部分:

1)GridLayout:存放两个TextView(【score】以及当前所得分数数值)

2)自定义控件GameView(GridLayout):4*4方格,每个方格中存放一个TextView(用于存放num)

3)Button重新开始

代码:

Main:

package com.example.project2048;import com.example.project2048.R;  //加入自定义控件import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;public class MainActivity extends Activity implements OnClickListener{private int score = 0;private TextView tvScore;   //定义一个文本框,用于存储所得分数private static  MainActivity mainActivity = null;private GameView gameView;   //自定义控件(4*4卡片的操作,即游戏主体)private Button btRestart;  //按钮"重新开始"public MainActivity(){mainActivity = this;}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);tvScore = (TextView) findViewById(R.id.tvScore);  //实例化(卡片移动函数可调用)gameView = (GameView) findViewById(R.id.gameView);btRestart = (Button) findViewById(R.id.btRestart);btRestart.setOnClickListener(this);}public static MainActivity getMainActivity(){return mainActivity;}public void showScore(){tvScore.setText(score+"");}public void addScore(int s){  //分数计算score += s;showScore();}public void clearScore(){  //分数清0score = 0;showScore();}@Overridepublic void onClick(View v) {gameView.restartGame();}
}

GameView:

package com.example.project2048;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.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.GridLayout;
import android.widget.Toast;/** 自定义控件:* 1.新建一个类,继承view/view的子类    *增加相应的构造方法* 2.在布局文件中加入该类   *使用全类名*/
public class GameView extends GridLayout {private Card[][] cardsMap = new Card[4][4];   //存储4*4方格中的数字private List<Point> lists = new ArrayList<Point>();public GameView(Context context, AttributeSet attrs) {super(context, attrs);// TODO Auto-generated constructor stubinitGame(); }private void initGame(){   //初始化setColumnCount(4);   //设置4行4列setBackgroundColor(0xffbbada0);   //设置背景颜色setOnTouchListener(new OnTouchListener() {   //(手指)移动监听private float startX,startY,offsetX,offsetY;@Overridepublic boolean onTouch(View v, MotionEvent event) {// TODO Auto-generated method stubswitch (event.getAction()) {case MotionEvent.ACTION_DOWN:    //(手指)按下//获取当前位置坐标startX = event.getX();startY = event.getY();break;case MotionEvent.ACTION_UP:      //(手指)抬起//获取手指X,Y轴的位移(有方向)offsetX = event.getX() - startX;offsetY = event.getY() - startY;/*判断手指移动方向(上下左右)*(-5,5)为误差范围内(误差:eg.手指不小心滑动) */if (Math.abs(offsetX) > Math.abs(offsetY)) {if (offsetX < -5) {swipeLeft();//Toast.makeText(getContext(), "向左滑动", Toast.LENGTH_LONG).show();} else if(offsetX > 5) {swipeRight();//Toast.makeText(getContext(), "向右滑动", Toast.LENGTH_LONG).show();}}else {if (offsetY < -5) {swipeUp();//Toast.makeText(getContext(), "向上滑动", Toast.LENGTH_LONG).show();}else if (offsetY > 5) {swipeDown();//Toast.makeText(getContext(), "向下滑动", Toast.LENGTH_LONG).show();}}break;}return true;}});}@Overrideprotected void onSizeChanged(int w, int h, int oldw, int oldh) {// TODO Auto-generated method stubsuper.onSizeChanged(w, h, oldw, oldh);int cardWidth = (Math.min(w, h)-10)/4; //获取卡片大小addCard(cardWidth, cardWidth);startGame();}private void addCard(int cardWidth,int cardHeigh){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, cardHeigh);cardsMap[x][y] = c;}}}private void startGame(){   //游戏开始MainActivity.getMainActivity().clearScore();   //分数清0for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {cardsMap[x][y].setNum(0);   //4*4方格上的数字全部置为0}}//添加两个随机数addRandomNum();addRandomNum();}private void addRandomNum(){   //添加随机数lists.clear();//遍历4*4方格,寻找空白方格(即数字为0的)for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {if (cardsMap[x][y].getNum() <= 0) {lists.add(new Point(x, y));}}}Point p = lists.remove((int)(Math.random()*lists.size()));  //避免越界cardsMap[p.x][p.y].setNum(Math.random()>0.1 ? 2 : 4);//9:1}//上下左右移动private void swipeLeft(){   //左移boolean add = false;for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {for (int x1 = x+1; x1 < 4; x1++) {if (cardsMap[x1][y].getNum() > 0) {  //右边存在不为空(不为0)的卡片//左边卡片为空(为0),右边卡片左移if (cardsMap[x][y].getNum()<=0) {cardsMap[x][y].setNum(cardsMap[x1][y].getNum());cardsMap[x1][y].setNum(0);x--;add = 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()); //分数相应增加add = true;}break;}}}}if (add) {addRandomNum();  //移动后添加随机数endGame();   //判断游戏是否结束}}private void swipeRight(){   //右移boolean add = 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++;add = 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());add = true;}break;}}}}if (add) {addRandomNum();endGame();}}private void swipeUp(){   //上移boolean add = 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--;add = 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());add = true;}break;}}}}if (add) {addRandomNum();endGame();}}private void swipeDown(){   //下移boolean add = 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++;add = 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());add = true;}break;}}}}if (add) {addRandomNum();endGame();}}private void endGame(){   //判断游戏是否结束boolean complete = true;ALL:for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {//卡片仍有为空(为0),或连续两张有值相等的,则游戏继续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;}}}//ALL:有一个条件满足循环即中断,提高效率if (complete) {  //若游戏结束new AlertDialog.Builder(getContext())   //弹出提示对话框.setTitle("你好!").setMessage("游戏结束")//为“重新开始”按钮设置监听事件.setPositiveButton("重新开始", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {// TODO Auto-generated method stubstartGame();}}).show();}}public void restartGame(){   //重新开始游戏MainActivity.getMainActivity().clearScore();  //分数清0//遍历4*4方格,将值不为0的所有卡片置为0for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {if (cardsMap[x][y] ==null) {continue;}cardsMap[x][y].setNum(0);}}//添加两个随机数addRandomNum();addRandomNum();}}

Card:

package com.example.project2048;import android.content.Context;
import android.graphics.Color;
import android.view.Gravity;
import android.widget.FrameLayout;
import android.widget.TextView;public class Card extends FrameLayout {private TextView tv;  //文本框(卡片中存放数值)private int num = 0;public Card(Context context) {super(context);tv = new TextView(getContext());tv.setTextSize(32);tv.setGravity(Gravity.CENTER);  //在方格中居中放置tv.setBackgroundColor(0x33ffffff);   LayoutParams params = new LayoutParams(-1, -1);params.setMargins(10, 10, 0, 0);addView(tv, params);  //将文本框添加至方格上}public int getNum() {return num;}public void setNum(int num) {this.num = num;//根据卡片上的值不同,设置相应卡片背景颜色if (num <= 0) {tv.setBackgroundColor(0x33ffffff);tv.setText("");   //若卡片值为0,则不显示数值} else {if(num == 2)tv.setBackgroundColor(Color.parseColor("#CDB79E"));//深灰if(num == 4)tv.setBackgroundColor(Color.parseColor("#CDB38B"));//加深灰if(num == 8)tv.setBackgroundColor(Color.parseColor("#FF8C00"));//橙色if(num == 16)tv.setBackgroundColor(Color.parseColor("#FF7F00"));//橙色if(num == 32)tv.setBackgroundColor(Color.parseColor("#FF4500"));//桔红if(num == 64)tv.setBackgroundColor(Color.parseColor("#FF0000"));//红if(num == 128)tv.setBackgroundColor(Color.parseColor("#FFF68F"));//浅桔/*tv.setText(num);* tv.setText(num+"");* 方法重载(int/char)*/tv.setText(num+"");  }}public boolean equals(Card c) {return this.getNum()==c.getNum();}}

2048(Android)相关推荐

  1. Android简单美观计算器(界面部分)

    一 问题描述: 总体任务:制作一个简单的计算器,实现计算功能.本部分内容:完成计算器的界面制作. 二 解题思路: 布局细分线框图: 采用LinearLayout布局内包含一个LinearLayout用 ...

  2. Android 常用开发功能 博客导航

    转载地址:http://blog.csdn.net/ciqing123/article/details/52931663?locationNum=16&fps=1 简介:第一次在CSDN上发表 ...

  3. 是男人就下100层【第五层】——换肤版2048游戏

    ---------------------------------------------------------------------------------------------------- ...

  4. 应用与系统稳定性第三篇---FD泄露问题漫谈

    cat /proc/pid/limits 查看最大打开文件Max open files cat /proc/pid/fd 查看打开文件 cat /proc/sys/kernel/threads-max ...

  5. 搜集整理的一些博客导航

    简介:第一次在CSDN上发表博客,将自己关注或者看过的一些博客整理了一下,其中包含了鸿神和郭神的全部博客,包括两位大神微信公众号推荐的博客,另外还有一些安卓开发社区的博客,后续每天都会更新这个导航,希 ...

  6. 主流手机参数(不定期更新)

    2019独角兽企业重金招聘Python工程师标准>>> 2014/4更新 不按照权威统计的格式和顺序,主要关注尺寸.分辨率和内存的配置等参数. 按屏幕尺寸升序 手机名称 尺寸(单位: ...

  7. 第四周作业-项目技术指标(招标文件)

    招标编号:XXXXX 招标名称:基于Android的2048 小游戏设计与实现 采购人:任甜加粗样式202031102593 王斌202031103152 采购代理机构:XXXXX 2022年10月 ...

  8. Cocos2dx引擎笔记——内存优化

    内存优化原理 纹理最耗应用内存, 纹理几乎会占据90%应用内存.所以尽量最小化应用的纹理内存使用,否则应用很有可能会因为低内存而崩溃. 认识瓶颈寻找方案 什么样的纹理最耗应用内存?消耗多少内存?利用苹 ...

  9. Android开发之2048安卓版

    之前是在eclipse上写的,后面换成了android sudio. 2048游戏的UI整体可以采用线性布局,即LinearLayout,其中嵌套一个线性布局和一个GridLayout,内嵌的线性布局 ...

最新文章

  1. 银行业务常用基本概念
  2. Java中ArrayList最大容量为什么是Integer.MAX_VALUE-8?
  3. 直方图应用:直方图均衡化,直方图匹配,对比直方图
  4. 找出那个数字出现3次的数字
  5. vue复选框CheckBox清空选中的值
  6. 小程序中添加快递查询
  7. Jaccard相似度和广义Jaccard相似度
  8. Codeforces914D Bash and a Tough Math Puzzle (思维 线段树)
  9. 软件开发人员是一种很棒的职业选择的五大理由
  10. arduino控制步进电机和舵机
  11. 如何在MySQL高效的join3个表
  12. R语言使用sort函数对日期向量数据进行排序、默认从小到大升序排序、设置decreasing参数为真进行降序排序
  13. ValueError: n_splits=4 cannot be greater than the number of members in each class
  14. php过滤微信表情符号的正则表达式方法
  15. 李沐笔记(softmax回归)
  16. linux游戏星际公民,鲜游快报:《星际公民》众筹破3.1亿美元 公布新视频展示新机制...
  17. https自签证书tls握手时错误或go系统错误处理
  18. 案例分析——快手百万在线直播
  19. 【Visual Studio】创建并使用静态库(.lib)
  20. NOI2007.Day2.T3.追捕盗贼

热门文章

  1. MarkDown添加图片的三种方式
  2. 五个学习管理系统的优点
  3. css伪类加垂直分割线
  4. 小豆社保「社保代缴」短信接口被盗刷解决方案-企业短信防火墙
  5. Android学习:Service自问自答
  6. Git 修改前面提交commit的名字
  7. Teamviewer被检查成商业用途的解决方法
  8. 航运人工智能提升全球集装箱海陆各环节作业效率,箱管控,CIMCAI自动化集装箱况残损检测/箱信息识别数字化录入,智慧航运智能航运
  9. 天梯赛 L1-054 福到了 (15 分) C++
  10. Android apps 拍立知-功能实现2(相机/选择相册及图像识别调用)