五子棋 手打稍加改变自慕课网hyman

来源:互联网 发布:微信加友软件免费下载 编辑:程序博客网 时间:2024/04/29 01:48

我整理了一下,顺便加了一点屏幕切换的代码,网速太不给力,好几次都坑了

直接上代码吧,稍后总结,简单粗暴,详情看题目
主程序:

package com.andy.andy.myapplication;import android.content.res.Configuration;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.util.Log;import android.view.Menu;import android.view.MenuItem;import android.view.View;import android.view.ViewGroup;import android.widget.Button;import android.widget.RelativeLayout;public class MainActivity extends ActionBarActivity {    Button button;    RelativeLayout layout;    WuziqiPannel wuziqiPannel;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        layout = (RelativeLayout) findViewById(R.id.layout);        button = (Button) findViewById(R.id.button);        wuziqiPannel = (WuziqiPannel) findViewById(R.id.wuziqi);        button.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                wuziqiPannel.start();            }        });        //  int orientationPortrait = Configuration.ORIENTATION_PORTRAIT;//1  竖着的        // layout.addView(button, lp);    }    /**     * 优点:我们可以随时监听屏幕旋转变化,并对应做出相应的操作;     * 缺点:它只能一次旋转90度,如果一下子旋转180度,onConfigurationChanged函数不会被调用。     *     * @param newConfig     */    @Override    public void onConfigurationChanged(Configuration newConfig) {        super.onConfigurationChanged(newConfig);        RelativeLayout.LayoutParams lp = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);        Log.e("lc---", "onConfigurationChanged");        // int isVer = getResources().getConfiguration().orientation;        if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {            // lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM, R.id.button);            lp.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);            // button.setLayoutParams(new RelativeLayout.LayoutParams());        } else if (newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE) {            //  lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, R.id.button);//            lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT, R.id.button);            lp.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);            //  button.setLayoutParams(lp);//好用        }        button.setLayoutParams(lp);    }}

自定义控件WuziqiPannel.java

