編輯:關於Android編程
象棋,很多人多接觸過,學者寫了一個,大神可以指點一下~直接上代碼:
貼出主要代碼,想要Demo的點擊下載:中國象棋Demo
package wyf.ytl; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.media.MediaPlayer; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; /** * 該類是整個程序最主要的類,是主游戲的界面 * 該界面繼承自SurfaceView並實現了SurfaceHolder.Callback接口 * 其中包含了一個刷幀的線程類 * */ public class GameView extends SurfaceView implements SurfaceHolder.Callback{ private TutorialThread thread;//刷幀的線程 TimeThread timeThread ; ChessActivity activity;//聲明Activity的引用 Bitmap qiPan;//棋盤 Bitmap qizibackground;//棋子的背景圖片 Bitmap win;//勝利的圖片 Bitmap lost;//失敗的圖片 Bitmap ok;//確定按鈕 Bitmap vs;//黑方紅方VS的圖片 Bitmap right;//向右的指針 Bitmap left;//向左的指針 Bitmap current;//“當前”文字 Bitmap exit2;//退出按鈕圖片 Bitmap sound2;//聲音按鈕圖片 Bitmap sound3;//當前是否播放了聲音 Bitmap time;//冒號 Bitmap redtime;//紅色冒號 Bitmap background;//背景圖片 MediaPlayer go;//下棋聲音 Paint paint;//畫筆 boolean caiPan = true;//是否為玩家走棋 boolean focus = false;//當前是否有選中的棋子 int selectqizi = 0; //當然選中的棋子 int startI, startJ;//記錄當前棋子的開始位置 int endI, endJ;//記錄當前棋子的目標位置 Bitmap[] heiZi = new Bitmap[7];//黑子的圖片數組 Bitmap[] hongZi = new Bitmap[7];//紅子的圖片數組 Bitmap[] number = new Bitmap[10];//數字的圖片數組,用於顯示時間 Bitmap[] redNumber = new Bitmap[10];//紅色數字的圖片,用於顯示時間 GuiZe guiZe;//規則類 int status = 0;//游戲狀態。0游戲中,1勝利, 2失敗 int heiTime = 0;//黑方總共思考時間 int hongTime = 0;//紅方總共思考時間 int[][] qizi = new int[][]{//棋盤 {2,3,6,5,1,5,6,3,2}, {0,0,0,0,0,0,0,0,0}, {0,4,0,0,0,0,0,4,0}, {7,0,7,0,7,0,7,0,7}, {0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0}, {14,0,14,0,14,0,14,0,14}, {0,11,0,0,0,0,0,11,0}, {0,0,0,0,0,0,0,0,0}, {9,10,13,12,8,12,13,10,9}, }; public GameView(Context context,ChessActivity activity) {//構造器 super(context); this.activity = activity;//得到Activity的引用 getHolder().addCallback(this); go = MediaPlayer.create(this.getContext(), R.raw.go);//加載下棋的聲音 this.thread = new TutorialThread(getHolder(), this);//初始化刷幀線程 this.timeThread = new TimeThread(this);//初始化思考時間的線程 init();//初始化所需資源 guiZe = new GuiZe();//初始化規則類 } public void init(){//初始化方法 paint = new Paint();//初始化畫筆 qiPan = BitmapFactory.decodeResource(getResources(), R.drawable.qipan);//棋盤圖片 qizibackground = BitmapFactory.decodeResource(getResources(), R.drawable.qizi);//棋子的背景 win = BitmapFactory.decodeResource(getResources(), R.drawable.win);//勝利的圖片 lost = BitmapFactory.decodeResource(getResources(), R.drawable.lost);//失敗的圖片 ok = BitmapFactory.decodeResource(getResources(), R.drawable.ok);//確定按鈕圖片 vs = BitmapFactory.decodeResource(getResources(), R.drawable.vs);//vs字樣的圖片 right = BitmapFactory.decodeResource(getResources(), R.drawable.right);//向右的指針 left = BitmapFactory.decodeResource(getResources(), R.drawable.left);//向左的指針 current = BitmapFactory.decodeResource(getResources(), R.drawable.current);//文字“當前” exit2 = BitmapFactory.decodeResource(getResources(), R.drawable.exit2);//退出按鈕圖片 sound2 = BitmapFactory.decodeResource(getResources(), R.drawable.sound2);//聲音按鈕圖片 time = BitmapFactory.decodeResource(getResources(), R.drawable.time);//黑色冒號 redtime = BitmapFactory.decodeResource(getResources(), R.drawable.redtime);//紅色冒號 sound3 = BitmapFactory.decodeResource(getResources(), R.drawable.sound3); heiZi[0] = BitmapFactory.decodeResource(getResources(), R.drawable.heishuai);//黑帥 heiZi[1] = BitmapFactory.decodeResource(getResources(), R.drawable.heiju);//黑車 heiZi[2] = BitmapFactory.decodeResource(getResources(), R.drawable.heima);//黑馬 heiZi[3] = BitmapFactory.decodeResource(getResources(), R.drawable.heipao);//黑炮 heiZi[4] = BitmapFactory.decodeResource(getResources(), R.drawable.heishi);//黑士 heiZi[5] = BitmapFactory.decodeResource(getResources(), R.drawable.heixiang);//黑象 heiZi[6] = BitmapFactory.decodeResource(getResources(), R.drawable.heibing);//黑兵 hongZi[0] = BitmapFactory.decodeResource(getResources(), R.drawable.hongjiang);//紅將 hongZi[1] = BitmapFactory.decodeResource(getResources(), R.drawable.hongju);//紅車 hongZi[2] = BitmapFactory.decodeResource(getResources(), R.drawable.hongma);//紅馬 hongZi[3] = BitmapFactory.decodeResource(getResources(), R.drawable.hongpao);//紅砲 hongZi[4] = BitmapFactory.decodeResource(getResources(), R.drawable.hongshi);//紅仕 hongZi[5] = BitmapFactory.decodeResource(getResources(), R.drawable.hongxiang);//紅相 hongZi[6] = BitmapFactory.decodeResource(getResources(), R.drawable.hongzu);//紅卒 number[0] = BitmapFactory.decodeResource(getResources(), R.drawable.number0);//黑色數字0 number[1] = BitmapFactory.decodeResource(getResources(), R.drawable.number1);//黑色數字1 number[2] = BitmapFactory.decodeResource(getResources(), R.drawable.number2);//黑色數字2 number[3] = BitmapFactory.decodeResource(getResources(), R.drawable.number3);//黑色數字3 number[4] = BitmapFactory.decodeResource(getResources(), R.drawable.number4);//黑色數字4 number[5] = BitmapFactory.decodeResource(getResources(), R.drawable.number5);//黑色數字5 number[6] = BitmapFactory.decodeResource(getResources(), R.drawable.number6);//黑色數字6 number[7] = BitmapFactory.decodeResource(getResources(), R.drawable.number7);//黑色數字7 number[8] = BitmapFactory.decodeResource(getResources(), R.drawable.number8);//黑色數字8 number[9] = BitmapFactory.decodeResource(getResources(), R.drawable.number9);//黑色數字9 redNumber[0] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber0);//紅色數字0 redNumber[1] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber1);//紅色數字1 redNumber[2] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber2);//紅色數字2 redNumber[3] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber3);//紅色數字3 redNumber[4] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber4);//紅色數字4 redNumber[5] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber5);//紅色數字5 redNumber[6] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber6);//紅色數字6 redNumber[7] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber7);//紅色數字7 redNumber[8] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber8);//紅色數字8 redNumber[9] = BitmapFactory.decodeResource(getResources(), R.drawable.rednumber9);//紅色數字9 background = BitmapFactory.decodeResource(getResources(), R.drawable.bacnground); } /** * 該方法是自己定義的並非重寫的 * 該方法是死的,只根據數據繪制屏幕 */ public void onDraw(Canvas canvas){//自己寫的繪制方法 canvas.drawColor(Color.WHITE); canvas.drawBitmap(background, 0,0, null);//清背景 canvas.drawBitmap(qiPan, 10, 10, null);//繪制棋盤 for(int i=0; i<qizi.length; i++){ for(int j=0; j<qizi[i].length; j++){//繪制棋子 if(qizi[i][j] != 0){ canvas.drawBitmap(qizibackground, 9+j*34, 10+i*35, null);//繪制棋子的背景 if(qizi[i][j] == 1){//為黑帥時 canvas.drawBitmap(heiZi[0], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 2){//為黑車時 canvas.drawBitmap(heiZi[1], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 3){//為黑馬時 canvas.drawBitmap(heiZi[2], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 4){//為黑炮時 canvas.drawBitmap(heiZi[3], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 5){//為黑士時 canvas.drawBitmap(heiZi[4], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 6){//為黑象時 canvas.drawBitmap(heiZi[5], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 7){//為黑兵時 canvas.drawBitmap(heiZi[6], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 8){//為紅將時 canvas.drawBitmap(hongZi[0], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 9){//為紅車時 canvas.drawBitmap(hongZi[1], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 10){//為紅馬時 canvas.drawBitmap(hongZi[2], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 11){//為紅砲時 canvas.drawBitmap(hongZi[3], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 12){//為紅仕時 canvas.drawBitmap(hongZi[4], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 13){//為紅相時 canvas.drawBitmap(hongZi[5], 12+j*34, 13+i*35, paint); } else if(qizi[i][j] == 14){//為紅卒時 canvas.drawBitmap(hongZi[6], 12+j*34, 13+i*35, paint); } } } } canvas.drawBitmap(vs, 10, 360, paint);//繪制VS背景圖 //繪制黑方的時間 canvas.drawBitmap(time, 81, 411, paint);//繪制冒號 int temp = this.heiTime/60;//換算時間 String timeStr = temp+"";//轉換成字符串 if(timeStr.length()<2){//當不足兩位時前面填0 timeStr = "0" + timeStr; } for(int i=0;i<2;i++){//循環繪制時間 int tempScore=timeStr.charAt(i)-'0'; canvas.drawBitmap(number[tempScore], 65+i*7, 412, paint); } //畫分鐘 temp = this.heiTime%60; timeStr = temp+"";//轉換成字符串 if(timeStr.length()<2){ timeStr = "0" + timeStr;//當長度小於2時在前面添加一個0 } for(int i=0;i<2;i++){//循環 int tempScore=timeStr.charAt(i)-'0'; canvas.drawBitmap(number[tempScore], 85+i*7, 412, paint);//繪制 } //開始繪制紅方時間 canvas.drawBitmap(this.redtime, 262, 410, paint);//紅方的冒號 int temp2 = this.hongTime/60;//換算時間 String timeStr2 = temp2+"";//轉換成字符串 if(timeStr2.length()<2){//當不足兩位時前面填0 timeStr2 = "0" + timeStr2; } for(int i=0;i<2;i++){//循環繪制時間 int tempScore=timeStr2.charAt(i)-'0'; canvas.drawBitmap(redNumber[tempScore], 247+i*7, 411, paint);//繪制 } //畫分鐘 temp2 = this.hongTime%60;//求出當前的秒數 timeStr2 = temp2+"";//轉換成字符串 if(timeStr2.length()<2){//不足兩位時前面用0補 timeStr2 = "0" + timeStr2; } for(int i=0;i<2;i++){//循環繪制 int tempScore=timeStr2.charAt(i)-'0'; canvas.drawBitmap(redNumber[tempScore], 267+i*7, 411, paint);//繪制時間數字 } if(caiPan == true){//當該玩家走棋時,即紅方走棋 canvas.drawBitmap(right, 155, 420, paint);//繪制向右的指針 } else{//黑方走棋,即電腦走棋時 canvas.drawBitmap(left, 120, 420, paint);//繪制向左的指針 } canvas.drawBitmap(current, 138, 445, paint);//繪制當前文字 canvas.drawBitmap(sound2, 10, 440, paint);//繪制聲音 if(activity.isSound){//如果正在播放聲音 canvas.drawBitmap(sound3, 80, 452, paint);//繪制 } canvas.drawBitmap(exit2, 250, 440, paint);//繪制退出按鈕 if(status == 1){//當勝利時 canvas.drawBitmap(win, 85, 150, paint);//繪制勝利圖片 canvas.drawBitmap(ok, 113, 240, paint); } if(status == 2){//失敗後 canvas.drawBitmap(lost, 85, 150, paint);//繪制失敗界面 canvas.drawBitmap(ok, 113, 236, paint); } } /** * 該方法是游戲主要邏輯接口 * 接受玩家輸入 * 根據點擊的位置和當前的游戲狀態做出相應的處理 * 而當需要切換View時,通過給Activity發送Handler消息來處理 * 注意的是只取屏幕被按下的事件 */ @Override public boolean onTouchEvent(MotionEvent event) {//重寫的屏幕監聽 if(event.getAction() == MotionEvent.ACTION_DOWN){//只取鼠標按下的事件 if(event.getX()>10&&event.getX()<10+sound2.getWidth() && event.getY()>440 && event.getY()<440+sound2.getHeight()){//按下了聲音按鈕 activity.isSound = !activity.isSound;//聲音取反 if(activity.isSound){//當需要放聲音時 if(activity.gamesound != null){//gamesound不為空時 if(!activity.gamesound.isPlaying()){//當前沒有音樂時 activity.gamesound.start();//播放音樂 } } } else{ if(activity.gamesound != null){//gamesound不為空時 if(activity.gamesound.isPlaying()){//當前有音樂時 activity.gamesound.pause();//停止音樂 } } } }//end 按下了聲音按鈕 if(event.getX()>250&&event.getX()<250+exit2.getWidth() && event.getY()>440 && event.getY()<440+exit2.getHeight()){//按下了退出按鈕 activity.myHandler.sendEmptyMessage(1);//發送消息,切換到MenuView } if(status == 1){//勝利後 if(event.getX()>135&&event.getX()<190 && event.getY()>249 && event.getY()<269){//點擊了確定按鈕 activity.myHandler.sendEmptyMessage(1);//發送消息,切換到MenuView } } else if(status == 2){//失敗後 if(event.getX()>135&&event.getX()<190 && event.getY()>245 && event.getY()<265){//點擊了確定按鈕 activity.myHandler.sendEmptyMessage(1);//發送消息,切換到MenuView } } /** * 游戲過程中的邏輯處理 * 當點擊棋盤時,先判斷當前是否為玩家走棋, * 然後再判斷當然玩家是否已經有選中的棋子,如果沒有則選中 * 如果之前有選中的棋子,再判斷點擊的位置是空地、對方棋子還是自己的棋子 * 是空地判斷是否可走 * 是對方棋子同樣判斷是否可以走,能走自然吃子 * 是自己的棋子則選中該棋子 */ else if(status == 0){//游戲中時 if(event.getX()>10&&event.getX()<310 && event.getY()>10 && event.getY()<360){//點擊的位置在棋盤內時 if(caiPan == true){//如果是該玩家走棋 int i = -1, j = -1; int[] pos = getPos(event);//根據坐標換算成所在的行和列 i = pos[0]; j = pos[1]; if(focus == false){//之前沒有選中的棋子 if(qizi[i][j] != 0){//點擊的位置有棋子 if(qizi[i][j] > 7){//點擊的是自己的棋子。即下面的黑色棋子 selectqizi = qizi[i][j];//將該棋子設為選中的棋子 focus = true;//標記當前有選中的棋子 startI = i; startJ = j; } } } else{//之前選中過棋子 if(qizi[i][j] != 0){//點擊的位置有棋子 if(qizi[i][j] > 7){//如果是自己的棋子. selectqizi = qizi[i][j];//將該棋子設為選中的棋子 startI = i; startJ = j; } else{//如果是對方的棋子 endI = i; endJ = j;//保存該點 boolean canMove = guiZe.canMove(qizi, startI, startJ, endI, endJ); if(canMove){//如果可以移動過去 caiPan = false;//不讓玩家走了 if(qizi[endI][endJ] == 1 || qizi[endI][endJ] == 8){//如果是“帥”或“將” this.success();//勝利了 } else{ if(activity.isSound){ go.start();//播放下棋聲音 } qizi[endI][endJ] = qizi[startI][startJ];//移動棋子 qizi[startI][startJ] = 0;//將原來處設空 startI = -1; startJ = -1; endI = -1; endJ = -1;//還原保存點 focus = false;//標記當前沒有選中棋子 ChessMove cm = guiZe.searchAGoodMove(qizi);//根據當前局勢查詢一個最好的走法 if(activity.isSound){ go.start();//播放下棋聲音 } qizi[cm.toX][cm.toY] = qizi[cm.fromX][cm.fromY];//移動棋子 qizi[cm.fromX][cm.fromY] = 0; caiPan = true;//恢復玩家響應 } } } }//end點擊的位置有棋子 else{//如果點擊的位置沒有棋子 endI = i; endJ = j; boolean canMove = guiZe.canMove(qizi, startI, startJ, endI, endJ);//查看是否可走 if(canMove){//如果可以移動 caiPan = false;//不讓玩家走了 if(activity.isSound){ go.start();//播放下棋聲音 } qizi[endI][endJ] = qizi[startI][startJ];//移動棋子 qizi[startI][startJ] = 0;//將原來處置空 startI = -1; startJ = -1; endI = -1; endJ = -1;//還原保存點 focus = false;//標志位設false ChessMove cm = guiZe.searchAGoodMove(qizi);//得到一步走法 if(qizi[cm.toX][cm.toY] == 8){//電腦吃了您的將 status = 2;//切換游戲狀態為失敗 } if(activity.isSound){//需要播放聲音時 go.start();//播放下棋聲音 } qizi[cm.toX][cm.toY] = qizi[cm.fromX][cm.fromY];//移動棋子 qizi[cm.fromX][cm.fromY] = 0; caiPan = true;//恢復玩家響應 } } }//end 之前選中過棋子 } }//end點擊的位置在棋盤內時 }//end游戲中時 } return super.onTouchEvent(event); } public int[] getPos(MotionEvent e){//將坐標換算成數組的維數 int[] pos = new int[2]; double x = e.getX();//得到點擊位置的x坐標 double y = e.getY();//得到點擊位置的y坐標 if(x>10 && y>10 && x<10+qiPan.getWidth() && y<10+qiPan.getHeight()){//點擊的是棋盤時 pos[0] = Math.round((float)((y-21)/36));//取得所在的行 pos[1] = Math.round((float)((x-21)/35));//取得所在的列 } else{//點擊的位置不是棋盤時 pos[0] = -1;//將位置設為不可用 pos[1] = -1; } return pos;//將坐標數組返回 } public void success(){//勝利了 status = 1;//切換到勝利狀態 } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } public void surfaceCreated(SurfaceHolder holder) {//重寫的 this.thread.setFlag(true); this.thread.start();//啟動刷幀線程 timeThread.setFlag(true); timeThread.start();//啟動思考時間的線程 } public void surfaceDestroyed(SurfaceHolder holder) {//view被釋放時調用的 boolean retry = true; thread.setFlag(false);//停止刷幀線程 timeThread.setFlag(false);//停止思考時間線程 while (retry) { try { thread.join(); timeThread.join();//等待線程結束 retry = false;//設置循環標志位為false } catch (InterruptedException e) {//不斷地循環,直到等待的線程結束 } } } class TutorialThread extends Thread{//刷幀線程 private int span = 300;//睡眠的毫秒數 private SurfaceHolder surfaceHolder;//SurfaceHolder的引用 private GameView gameView;//gameView的引用 private boolean flag = false;//循環標志位 public TutorialThread(SurfaceHolder surfaceHolder, GameView gameView) {//構造器 this.surfaceHolder = surfaceHolder;//得到SurfaceHolder引用 this.gameView = gameView;//得到GameView的引用 } public void setFlag(boolean flag) {//設置循環標記 this.flag = flag; } public void run() {//重寫的方法 Canvas c;//畫布 while (this.flag) {//循環繪制 c = null; try { c = this.surfaceHolder.lockCanvas(null); synchronized (this.surfaceHolder) { gameView.onDraw(c);//調用繪制方法 } } finally {//用finally保證下面代碼一定被執行 if (c != null) { //更新屏幕顯示內容 this.surfaceHolder.unlockCanvasAndPost(c); } } try{ Thread.sleep(span);//睡眠span毫秒 }catch(Exception e){//不會異常信息 e.printStackTrace();//打印異常堆棧信息 } } } } }
以上就是本文的全部內容,好好玩吧,希望對大家的學習也有幫助。
BottomBar BottomBar是Github上的一個開源框架,因為從1.3.3開始不支持fragments了,要自己配置,弄了很久,不管是app的fragm
在搜集Android view繪制流程的相關知識時,發現這裡面的流程還是有些復雜的,准備了好幾天,才敢提起筆來。下面就直入主題吧!view繪制流程是從ViewRoot的p
前言:之前使用NPOI插件編寫的導表工具,其實就是直接將數據進行序列化,解析時還需要進行反序列化,步驟比較繁復,最近看到Google的一個開源的項目protobuf,不僅
相信大家對MVC,MVP和MVVM都不陌生,作為三個最耳熟能詳的Android框架,它們的應用可以是非常廣泛的,但是對於一些新手來說,可能對於區分它們三個都有困難,更別說