版權聲明:本文為部落客原創文章,轉載請标明出處。 https://blog.csdn.net/chaoyu168/article/details/51426882
象棋,很多人多接觸過,學者寫了一個,大神可以指點一下~直接上代碼:
貼出主要代碼,想要Demo的點選下載下傳:
中國象棋Demopackage 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();//列印異常堆棧資訊
}
}
}
}
}