Android實訓(xùn)案例(八)——單機五子棋游戲,自定義棋盤,線條,棋子,游戲邏輯,游戲狀態(tài)存儲,再來一局_第1頁
Android實訓(xùn)案例(八)——單機五子棋游戲,自定義棋盤,線條,棋子,游戲邏輯,游戲狀態(tài)存儲,再來一局_第2頁
Android實訓(xùn)案例(八)——單機五子棋游戲,自定義棋盤,線條,棋子,游戲邏輯,游戲狀態(tài)存儲,再來一局_第3頁
Android實訓(xùn)案例(八)——單機五子棋游戲,自定義棋盤,線條,棋子,游戲邏輯,游戲狀態(tài)存儲,再來一局_第4頁
Android實訓(xùn)案例(八)——單機五子棋游戲,自定義棋盤,線條,棋子,游戲邏輯,游戲狀態(tài)存儲,再來一局_第5頁
已閱讀5頁,還剩14頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Android實訓(xùn)案例(八)單機五子棋游戲,自定義棋盤,線條,棋子,游戲邏輯,游戲狀態(tài)存儲,再來一局一.棋盤我們一看就知道,我們必須自定義View,這里我們定義一個GameView來做游戲主類,第一步,先測量,我們這里不難知道,五子棋他的棋盤是一個正方形,所以我們需要去測量 /* * 測量 * * param widthMeasureSpec * param heightMeasureSpec */ Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) /獲取高寬值 int widthSiz

