android自定义View 五子棋小游戏
来源:互联网 发布:java开源网 编辑:程序博客网 时间:2024/05/21 06:52
做一个五子棋练练手,没什么特别的,再复习一下自定义View的知识,onMeasure,MeasureSpec , onDraw以及OnTouchEvent方法等,
效果图
代码如下:
package com.fivechess;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.view.MotionEvent;import android.view.View;import android.widget.Toast;import java.util.ArrayList;import java.util.List;public class GamePanel 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(); //定义黑白棋子的Bitmap private Bitmap mWhitePiece ; private Bitmap mBlackPiece ; //棋子占一个棋格的比例,这里是3/4 private float ratioPieceOfLineHeight = 3 * 1.0f / 4 ; private boolean isWhite = false ; //存放已下过的棋子的数组 private ArrayList<Point> mWhiteArray = new ArrayList<>(); private ArrayList<Point> mBlackArray = new ArrayList<>(); //标识对局是否结束 private boolean isGameOver ; //判断白棋是否获胜 private boolean isWhiteWinner ; //构造方法 public GamePanel(Context context, AttributeSet attrs) { super(context, attrs); setBackgroundColor(0x80f8c866); init(); } //初始化画笔及Bitmap private void init() { mPaint.setColor(0x88000000); mPaint.setAntiAlias(true); mPaint.setDither(true); mPaint.setStyle(Paint.Style.STROKE); mWhitePiece = BitmapFactory.decodeResource(getResources() , R.drawable.white_chess) ; mBlackPiece = BitmapFactory.decodeResource(getResources() , R.drawable.black_chess) ; } //测量过程 @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); } @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 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 ){ isGameOver = true ; isWhiteWinner = whiteWin ; String text = isWhiteWinner ? "白棋胜利" : "黑棋胜利" ; 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 = checkLeftDown( x , y , points) ; if( win ) return true ; win = checkRightDown( x , y , points) ; if( win ) return true ; } return false; } /** * 判断x,y位置的棋子是否横向有相邻的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 ; } /** * 判断x,y位置的棋子是否垂直方向有相邻的5个一致 * @param x * @param y * @param points * @return */ 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 checkLeftDown(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 checkRightDown(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 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 ); } } @Override public boolean onTouchEvent(MotionEvent event) { if( isGameOver ) 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( isWhite ){ mWhiteArray.add(p); }else { mBlackArray.add(p); } invalidate(); isWhite = !isWhite ; } return true; } //获取点击的有效地址 private Point getValidPoint(int x, int y) { return new Point( (int )(x / mLineHeight) , (int ) (y / mLineHeight) ); } //再来一局 public void restart(){ mWhiteArray.clear(); mBlackArray.clear(); isGameOver = false ; isWhiteWinner = false ; invalidate(); }/* //定义常量 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 , isGameOver); bundle.putParcelableArray(INSTANCE_WHITE_ARRAY , mWhiteArray); bundle.putParcelableArray(INSTANCE_BLACK_ARRAY , mBlackArray); return bundle ; } //恢复棋局状态 @Override protected void onRestoreInstanceState(Parcelable state) { if( state instanceof Bundle ){ Bundle bundle = (Bundle) state; isGameOver = 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); }*/}
在布局文件中引入该View
<?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/activity_main" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.fivechess.MainActivity" android:background="@drawable/board_bg"> <com.fivechess.GamePanel android:id="@+id/game_panel" android:layout_width="match_parent" android:layout_height="match_parent" /> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="再来一局" android:layout_alignParentBottom="true"/></RelativeLayout>
MainActivity的代码
package com.fivechess;import android.support.v7.app.AppCompatActivity;import android.os.Bundle;import android.view.View;import android.widget.Button;public class MainActivity extends AppCompatActivity { private Button button ; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); button = (Button) findViewById(R.id.button); final GamePanel gamePanel = (GamePanel) findViewById(R.id.game_panel); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { gamePanel.restart(); } }); }}
阅读全文
0 0
- android自定义View 五子棋小游戏
- android自定义View之五子棋小游戏
- Android自定义View实现五子棋小游戏
- Android 开发 -------- 自定义View 画 五子棋
- Android之自定义view的五子棋游戏
- 自定义View之一五子棋
- android 自定义view实现推箱子小游戏。
- 自定义View实现五子棋游戏
- 自定义view(二)五子棋
- 五子棋--小游戏
- 小游戏-五子棋
- android 自定义五子棋
- Android 小游戏之五子棋 代码简单实现
- 自定义View+五子棋的简单实现
- 通过自定义view来做一个五子棋
- 弹球小游戏(自定义view应用)
- 介绍一款Android小游戏--交互式人机对战五子棋
- 介绍一款Android小游戏--交互式人机对战五子棋
- servlet 数据存储几种方式和jsp 作用域
- 又遇JAVA中文乱码“坑”
- 学习攻略 | Python数据挖掘学习路线图
- 根据 *_train_test.prototxt文件生成 *_deploy.prototxt文件
- mysql不能插入中文的问题
- android自定义View 五子棋小游戏
- window驱动开发
- 一篇通俗易懂的文章---关于Java中的Annotation
- 浅析地址解析协议ARP
- C语言入门第一篇,初识C语言
- Android BroadcastReceiver监听手机短信
- Tomcat——学习心得
- KL距离>=0的证明
- hf 主页布局