android自定义View实现简单五子棋游戏
短信预约 -IT技能 免费直播动态提醒
做一个五子棋练练手,没什么特别的,再复习一下自定义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;
}
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 ;
//判断上边
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();
}
}
在布局文件中引入该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();
}
});
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持编程网。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341