文档章节

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

 冷小菜
发布于 2014/12/13 14:07
字数 3571
阅读 75
收藏 1
转载请标明出处: http://blog.csdn.net/lmj623565791/article/details/40020137,本文出自: 【张鸿洋的博客】

1、概述

博主本想踏入游戏开放行业,无奈水太深,不会游泳;于是乎,只能继续开发应用,但是原生Android也能开发游戏么,2048、像素鸟、别踩什么来着;今天给大家带来一篇2048的开发篇,别怕不分上下文,或者1、2、3、4,一篇包你能玩happy~虽然我从来没有玩到过2048!!!其实大家也可以当作自定义控件来看~~~

特别说明一下,游戏2048里面的方块各种颜色来源于:http://download.csdn.net/detail/qq1121674367/7155467,这个2048的代码中,其他代码,太多,未参考;特此感谢分享;大家也可以下载下,对比学习下;

接下来贴个我们项目的效果图:


ok 看完效果图,我就准备带领大家征服这款游戏了~~~

2、实现分析

贴一张静态图,开始对我们游戏的设计:


可以看到,游戏其实就是一个容器,里面很多个方块,触摸容器,里面的方块的形态会发生变化。那么:

1、容器我们准备自定义ViewGroup ,叫做Game2048Layout ; 里面的块块自定义View ,叫做Game2048Item

接下来从简单的开始:

2、Game2048Item

Game2048Item是个View,并且需要哪些属性呢?

首先得有个number,显示数字嘛,然后绘制的时候根据number绘制背景色;还需要呢?嗯,需要正方形边长,再考虑下,这个边长应该Item自己控制么?显然不是的,Game2048Layout 是个n*n的面板,这个n是不确定的,所以Item的边长肯定是Game2048Layout 计算好传入的。这样必须的属性就这两个。

3、Game2048Layout

 Game2048Layout是个容器,我们观察下,里面View是个 n*n的排列,我们准备让其继承RelativeLayout ; 这样可以通过设置Item的RIGHT_OF之类的属性进行定位;

我们在onMeasure里面得到Layout的宽和高,然后根据n*n,生成一定数目的Item,为其设置宽和高,放置到Layout中,这样整个游戏的布局就做好了;绘制的细节上:Item间有横向与纵向的间距,所以需要设置这个值,叫做mMargin。然后Item的边长 =  ( Layout边长 - (n-1)*mMagin ) / n ; 

剩下的就是onTouchEvent里面去判断用户手势了,然后就行各种逻辑操作了~

3、代码之旅

首先来看看我们的Game2048Item

1、Game2048Item

package com.zhy.game2048.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;

/**
 * 2048的每个Item
 * 
 * @author zhy
 * 
 */
public class Game2048Item extends View
{
	/**
	 * 该View上的数字
	 */
	private int mNumber;
	private String mNumberVal;
	private Paint mPaint;
	/**
	 * 绘制文字的区域
	 */
	private Rect mBound;

	public Game2048Item(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);
		mPaint = new Paint();

	}

	public Game2048Item(Context context)
	{
		this(context, null);
	}

	public Game2048Item(Context context, AttributeSet attrs)
	{
		this(context, attrs, 0);
	}

	public void setNumber(int number)
	{
		mNumber = number;
		mNumberVal = mNumber + "";
		mPaint.setTextSize(30.0f);
		mBound = new Rect();
		mPaint.getTextBounds(mNumberVal, 0, mNumberVal.length(), mBound);
		invalidate();
	}
	
	

	public int getNumber()
	{
		return mNumber;
	}

	@Override
	protected void onDraw(Canvas canvas)
	{
		
		super.onDraw(canvas);
		String mBgColor = "";
		switch (mNumber)
		{
		case 0:
			mBgColor = "#CCC0B3";
			break;
		case 2:
			mBgColor = "#EEE4DA";
			break;
		case 4:
			mBgColor = "#EDE0C8";
			break;
		case 8:
			mBgColor = "#F2B179";// #F2B179
			break;
		case 16:
			mBgColor = "#F49563";
			break;
		case 32:
			mBgColor = "#F5794D";
			break;
		case 64:
			mBgColor = "#F55D37";
			break;
		case 128:
			mBgColor = "#EEE863";
			break;
		case 256:
			mBgColor = "#EDB04D";
			break;
		case 512:
			mBgColor = "#ECB04D";
			break;
		case 1024:
			mBgColor = "#EB9437";
			break;
		case 2048:
			mBgColor = "#EA7821";
			break;
		default:
			mBgColor = "#EA7821";
			break;
		}

		mPaint.setColor(Color.parseColor(mBgColor));
		mPaint.setStyle(Style.FILL);
		canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint);

		if (mNumber != 0)
			drawText(canvas);

	}

	/**
	 * 绘制文字
	 * 
	 * @param canvas
	 */
	private void drawText(Canvas canvas)
	{
		
		mPaint.setColor(Color.BLACK);
		float x = (getWidth() - mBound.width()) / 2;
		float y = getHeight() / 2 + mBound.height() / 2;
		canvas.drawText(mNumberVal, x, y, mPaint);
	}

}

