转载请注明出处:http://blog.csdn.net/sw950729/article/details/52211315
本文出自:马云飞的博客
前天去osc原创会溜了一圈,结果因为G20找个住的地方都难- - !然后各种悲剧就发生了。昨天下午回家睡了一觉,原本晚上更新的,结果发生电脑充电器扔公司。什么鬼,fuck++,有史以来最惨的一个周末。(说好的一周最少一更的~~~~)好了话不多说,进入正题。
关于自定义view我们前面讲到了五子棋。这次讲个简单的,2048的实现。当然,如果你看懂了前面的自定义,今天的都不是问题。
首先需要自定义Gridlayout来实现自定义的几个方法,我们来看看初始化,设置每行最大数量以及颜色和手势滑动,代码如下:

private void initalgame() {setColumnCount(4);// 设置每行最多4个setBackgroundColor(0xffbbada0);setOnTouchListener(new View.OnTouchListener() {private float startX, startY, changeX, changeY;public boolean onTouch(View v, MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:startX = event.getX();// 起始的X坐标startY = event.getY();// 起始的Y坐标break;case MotionEvent.ACTION_UP:changeX = event.getX() - startX;// 改变的X坐标=现在的-起始的changeY = event.getY() - startY;// 改变的Y坐标=现在的-起始的// 若X的绝对值>Y的绝对值,则是左右移动,否则为上下移动,左上角坐标为(0,0)if (Math.abs(changeX) > Math.abs(changeY)) {if (changeX < -5) {Left();} else if (changeX > 5) {Right();}} else {if (changeY < -5) {Up();} else if (changeY > 5) {Down();}}break;}return true;}});}

我们需要一个卡片类来给Gridlayout的item设置内容和背景色:


public class Card extends FrameLayout {private TextView label;private int num = 0;public Card(Context context) {super(context);label = new TextView(getContext());// 新建个textviewlabel.setTextSize(32);// 设置字体大小label.setBackgroundColor(0x338B8B00);// 背景色label.setTextColor(0x330D0D0D);// 设置字体颜色label.setGravity(Gravity.CENTER);// 设置字体居中// LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT,// LayoutParams.MATCH_PARENT);// 铺满屏幕LayoutParams lp = new LayoutParams(-1, -1);lp.setMargins(10, 10, 0, 0);// 间距10像素addView(label, lp);setNum(0);}public int getNum() {return num;}public void setNum(int num) {this.num = num;label.setBackgroundColor(getBackColor(num));// 背景色// 如果值为0,就不设置内容if (num <= 0) {label.setText("");} else {label.setText(num + "");}}// 设置背景色private int defaultBackColor = 0x338B8B00;private int getBackColor(int num) {int bgcolor = defaultBackColor;switch (num) {case 0:bgcolor = 0xffCCC0B3;break;case 2:bgcolor = 0xffEEE4DA;break;case 4:bgcolor = 0xffEDE0C8;break;case 8:bgcolor = 0xffF2B179;// #F2B179break;case 16:bgcolor = 0xffF49563;break;case 32:bgcolor = 0xffF5794D;break;case 64:bgcolor = 0xffF55D37;break;case 128:bgcolor = 0xffEEE863;break;case 256:bgcolor = 0xffEDB04D;break;case 512:bgcolor = 0xffECB04D;break;case 1024:bgcolor = 0xffEB9437;break;case 2048:bgcolor = 0xffEA7821;break;default:bgcolor = 0xffEA7821;break;}return bgcolor;}// 判断2个数是否相等public boolean equals(Card c) {return getNum() == c.getNum();}}

同时在自定义layout,我们需要计算出每个卡片的宽高:

private Card[][] cardsMap = new Card[4][4];// 计算卡片的宽高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;// 添加卡片addCard(cardwidth, cardwidth);start();// 开始游戏}

开始游戏时,我们随机添加2个卡片。卡片内容为2或4,比例为9:1。

// 添加卡片private void addCard(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;}}}
// 开始游戏private void start() {MainActivity.getMainActivity().clear();for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {cardsMap[x][y].setNum(0);}}// 添加随机数addRandomNum();addRandomNum();}
// 添加随机数public void addRandomNum() {// 清空pointpoint.clear();for (int y = 0; y < 4; y++) {for (int x = 0; x < 4; x++) {// 如果这个位置没有值。添加if (cardsMap[x][y].getNum() <= 0) {point.add(new Point(x, y));}}}// 随机移除一个点Point p = point.remove((int) (Math.random() * point.size()));cardsMap[p.x][p.y].setNum(Math.random() > 0.1 ? 2 : 4);}

剩下的就是判断滑动方向来进行数的位移和相加了:

private void Left() {boolean flag = 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) {if (cardsMap[x][y].getNum() <= 0) {cardsMap[x][y].setNum(cardsMap[x1][y].getNum());cardsMap[x1][y].setNum(0);x--;flag = 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().add(cardsMap[x][y].getNum());flag = true;}break;}}}}if (flag) {addRandomNum();IsFinish();}}private void Right() {Boolean flag = 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++;flag = 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().add(cardsMap[x][y].getNum());flag = true;}break;}}}}if (flag) {addRandomNum();IsFinish();}}private void Up() {boolean flag = 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--;flag = 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().add(cardsMap[x][y].getNum());flag = true;}break;}}}}if (flag) {addRandomNum();IsFinish();}}private void Down() {boolean flag = 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++;flag = 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().add(cardsMap[x][y].getNum());flag = true;}break;}}}}if (flag) {addRandomNum();IsFinish();}}