2、e = MeasureSpec.getSize(widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int hightSize = MeasureSpec.getSize(heightMeasureSpec); int hightMode = MeasureSpec.getMode(heightMeasureSpec); /拿到寬和高的最小值,也就是寬 int width = Math.min(widthSize, heightMeasureSpec); /根據(jù)測量模式細(xì)節(jié)處理 if (widthM

3、ode = MeasureSpec.UNSPECIFIED) width = hightSize; else if (hightMode = MeasureSpec.UNSPECIFIED) width = widthSize; /設(shè)置這樣就是一個正方形了 setMeasuredDimension(width, width); 這里的邏輯還是十分簡單的,我們拿到長和寬去比較一下,設(shè)置這個View的長寬Wie最小值,就是一個正方形了,所以我們的layout_main.xml是這樣寫的<?xml version="1.0" encoding="utf-8&quo

4、t;?><LinearLayout xmlns:android=" xmlns:tools=" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:background="drawable/main_bg" > <com.lgl.fiverow.GameView android:layout_width

5、="match_parent" android:layout_height="match_parent" /></LinearLayout>這里我在構(gòu)造方法中設(shè)置了一個半透明的紅色背景,是在我們調(diào)試的時候可以更加清晰的看清楚GameView的大小,所以,運行的結(jié)果二.線條這個應(yīng)該也算是棋盤的一部分吧,就是棋盤上的線條,我們應(yīng)該怎么去畫,首先,我們要去定義一些屬性 /線條數(shù)量 private static final int MAX_LINE = 10; /線條的寬度 private int mPanelWidth; /線條的高度 pri

6、vate float mLineHeight;然后,我們要去確定大小/* * 測量大小 * * 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); /拿到寬 mPanelWidth = w; /分割 mLineHeight = mPanelWidth * 1.0f / MAX_LINE; 不要著急,這些都只是一些準(zhǔn)備的工作,我們畫線條

7、是必須要在onDraw(0方法里的,但是前期我們要準(zhǔn)備一只畫筆,對吧,所以我們要初始化畫筆 /* * 初始化畫筆 */ private void initPaint() /設(shè)置顏色 mPaint.setColor(0x88000000); /抗鋸齒 mPaint.setAntiAlias(true); /設(shè)置防抖動 mPaint.setDither(true); /設(shè)置Style mPaint.setStyle(Paint.Style.STROKE); 現(xiàn)在我們可以去繪制了,我們在OnDraw(0方法里寫一個drawLine方法來專門繪制線條 /* * 繪制棋盤的方法 * * param ca

8、nvas */ private void drawLine(Canvas canvas) /獲取高寬 int w = mPanelWidth; float lineHeight = mLineHeight; /遍歷,繪制線條 for (int i = 0; i < MAX_LINE; i+) /橫坐標(biāo) int startX = (int) (lineHeight / 2); int endX = (int) (w - lineHeight / 2); /縱坐標(biāo) int y = (int) (0.5 + i) * lineHeight); /繪制橫 canvas.drawLine(star

9、tX, y, endX, y, mPaint); /繪制縱 canvas.drawLine(y, startX, y, endX, mPaint); 我們運行一下好的,這里,注意一下,我在activity_main.xml中定義了一個android:gravity="center"屬性,所以讓他居中,同樣的,我們在initPaint中加上點代碼讓我們看的更加直觀一點/設(shè)置顏色mPaint.setColor(Color.BLACK);/設(shè)置線條寬度mPaint.setStrokeWidth(3);同樣的,我們把構(gòu)造法里的設(shè)置背景的測試代碼注釋掉/測試代碼/setBackgro

10、undColor(0x44ff0000);這樣,我們運行一下得,我們現(xiàn)在有模有樣了三.棋子棋子我們事先準(zhǔn)備好了兩張圖片,但是這里我們要考慮他的大小的問題了,我們的思路是讓他是行高的四分之三大小,所以先聲明 /黑棋子 private Bitmap mBlack; /白棋子 private Bitmap mWhite;/比例,棋子的大小是高的四分之三 private float rowSize = 3 * 1.0f / 4;然后我們定義一個方法區(qū)初始化Bitmap /* * 初始化棋子 */ private void initBitmap() /拿到圖片資源 mBlack = BitmapFact

11、ory.decodeResource(getResources(), R.drawable.stone_black); mWhite = BitmapFactory.decodeResource(getResources(), R.drawable.stone_white); 拿到資源之后我們就可以設(shè)置大小了,我們在onSizeChanged()里面設(shè)置 /棋子寬度 int mWhiteWidth = (int) (mLineHeight * rowSize); /修改棋子大小 mWhite = Bitmap.createScaledBitmap(mWhite, mWhiteWidth, mW

12、hiteWidth, false); mBlack = Bitmap.createScaledBitmap(mBlack, mWhiteWidth, mWhiteWidth, false);不過棋子可沒我們想象的那么簡單,我們要點擊一下再去繪制一個棋子,這樣的思路該怎么去實現(xiàn)呢?我們實現(xiàn)它的點擊事件,這里先定義幾個變量 /存儲用戶點擊的坐標(biāo) private List<Point> mWhiteArray = new ArrayList<>(); private List<Point> mBlackArray = new ArrayList<>()

13、; /標(biāo)記,是執(zhí)黑子還是白子 ,白棋先手 private boolean mIsWhite = true;這樣才和觸摸事件相得映彰 /* * 觸摸事件 * * param event * return */ Override public boolean onTouchEvent(MotionEvent event) switch (event.getAction() /按下事件 case MotionEvent.ACTION_UP: int x = (int) event.getX(); int y = (int) event.getY(); /封裝成一個Point Point p = ge

14、tValidPoint(x, y); /判斷當(dāng)前這個點是否有棋子了 if(mWhiteArray.contains(p) | mBlackArray.contains(p) /點擊不生效 return false; /判斷如果是白子就存白棋集合,反之則黑棋集合 if (mIsWhite) mWhiteArray.add(p); else mBlackArray.add(p); /刷新 invalidate(); /改變值 mIsWhite = !mIsWhite; break; return true;這樣,有幾點是要說明一下的,首先我們new Point的時候為了避免重復(fù)繪制我們是實現(xiàn)了一個

15、方法/* * 不能重復(fù)點擊 * * param x * param y * return */ private Point getValidPoint(int x, int y) return new Point(int) (x / mLineHeight), (int) (y / mLineHeight); 緊接著我們就判斷,要是重復(fù)點擊,返回false,而且我們在action選擇也是選擇了ACTION_UP,為什么?為什么不是ACTION_DOWN?因為這個畢竟是一個View,父View會攔截(某些場景),所以我們選在UP上才是合情合理的好的,當(dāng)我們點擊之后就要繪制棋子了,這里我們也寫一個

16、方法 /* * 繪制棋子的方法 * * param canvas */ private void drawPieces(Canvas canvas) for (int i = 0; i < mWhiteArray.size(); i+) /獲取白棋子的坐標(biāo) Point whitePoint = mWhiteArray.get(i); canvas.drawBitmap(mBlack, (whitePoint.x + (1 - rowSize) / 2) * mLineHeight, (whitePoint.y + (1 - rowSize) / 2) * mLineHeight, nul

17、l); for (int i = 0; i < mBlackArray.size(); i+) /獲取黑棋子的坐標(biāo) Point blackPoint = mBlackArray.get(i); canvas.drawBitmap(mWhite, (blackPoint.x + (1 - rowSize) / 2) * mLineHeight, (blackPoint.y + (1 - rowSize) / 2) * mLineHeight, null); OK,我們實際運行一下四.游戲邏輯現(xiàn)在什么都有了,基本上都可用玩了,但是還少了重要的一點就是游戲結(jié)束,你到了五顆也需要判斷是否勝利呀,

18、對吧,我們寫一個方法,在每次繪制完成之后就去判斷是否有贏家 /* * 判斷是否勝利 */ private void checkWin() /判斷白棋是否有五個相同的棋子相連 boolean mWhiteWin = checkFiveLine(mWhiteArray); /判斷黑棋是否有五個相同的棋子相連 boolean mBlackWin = checkFiveLine(mBlackArray); /只要有一個勝利,游戲就結(jié)束 if (mWhiteWin | mBlackWin) mIsGameOver = true; mIsWhiteWin = mWhiteWin; Toast.makeTe

19、xt(getContext(), mIsWhiteWin ? "白棋勝利" : "黑棋勝利", Toast.LENGTH_SHORT).show(); 好的,我們重點邏輯就在checkFiveLine這個方法上了,這里,我們所知道的勝利有四種情況我們先定義一個常量 /勝利棋子數(shù)量 private static final int MAX_COUNT_IN_LINE = 5;OK,接下來我們可以實現(xiàn)以下勝利的邏輯了 /* * /判斷棋子是否有五個相同的棋子相連 * * param points * return */ private boolean che

20、ckFiveLine(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 = checkLeft(x, y, points); if (win)

21、 return true; /右斜 win = checkRight(x, y, points); if (win) return true; return false; 我們不管哪個方向只要返回true就返回true,然后彈Toast,這里,四個方向的邏輯橫 /* * 判斷橫向的棋子 * * param x * param y * param points */ private boolean checkHorizontal(int x, int y, List<Point> points) /棋子標(biāo)記,記錄是否有五個 =1是因為自身是一個 int count = 1; /左 f

22、or (int i = 1; i < MAX_COUNT_IN_LINE; i+) /如果有 if (points.contains(new Point(x - i, y) count+; else break; /有五個就為true 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; /有五個就為true if (count

23、= MAX_COUNT_IN_LINE) return true; return false; 橫 /* * 判斷縱向的棋子 * * param x * param y * param points */ private boolean checkVertical(int x, int y, List<Point> points) /棋子標(biāo)記,記錄是否有五個 =1是因為自身是一個 int count = 1; /上 for (int i = 1; i < MAX_COUNT_IN_LINE; i+) /如果有 if (points.contains(new Point(x,

24、y - i) count+; else break; /有五個就為true 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; /有五個就為true if (count = MAX_COUNT_IN_LINE) return true; return false; 左斜 /* * 判斷左斜向的棋子 * * param x * para

25、m y * param points */ private boolean checkLeft(int x, int y, List<Point> points) /棋子標(biāo)記,記錄是否有五個 =1是因為自身是一個 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; /有五個就為true if (count = MAX_COUNT_IN_LINE) return true; fo

26、r (int i = 1; i < MAX_COUNT_IN_LINE; i+) /如果有 if (points.contains(new Point(x + i, y - i) count+; else break; /有五個就為true if (count = MAX_COUNT_IN_LINE) return true; return false; 右斜 /* * 判斷右斜向的棋子 * * param x * param y * param points */ private boolean checkRight(int x, int y, List<Point> po

27、ints) /棋子標(biāo)記,記錄是否有五個 =1是因為自身是一個 int count = 1; for (int i = 1; i < MAX_COUNT_IN_LINE; i+) /如果有 if (points.contains(new Point(x - i, y - i) unt+; else break; /有五個就為true 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

28、, y + i) count+; else break; /有五個就為true if (count = MAX_COUNT_IN_LINE) return true; return false; 這樣,我們運行一下嘿嘿,好玩吧!五.游戲狀態(tài)存儲這個就是當(dāng)我們游戲掛后臺之后,再回來游戲就沒了,我們應(yīng)該存儲他的狀態(tài),讓他每一次進(jìn)入的時候要是上一句沒有下完接著下,那我們該怎么去實現(xiàn)呢?和Activity一樣,我們View也有存儲狀態(tài)的方法 /* * 存儲狀態(tài) * * return */ Override protected Parcelable onSaveInstanceState() Bundl

29、e bundle = new Bundle(); bundle.putParcelable(INSTANCE, super.onSaveInstanceState(); bundle.putBoolean(INSTANCE_GAMEOVER, mIsGameOver); bundle.putParcelableArrayList(INSTANCE_WHITE_ARRAY, mWhiteArray); bundle.putParcelableArrayList(INSTANCE_BLACK_ARRAY, mBlackArray); return bundle; /* * 重新運行 * * par

30、am state */ Override protected void onRestoreInstanceState(Parcelable state) /取值 if (state instanceof Bundle) Bundle bundle = (Bundle) state; mIsGameOver = bundle.getBoolean(INSTANCE_GAMEOVER); mWhiteArray = bundle.getParcelableArrayList(INSTANCE_WHITE_ARRAY); mBlackArray = bundle.getParcelableArrayList(INSTANCE_BLACK_ARRAY); /調(diào)用 super.onRestoreInstanceState(bundle.getParcelable(INSTANCE); return; super.onRestoreInstanceState(state); 這樣就可以了,但是,有一點要知道,不要忘記在布局文件上給控件加上ID,不然狀態(tài)不會存儲哦 <com.lgl.fiverow.GameView andro

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論