很简单,基本就一个onDraw通过number来绘制背景和数字;number通过调用setNumer进行设置;它的宽和高都是固定值,所以我们并不需要自己进行测量~~

2、Game2048Layout

1、成员变量

这就是我们最主要的一个类了,首先我们看看这个类的成员变量,先看看各个成员变量的作用:

/**
	 * 设置Item的数量n*n;默认为4
	 */
	private int mColumn = 4;
	/**
	 * 存放所有的Item
	 */
	private Game2048Item[] mGame2048Items;

	/**
	 * Item横向与纵向的边距
	 */
	private int mMargin = 10;
	/**
	 * 面板的padding
	 */
	private int mPadding;
	/**
	 * 检测用户滑动的手势
	 */
	private GestureDetector mGestureDetector;

	// 用于确认是否需要生成一个新的值
	private boolean isMergeHappen = true;
	private boolean isMoveHappen = true;

	/**
	 * 记录分数
	 */
	private int mScore;

主要的成员变量就这些,直接看注释也比较容易理解~~

了解了成员变量,接下来我们需要在构造方法里面得到一些值和初始化一些变量

2、构造方法

public Game2048Layout(Context context, AttributeSet attrs, int defStyle)
	{
		super(context, attrs, defStyle);

		mMargin = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
				mMargin, getResources().getDisplayMetrics());
		// 设置Layout的内边距,四边一致,设置为四内边距中的最小值
		mPadding = min(getPaddingLeft(), getPaddingTop(), getPaddingRight(),
				getPaddingBottom());

		mGestureDetector = new GestureDetector(context , new MyGestureDetector());

	}

我们在构造方法里面得到Item间的边距(margin)和我们容器的内边距(padding,),这个值应该四边一致,于是我们取四边的最小值;这两个属性可以抽取为自定义的属性;然后初始化了我们的mGestureDetector

有了margin和padding,我们就可以计算我们item的边长了。这个计算过程肯定在onMeasure里面,因为我们需要在onMeasure获取容器的宽和高


3、onMeasure

private boolean once;

	/**
	 * 测量Layout的宽和高,以及设置Item的宽和高,这里忽略wrap_content 以宽、高之中的最小值绘制正方形
	 */
	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
	{
		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
		// 获得正方形的边长
		int length = Math.min(getMeasuredHeight(), getMeasuredWidth());
		// 获得Item的宽度
		int childWidth = (length - mPadding * 2 - mMargin * (mColumn - 1))
				/ mColumn;

		if (!once)
		{
			if (mGame2048Items == null)
			{
				mGame2048Items = new Game2048Item[mColumn * mColumn];
			}
			// 放置Item
			for (int i = 0; i < mGame2048Items.length; i++)
			{

				Game2048Item item = new Game2048Item(getContext());

				mGame2048Items[i] = item;
				item.setId(i + 1);
				RelativeLayout.LayoutParams lp = new LayoutParams(childWidth,
						childWidth);
				// 设置横向边距,不是最后一列
				if ((i + 1) % mColumn != 0)
				{
					lp.rightMargin = mMargin;
				}
				// 如果不是第一列
				if (i % mColumn != 0)
				{
					lp.addRule(RelativeLayout.RIGHT_OF,//
							mGame2048Items[i - 1].getId());
				}
				// 如果不是第一行,//设置纵向边距,非最后一行
				if ((i + 1) > mColumn)
				{
					lp.topMargin = mMargin;
					lp.addRule(RelativeLayout.BELOW,//
							mGame2048Items[i - mColumn].getId());
				}
				addView(item, lp);
			}
			generateNum();
		}
		once = true;

		setMeasuredDimension(length, length);
	}