最后我们每次滑动结束都是需要判断游戏是否结束,判断条件则是列表被铺满而且无法进行相加:

private void IsFinish() {boolean finish = true;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]))) {finish = false;break ALL;}}}if (finish) {new AlertDialog.Builder(getContext()).setTitle("游戏结束!").setMessage("您的得分为:" + MainActivity.score).setPositiveButton("重来",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {start();}}).setNegativeButton("退出",new DialogInterface.OnClickListener() {public void onClick(DialogInterface dialog,int which) {MainActivity.getMainActivity().finish();}}).show();}}

而我们需要一个类来保存我们的最高分,这里用了一个最简单的数据存储,Shareperference。代码很简单:


public class BestScode {private SharedPreferences sp;public BestScode(Context context){sp = context.getSharedPreferences("bestscode", context.MODE_PRIVATE);}public int getBestScode(){int bestscode = sp.getInt("bestscode", 0);return bestscode;}public void setBestScode(int bestScode){Editor editor = sp.edit();editor.putInt("bestscode", bestScode);editor.commit();}
}

剩下的就是主activity了:

private TextView text;public static int score;private static MainActivity mainactivity = null;private TextView tv_bestScore;private int current_score = 0;private int currentBestScore;public MainActivity() {mainactivity = this;}public static MainActivity getMainActivity() {return mainactivity;}protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);inital();}public void inital() {text = (TextView) findViewById(R.id.text);tv_bestScore = (TextView) findViewById(R.id.tv_bestScore);BestScode bs = new BestScode(this);currentBestScore = bs.getBestScode();tv_bestScore.setText("" + currentBestScore);// WindowManager wm = (WindowManager) this// .getSystemService(Context.WINDOW_SERVICE);// int width = wm.getDefaultDisplay().getWidth();// int height = wm.getDefaultDisplay().getHeight();// iv=(ImageView) findViewById(R.id.image);// 生成图片// iv.setImageResource(R.drawable.myname);// iv.setScaleType(ImageView.ScaleType.FIT_XY);// iv.setAdjustViewBounds(true);// iv.setMaxHeight(height);// 屏幕高度// iv.setMaxWidth(width);// 屏幕宽度}// 清空分数public void clear() {score = 0;show();}// 显示分数public void show() {text.setText("" + score);}// 添加分数public void add(int s) {score += s;show();if (score > currentBestScore) {currentBestScore = score;BestScode bs = new BestScode(this);bs.setBestScode(currentBestScore);tv_bestScore.setText("" + currentBestScore);}}/*** 菜单、返回键响应*/private long exitTime = 0;public boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK&& event.getAction() == KeyEvent.ACTION_DOWN) {if ((System.currentTimeMillis() - exitTime) > 2000) {Toast.makeText(this, "再按一次退出程序", 1000).show();exitTime = System.currentTimeMillis();} else {finish();System.exit(0);}return true;}return super.onKeyDown(keyCode, event);}

最后附上我的layout:

<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:background="#bbada0"android:orientation="vertical" ><LinearLayout
        android:id="@+id/ll_best"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_alignParentRight="true"android:layout_marginRight="10dp"android:orientation="vertical" ><TextView
            android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="最高纪录:"android:textColor="#FF0000"android:textSize="18sp" /><TextView
            android:id="@+id/tv_bestScore"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="0"android:textColor="#FF0000"android:textSize="20sp" /></LinearLayout><com.example.game2048.GameView
        android:layout_width="match_parent"android:layout_height="0dp"android:layout_weight="4" ></com.example.game2048.GameView><LinearLayout
        android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="horizontal" ><TextView
            android:layout_width="match_parent"android:layout_height="wrap_content"android:text="得分:"android:textColor="#98F5FF"android:textSize="50sp" /><TextView
            android:id="@+id/text"android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:textColor="#98F5FF"android:textSize="50sp" /></LinearLayout><LinearLayout
        android:layout_width="wrap_content"android:layout_height="0dp"android:layout_weight="1"android:orientation="horizontal" ><TextView
            android:layout_width="match_parent"android:layout_height="wrap_content"android:layout_gravity="center"android:text="作者:\n我就是马云飞"android:textColor="#90EE90"android:textSize="38sp" /></LinearLayout></LinearLayout>

好了。有兴趣可以把这个demo进行延伸,写了等级划分啊,自定义背景啊~~~。
我的android交流群:232748032

android 2048的简单实现相关推荐

  1. android实现计算器功能吗,利用Android实现一个简单的计算器功能

    利用Android实现一个简单的计算器功能 发布时间:2020-11-20 16:25:01 来源:亿速云 阅读:90 作者:Leah 今天就跟大家聊聊有关利用Android实现一个简单的计算器功能, ...

  2. Android开发环境简单配置

    为什么80%的码农都做不了架构师?>>>    ·         Android开发环境简单配置 写这个系列的原因也是因为自己对android比较感兴趣,而网上多数教程都是直接参照 ...

  3. 文件管理器android实现,Android开发之简单文件管理器实现方法

    易采站长站为您分析Android开发之简单文件管理器实现方法,简单实现了Android的文件目录查看,文件重命名,打开,删除等功能,需要的朋友可以参考下 本文实例讲述了Android开发之简单文件管理 ...

  4. android 观察者,Android开发实现简单的观察者与被观察者示例

    本文实例讲述了Android开发实现简单的观察者与被观察者.分享给大家供大家参考,具体如下: 概述: 观察者模式(又被称为发布-订阅(Publish/Subscribe)模式,属于行为型模式的一种,它 ...

  5. android EventBus的简单使用

    今天,简单讲讲Android里关于EventBus的使用. 这几天,由于面试的缘故,我听到了很多Android的流行框架,但是之前自己在公司做APP时并没有使用,所以没有了解.于是在网上查找了资料,学 ...

  6. android ButterKnife的简单使用

    今天,简单讲讲android里如何使用ButterKnife. Android框架系列: 一.android EventBus的简单使用 二.android Glide简单使用 三.android O ...

  7. android EventBus的简单使用

    今天,简单讲讲Android里关于EventBus的使用. 这几天,由于面试的缘故,我听到了很多Android的流行框架,但是之前自己在公司做APP时并没有使用,所以没有了解.于是在网上查找了资料,学 ...

  8. 做简单的android 软件推荐,Android_适用于Android开发的简单聊天软件,适用于android 开发。是一个简 - phpStudy...

    适用于Android开发的简单聊天软件 适用于android 开发.是一个简单的聊天软件,包括知识点,各个控件的运用(ExpandableListView,ViewPager,Spinner,Line ...

  9. android开发按钮颜色,Android编程实现简单设置按钮颜色的方法

    本文实例讲述了Android编程实现简单设置按钮颜色的方法.分享给大家供大家参考,具体如下: 1.工程目录 a.在res目录-新建drawble文件夹放入自定义图片 2.main.xml androi ...

最新文章

  1. linux各种模式切换
  2. 【java开发系列】—— 自定义注解
  3. VC++深入详解 孙鑫 高清PDF + 配套视频下载
  4. php获取压缩文件列表,php获取所有文件并压缩
  5. lombok插件_lombok插件,让代码更简洁
  6. 【python基础知识】python输出时出错,UnicodeEncodeError: 'gbk' codec can't encode character '\ue4bf.....
  7. 新能源车为什么不加变速箱解决高速高耗电的问题?
  8. ZT pthread_detach
  9. 【Matlab】三维绘图总结
  10. java-php-python-ssm网上游戏商店设计计算机毕业设计
  11. Python自然语言处理 | 编写结构化程序
  12. Ubuntu 20.04 系统5分钟后老是自动锁屏怎么取消?
  13. 关于open_cursors和session_cached_cursors的参数值
  14. C语言写的简单病毒程序
  15. 单链表Java数据结构
  16. 任何的html标记都拥有style属性,【判断题】在CSS中,任何的HTML标记都拥有style属性。...
  17. 《狼图腾》作者:姜戎
  18. 【新手入门】Oozie workflow如何在action之间传递参数
  19. [翻译] MZTimerLabel 用作秒表或者倒计时
  20. Vue使用指南(一)

热门文章

  1. 谁动了“支付”的奶酪?移动支付蓝海剖析
  2. 亚洲诚信助力看雪安全开发者峰会
  3. Windows7光盘制作: 向脱机映像添加补丁
  4. 产品经理、交互设计师必备的超赞Web端Axure原型设计组件库、元件库、图表组件库
  5. Echarts 南海诸岛简图显示位置调整
  6. 基于matlab的立体图像编码解码算法仿真与分析
  7. 配置nginx+mongrel的rails部署环境
  8. Clamav杀毒安装配置手册
  9. Unity 3D 导入三维模型||Unity 3D 动画系统简介(Mecanim)
  10. Dota 狼人一级野