第一次使用Android Studio时你应该知道的一切配置
http://www.cnblogs.com/smyhvae/p/4390905.html
练习:能够画出9*9格,有两个棋手A,B,交替输入列数0-9,由于重力原理,输入这个列下几行没有棋子,则自动下落;A显示棋子是X,B显示棋子O,要求当出现四连胜利!A和B交替进行;
MainActivity源码:
package com.imooc.wuziqi; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends AppCompatActivity { public wuziqipanel wuziqipanel; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); wuziqipanel=(wuziqipanel) findViewById(R.id.id_wuziqi); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.menu_main,menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { int id=item.getItemId(); if(id==R.id.action_settings){ wuziqipanel.start(); return true; } return super.onOptionsItemSelected(item); } }
自定义view源码
package com.imooc.wuziqi; import android.animation.ValueAnimator; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Point; import android.os.Bundle; import android.os.Parcelable; import android.support.annotation.IntegerRes; import android.support.annotation.Nullable; import android.util.AttributeSet; import android.view.MotionEvent; import android.view.View; import android.view.animation.LinearInterpolator; import android.view.animation.TranslateAnimation; import android.widget.ImageView; import android.widget.Toast; import java.io.FileReader; import java.util.ArrayList; import java.util.List; /** * Created by Administrator on 2018/7/29. */ public class wuziqipanel extends View { private int mpanelWidth; private float mLineHeight; private int MAX_LINE=10; private int MAX_COUNT_IN_COUNT=4; TranslateAnimation translateAnimation=null; private Paint mpaint=new Paint(); private Bitmap mwhitepiece; private Bitmap mbiackpiece; private float ratiopieceoflineheight=3*1.0f/4; // wuziqipanel wuziqi=new wuziqipanel(); // private ImageView greenImage = null; private boolean miswhite=true; private ArrayList<Point> mwhitearray=new ArrayList<>(); private ArrayList<Point> Mblackarray=new ArrayList<>(); private boolean misgameover; private boolean miswhitewinner; public wuziqipanel(Context context, AttributeSet attrs) { super(context, attrs); // setBackgroundColor(0x44ff0000); init(); } private void init() { mpaint.setColor(0x88000000); mpaint.setAntiAlias(true); mpaint.setDither(true); mpaint.setStyle(Paint.Style.STROKE); mwhitepiece= BitmapFactory.decodeResource(getResources(),R.drawable.stone_w2); mbiackpiece= BitmapFactory.decodeResource(getResources(),R.drawable.stone_b1); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { int widthSize=MeasureSpec.getSize(widthMeasureSpec); int widtfMode=MeasureSpec.getMode(widthMeasureSpec); int heightSize=MeasureSpec.getSize(heightMeasureSpec); int heightMode=MeasureSpec.getMode(heightMeasureSpec); int width=Math.min(widthSize,heightSize); if(widtfMode==MeasureSpec.UNSPECIFIED){ width=heightSize; }else if(heightMode==MeasureSpec.UNSPECIFIED){ width=widthSize; } setMeasuredDimension(width,width); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { super.onSizeChanged(w, h, oldw, oldh); mpanelWidth = w; mLineHeight=mpanelWidth*1.0f/MAX_LINE; int piecewidth=(int)(mLineHeight*ratiopieceoflineheight); mwhitepiece=Bitmap.createScaledBitmap(mwhitepiece,piecewidth,piecewidth,false); mbiackpiece=Bitmap.createScaledBitmap(mbiackpiece,piecewidth,piecewidth,false); } public void startani(int fir, int last, final Point point){ ValueAnimator animator = ValueAnimator.ofInt(fir,last); animator.setDuration((last-fir)*100); animator.setRepeatCount(0); // animator.setRepeatMode(ValueAnimator.r); animator.setInterpolator(new LinearInterpolator()); animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { int by = (int) animation.getAnimatedValue(); point.y=by; invalidate(); } }); animator.start(); } public boolean onTouchEvent(MotionEvent event) { if(misgameover){ return false; } int action=event.getAction(); if(action==MotionEvent.ACTION_UP){ float x=event.getX(); float y=event.getY(); Point p = getvalidpoint(x,y); if(Mblackarray.contains(p)||mwhitearray.contains(p))return false; int i; int n=p.x; int m=p.y; for ( i = p.y; i <=8 ; i++) { p.set(n,i); if(mwhitearray.contains(p)||Mblackarray.contains(p)){ break; }else{ p.y=i; } } p.y=i-1; if(miswhite){ mwhitearray.add(p); wuziqipanel.this.setClickable(false); startani(m,p.y,p); wuziqipanel.this.setClickable(true); miswhite=!miswhite; }else{ Mblackarray.add(p); wuziqipanel.this.setClickable(false); startani(m,p.y,p); wuziqipanel.this.setClickable(true); miswhite=!miswhite; } invalidate(); } return true; } private Point getvalidpoint(float x, float y) { return new Point((int)((x-mLineHeight/2)/mLineHeight),(int)(y/mLineHeight)); } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBoard(canvas); drawpieces(canvas); checkgameover(); } private void checkgameover() { boolean whitewin= checkfiveinline(mwhitearray); boolean blackwin= checkfiveinline(Mblackarray); if(whitewin||blackwin){ misgameover=true; miswhitewinner=whitewin; String text=miswhitewinner?"白棋胜利":"黑棋胜利"; Toast.makeText(getContext(),text,Toast.LENGTH_SHORT).show(); } } private boolean checkfiveinline(List<Point> points) { for(Point p:points){ int x=p.x; int y=p.y; boolean win= checkhorizontal(x,y,points); if(win)return true; win= checkvertical(x,y,points); if(win)return true; win= checkleftdiagonal(x,y,points); if(win)return true; win= checkrightdiagonal(x,y,points); if(win)return true; } return false; } //判断横向是否成五子 private boolean checkhorizontal(int x, int y, List<Point> points) { int count=1; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x-i,y))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x+i,y))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; return false; } private boolean checkvertical(int x, int y, List<Point> points) { int count=1; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x,y-i))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x,y+i))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; return false; } private boolean checkleftdiagonal(int x, int y, List<Point> points) { int count=1; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x-i,y+i))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x+i,y-i))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; return false; } private boolean checkrightdiagonal(int x, int y, List<Point> points) { int count=1; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x-i,y-i))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; for (int i = 1; i <MAX_COUNT_IN_COUNT ; i++) { if(points.contains(new Point(x+i,y+i))){ count++; }else{ break; } } if(count==MAX_COUNT_IN_COUNT)return true; return false; } private void drawpieces(Canvas canvas) { for (int i = 0,n=mwhitearray.size(); i <n ; i++) { Point whitepoint=mwhitearray.get(i); canvas.drawBitmap(mwhitepiece,(whitepoint.x+1-(ratiopieceoflineheight/2))*mLineHeight, (whitepoint.y+1-(ratiopieceoflineheight/2))*mLineHeight,null); } for (int i = 0,n=Mblackarray.size(); i <n ; i++) { Point blackpoint=Mblackarray.get(i); canvas.drawBitmap(mbiackpiece,(blackpoint.x+1-(ratiopieceoflineheight/2))*mLineHeight, (blackpoint.y+1-(ratiopieceoflineheight/2))*mLineHeight,null); } } private void drawBoard(Canvas canvas) { int w=mpanelWidth; float lineHeight=mLineHeight; for (int i = 0; i <MAX_LINE ; i++) { // int startx=(int)(lineHeight); // int end=(int)(w-lineHeight); int startx=(int)(lineHeight/2); int end=(int)(w-lineHeight/2); int y=(int)((0.5+i)*lineHeight); // 上三行代码使旗子下在中间 // int y=(int)(i*lineHeight); canvas.drawLine(startx,y,end,y,mpaint); canvas.drawLine(y,startx,y,end,mpaint); } } private static final String INSTANCE="instance"; private static final String INSTANCE_GAME_OVER="instance_game_over"; private static final String INSTANCE_WHITE_ARRAY="instance_white_array"; private static final String INSTANCE_BLACK_ARRAY="instance_black_array"; @Override protected Parcelable onSaveInstanceState() { Bundle bundle=new Bundle(); bundle.putParcelable(INSTANCE,super.onSaveInstanceState()); bundle.putBoolean(INSTANCE_GAME_OVER,misgameover); bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY,mwhitearray); bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY,Mblackarray); return bundle; } @Override protected void onRestoreInstanceState(Parcelable state) { if(state instanceof Bundle){ Bundle bundle=(Bundle)state; misgameover=bundle.getBoolean(INSTANCE_GAME_OVER); mwhitearray=bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY); Mblackarray=bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY); super.onRestoreInstanceState(bundle.getParcelable(INSTANCE)); return; } super.onRestoreInstanceState(state); } public void start(){ mwhitearray.clear(); Mblackarray.clear(); miswhitewinner=false; misgameover=false; invalidate(); } } layout:源码
<?xml version="1.0" encoding="utf-8"?> <RelativeLayout 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="@drawable/bg" tools:context="com.imooc.wuziqi.MainActivity"> <com.imooc.wuziqi.wuziqipanel android:id="@+id/id_wuziqi" android:layout_centerInParent="true" android:layout_width="match_parent" android:layout_height="match_parent" /> </RelativeLayout>
menu:源码:
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:context=".MainActivity"> <item android:title="再来一局" android:id="@+id/action_settings" android:orderInCategory="100" app:showAsAction="never"/> </menu>
存在的bug: 1.快速点击会使棋子下落受阻
2.胜负判定失误
原因:
1.动画未执行完就传入点击事件
2,y坐标未处理就传入判定方法。
githab源码地址