本文主要跟大家分享一下我在Android上寫的一個五子棋的小程序。首先說說我對Android的感覺,Android SDK雖然也使用Java,但跟Java ME有很多不同,Android SDK沒有實現所有的Java ME標准,原來運行在KJava上的應用程序是不能在Android上直接運行的,另外就是Android SDK有大量自己的API,需要Android開發人員去學習。
Android五子棋游戲簡介
這個五子棋游戲是我參照Android的Snake這個Demo還有別的例子,加上自己的需求寫出來的。其中實現了棋盤、下棋、判斷輸贏、重新開局等功能。目前暫時沒有實現機器智能走棋子的功能。
Android的觸屏功能是比較好用的,而且Android的“Window” 窗、"Shade"簾加上觸摸,顯得很炫。呃,這個五子棋,也是用觸摸屏實現走棋的。點一下棋盤的位子,把棋子落到棋盤上。
Android五子棋游戲界面
先貼個圖看看效果吧。
Android五子棋游戲的實現代碼
好了,下面直接貼代碼:
Java代碼
- /*
- * Five In a Row. (五子棋)
- * 這是一個簡單的五子棋程序,是我自己的一個練習,貼出來跟大家分享。
- * 希望跟大家一起多交流。 我的GoogleTalk: lixinso <at> gmail.com
- *
- *
- */
- //----------------------
- //TBD:AI,悔棋
- //---------------------
-
- package lixinsong.game.gobang;
-
- import android.app.Activity;
- import android.os.Bundle;
- import android.util.Log;
- import android.view.View;
- import android.widget.TextView;
- //這是主程序,繼承自Activity,實現onCreate方法。:
-
-
- public class gobang extends Activity {
- GobangView gbv;
-
- /** Called when the activity is first created. */
- @Override
- public void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- setContentView(R.layout.main);
-
-
- gbv = (GobangView)this.findViewById(R.id.gobangview);
- gbv.setTextView((TextView)this.findViewById(R.id.text));
-
- }
上面代碼中的R.id.gobangview是在res中定義的View:
XML/HTML代碼
- <?xml version="1.0" encoding="utf-8"?>
- <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent">
-
- <lixinsong.game.gobang.GobangView android:id="@+id/gobangview"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:text="aaaaa" tileSize="24" />
-
- <RelativeLayout
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true" >
-
- <TextView
- android:id="@+id/text"
- android:text="hahahhaha"
- android:visibility="visible"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_centerInParent="true"
- android:gravity="center_horizontal"
- android:textColor="#ffff0000"
- android:textStyle="bold"
- android:textSize="24sp" />
-
- </RelativeLayout>
-
- </FrameLayout>
Java代碼
- //五子棋的View
-
-
-
- package lixinsong.game.gobang;
-
- import android.content.Context;
- import android.content.res.Resources;
- import android.graphics.Bitmap;
- import android.graphics.Canvas;
- import android.graphics.Color;
- import android.graphics.Paint;
- import android.graphics.Paint.Style;
- import android.graphics.drawable.Drawable;
- import android.util.AttributeSet;
- import android.util.Log;
- import android.view.KeyEvent;
- import android.view.MotionEvent;
- import android.view.View;
- import android.widget.TextView;
-
- /*棋盤一共10×10格
- * 棋盤居中
- *
- *
- *
- */
- //public class GobangView extends View implements Runnable {
- public class GobangView extends View{
-
-
- protected static int GRID_SIZE = 10;
- protected static int GRID_WIDTH = 30; // 棋盤格的寬度
- protected static int CHESS_DIAMETER = 26; // 棋的直徑
- protected static int mStartX;// 棋盤定位的左上角X
- protected static int mStartY;// 棋盤定位的左上角Y
-
- private Bitmap[] mChessBW; // 黑棋和白棋
- private static int[][] mGridArray; // 網格
-
- boolean key = false;
-
- int wbflag = 1; //該下白棋了=2,該下黑棋了=1. 這裡先下黑棋(黑棋以後設置為機器自動下的棋子)
- int mLevel = 1; //游戲難度
- int mWinFlag = 0;
- private final int BLACK=1;
- private final int WHITE=2;
-
- int mGameState = GAMESTATE_RUN; //游戲階段:0=尚未游戲,1=正在進行游戲,2=游戲結束
- static final int GAMESTATE_PRE = 0;
- static final int GAMESTATE_RUN = 1;
- static final int GAMESTATE_PAUSE = 2;
- static final int GAMESTATE_END = 3;
-
- //private TextView mStatusTextView; // 根據游戲狀態設置顯示的文字
- public TextView mStatusTextView; // 根據游戲狀態設置顯示的文字
-
- private Bitmap btm1;
- private final Paint mPaint = new Paint();
-
- CharSequence mText;
- CharSequence STRING_WIN = "White win! /n Press Fire Key to start new game.";
- CharSequence STRING_LOSE = "Black win! /n Press Fire Key to start new game.";
- CharSequence STRING_EQUAL = "Cool! You are equal! /n Press Fire Key to start new Game.";
-
- public GobangView(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- public GobangView(Context context, AttributeSet attrs) { //好像調用的是這個構造函數,為什麼不是前面的呢
- super(context, attrs);
- this.setFocusable(true); //20090530
- this.setFocusableInTouchMode(true);
-
- init();
- }
-
-
- //這裡畫棋子後來沒有用圖片畫,而是直接畫了圓。因為我做的圖片不好看。
- // 初始化黑白棋的Bitmap
- public void init() {
- mGameState = 1; //設置游戲為開始狀態
- wbflag = BLACK; //初始為先下黑棋
- mWinFlag = 0; //清空輸贏標志。
- mGridArray = new int[GRID_SIZE-1][GRID_SIZE-1];
-
- mChessBW = new Bitmap[2];
-
- Bitmap bitmap = Bitmap.createBitmap(CHESS_DIAMETER, CHESS_DIAMETER, Bitmap.Config.ARGB_8888);
- Canvas canvas = new Canvas(bitmap);
- Resources r = this.getContext().getResources();
-
- Drawable tile = r.getDrawable(R.drawable.chess1);
- tile.setBounds(0, 0, CHESS_DIAMETER, CHESS_DIAMETER);
- tile.draw(canvas);
- mChessBW[0] = bitmap;
-
- tile = r.getDrawable(R.drawable.chess2);
- tile.setBounds(0, 0, CHESS_DIAMETER, CHESS_DIAMETER);
- tile.draw(canvas);
- mChessBW[1] = bitmap;
- }
-
-
- public void setTextView(TextView tv){
- mStatusTextView =tv;
- mStatusTextView.setVisibility(View.INVISIBLE);
- }
-
- @Override
- protected void onSizeChanged(int w, int h, int oldw, int oldh) {
- mStartX = w / 2 - GRID_SIZE * GRID_WIDTH / 2;
- mStartY = h / 2 - GRID_SIZE * GRID_WIDTH / 2;
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent event){
- switch (mGameState) {
- case GAMESTATE_PRE:
- break;
- case GAMESTATE_RUN: {
- int x;
- int y;
- float x0 = GRID_WIDTH - (event.getX() - mStartX) % GRID_WIDTH;
- float y0 = GRID_WIDTH - (event.getY() - mStartY) % GRID_WIDTH;
- if (x0 < GRID_WIDTH / 2) {
- x = (int) ((event.getX() - mStartX) / GRID_WIDTH);
- } else {
- x = (int) ((event.getX() - mStartX) / GRID_WIDTH) - 1;
- }
- if (y0 < GRID_WIDTH / 2) {
- y = (int) ((event.getY() - mStartY) / GRID_WIDTH);
- } else {
- y = (int) ((event.getY() - mStartY) / GRID_WIDTH) - 1;
- }
- if ((x >= 0 && x < GRID_SIZE - 1)
- && (y >= 0 && y < GRID_SIZE - 1)) {
- if (mGridArray[x][y] == 0) {
- if (wbflag == BLACK) {
- putChess(x, y, BLACK);
- //this.mGridArray[x][y] = 1;
- if(checkWin(BLACK)){ //如果是黑棋贏了
- mText = STRING_LOSE;
- mGameState = GAMESTATE_END;
- showTextView(mText);
- }else if(checkFull()){//如果棋盤滿了
- mText = STRING_EQUAL;
- mGameState = GAMESTATE_END;
- showTextView(mText);
- }
-
- wbflag = WHITE;
- } else if (wbflag == WHITE) {
- putChess(x, y, WHITE);
- //this.mGridArray[x][y] = 2;
- if(checkWin(WHITE)){
- mText = STRING_WIN;
- mGameState = GAMESTATE_END;
- showTextView(mText);
- }else if(checkFull()){//如果棋盤滿了
- mText = STRING_EQUAL;
- mGameState = GAMESTATE_END;
- showTextView(mText);
- }
- wbflag = BLACK;
- }
- }
- }
- }
-
- break;
- case GAMESTATE_PAUSE:
- break;
- case GAMESTATE_END:
- break;
- }
-
- this.invalidate();
- return true;
-
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent msg) {
- Log.e("KeyEvent.KEYCODE_DPAD_CENTER", " " + keyCode);
-
- if(keyCode == KeyEvent.KEYCODE_DPAD_CENTER){
- switch(mGameState){
- case GAMESTATE_PRE:
- break;
- case GAMESTATE_RUN:
- break;
- case GAMESTATE_PAUSE:
- break;
- case GAMESTATE_END:
- {//游戲結束後,按CENTER鍵繼續
-
- Log.e("Fire Key Pressed:::", "FIRE");
- mGameState = GAMESTATE_RUN;
- this.setVisibility(View.VISIBLE);
- this.mStatusTextView.setVisibility(View.INVISIBLE);
- this.init();
- this.invalidate();
-
-
- }
- break;
- }
- }
-
- return super.onKeyDown(keyCode, msg);
- }
-
- @Override
- public void onDraw(Canvas canvas) {
-
- canvas.drawColor(Color.YELLOW);
-
- // 畫棋盤
- {
- Paint paintRect = new Paint();
- paintRect.setColor(Color.GRAY);
- paintRect.setStrokeWidth(2);
- paintRect.setStyle(Style.STROKE);
-
- for (int i = 0; i < GRID_SIZE; i++) {
- for (int j = 0; j < GRID_SIZE; j++) {
- int mLeft = i * GRID_WIDTH + mStartX;
- int mTop = j * GRID_WIDTH + mStartY;
- int mRright = mLeft + GRID_WIDTH;
- int mBottom = mTop + GRID_WIDTH;
- canvas.drawRect(mLeft, mTop, mRright, mBottom, paintRect);
- }
- }
-
- //畫棋盤的外邊框
- paintRect.setStrokeWidth(4);
- canvas.drawRect(mStartX, mStartY, mStartX + GRID_WIDTH*GRID_SIZE, mStartY + GRID_WIDTH*GRID_SIZE, paintRect);
- }
-
- //畫棋子
-
- for (int i = 0; i < GRID_SIZE-1; i++) {
- for (int j = 0; j < GRID_SIZE-1; j++) {
- if(mGridArray[i][j] == BLACK){
- //通過圖片來畫
- //canvas.drawBitmap(mChessBW[0], mStartX + (i+1) * GRID_WIDTH - CHESS_DIAMETER/2 , mStartY + (j+1)* GRID_WIDTH - CHESS_DIAMETER/2 , mPaint);
-
- //通過圓形來畫
- {
- Paint paintCircle = new Paint();
- paintCircle.setColor(Color.BLACK);
- canvas.drawCircle(mStartX + (i+1) * GRID_WIDTH, mStartY + (j+1)* GRID_WIDTH, CHESS_DIAMETER/2, paintCircle);
- }
-
- }else if(mGridArray[i][j] == WHITE){
- //通過圖片來畫
- //canvas.drawBitmap(mChessBW[1], mStartX + (i+1) * GRID_WIDTH - CHESS_DIAMETER/2 , mStartY + (j+1)* GRID_WIDTH - CHESS_DIAMETER/2 , mPaint);
-
- //通過圓形來畫
- {
- Paint paintCircle = new Paint();
- paintCircle.setColor(Color.WHITE);
- canvas.drawCircle(mStartX + (i+1) * GRID_WIDTH, mStartY + (j+1)* GRID_WIDTH, CHESS_DIAMETER/2, paintCircle);
- }
- }
- }
- }
- }
-
- public void putChess(int x, int y, int blackwhite){
- mGridArray[x][y] = blackwhite;
- }
-
- public boolean checkWin(int wbflag){
- for(int i = 0; i < GRID_SIZE - 1 ; i++ ) //i表示列(根據寬度算出來的)
- for(int j = 0; j < GRID_SIZE - 1; j++){//i表示行(根據高度算出來的)
- //檢測橫軸五個相連
- if(((i+4) < (GRID_SIZE - 1))&&
- (mGridArray[i][j] == wbflag) && (mGridArray[i+1][j] == wbflag)&& (mGridArray[i + 2][j] == wbflag) && (mGridArray[i + 3][j] == wbflag) && (mGridArray[i + 4][j] == wbflag)){
- Log.e("check win or loss:", wbflag + "win");
-
- mWinFlag = wbflag;
- }
-
- //縱軸5個相連
- if(((j+4) < (GRID_SIZE - 1))&&
- (mGridArray[i][j] == wbflag) && (mGridArray[i][j+1] == wbflag)&& (mGridArray[i ][j+ 2] == wbflag) && (mGridArray[i ][j+ 3] == wbflag) && (mGridArray[i ][j+ 4] == wbflag)){
- Log.e("check win or loss:", wbflag + "win");
-
- mWinFlag = wbflag;
- }
-
- //左上到右下5個相連
- if(((j+4) < (GRID_SIZE - 1))&& ((i+4) < (GRID_SIZE - 1)) &&
- (mGridArray[i][j] == wbflag) && (mGridArray[i+1][j+1] == wbflag)&& (mGridArray[i + 2 ][j+ 2] == wbflag) && (mGridArray[i + 3][j+ 3] == wbflag) && (mGridArray[i + 4 ][j+ 4] == wbflag)){
- Log.e("check win or loss:", wbflag + "win");
-
- mWinFlag = wbflag;
- }
-
- //右上到左下5個相連
- if(((i-4) >= 0)&& ((j+4) < (GRID_SIZE - 1)) &&
- (mGridArray[i][j] == wbflag) && (mGridArray[i-1][j+1] == wbflag)&& (mGridArray[i - 2 ][j+ 2] == wbflag) && (mGridArray[i - 3][j+ 3] == wbflag) && (mGridArray[i - 4 ][j+ 4] == wbflag)){
- Log.e("check win or loss:", wbflag + "win");
-
- mWinFlag = wbflag;
- }
- }
-
- if( mWinFlag == wbflag){
- return true;
- }else
- return false;
-
-
- }
-
- public boolean checkFull(){
- int mNotEmpty = 0;
- for(int i = 0; i < GRID_SIZE -1; i ++)
- for(int j = 0; j < GRID_SIZE - 1; j ++){
- if(mGridArray[i][j] != 0) mNotEmpty +=1;
- }
-
- if(mNotEmpty == (GRID_SIZE-1)*(GRID_SIZE-1)) return true;
- else return false;
- }
-
- public void showTextView(CharSequence mT){
- this.mStatusTextView.setText(mT);
- mStatusTextView.setVisibility(View.VISIBLE);
-
- }
-
- }