安卓开发之五子棋

昨天心血来潮做了一个手机移动小游戏–五子棋,现在过来做个技术总结。
开发工具 Android studio
首先在网络上下载一些自己喜欢的图片(后面会用到布局背景,棋子背景上面)
第一步,创建一个android项目,里面xml文件代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:background="@drawable/bg"
    tools:context="com.dahuijii.liziguo.wuziqi.MainA_wuziqictivity">

    <com.dahuijii.liziguo.wuziqi.wuziqiPanel
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        />

</LinearLayout>

其中主程序wuziqi.Java文件不做任何修改
新创建的wuziqiPane.Java文件程序如下

package com.dahuijii.liziguo.wuziqi;

import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Point;
import android.support.annotation.Nullable;
import android.util.AttributeSet;
import android.util.Size;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;
public class wuziqiPanel extends View {
    private int mPanelWidth;
    private float mLineHeight;
    private int MAX_LINE=10;
    private int MAX_COUNT_IN_LINE=5;
    private Paint mPaint=new Paint();
    private Bitmap mBlackPiece;
    private Bitmap mWhitePiece;
    private float ratioPieceofLineHeight=3*1.0f/4;
    private boolean mIsWhite=true;
    private List<Point> mWhiteArray=new ArrayList<>();
    private List<Point> mBlackArray=new ArrayList<>();
    private boolean mIsGameOver;
    private boolean mIsWhiteWinner;

