分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/42965779 ,本文出自:【张鸿洋的博客】

1、概述

哈,记得以前写过Android SurfaceView实战 打造抽奖转盘 , 同属于SurfaceView系列,基本可以从这篇博文中学习到SurfaceView的用法,以及利用SurfaceView做抽奖转盘。但是其中缺少一部分的知识点,就是与用户交互时界面的改变,所以今天给大家再带来本篇博文教大家如何做flabby bird这款游戏,这游戏虽然不难,但是也为其作者挣了不少钱,大家在学会以后,可以尽可能发挥自己的创意,做属于自己的游戏,说不定下一个火的奏是你。

ok,那么首先上下效果图:

再来张动态的:

由于上传图片最大限制为2M,所以做了压缩处理,凑合看吧 ~~~

2、分析

仔细观察游戏,需要绘制的有:背景、地板、鸟、管道、分数;

游戏开始时:

地板给人一种想左移动的感觉;

管道与地板同样的速度向左移动;

鸟默认下落;

当用户touch屏幕时,鸟上升一段距离后,下落;

运动过程中需要判断管道和鸟之间的位置关系,是否触碰,是否穿过等,需要计算分数。

好了,大概就这么多,那我们首先开始考虑绘制~~~

3、SurfaceView的一般写法

接下来,我们首先编写下SurfaceView的一般写法:

package com.zhy.view;import android.content.Context;import android.graphics.Canvas;import android.graphics.PixelFormat;import android.util.AttributeSet;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;public class GameFlabbyBird extends SurfaceView implements Callback, Runnable{ private SurfaceHolder mHolder; /**  * 与SurfaceHolder绑定的Canvas  */ private Canvas mCanvas; /**  * 用于绘制的线程  */ private Thread t; /**  * 线程的控制开关  */ private boolean isRunning; public GameFlabbyBird(Context context) {  this(context, null); } public GameFlabbyBird(Context context, AttributeSet attrs) {  super(context, attrs);  mHolder = getHolder();  mHolder.addCallback(this);  setZOrderOnTop(true);// 设置画布 背景透明  mHolder.setFormat(PixelFormat.TRANSLUCENT);  // 设置可获得焦点  setFocusable(true);  setFocusableInTouchMode(true);  // 设置常亮  this.setKeepScreenOn(true); } @Override public void surfaceCreated(SurfaceHolder holder) {  // 开启线程  isRunning = true;  t = new Thread(this);  t.start(); } @Override public void surfaceChanged(SurfaceHolder holder, int format, int width,   int height) {  // TODO Auto-generated method stub } @Override public void surfaceDestroyed(SurfaceHolder holder) {  // 通知关闭线程  isRunning = false; } @Override public void run() {  while (isRunning)  {   long start = System.currentTimeMillis();   draw();   long end = System.currentTimeMillis();   try   {    if (end - start < 50)    {     Thread.sleep(50 - (end - start));    }   } catch (InterruptedException e)   {    e.printStackTrace();   }  } } private void draw() {  try  {   // 获得canvas   mCanvas = mHolder.lockCanvas();   if (mCanvas != null)   {    // drawSomething..   }  } catch (Exception e)  {  } finally  {   if (mCanvas != null)    mHolder.unlockCanvasAndPost(mCanvas);  } }}

这个基础的类,在Android SurfaceView实战 打造抽奖转盘已经出现过,就不多说了,大家以后写SurfaceView的相关程序,可以直接拷贝,在此类基础上编写。

4、绘制

1、绘制背景

最简单的当然是背景了,直接drawBitmap即可。

我们添加需要的成员变量,以及初始化一些参数,然后添加drawBg方法,最后在draw中调用drawBg;

public class CopyOfGameFlabbyBird extends SurfaceView implements Callback,  Runnable{ /**  * 当前View的尺寸  */ private int mWidth; private int mHeight; private RectF mGamePanelRect = new RectF(); /**  * 背景  */ private Bitmap mBg; public CopyOfGameFlabbyBird(Context context, AttributeSet attrs) {  //省略了很多代码  initBitmaps(); } /**  * 初始化图片  */ private void initBitmaps() {  mBg = loadImageByResId(R.drawable.bg1); } private void draw() {  //省略了很多代码  drawBg();  //省略了很多代码 } /**  * 绘制背景  */ private void drawBg() {  mCanvas.drawBitmap(mBg, null, mGamePanelRect, null); } /**  * 初始化尺寸相关  */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {  super.onSizeChanged(w, h, oldw, oldh);  mWidth = w;  mHeight = h;  mGamePanelRect.set(0, 0, w, h); } /**  * 根据resId加载图片  *   * @param resId  * @return  */ private Bitmap loadImageByResId(int resId) {  return BitmapFactory.decodeResource(getResources(), resId); }}

基本就是添加成员变量,然后初始化,然后绘制,上述代码经过删减,贴出的都是与前面基础代码不同的部分,大家可以将代码对号入座进行填充。

好了,现在背景图绘制好了,接下来,我们绘制小鸟~~~

2、绘制bird

鸟在我们的屏幕中,初始化时需要一个位置,x上,肯定是居中,y上我们取2/3的高度;

关于bird,我们单独创建一个类:

package com.zhy.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.RectF;public class Bird{ /**  * 鸟在屏幕高度的2/3位置  */ private static final float RADIO_POS_HEIGHT = 2 / 3F; /**  * 鸟的宽度 30dp  */ private static final int BIRD_SIZE = 30; /**  * 鸟的横坐标  */ private int x; /**  * 鸟的纵坐标  */ private int y; /**  * 鸟的宽度  */ private int mWidth; /**  * 鸟的高度  */ private int mHeight; /**  * 鸟的bitmap  */ private Bitmap bitmap; /**  * 鸟绘制的范围  */ private RectF rect = new RectF(); public Bird(Context context, int gameWith, int gameHeight, Bitmap bitmap) {  this.bitmap = bitmap;  //鸟的位置  x = gameWith / 2 - bitmap.getWidth() / 2;  y = (int) (gameHeight * RADIO_POS_HEIGHT);  // 计算鸟的宽度和高度  mWidth = Util.dp2px(context, BIRD_SIZE);  mHeight = (int) (mWidth * 1.0f / bitmap.getWidth() * bitmap.getHeight()); } /**  * 绘制自己  *   * @param canvas  */ public void draw(Canvas canvas) {  rect.set(x, y, x + mWidth, y + mHeight);  canvas.drawBitmap(bitmap, null, rect, null); } public int getY() {  return y; } public void setY(int y) {  this.y = y; } public int getWidth() {  return mWidth; } public int getHeight() {  return mHeight; }}

定义了一个类,代表我们的鸟,以及一堆成员变量,并且提供一个draw方法对外;

在GameFlabbyBird中,只需要,初始化我们的Bird,在draw里面调用bird.draw即可;

部分筛检后代码:

public class CopyOfGameFlabbyBird extends SurfaceView implements Callback,  Runnable{ /**  * *********鸟相关**********************  */ private Bird mBird; private Bitmap mBirdBitmap; /**  * 初始化图片  */ private void initBitmaps() {  mBg = loadImageByResId(R.drawable.bg1);  mBirdBitmap = loadImageByResId(R.drawable.b1); } private void draw() {  // drawSomething..  drawBg();  drawBird(); } private void drawBird() {  mBird.draw(mCanvas); } /**  * 初始化尺寸相关  */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {  // 初始化mBird  mBird = new Bird(getContext(), mWidth, mHeight, mBirdBitmap); }}

是不是很简单,下面看下此时效果图:

Activity里面这么调用即可:

package com.zhy.surfaceViewDemo;import com.zhy.view.GameFlabbyBird;import android.app.Activity;import android.os.Bundle;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity{ GameFlabbyBird mGame; @Override protected void onCreate(Bundle savedInstanceState) {  super.onCreate(savedInstanceState);  getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,    WindowManager.LayoutParams.FLAG_FULLSCREEN);  requestWindowFeature(Window.FEATURE_NO_TITLE);  mGame = new GameFlabbyBird(this);  setContentView(mGame); }}

效果图:

不管咋样,我们的鸟已经在指定的位置了~~~有木有一点小激动~~

下面开始添加地板;

3、绘制地板

绘制地板相比来说会难一点,因为我们需要考虑怎么让地板运动,起初我截取了两个大图,希望通过两张图不断变化,产生动画效果,but,动画的太卡,有跳跃感;

于是,我忽然想到了一个东西可以做,我就把基础图变成了这样:

很小的一块图,先不考虑运动,如何填充成我们目标效果呢?

还记得有个类叫做BitmapShader么?我们可以利用它进行填充。

相关知识可以参考:Android BitmapShader 实战 实现圆形、圆角图片

首先我们依旧是定义一个地板类:Floor

package com.zhy.view;import java.util.concurrent.TimeUnit;import com.zhy.surfaceViewDemo.Config;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapShader;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.Paint.Style;import android.graphics.Shader.TileMode;public class Floor{ /*  * 地板位置游戏面板高度的4/5到底部  */ private static final float FLOOR_Y_POS_RADIO = 4 / 5F; // height of 4/5 /**  * x坐标  */ private int x; /**  * y坐标  */ private int y; /**  * 填充物  */ private BitmapShader mFloorShader; private int mGameWidth; private int mGameHeight; public Floor(int gameWidth, int gameHeight, Bitmap floorBg) {  mGameWidth = gameWidth;  mGameHeight = gameHeight;  y = (int) (gameHeight * FLOOR_Y_POS_RADIO);  mFloorShader = new BitmapShader(floorBg, TileMode.REPEAT,    TileMode.CLAMP); } /**  * 绘制自己  *   * @param mCanvas  * @param mPaint  */ public void draw(Canvas mCanvas, Paint mPaint) {  if (-x > mGameWidth)  {   x = x % mGameWidth;  }  mCanvas.save(Canvas.MATRIX_SAVE_FLAG);  //移动到指定的位置  mCanvas.translate(x, y);  mPaint.setShader(mFloorShader);  mCanvas.drawRect(x, 0, -x + mGameWidth, mGameHeight - y, mPaint);  mCanvas.restore();  mPaint.setShader(null); } public int getX() {  return x; } public void setX(int x) {  this.x = x; }}

定义了一堆成员变量,核心就在于,我们传入地板背景的填充物,然后初始化我们的mFloorShader,横向重复,纵向拉伸(这里的拉伸是指,纵向的最后一个像素不断重复)。

我们对外公布了draw方法,传入Canvas,我们首先调用canvas.save(),然后将canvas移动到指定的位置,然后绘制我们的矩形,矩形的填充就是我们的地板了~~;

这里,注意一下,我们这里使用了一个变量x,而不是0;为什么呢?因为我们的地板需要利用这个x运动。

那么现在我们如何才能动呢?

首先我们在GameFlabbyBird定义一个变量,表示移动速度mSpeed,然后在draw中不断更新mFloor的x坐标为:mFloor.setX(mFloor.getX() - mSpeed);

这样的画,每次绘制我们floor的起点,会向左移动mSpeed个位置,就形成了运行的效果;但是呢?不能一直减下去,不然最终我们的x岂不是负无穷了,那得绘制多大?

所以我们:

if (-x > mGameWidth)
  {
   x = x % mGameWidth;
  }

如果x的正值大于宽度了,我们取余一下~~~

最终我们的绘制范围是:

mCanvas.drawRect(x, 0, -x + mGameWidth, mGameHeight - y, mPaint);

ok,贴下筛检后GameFlabbyBird代码:

package com.zhy.view;import android.content.Context;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.graphics.PixelFormat;import android.graphics.RectF;import android.util.AttributeSet;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceHolder.Callback;import android.view.SurfaceView;import com.zhy.surfaceViewDemo.R;public class CopyOfGameFlabbyBird extends SurfaceView implements Callback,  Runnable{ private Paint mPaint; /**  * 地板  */ private Floor mFloor; private Bitmap mFloorBg; private int mSpeed; public CopyOfGameFlabbyBird(Context context, AttributeSet attrs) {  super(context, attrs);  mPaint = new Paint();  mPaint.setAntiAlias(true);  mPaint.setDither(true);  initBitmaps();  // 初始化速度  mSpeed = Util.dp2px(getContext(), 2); } /**  * 初始化图片  */ private void initBitmaps() {  mFloorBg = loadImageByResId(R.drawable.floor_bg2); } private void draw() {  // drawSomething..  drawBg();  drawBird();  drawFloor();  // 更新我们地板绘制的x坐标  mFloor.setX(mFloor.getX() - mSpeed); } private void drawFloor() {  mFloor.draw(mCanvas, mPaint); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {  // 初始化地板  mFloor = new Floor(mWidth, mHeight, mFloorBg); }}

其实很简单,就是声明几个变量,初始化一下;记得在draw中更新mFloor的x即可。

现在的效果:

好了,最后剩下个管道了~~~

4、绘制管道

然后是写搞一个管道类Pipe,注意我们的管道分为上下,每个管道的高度可能不同,所以会多一些成员变量;

package com.zhy.view;import java.util.Random;import android.content.Context;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.RectF;/** * 管道分为上下 *  * @author zhy *  */public class Pipe{ /**  * 上下管道间的距离  */ private static final float RADIO_BETWEEN_UP_DOWN = 1 / 5F; /**  * 上管道的最大高度  */ private static final float RADIO_MAX_HEIGHT = 2 / 5F; /**  * 上管道的最小高度  */ private static final float RADIO_MIN_HEIGHT = 1 / 5F; /**  * 管道的横坐标  */ private int x; /**  * 上管道的高度  */ private int height; /**  * 上下管道间的距离  */ private int margin; /**  * 上管道图片  */ private Bitmap mTop; /**  * 下管道图片  */ private Bitmap mBottom; private static Random random = new Random(); public Pipe(Context context, int gameWidth, int gameHeight, Bitmap top,   Bitmap bottom) {  margin = (int) (gameHeight * RADIO_BETWEEN_UP_DOWN);  // 默认从最左边出现  x = gameWidth;  mTop = top;  mBottom = bottom;  randomHeight(gameHeight); } /**  * 随机生成一个高度  */ private void randomHeight(int gameHeight) {  height = random    .nextInt((int) (gameHeight * (RADIO_MAX_HEIGHT - RADIO_MIN_HEIGHT)));  height = (int) (height + gameHeight * RADIO_MIN_HEIGHT); } public void draw(Canvas mCanvas, RectF rect) {  mCanvas.save(Canvas.MATRIX_SAVE_FLAG);  // rect为整个管道,假设完整管道为100,需要绘制20,则向上偏移80  mCanvas.translate(x, -(rect.bottom - height));  mCanvas.drawBitmap(mTop, null, rect, null);  // 下管道,便宜量为,上管道高度+margin  mCanvas.translate(0, (rect.bottom - height) + height + margin);  mCanvas.drawBitmap(mBottom, null, rect, null);  mCanvas.restore(); } public int getX() {  return x; } public void setX(int x) {  this.x = x; }}

我们直接看draw方法,我们的传入的rect是固定的一个矩形,我们的上下管道都是完整的绘制在这个rect中;

然后根据height,去偏移canvas的y,让rect显示出height部分,主要是因为,这样可以保证每个管道样子是一样的(如果根据height,使用不同的rect,会产生缩放);

Pipe写好了~~我们需要在GameFlabbyBird中去使用;但是考虑一下,游戏中的管道不像鸟和地面,有很多个,且是在运行中不断生成新的~~~

所以我们保存Pipe最起码是个List<Pipe>

筛检后的代码:

public class GameFlabbyBird extends SurfaceView implements Callback, Runnable{ /**  * *********管道相关**********************  */ /**  * 管道  */ private Bitmap mPipeTop; private Bitmap mPipeBottom; private RectF mPipeRect; private int mPipeWidth; /**  * 管道的宽度 60dp  */ private static final int PIPE_WIDTH = 60; private List<Pipe> mPipes = new ArrayList<Pipe>(); public GameFlabbyBird(Context context, AttributeSet attrs) {  super(context, attrs);  mPipeWidth = Util.dp2px(getContext(), PIPE_WIDTH); } /**  * 初始化图片  */ private void initBitmaps() {  ;  mPipeTop = loadImageByResId(R.drawable.g2);  mPipeBottom = loadImageByResId(R.drawable.g1); } private void draw() {  drawBg();  drawBird();  drawPipes();  drawFloor(); } /**  * 绘制管道  */ private void drawPipes() {  for (Pipe pipe : mPipes)  {   pipe.setX(pipe.getX() - mSpeed);   pipe.draw(mCanvas, mPipeRect);  } } /**  * 初始化尺寸相关  */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {  super.onSizeChanged(w, h, oldw, oldh);  // 初始化管道范围  mPipeRect = new RectF(0, 0, mPipeWidth, mHeight);  Pipe pipe = new Pipe(getContext(), w, h, mPipeTop, mPipeBottom);  mPipes.add(pipe); }}

我们在onSizeChanged中初始化了一个Pipe,添加到了mPipes中,然后在draw里面,动态改变Pipe的x为pipe.setX(pipe.getX() - mSpeed);

下面来看下效果:

我们的管道从右侧进入界面,然后消失在左侧~

当然了,关于管道还有很多需要编写,比如管道每隔多远生成一个,也不能让无限生成,当管道从界面移除应该从mPipes中移出;

以及判断管道和鸟的碰撞,这些都放置到下一篇博客叙述~~

5、绘制分数

分数的绘制比较简单,我准备了10个图,对应于0-9

没有单独定义类了,直接写了~~

筛检后的代码:

public class GameFlabbyBird extends SurfaceView implements Callback,  Runnable{ /**  * 分数  */ private final int[] mNums = new int[] { R.drawable.n0, R.drawable.n1,   R.drawable.n2, R.drawable.n3, R.drawable.n4, R.drawable.n5,   R.drawable.n6, R.drawable.n7, R.drawable.n8, R.drawable.n9 }; private Bitmap[] mNumBitmap; private int mGrade = 100; /**  * 单个数字的高度的1/15  */ private static final float RADIO_SINGLE_NUM_HEIGHT = 1 / 15f; /**  * 单个数字的宽度  */ private int mSingleGradeWidth; /**  * 单个数字的高度  */ private int mSingleGradeHeight; /**  * 单个数字的范围  */ private RectF mSingleNumRectF; /**  * 初始化图片  */ private void initBitmaps() {  mNumBitmap = new Bitmap[mNums.length];  for (int i = 0; i < mNumBitmap.length; i++)  {   mNumBitmap[i] = loadImageByResId(mNums[i]);  } } private void draw() {  // drawSomething..  drawBg();  drawBird();  drawPipes();  drawFloor();  drawGrades(); } /**  * 绘制分数  */ private void drawGrades() {  String grade = mGrade + "";  mCanvas.save(Canvas.MATRIX_SAVE_FLAG);  mCanvas.translate(mWidth / 2 - grade.length() * mSingleGradeWidth / 2,    1f / 8 * mHeight);  // draw single num one by one  for (int i = 0; i < grade.length(); i++)  {   String numStr = grade.substring(i, i + 1);   int num = Integer.valueOf(numStr);   mCanvas.drawBitmap(mNumBitmap[num], null, mSingleNumRectF, null);   mCanvas.translate(mSingleGradeWidth, 0);  }  mCanvas.restore(); } /**  * 初始化尺寸相关  */ @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) {  super.onSizeChanged(w, h, oldw, oldh);  // 初始化分数  mSingleGradeHeight = (int) (h * RADIO_SINGLE_NUM_HEIGHT);  mSingleGradeWidth = (int) (mSingleGradeHeight * 1.0f    / mNumBitmap[0].getHeight() * mNumBitmap[0].getWidth());  mSingleNumRectF = new RectF(0, 0, mSingleGradeWidth, mSingleGradeHeight); }}

我们定义了单个数字的范围,然后假设现在为100分,注意在绘制的时候,直接提取数字,把数字作为下标,找到对于的图片进行绘制;

绘制前,根据数字的位数,对画布进行偏移到中心位置,然后绘制;绘制过程中,每绘制完成一个数字则偏移一个数字的宽度;

现在的效果:

ok,到此为止,我们完成了所有需要绘制的东西~~由于篇幅原因,下一篇,将在此基础上完善剩下的所有内容~~~

有兴趣的,可以在此基础上直接尝试写了~~~

源码点击下载

给我老师的人工智能教程打call!http://blog.csdn.net/jiangjunshow

Android SurfaceView实战 带你玩转flabby bird (上)相关推荐

  1. Android SurfaceView实战 带你玩转flabby bird (下)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/43063331,本文出自:[张鸿洋的博客] 1.概述 在Android Surfa ...

  2. Android SurfaceView实战 带你玩转flabby bird

    分析 仔细观察游戏,需要绘制的有:背景.地板.鸟.管道.分数: 游戏开始时: 地板给人一种想左移动的感觉: 管道与地板同样的速度向左移动: 鸟默认下落: 当用户touch屏幕时,鸟上升一段距离后,下落 ...

  3. Android SurfaceView实战 带你玩切水果1.0

    1.概述 最近开发一个智能项目,项目对象是某智能早教机器人,这个产品主要定位是儿童益智玩的游戏,并且可以从中学习到相关历史知识等相关知识,其中有个游戏关卡就是去到不同国家,可以玩不同的游戏.领导说要用 ...

  4. 详解与重构hyman《Android SurfaceView实战 打造抽奖转盘》

    详解与重构hyman<Android SurfaceView实战 打造抽奖转盘> 作者:邵励治 一.概述--关于SurfaceView您不得不知道的二三事 1.SurfaceView是干什 ...

  5. Android SurfaceView实战 打造抽奖转盘

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/41722441 ,本文出自:[张鸿洋的博客] 1.概述 今天给大家带来Surfac ...

  6. android游戏之flabby bird(上)

    1.写在前面的话: 一次无意中在csdn上找到一个资源<android高仿flappy bird源码>,下载下来运行一下,效果非常不错,再进去一看代码,乖乖,好东西啊,整个游戏的框架非常的 ...

  7. 12个真实项目实战带你玩转Java并发编程

    这篇博客,我会总结如下内容,满满的干货,篇幅可能会很长,做好心理准备 Immutable Object:不可变对象模式:在不引入锁的条件下,能保证访问共享变量时是线程安全的,缺点是会频繁的创建变量. ...

  8. Android自定义控件实战——实现仿IOS下拉刷新上拉加载 PullToRefreshLayout

    下拉刷新控件,网上有很多版本,有自定义Layout布局的,也有封装控件的,各种实现方式的都有.但是很少有人告诉你具体如何实现的,今天我们就来一步步实现自己封装的 PullToRefreshLayout ...

  9. 超详细SVG实战——徒手画pipeline,带你玩转SVG

    记录个 svg 实战应用-最近断断续续在搞公司的前端发布平台,本想搞 pipeline ,结果先给 svg 给拦下了.基于发布平台没有同时多项目发布的能力,so-笔者决定搞个 pipeline 把 j ...

最新文章

  1. SQL学习笔记:库和表的创建
  2. linux ftp 不能上传,linux ftp用户没法上传。
  3. linux fcitx 守护进程,解决ubuntu下输入法切换问题
  4. php 连续点击事件,javascript设置连续两次点击按钮时间间隔的方法_javascript技巧...
  5. q7goodies事例_Java 8 Friday Goodies:Lambda和SQL
  6. JDK 9 REPL:入门
  7. JAVA不同类型数组重载_方法的重载;数组 (Java Day05)
  8. 经验 | 计算机视觉顶会上的灌水文都有哪些特征?
  9. Java8-初识Lambda
  10. SQLSERVER聚集索引的整理(重建)的必要性测试
  11. 國外空間亂碼解決方法
  12. 周鸿祎回应年会特等奖「免裁券」;微信放开 5000 人好友上限;Firefox 72 正式发布| 极客头条...
  13. Bilateral Filters(双边滤波算法)原理及实现
  14. python里字典的基本用法(包括嵌套字典)_Python使用字典的嵌套功能详解 python 嵌套中的字典赋值...
  15. 学会提问pdf_原来只要1分钟,Word、PPT、PDF文件就能随意互相转换,快学学
  16. 微软商店下载的python_微软商店可下载安装Python 3.7啦
  17. openwrt 怎么进入串口_OpenWrt路由器读取串口数据,建立tcp服务
  18. matlab中的函数简化,怎么简化solve函数的求解结果
  19. 小程序遵循的语法_2020年遵循的最佳应用程序开发实践
  20. Tiger DAO VC:DAO组织风险投资时代来临

热门文章

  1. 密码*** ,continue,等差求和
  2. 吐血推荐—计算机专业不可不看。
  3. 2017蓝桥杯省赛C++B组真题与题解
  4. JAVA毕业设计共享顺风车管理系统计算机源码+lw文档+系统+调试部署+数据库
  5. 初学算法——第一天:发现算法之美
  6. apollo自动驾驶进阶学习之:如何调试TrafficLight红绿灯交通规则参数调整
  7. dcf是ea211发动机吗_【图】新一代神机? 大众EA211发动机全解析_汽车之家
  8. erp oracle mrp,Oracle_ERP_MRP培训.ppt
  9. PDF编辑器怎么用?PDF编辑器的使用方法
  10. 你真的了解网络管理员这份工作吗?