android五子棋源代码,Android五子棋游戏源码详解
最近看了鴻洋大牛的五子棋教程,受益匪淺,講的非常好,關于五子棋的游戲原理非常清楚,并且學到了不少知識,在這里感謝鴻洋大神的分享。我覺得我的源碼注釋寫的非常清楚了,希望能給你帶來不少的收獲。
布局<?xml ?version="1.0"?encoding="utf-8"?>
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@mipmap/bg"
android:paddingTop="80dp"
android:orientation="vertical"
tools:context="com.yaodan.fivechessdemo.MainActivity">
android:id="@+id/custon_chess_main"
android:layout_width="match_parent"
android:layout_height="match_parent"?/>
android:id="@+id/bt_restart"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:text="再來一局"/>
自定義View的工具類package?com.yaodan.fivechessdemo.view;import?android.app.AlertDialog;import?android.content.Context;import?android.content.DialogInterface;import?android.graphics.Bitmap;import?android.graphics.BitmapFactory;import?android.graphics.Canvas;import?android.graphics.Color;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?com.yaodan.fivechessdemo.R;import?com.yaodan.fivechessdemo.contral.IsChessWin;import?java.util.ArrayList;/**
*?Created?by?swk?on?2016/12/5.
*/public?class?ChessView?extends?View?{????private?int?mPanelWith;?//棋盤的寬度(棋盤使方形的)
private?float?mLineHeigth;??//棋盤每一個空格的高度
private?int?MAX_LINE?=?10;????//棋盤的行數
private?Paint?mPint?=?new?Paint();????//創建畫筆
private?Bitmap?wPieces;?????//白棋
private?Bitmap?bPieces;?????//黑棋
private?ArrayList?wPoints?=?new?ArrayList<>();???//白棋坐標的集合
private?ArrayList?bPoints?=?new?ArrayList<>();???//黑棋坐標的集合
private?float?radioPoeces?=?1.0f?*?3?/?4;????//棋子與棋格的大小比例
private?boolean?mIsWitch?=?true;??//判斷是否白子畫在棋盤上
private?boolean?isGameOver?=?false;??//判讀是否游戲結束
private?Context?mContext;????private?IsChessWin?isChessWin;??//一個用來處理勝利與否的邏輯
private?String?TAG?=?"CHESSVIEW";????public?ChessView(Context?context)?{????????super(context);
mContext?=?context;
init();
}????public?ChessView(Context?context,?AttributeSet?attrs)?{????????super(context,?attrs);
mContext?=?context;
init();
}????public?ChessView(Context?context,?AttributeSet?attrs,?int?defStyleAttr)?{????????super(context,?attrs,?defStyleAttr);
mContext?=?context;
init();
}????/**
*?再來一局方法
*/
public?void?myreStart()?{
wPoints.clear();
bPoints.clear();
isGameOver?=?false;
Log.i(TAG,?"myreStart:?"?+?wPoints.size()?+?":::"?+?bPoints.size());
invalidate();
}????/**
*?初始化
*/
public?void?init()?{????????//設置畫筆的顏色
mPint.setColor(Color.BLACK);????????//設置抗鋸齒功能(圖像邊緣相對清晰一點,鋸齒痕跡不那么明顯)
mPint.setAntiAlias(true);????????//設置防抖動功能(使圖像更柔和一點)
mPint.setDither(true);????????//設置畫筆的風格為空心
mPint.setStyle(Paint.Style.STROKE);????????//獲取棋子的資源文件
wPieces?=?BitmapFactory.decodeResource(getResources(),?R.drawable.stone_w2);
bPieces?=?BitmapFactory.decodeResource(getResources(),?R.drawable.stone_b1);
}????@Override
protected?void?onMeasure(int?widthMeasureSpec,?int?heightMeasureSpec)?{????????super.onMeasure(widthMeasureSpec,?heightMeasureSpec);????????/**
*?獲取view的寬度和mode
*?mode分為:
*?EXACTLY:EXACTLY是精確尺寸,當我們將控件的layout_width或layout_height指定為具體數值時如andorid:layout_width="50dip",或者為FILL_PARENT是,都是控件大小已經確定的情況,都是精確尺寸。
*?AT_MOST:最大尺寸,當控件的layout_width或layout_height指定為WRAP_CONTENT時,控件大小一般隨著控件的子空間或內容進行變化,此時控件尺寸只要不超過父控件允許的最大尺寸即可。因此,此時的mode是AT_MOST,size給出了父控件允許的最大尺寸。
*?UNSPECIFIED:未指定尺寸,這種情況不多,一般都是父控件是AdapterView,通過measure方法傳入的模式
*/
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);????????//如果上方有一個是UNSPECIFIED,相對應的有一個尺寸是0,如果有一個是0,那么width就是0顯示不出來
if?(widthMode?==?MeasureSpec.UNSPECIFIED)?{
width?=?heightSize;
}?else?if?(heightMode?==?MeasureSpec.UNSPECIFIED)?{
width?=?widthSize;
}????????//設置實際的長和寬設置上去
setMeasuredDimension(width,?width);
}????/**
*?當view的尺寸改變時,會回掉這個方法
*
*?@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);
mPanelWith?=?w;
mLineHeigth?=?mPanelWith?*?1.0f?/?MAX_LINE;????????int?piecesWidth?=?(int)?(mLineHeigth?*?radioPoeces);????????//按照以前存在的位圖按照一定的比例構建一個新的位圖
wPieces?=?Bitmap.createScaledBitmap(wPieces,?piecesWidth,?piecesWidth,?true);
bPieces?=?Bitmap.createScaledBitmap(bPieces,?piecesWidth,?piecesWidth,?true);
}????/**
*?獲取坐標的集合
*
*?@param?event
*?@return
*/
@Override
public?boolean?onTouchEvent(MotionEvent?event)?{
isGameOver?=?isChessWin.isGameOverMethod(wPoints,?bPoints);????????if?(isGameOver)?{
showDialog();????????????return?false;
}????????int?action?=?event.getAction();????????if?(action?==?MotionEvent.ACTION_UP)?{????????????int?x?=?(int)?event.getX();????????????int?y?=?(int)?event.getY();
Point?point?=?getSimulatePoint(x,?y);????????????//如果黑棋的集合或者白棋的集合包含這個坐標,那么返回false
//contains和eequals比較的不是內存空間的地址,而是x,y值是否一致
if?(wPoints.contains(point)?||?bPoints.contains(point))?{????????????????return?false;
}????????????if?(mIsWitch)?{
wPoints.add(point);
}?else?{
bPoints.add(point);
}
mIsWitch?=?!mIsWitch;????????????//刷新View
invalidate();????????????return?true;
}????????return?true;
}????/**
*?根據真實的坐標模擬出絕對值坐標
*
*?@param?x
*?@param?y
*?@return
*/
public?Point?getSimulatePoint(int?x,?int?y)?{????????return?new?Point((int)?(x?/?mLineHeigth),?(int)?(y?/?mLineHeigth));
}????/**
*?顯示白棋或者黑棋獲勝的提示的對話框
*/
public?void?showDialog()?{
String?successText?=?isChessWin.isWhiteWinFlag()???"白棋獲勝!"?:?"黑棋獲勝!";????????new?AlertDialog.Builder(mContext)
.setMessage("恭喜"?+?successText?+?",是否再來一局?")
.setCancelable(false)
.setPositiveButton("確定",?new?DialogInterface.OnClickListener()?{????????????????????@Override
public?void?onClick(DialogInterface?dialogInterface,?int?i)?{
myreStart();
}
})
.setNegativeButton("取消",?new?DialogInterface.OnClickListener()?{????????????????????@Override
public?void?onClick(DialogInterface?dialogInterface,?int?i)?{
}
})
.show();
}????@Override
protected?void?onDraw(Canvas?canvas)?{????????super.onDraw(canvas);
drawBoard(canvas);
drawPieces(canvas);????????//下面的實例用來判斷是否勝利
isChessWin?=?new?IsChessWin(mContext);
isGameOver?=?isChessWin.isGameOverMethod(wPoints,?bPoints);????????//判斷是否結束游戲
if(isGameOver){
showDialog();
}
}????/**
*?畫棋盤的線
*
*?@param?canvas
*/
public?void?drawBoard(Canvas?canvas)?{????????int?w?=?mPanelWith;????????float?lineHeight?=?mLineHeigth;????????//畫十條線
for?(int?i?=?0;?i?
int?startX?=?(int)?(lineHeight?/?2);????????????//設置終點X橫坐標為寬度減去半個lineHeight(棋盤空格寬度)
int?endX?=?(int)?(w?-?lineHeight?/?2);????????????int?y?=?(int)?((0.5?+?i)?*?lineHeight);????????????//畫橫線
canvas.drawLine(startX,?y,?endX,?y,?mPint);????????????//畫縱線,坐標反過來
canvas.drawLine(y,?startX,?y,?endX,?mPint);
}
}????/**
*?畫棋子
*/
public?void?drawPieces(Canvas?canvas)?{
Log.i(TAG,?"drawPieces:?"?+?wPoints.size()?+?":::"?+?bPoints.size());????????for?(int?i?=?0;?i?
Point?point?=?wPoints.get(i);????????????//drawBitmap是將圖片的右下角為坐標
canvas.drawBitmap(wPieces,?((point.x?+?(1?-?radioPoeces)?/?2)?*?mLineHeigth),?(point.y?+?(1?-?radioPoeces)?/?2)?*?mLineHeigth,?null);
}????????for?(int?i?=?0;?i?
Point?point?=?bPoints.get(i);
canvas.drawBitmap(bPieces,?((point.x?+?(1?-?radioPoeces)?/?2)?*?mLineHeigth),?(point.y?+?(1?-?radioPoeces)?/?2)?*?mLineHeigth,?null);
}
}????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,?isGameOver);????????//保存白棋的子數
bundle.putParcelableArrayList(INSTANCE_WHITEARRAY,?wPoints);????????//保存黑棋的子數
bundle.putParcelableArrayList(INSTANCE_BLACKARRAY,?bPoints);????????return?bundle;
}????/**
*?取出保存的值
*
*?@param?state
*/
@Override
protected?void?onRestoreInstanceState(Parcelable?state)?{????????if?(state?instanceof?Bundle)?{
Bundle?bundle?=?(Bundle)?state;
isGameOver?=?bundle.getBoolean(INSTANCE_GAMEOVER);
wPoints?=?bundle.getParcelableArrayList(INSTANCE_WHITEARRAY);
bPoints?=?bundle.getParcelableArrayList(INSTANCE_BLACKARRAY);????????????super.onRestoreInstanceState(bundle.getParcelable(INSTANCE));????????????return;
}????????super.onRestoreInstanceState(state);
}
}
判斷是否勝利的類package?com.yaodan.fivechessdemo.contral;import?android.content.Context;import?android.graphics.Point;import?java.util.List;/**
*?Created?by?swk?on?2016/12/5.
*?判斷是否勝利類
*/public?class?IsChessWin?{????private?boolean?isGameOver?=?false;???//判斷是否游戲結束
private?boolean?isWhiteWin;?????//判斷是否白棋勝
private?int?MAX_NUMWIN?=?5;??//設置5子連在一起勝利
private?int?CURRENT_NUM?=?0;????private?Context?mContext;????private?boolean?isRestart=false;????public?IsChessWin(Context?context)?{????????super();
mContext?=?context;
}????/**
*?判斷是否勝利
*?@param?whitePoints
*?@param?blackPoints
*?@return
*/
public?boolean?isGameOverMethod(List?whitePoints,?List?blackPoints)?{????????boolean?whiteWin?=?isWhiteWin(whitePoints);????????boolean?blackWin?=?isBlackWin(blackPoints);????????if?(whiteWin?||?blackWin)?{
isGameOver?=?true;
isWhiteWin?=?whiteWin;
}????????return?isGameOver;
}????/**
*?返回是否白棋取勝
*?@return
*/
public?boolean?isWhiteWinFlag(){????????return?isWhiteWin;
}????/**
*?判斷是否白棋取勝
*?@param?points
*?@return
*/
private?boolean?isWhiteWin(List?points)?{????????if?(isFiveConnect(points))?{????????????return?true;
}????????return?false;
}????/**
*?判斷是否黑棋取勝
*?@param?points
*?@return
*/
private?boolean?isBlackWin(List?points)?{????????if?(isFiveConnect(points))?{????????????return?true;
}????????return?false;
}????/**
*?判斷是否五子連珠
*?@param?points
*?@return
*/
private?boolean?isFiveConnect(List?points)?{????????for?(Point?p?:?points)?{????????????int?x?=?p.x;????????????int?y?=?p.y;????????????if?(isHorizontalFive(x,?y,?points))?{????????????????return?true;
}?else?if?(isVerticalFive(x,?y,?points))?{????????????????return?true;
}?else?if?(isSkewFive(x,?y,?points))?{????????????????return?true;
}
}????????return?false;
}????/**
*?判斷是否橫向五子連珠
*?@param?x
*?@param?y
*?@param?points
*?@return
*/
private?boolean?isHorizontalFive(int?x,?int?y,?List?points)?{????????//判斷橫向向右是否練成5子,points里面存的值為int類型,所以可以進行加一或者減一的運算
for?(int?i?=?0;?i?
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if?(MAX_NUMWIN?==?CURRENT_NUM)?{????????????return?true;
}?else?{
CURRENT_NUM?=?0;
}????????//判斷橫向向左是否連成5子
for?(int?i?=?0;?i?
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if?(MAX_NUMWIN?==?CURRENT_NUM)?{????????????return?true;
}?else?{
CURRENT_NUM?=?0;
}????????return?false;
}????/**
*?判斷是否豎直五子連珠
*?@param?x
*?@param?y
*?@param?points
*?@return
*/
private?boolean?isVerticalFive(int?x,?int?y,?List?points)?{????????for?(int?i?=?0;?i?
if?(points.contains(new?Point(x,?y?+?i)))?{
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if?(MAX_NUMWIN?==?CURRENT_NUM)?{????????????return?true;
}?else?{
CURRENT_NUM?=?0;
}????????//判斷向上是否5子連珠
for?(int?i?=?0;?i?
CURRENT_NUM++;????????????????if?(5?==?CURRENT_NUM)?{????????????????????return?true;
}
}?else?{
CURRENT_NUM?=?0;????????????????break;
}
}????????if?(MAX_NUMWIN?==?CURRENT_NUM)?{????????????return?true;
}?else?{
CURRENT_NUM?=?0;
}????????return?false;
}????/**
*?判斷斜著是否五子連珠
*?@param?x
*?@param?y
*?@param?points
*?@return
*/
private?boolean?isSkewFive(int?x,?int?y,?List?points)?{????????//判斷左斜下是否5子連珠
for?(int?i?=?0;?i?
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if?(MAX_NUMWIN?==?CURRENT_NUM)?{????????????return?true;
}?else?{
CURRENT_NUM?=?0;
}????????//判斷左上是否5子連珠
for?(int?i?=?0;?i?
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if?(MAX_NUMWIN?==?CURRENT_NUM)?{????????????return?true;
}?else?{
CURRENT_NUM?=?0;
}????????//判斷右上是否5子連珠
for?(int?i?=?0;?i?
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if?(MAX_NUMWIN?==?CURRENT_NUM)?{????????????return?true;
}?else?{
CURRENT_NUM?=?0;
}????????//判斷右斜上是否5子連珠
for?(int?i?=?0;?i?
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if(MAX_NUMWIN==CURRENT_NUM){????????????return?true;
}else{
CURRENT_NUM=0;
}????????//判斷右斜下是否5子連珠
for?(int?i?=?0;?i?
CURRENT_NUM++;
}?else?{????????????????break;
}
}????????if(MAX_NUMWIN==CURRENT_NUM){????????????return?true;
}else{
CURRENT_NUM=0;
}????????return?false;
}
}
主方法的調用package?com.yaodan.fivechessdemo;import?android.support.v7.app.AppCompatActivity;import?android.os.Bundle;import?android.view.View;import?android.widget.Button;import?com.yaodan.fivechessdemo.view.ChessView;public?class?MainActivity?extends?AppCompatActivity?implements?View.OnClickListener?{????private?Button?btn_reatart;????private?ChessView?chessView;????@Override
protected?void?onCreate(Bundle?savedInstanceState)?{????????super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn_reatart?=?(Button)?findViewById(R.id.bt_restart);
chessView=?(ChessView)?findViewById(R.id.custon_chess_main);
btn_reatart.setOnClickListener(this);
}????@Override
public?void?onClick(View?view)?{????????switch?(view.getId())?{????????????case?R.id.bt_restart:
chessView.myreStart();????????????????break;
}
}
}
總結
以上是生活随笔為你收集整理的android五子棋源代码,Android五子棋游戏源码详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 模拟ic流片经验分享
- 下一篇: RK3399 Android7.1 充电