    public wuziqiPanel(Context context, @Nullable 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);
        mBlackPiece= BitmapFactory.decodeResource(getResources(), R.drawable.stone_b2);
    }
 @Override   //测量的方法
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    {
        int widthSize=MeasureSpec.getSize(widthMeasureSpec);
        int widthMode=MeasureSpec.getMode(widthMeasureSpec);

        int heightSize=MeasureSpec.getSize(widthMeasureSpec);
        int heightMode=MeasureSpec.getMode(widthMeasureSpec);

        int width=Math.min(widthSize,heightSize);

        if (widthMode==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);
        mBlackPiece=Bitmap.createScaledBitmap(mBlackPiece,pieceWidth,pieceWidth,false);

    }

    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));
    }
    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=checkRightDiagnoal(x,y,points);
            if(win) return true;

        }
        return false;
    }

    private boolean checkRightDiagnoal(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+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 checkLeftDiagonal(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+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 checkVertical(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,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 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 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(mBlackPiece,
                    (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/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);
        }
    }

}

测试中出现的问题:
真机运行老是出现闪退现象:后面发现这是因为图片资源放错位置导致,在drawable文件夹中放的文件有时候会默认存储为xx.png(v-24),这时候就要重新放置文件,确保不是放在隐藏文件夹drawable-v24下。
项目运行文件冲突问题:我一方面建了一个项目运行这个程序,另一方面我在module组件下也建立了这样一个程序。导致程序运行时会发生不必要的冲突。

最后我做的五子棋demo如下展示:

12

  • 3
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,下面是一个简单的Android五子棋小游戏的开发流程: 1. 创建一个Android项目并添加必要的依赖库和资源文件。 2. 创建主界面布局,包括棋盘和游戏控制按钮等元素。 3. 实现棋盘的绘制,包括棋盘线条和棋子的绘制。 4. 实现游戏逻辑,包括判断胜负、切换玩家等功能。 5. 实现游戏控制按钮的响应事件,包括重新开始游戏和悔棋等功能。 6. 测试并调试游戏,确保游戏可以正常运行。 以下是一个简单的代码示例: 1. 创建主界面布局: ``` <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent"> <com.example.gobang.GameView android:id="@+id/game_view" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:id="@+id/btn_restart" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="重新开始" android:layout_alignParentBottom="true" android:layout_centerHorizontal="true" android:layout_marginBottom="20dp" /> <Button android:id="@+id/btn_undo" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="悔棋" android:layout_alignParentBottom="true" android:layout_toLeftOf="@id/btn_restart" android:layout_marginBottom="20dp" /> </RelativeLayout> ``` 2. 创建GameView类,实现棋盘的绘制和游戏逻辑: ``` public class GameView extends View { private static final int BOARD_SIZE = 15; private static final int PIECE_SIZE = 40; private Paint mPaint; private int[][] mBoard; private boolean mIsBlackTurn; public GameView(Context context, AttributeSet attrs) { super(context, attrs); init(); } private void init() { mPaint = new Paint(); mBoard = new int[BOARD_SIZE][BOARD_SIZE]; mIsBlackTurn = true; } @Override protected void onDraw(Canvas canvas) { super.onDraw(canvas); drawBoard(canvas); drawPieces(canvas); } private void drawBoard(Canvas canvas) { mPaint.setColor(Color.BLACK); mPaint.setStrokeWidth(2); for (int i = 0; i < BOARD_SIZE; i++) { canvas.drawLine(PIECE_SIZE / 2, PIECE_SIZE / 2 + i * PIECE_SIZE, PIECE_SIZE / 2 + (BOARD_SIZE - 1) * PIECE_SIZE, PIECE_SIZE / 2 + i * PIECE_SIZE, mPaint); canvas.drawLine(PIECE_SIZE / 2 + i * PIECE_SIZE, PIECE_SIZE / 2, PIECE_SIZE / 2 + i * PIECE_SIZE, PIECE_SIZE / 2 + (BOARD_SIZE - 1) * PIECE_SIZE, mPaint); } } private void drawPieces(Canvas canvas) { for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (mBoard[i][j] == 1) { mPaint.setColor(Color.BLACK); canvas.drawCircle(PIECE_SIZE / 2 + i * PIECE_SIZE, PIECE_SIZE / 2 + j * PIECE_SIZE, PIECE_SIZE / 2, mPaint); } else if (mBoard[i][j] == 2) { mPaint.setColor(Color.WHITE); canvas.drawCircle(PIECE_SIZE / 2 + i * PIECE_SIZE, PIECE_SIZE / 2 + j * PIECE_SIZE, PIECE_SIZE / 2, mPaint); } } } } @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { int x = (int) event.getX(); int y = (int) event.getY(); int i = x / PIECE_SIZE; int j = y / PIECE_SIZE; if (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE && mBoard[i][j] == 0) { mBoard[i][j] = mIsBlackTurn ? 1 : 2; mIsBlackTurn = !mIsBlackTurn; invalidate(); } } return true; } public void restart() { for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { mBoard[i][j] = 0; } } mIsBlackTurn = true; invalidate(); } public void undo() { for (int i = BOARD_SIZE - 1; i >= 0; i--) { for (int j = BOARD_SIZE - 1; j >= 0; j--) { if (mBoard[i][j] != 0) { mBoard[i][j] = 0; mIsBlackTurn = !mIsBlackTurn; invalidate(); return; } } } } public boolean isGameOver() { return checkWin() || isBoardFull(); } private boolean checkWin() { int[][] directions = {{0, 1}, {1, 0}, {1, 1}, {-1, 1}}; for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (mBoard[i][j] != 0) { for (int[] direction : directions) { int count = 1; int x = i; int y = j; while (count < 5) { x += direction[0]; y += direction[1]; if (x < 0 || x >= BOARD_SIZE || y < 0 || y >= BOARD_SIZE || mBoard[x][y] != mBoard[i][j]) { break; } count++; } if (count == 5) { return true; } } } } } return false; } private boolean isBoardFull() { for (int i = 0; i < BOARD_SIZE; i++) { for (int j = 0; j < BOARD_SIZE; j++) { if (mBoard[i][j] == 0) { return false; } } } return true; } } ``` 3. 在MainActivity中设置按钮的响应事件: ``` public class MainActivity extends AppCompatActivity implements View.OnClickListener { private GameView mGameView; private Button mBtnRestart; private Button mBtnUndo; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mGameView = findViewById(R.id.game_view); mBtnRestart = findViewById(R.id.btn_restart); mBtnUndo = findViewById(R.id.btn_undo); mBtnRestart.setOnClickListener(this); mBtnUndo.setOnClickListener(this); } @Override public void onClick(View v) { switch (v.getId()) { case R.id.btn_restart: mGameView.restart(); break; case R.id.btn_undo: mGameView.undo(); break; } } } ``` 这样,一个简单的Android五子棋小游戏就开发完成了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值