package com.andy.andy.myapplication;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.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.view.View;import android.widget.Toast;import java.util.ArrayList;import java.util.List;/** * Created by andy on 2016/6/12. */public class WuziqiPannel extends View {    private int mPanelWidth;    private float mLineHeight;//行高  为何是float?精度,屏幕的宽 通常计算出来通常不是整数    private int MAX_LINE = 10;//尺寸相关,在哪里初始化呢  onsizechange()    private Paint mPaint = new Paint();    private Bitmap mWhitePiece;    private Bitmap mBlackPiece;    private float ratioPieceOfLineHeight = 3 * 1.0f / 4;    //白起先手 还是轮到白起?    private boolean mIsWhite = true;//    private List<Point> mWhiteArray = new ArrayList<Point>();//    private List<Point> mBlackArray = new ArrayList<Point>();    private ArrayList<Point> mWhiteArray = new ArrayList<Point>();    private ArrayList<Point> mBlackArray = new ArrayList<Point>();    private boolean mIsGameOver;    private boolean mIsWhiteWinner;    private  int MAX_COUNT_IN_LINE = 5;    public WuziqiPannel(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.bai);//从 资源文件中 取图片        mBlackPiece = BitmapFactory.decodeResource(getResources(), R.drawable.hei);    }    /*    首先 view 的测量     */    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        int widthSize = MeasureSpec.getSize(widthMeasureSpec);        int widthMode = MeasureSpec.getMode(widthMeasureSpec);        int heightSize = MeasureSpec.getSize(heightMeasureSpec);        int heightMode = MeasureSpec.getMode(heightMeasureSpec);        int width = Math.min(widthSize, heightSize);        /*        这个判断主要解决 自定义view 嵌套在scrollview 中时,获取不到宽高,或者宽高为0 的情况的处理         */        if (widthMode == MeasureSpec.UNSPECIFIED) {            width = heightSize;        } else if (heightMode == MeasureSpec.UNSPECIFIED) {            width = widthSize;        }        setMeasuredDimension(width, width);//一个正方形的框    }    /**     * 和尺寸相关的 初始化都写在这个地方     *     * @param w     * @param h     * @param oldw     * @param oldh     */    @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);        mBlackPiece = Bitmap.createScaledBitmap(mBlackPiece, pieceWidth, pieceWidth, false);    }    @Override    public boolean onTouchEvent(MotionEvent event) {        if (mIsGameOver){            return false;        }        int action = event.getAction();        if (action == MotionEvent.ACTION_DOWN) {            return true;        }        if (action == MotionEvent.ACTION_UP) {            int x = (int) event.getX();            int y = (int) event.getY();            // Point p = new Point(x,y);// 一个合法的区域            Point p = getValidPoint(x, y);            if (mWhiteArray.contains(p) || mBlackArray.contains(p)) {                return false;///?????---------o 不处理这个事件,不添加,不显示子            }            if (mIsWhite) {                mWhiteArray.add(p);            } else {                mBlackArray.add(p);            }            invalidate();            mIsWhite = !mIsWhite;            //  return true;//ACTION_DOWN一定要标明自己的态度,自己对这个事件感兴趣        }        return true;    }    private Point getValidPoint(int x, int y) {        return new Point((int) (x / 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;    }    /**     * 判断 横向 是否 5 个相连  每次只对当前落子的位置进行 判断,还不是很耗时     * @param x     * @param y     * @param points     * @return     */    private boolean checkHorizontal(int x, int y, List<Point> points) {        int count = 1;        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x-i,y))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x+i,y))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        return false;    }    private boolean checkVertical(int x, int y, List<Point> points) {        int count = 1;        //shang xia        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x,y-i))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x,y+i))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        return false;    }    private boolean checkLeftDiagonal(int x, int y, List<Point> points) {        int count = 1;        //shang xia        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x-i,y-i))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x+i,y+i))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        return false;    }    private boolean checkRightDiagonal(int x, int y, List<Point> points) {        int count = 1;        //shang xia        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x-i,y+i))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        for (int i = 1;i <MAX_COUNT_IN_LINE ;i++){            if (points.contains(new Point(x+i,y-i))){                count++;            }else {                break;            }        }        if (count ==MAX_COUNT_IN_LINE)return true;        return false;    }    /**     * 绘制棋子   测试 要减2 不知道是 什么鬼 gety  和 getRawy.     *     * @param canvas     */    private void drawPieces(Canvas canvas) {        for (int i = 0, n = mWhiteArray.size(); i < n; i++) {            Point whitePoint = mWhiteArray.get(i);            Log.e("lc---",(whitePoint.y)+"");            canvas.drawBitmap(mWhitePiece,                    (whitePoint.x + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight,                    (whitePoint.y  + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight, null);//// TODO: 2016/6/13  -2        }        for (int i = 0, n = mBlackArray.size(); i < n; i++) {            Point blackPoint = mBlackArray.get(i);            canvas.drawBitmap(mBlackPiece, (blackPoint.x + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight, (blackPoint.y  + (1 - ratioPieceOfLineHeight) / 2) * mLineHeight, null);        }    }    private void drawBoard(Canvas canvas) {        //上下各有 半个的 lineheight        int w = mPanelWidth;        float lineHeight = mLineHeight;        for (int i = 0; i < MAX_LINE; i++) {            int startX = (int) lineHeight / 2;            int endX = (int) (w - lineHeight / 2);            int y = (int) ((0.5 + i) * lineHeight);            canvas.drawLine(startX, y, endX, y, mPaint);//横线            canvas.drawLine(y, startX, y, endX, 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_BLACK_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));//// TODO: 2016/6/15 和 下边这句 super 不重复吗            return;        }        super.onRestoreInstanceState(state);//---    }    public void start(){        mWhiteArray.clear();        mBlackArray.clear();        mIsGameOver = false;        mIsWhiteWinner = false;        invalidate();    }}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.andy.andy.myapplication" >    <application        android:allowBackup="true"        android:icon="@mipmap/ic_launcher"        android:label="@string/app_name"        android:supportsRtl="true"        android:theme="@style/AppTheme" >        <activity            android:name=".MainActivity"            android:configChanges="keyboardHidden|orientation|screenSize"            android:label="@string/app_name" >            <intent-filter>                <action android:name="android.intent.action.MAIN" />                <category android:name="android.intent.category.LAUNCHER" />            </intent-filter>        </activity>    </application></manifest>

资源文件,drawable-hdpi
白子
黑子
棋盘背景

activity_main.xml 布局文件

<?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:id="@+id/layout"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:background="@drawable/backg"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    tools:context=".MainActivity">    <!--加上id才能保存状态信息-->    <com.andy.andy.myapplication.WuziqiPannel        android:id="@+id/wuziqi"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:text="Hello World!" />    <Button        android:id="@+id/button"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:layout_alignParentRight="true"        android:text="重开一局" /></RelativeLayout>

好了没有什么遗漏了.

总结下 自定义view的 步骤 思路:

  1. 编写xml布局
  2. 初始化测量 onMeasure 方法, onSizeChange()方法–初始化尺寸,
  3. 初始化 棋盘
  4. onTouch时间处理 down 的时候返回ture,表示我对这个触摸事件感兴趣,我要处理
  5. 绘制旗子 –
  6. 逻辑判断.三点 1 gameover 和 一个位置不可重复放子.2 在某个范围内 都下在 网格中心点上
  7. view的存储and恢复
  8. 再来一局
  9. 其他 屏幕尺寸改变需要注意的事项

备注: 自定义view的思路完全是自上而下的

0 0