Android之自定义view的五子棋游戏

       哈喽,我又来了。

       前段时间看了慕课网上的一个小游戏,自己比较喜欢,然后就跟着写了一遍,感觉还不错,一直没来得及跟你们分享,今天整好有空就来跟你们聊聊。
我是用的studio写的,你们也可以用别的尝试尝试。来,上菜,呸,代码尴尬

一。这次先来看看自定义view中是怎么写的吧

public class wuziqi extends View {
  //游戏是否结束
 private boolean mIsGameOver;
    //当前是否是白子赢
   private boolean mIsWhiteWinner;

    private int mPanelWidth;
    private float mLineHeight;
    private int Max_LINE=10;
    private Paint mPaint =new Paint();

    private Bitmap mWhitePiece;
    private Bitmap mBlackPiece;
    //白棋先手,当前轮到白棋
    private boolean mIsWhite=true;
    private ArrayList<Point> mWhiteArray=new ArrayList<Point>();
    private ArrayList<Point> mBlackArray=new ArrayList<Point>();

    private float radioPieceOfLineHeight=3*1.0f/4;
    private int Max_Count_IN_LINE=5;

    public wuziqi(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    private void init() {
        mPaint.setColor(0x88000000);
        mPaint.setAntiAlias(true);
        mPaint.setDither(true);
        mPaint.setStyle(Paint.Style.STROKE);

        mWhitePiece= BitmapFactory.decodeResource(getResources(), R.drawable.baiqi);
        mBlackPiece=BitmapFactory.decodeResource(getResources(),R.drawable.heiqi);
    }

    @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);

        if(widthMode==MeasureSpec.UNSPECIFIED){
            width=heightSize;
        }else if(heightMode==MeasureSpec.UNSPECIFIED){
            width=widthSize;
        }
        setMeasuredDimension(width,width);
    }

    /**
     * 跟尺寸相关的要在onSizeChanged中编写
     * @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*radioPieceOfLineHeight);
        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_UP){

            int x= (int) event.getX();
            int y=(int) event.getY();
            Point p = getValidPoint(x,y);
            if(mWhiteArray.contains(p)||mBlackArray.contains(p)){
                return false;
            }
            if(mIsWhite){
                mWhiteArray.add(p);
            }else{
                mBlackArray.add(p);
            }
            invalidate();
            mIsWhite=!mIsWhite;
        }
        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);
        drawPiece(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_LONG).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=checkLeft(x,y,points);//是否是左斜
            if(win)return true;
            win=checkRight(x,y,points);//是否是右斜
            if(win)return true;

        }
        return false;
    }

    /**
     * 判断x,y位置的棋子,是否横向有相邻的五个一致。
     * @param x
     * @param y
     * @param points
     * @return
     */
    private boolean checkHorizontal(int x, int y, List<Point> points) {
        int count=1;
        //左
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x-j,y))){
                count++;
            }else{
                break;
            }
        }
        if(count==Max_Count_IN_LINE)return true;
        //右
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x+j,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;
        //上
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x,y-j))){
                count++;
            }else{
                break;
            }
        }
        if(count==Max_Count_IN_LINE)return true;
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x,y+j))){
                count++;
            }else{
                break;
            }
        }
        if(count==Max_Count_IN_LINE)return true;
        return false;
    }
    private boolean checkLeft(int x, int y, List<Point> points) {
        int count=1;
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x-j,y+j))){
                count++;
            }else{
                break;
            }
        }
        if(count==Max_Count_IN_LINE)return true;
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x+j,y-j))){
                count++;
            }else{
                break;
            }
        }
        if(count==Max_Count_IN_LINE)return true;
        return false;
    }
    private boolean checkRight(int x, int y, List<Point> points) {
        int count=1;
        //上
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x-j,y-j))){
                count++;
            }else{
                break;
            }
        }
        if(count==Max_Count_IN_LINE)return true;
        //下
        for (int j=1;j<Max_Count_IN_LINE;j++){
            if(points.contains(new Point(x+j,y+j))){
                count++;
            }else{
                break;
            }
        }
        if(count==Max_Count_IN_LINE)return true;
        return false;
    }
    private void drawPiece(Canvas canvas) {
        for (int i=0,n=mWhiteArray.size();i<n;i++){
            Point whitePoint=mWhiteArray.get(i);
            canvas.drawBitmap(mWhitePiece,
                    (whitePoint.x+(1-radioPieceOfLineHeight)/2)*mLineHeight,
                    (whitePoint.y+(1-radioPieceOfLineHeight)/2)*mLineHeight,null);
        }
        for (int i=0,n=mBlackArray.size();i<n;i++){
            Point blackPoint=mBlackArray.get(i);
            canvas.drawBitmap(mBlackPiece,
                    (blackPoint.x+(1-radioPieceOfLineHeight)/2)*mLineHeight,
                    (blackPoint.y+(1-radioPieceOfLineHeight)/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/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);
        }
    }
//重新开始游戏时的操作,在MainActivity中调用
 public void start(){
        mWhiteArray.clear();
        mBlackArray.clear();
        mIsGameOver=false;
        mIsWhiteWinner=false;
        invalidate();;
    }

    private static final String INSTANCE="instance";
    private static final String INSTANCE_GAMEOVER="instance_gameover";
    private static final String INSTANCE_WHITEARRAY="instance_whiteArray";
    private static final String INSTANCE_BLACKARRAY="instance_blackArray";

    /**
     * 存储view
     * @return
     */
    @Override
    protected Parcelable onSaveInstanceState() {
        Bundle bundle=new Bundle();

        bundle.putParcelable(INSTANCE,super.onSaveInstanceState());
        bundle.putBoolean(INSTANCE_GAMEOVER,mIsGameOver);
        bundle.putParcelableArrayList(INSTANCE_WHITEARRAY,mWhiteArray);
        bundle.putParcelableArrayList(INSTANCE_BLACKARRAY,mBlackArray);
        return bundle;
    }
    /**
     * 恢复view
     * @param state
     */
    @Override
    protected void onRestoreInstanceState(Parcelable state) {
        if(state instanceof Bundle){
            Bundle bundle= (Bundle) state;
            mIsGameOver=bundle.getBoolean(INSTANCE_GAMEOVER);
            mWhiteArray=bundle.getParcelableArrayList(INSTANCE_WHITEARRAY);
            mBlackArray=bundle.getParcelableArrayList(INSTANCE_BLACKARRAY);
            super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));
            return;
        }
        super.onRestoreInstanceState(state);
    }
}
二。上面的主要步骤写完,就已经快完成了,下面的代码就很简单了,在MainActivity中调用,找到自定义view的id就可以了。我也做了一些小的完善,如果你游戏结束了,就点击menu键。选择重新开始,再来一局。

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    int id=item.getItemId();
    if(id==R.id.action_settings){
        wuziqiPanel.start();
        return true;
    }
    return super.onOptionsItemSelected(item);
}
三。其实到这里,就全部完成了。xml中的代码相信你们都会,将view引用进来就可以了

<com.example.wuziqi.com.example.view.wuziqi
    android:id="@+id/wuziqi"
    android:layout_centerInParent="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
     />
好了,这就是整个游戏的完整代码。我自己玩了一会,挺好的,就是自己跟自己对弈,哈哈,有点无聊。

就这样了。^-^      ^-^       ^-^




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值