首先设置容器的边长为宽高中的最小值;然后(length - mPadding * 2 - mMargin * (mColumn - 1)) / mColumn ; 去计算Item的边长;

拿到以后,根据我们的mColumn初始化我们的Item数组,然后遍历生成Item,设置Item的LayoutParams以及Rule(RIGHT_OF , BELOW),最后添加到我们的容器中;

最后我们通过setMeasuredDimension(length, length);改变我们布局占据的空间;

到此,我们整个面板绘制完成了;

接下来,就是根据用户的手势,去进行游戏逻辑操作了,手势那么肯定是onTouchEvent了:

4、onTouchEvent

@Override
	public boolean onTouchEvent(MotionEvent event)
	{
		mGestureDetector.onTouchEvent(event);
		return true;
	}

我们把触摸事件交给了mGestureDetector,我们去看看我们的mGestureDetector,在构造方法中有这么一句:

mGestureDetector = new GestureDetector(context , new MyGestureDetector());

so,我们需要去看看MyGestureDetector:

class MyGestureDetector extends GestureDetector.SimpleOnGestureListener
	{

		final int FLING_MIN_DISTANCE = 50;

		@Override
		public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
				float velocityY)
		{
			float x = e2.getX() - e1.getX();
			float y = e2.getY() - e1.getY();

			if (x > FLING_MIN_DISTANCE
					&& Math.abs(velocityX) > Math.abs(velocityY))
			{
				action(ACTION.RIGHT);

			} else if (x < -FLING_MIN_DISTANCE
					&& Math.abs(velocityX) > Math.abs(velocityY))
			{
				action(ACTION.LEFT);

			} else if (y > FLING_MIN_DISTANCE
					&& Math.abs(velocityX) < Math.abs(velocityY))
			{
				action(ACTION.DOWM);

			} else if (y < -FLING_MIN_DISTANCE
					&& Math.abs(velocityX) < Math.abs(velocityY))
			{
				action(ACTION.UP);
			}
			return true;

		}

	}

很简单,就是判读用户上、下、左、右滑动;然后去调用action(ACTION)方法;ACTION是个枚举:

/**
	 * 运动方向的枚举
	 * 
	 * @author zhy
	 * 
	 */
	private enum ACTION
	{
		LEFT, RIGHT, UP, DOWM
	}

这么看,核心代码都在action方法里面了:

5、根据用户手势重绘Item

看代码前,先考虑下,用户从右向左滑动时,面板应该如何变化;取其中一行,可能性为:

0 0 0 2 -> 2 0 0 0

2 0 4 0 -> 2 4 0 0 

2 2 4 0 -> 4 4 0 0 

大概就这3中可能;

我们算法是这么做的:

拿2 2 4 0 来说:

1、首先把每行有数字的取出来,临时存储下来,即[ 2, 2, 4 ];

2、然后遍历合并第一个相遇的相同的,即[ 4, 4 ,0 ]

3、然后直接放置到原行,不足补0,即[ 4, 4, 0 ,0 ]; 

中间还有几个操作:

1、生成一个新的数字,游戏在每次用户滑动时,可能会生成一个数字;我们的生成策略:如果发生移动或者合并,则生成一个数字;

移动的判断,拿原数据,即【 2 ,2,4,0】和我们第一步临时存储的做比较,一一对比(遍历临时表),发现不同,则认为移动了;

合并的判断,在合并的时候会设置合并的标志位为true;

2、加分,如果发生合并,则加分,分值为合并得到的数字,比如 4,4 -> 8 ,即加8分 ; 也只需要在合并的时候进行相加就行了;

介绍完了,来看我们的代码:

/**
	 * 根据用户运动,整体进行移动合并值等
	 */
	private void action(ACTION action)
	{
		// 行|列
		for (int i = 0; i < mColumn; i++)
		{
			List<Game2048Item> row = new ArrayList<Game2048Item>();
			// 行|列
			for (int j = 0; j < mColumn; j++)
			{
				// 得到下标
				int index = getIndexByAction(action, i, j);

				Game2048Item item = mGame2048Items[index];
				// 记录不为0的数字
				if (item.getNumber() != 0)
				{
					row.add(item);
				}
			}
			
			for (int j = 0; j < mColumn && j < row.size(); j++)
			{
				int index = getIndexByAction(action, i, j);
				Game2048Item item = mGame2048Items[index];

				if (item.getNumber() != row.get(j).getNumber())
				{
					isMoveHappen = true;
				}
			}
			
			// 合并相同的
			mergeItem(row);
			
			
			// 设置合并后的值
			for (int j = 0; j < mColumn; j++)
			{
				int index = getIndexByAction(action, i, j);
				if (row.size() > j)
				{
					mGame2048Items[index].setNumber(row.get(j).getNumber());
				} else
				{
					mGame2048Items[index].setNumber(0);
				}
			}

		}
		generateNum();

	}

大体上是两层循环,外层循环代码循环次数,内层有3个for循环;

第一个for循环,对应上述:首先把每行有数字的取出来,临时存储下来,即[ 2, 2, 4 ];

第二个for循环,判断是否发生移动;

// 合并相同的
mergeItem(row); 是去进行合并操作,对应上述:然后遍历合并第一个相遇的相同的,即[ 4, 4 ,0 ];以及加分和设置合并标志位都在方法中;

第三个for循环:设置合并后的值,对应上述:然后直接放置到原行,不足补0,即[ 4, 4, 0 ,0 ]; 

最后生成数字,方法内部会进行判断游戏是否结束,是否需要生成数字;

那么先看mergeItem的代码:

/**
	 * 合并相同的Item
	 * 
	 * @param row
	 */
	private void mergeItem(List<Game2048Item> row)
	{
		if (row.size() < 2)
			return;

		for (int j = 0; j < row.size() - 1; j++)
		{
			Game2048Item item1 = row.get(j);
			Game2048Item item2 = row.get(j + 1);

			if (item1.getNumber() == item2.getNumber())
			{
				isMergeHappen = true;

				int val = item1.getNumber() + item2.getNumber();
				item1.setNumber(val);

				// 加分
				mScore += val;
				if (mGame2048Listener != null)
				{
					mGame2048Listener.onScoreChange(mScore);
				}

				// 向前移动
				for (int k = j + 1; k < row.size() - 1; k++)
				{
					row.get(k).setNumber(row.get(k + 1).getNumber());
				}
				
				row.get(row.size() - 1).setNumber(0);
				return;
			}

		}

	}

也比较简单,循环查找相同的number,发现合并数字,加分;

加分我们设置了一个回调,把分数回调出去:

if (mGame2048Listener != null)
{
mGame2048Listener.onScoreChange(mScore);
}

最后看我们生成数字的代码:

/**
	 * 产生一个数字
	 */
	public void generateNum()
	{

		if (checkOver())
		{
			Log.e("TAG", "GAME OVER");
			if (mGame2048Listener != null)
			{
				mGame2048Listener.onGameOver();
			}
			return;
		}

		if (!isFull())
		{
			if (isMoveHappen || isMergeHappen)
			{
				Random random = new Random();
				int next = random.nextInt(16);
				Game2048Item item = mGame2048Items[next];

				while (item.getNumber() != 0)
				{
					next = random.nextInt(16);
					item = mGame2048Items[next];
				}

				item.setNumber(Math.random() > 0.75 ? 4 : 2);

				isMergeHappen = isMoveHappen = false;
			}

		}
	}

首先判断是否结束,如果结束了,依然是回调出去,得让玩的人知道结束了;

然后判断当然面板是有木有空的格子,如果没有,在判断需要生成新的数字么,需要则随机生成一个新的2或4;

那么如何判断是否结束呢?

首先肯定是没有空格了,然后四个方向上没有相同的数字就结束了:

/**
	 * 检测当前所有的位置都有数字,且相邻的没有相同的数字
	 * 
	 * @return
	 */
	private boolean checkOver()
	{
		// 检测是否所有位置都有数字
		if (!isFull())
		{
			return false;
		}

		for (int i = 0; i < mColumn; i++)
		{
			for (int j = 0; j < mColumn; j++)
			{

				int index = i * mColumn + j;

				// 当前的Item
				Game2048Item item = mGame2048Items[index];
				// 右边
				if ((index + 1) % mColumn != 0)
				{
					Log.e("TAG", "RIGHT");
					// 右边的Item
					Game2048Item itemRight = mGame2048Items[index + 1];
					if (item.getNumber() == itemRight.getNumber())
						return false;
				}
				// 下边
				if ((index + mColumn) < mColumn * mColumn)
				{
					Log.e("TAG", "DOWN");
					Game2048Item itemBottom = mGame2048Items[index + mColumn];
					if (item.getNumber() == itemBottom.getNumber())
						return false;
				}
				// 左边
				if (index % mColumn != 0)
				{
					Log.e("TAG", "LEFT");
					Game2048Item itemLeft = mGame2048Items[index - 1];
					if (itemLeft.getNumber() == item.getNumber())
						return false;
				}
				// 上边
				if (index + 1 > mColumn)
				{
					Log.e("TAG", "UP");
					Game2048Item itemTop = mGame2048Items[index - mColumn];
					if (item.getNumber() == itemTop.getNumber())
						return false;
				}

			}

		}

		return true;

	}

/**
	 * 是否填满数字
	 * 
	 * @return
	 */
	private boolean isFull()
	{
		// 检测是否所有位置都有数字
		for (int i = 0; i < mGame2048Items.length; i++)
		{
			if (mGame2048Items[i].getNumber() == 0)
			{
				return false;
			}
		}
		return true;
	}

到此,我们的代码介绍完毕~~~完成了我们的Game2048Layout ; 接下来看如何使用呢?

写游戏的过程很艰辛,但是用起来,看看什么叫so easy ; 当成普通的View即可:

4、实践

1、布局文件:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent" >

    <com.zhy.game2048.view.Game2048Layout
        android:id="@+id/id_game2048"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_centerInParent="true"
        android:background="#ffffff"
        android:padding="10dp" >
    </com.zhy.game2048.view.Game2048Layout>

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_above="@id/id_game2048"
        android:layout_centerHorizontal="true"
        android:layout_marginBottom="20dp"
        android:background="#EEE4DA"
        android:orientation="horizontal" >

        <TextView
            android:id="@+id/id_score"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:padding="4dp"
            android:text="Score: 0"
            android:textColor="#EA7821"
            android:textSize="30sp"
            android:textStyle="bold" />
    </LinearLayout>

</RelativeLayout>

2、MainActivity

package com.zhy.game2048;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.os.Bundle;
import android.widget.TextView;

import com.zhy.game2048.view.Game2048Layout;
import com.zhy.game2048.view.Game2048Layout.OnGame2048Listener;

public class MainActivity extends Activity implements OnGame2048Listener
{
	private Game2048Layout mGame2048Layout;

	private TextView mScore;

	@Override
	protected void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		mScore = (TextView) findViewById(R.id.id_score);
		mGame2048Layout = (Game2048Layout) findViewById(R.id.id_game2048);
		mGame2048Layout.setOnGame2048Listener(this);
	}

	@Override
	public void onScoreChange(int score)
	{
		mScore.setText("SCORE: " + score);
	}

	@Override
	public void onGameOver()
	{
		new AlertDialog.Builder(this).setTitle("GAME OVER")
				.setMessage("YOU HAVE GOT " + mScore.getText())
				.setPositiveButton("RESTART", new OnClickListener()
				{
					@Override
					public void onClick(DialogInterface dialog, int which)
					{
						mGame2048Layout.restart();
					}
				}).setNegativeButton("EXIT", new OnClickListener()
				{

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

}

很简单,代码主要就是设置个接口,当发生加分已经游戏结束时会交给Activity去处理~~~如果喜欢,你可以在一个界面放4个游戏~~~

当然了游戏Item的个数也可以动态设置~~~最后贴一个5*5游戏的截图~~



好了,2048到此结束,拿只笔开始设计,然后根据自定义View的经验去写,相信你可以学会不少东西~~~


并且我们的View是抽取出来的,其实换成图片也很简单~~

今天又看了war3十大经典战役,献上war3版,代码就不贴了,改动也就几行代码,贴个截图,纪念我们曾经的war3~~~:



额,咋都弄成5*5了~大家可以把mColumn改为4~~~



2048源码点击下载


war3版2048点击下载





---------------------------------------------------------------------------------------------------------

建了一个QQ群,方便大家交流。群号:55032675



----------------------------------------------------------------------------------------------------------

博主部分视频已经上线,如果你不喜欢枯燥的文本,请猛戳(初录,期待您的支持):

1、高仿微信5.2.1主界面及消息提醒

2、高仿QQ5.0侧滑


















本文转载自:http://blog.csdn.net/lmj623565791/article/details/40020137

粉丝 2
博文 63
码字总数 0
作品 0
海淀
私信 提问
Android 带你玩转实现游戏2048 其实2048只是个普通的控件

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lmj623565791/article/details/40020137 转载请标明出处:http://blog.csdn.net/lmj623565791/article/detai...

鸿洋_
2014/10/23
0
0
我也来开发2048之确定思路

以下内容拔自百度: 2048是比较流行的一款数字游戏。原版2048首先在github上发布,原作者是Gabriele Cirulli。它是基于《1024》和《小3传奇》的玩法开发 而成的新型数字游戏。随后2048便出现...

eclipse_xu
2014/04/19
0
0
如何在 Linux 中安装 2048 游戏

流行的移动益智游戏 2048 也可以在 Ubuntu 和 Linux 发行版上玩。啊!你甚至可以在 Linux 终端上玩 2048。如果你的生产率因为这个让人上瘾的游戏下降,请不要怪我。 早在 2014 年,2048 就是...

17%
2018/09/08
0
0
2048,成功和我

过去的几周对我而言是一次狂野之旅。在3月份,我为了娱乐开发了一款名叫2048的游戏,在GitHub上作为开源软件发布了。在接下来几周里,它出乎意料地成为世界级的成功,它已经被2千3百万用户玩...

腊八粥
2014/05/08
12K
42
前端特效【第04期】|果汁混合效果-下

往期回顾 在上一期的【前端特效】☜里,我们已经把果汁混合的效果里面的圆形菜单做好了,如果你错过了上篇文章今天我们要讨论的是杯子里面的液体生成问题 先来回顾下咱们的果汁混合效果吧 果...

我的卡
2018/11/15
17
0

没有更多内容

加载失败,请刷新页面

加载更多

关于AsyncTask的onPostExcute方法是否会在Activity重建过程中调用的问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/XG1057415595/article/details/86774575 假设下面一种情况...

shzwork
今天
6
0
object 类中有哪些方法?

getClass(): 获取运行时类的对象 equals():判断其他对象是否与此对象相等 hashcode():返回该对象的哈希码值 toString():返回该对象的字符串表示 clone(): 创建并返此对象的一个副本 wait...

happywe
今天
6
0
Docker容器实战(七) - 容器中进程视野下的文件系统

前两文中,讲了Linux容器最基础的两种技术 Namespace 作用是“隔离”,它让应用进程只能看到该Namespace内的“世界” Cgroups 作用是“限制”,它给这个“世界”围上了一圈看不见的墙 这么一...

JavaEdge
今天
8
0
文件访问和共享的方法介绍

在上一篇文章中,你了解到文件有三个不同的权限集。拥有该文件的用户有一个集合,拥有该文件的组的成员有一个集合,然后最终一个集合适用于其他所有人。在长列表(ls -l)中这些权限使用符号...

老孟的Linux私房菜
今天
7
0
面试套路题目

作者:抱紧超越小姐姐 链接:https://www.nowcoder.com/discuss/309292?type=3 来源:牛客网 面试时候的潜台词 抱紧超越小姐姐 编辑于 2019-10-15 16:14:56APP内打开赞 3 | 收藏 4 | 回复24 ...

MtrS
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部