(下载资源在文末)


实现中国象棋之类的游戏都会自定义一个View,本次用到SurfaceView,不了解的小伙伴可以自己了解一下。

  1. 象棋的运行思路

执行过程:点击屏幕(屏幕监听) ——>是否到自己走棋(是) ——>判断是否已经选中棋子(是) ——>判断点击位置是否有自己的棋子(是)——>选中该棋子(true)——>再次点击屏幕——>判断位置是否符合下棋规则(点击位置有对方棋子或空位)——>可以移动,改变棋盘(数组)。

  1. 代码实现

实现棋盘所有功能(1、显示棋盘 2、新局、悔棋、设置、返回功能 )

activity_pvm.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:id="@+id/relativeLayout"android:background="@drawable/background"tools:context="com.example.a77304.chessgame.PvMActivity"></RelativeLayout>

button_group.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:layout_alignParentStart="true"><Buttonandroid:id="@+id/btn_retry"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toLeftOf="@+id/btn_recall"android:layout_centerVertical="true"android:layout_margin="5dp"android:background="@drawable/selector_btn2"android:textSize="24dp"android:text="新局" /><Buttonandroid:id="@+id/btn_recall"android:soundEffectsEnabled="false"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toLeftOf="@+id/btn_null"android:layout_centerVertical="true"android:layout_margin="5dp"android:background="@drawable/selector_btn2"android:textSize="24dp"android:text="悔棋" /><Buttonandroid:id="@+id/btn_null"android:layout_width="0dp"android:layout_height="wrap_content"android:layout_centerInParent="true"android:text="" /><Buttonandroid:id="@+id/btn_setting"android:soundEffectsEnabled="false"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toRightOf="@+id/btn_null"android:layout_centerVertical="true"android:layout_margin="5dp"android:background="@drawable/selector_btn2"android:textSize="24dp"android:text="设置" /><Buttonandroid:id="@+id/btn_back"android:soundEffectsEnabled="false"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_toRightOf="@+id/btn_setting"android:layout_centerVertical="true"android:layout_margin="5dp"android:background="@drawable/selector_btn2"android:textSize="24dp"android:text="返回" /></RelativeLayout>

PvMActivity.java


import android.content.SharedPreferences;
import android.os.Looper;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.RelativeLayout;
import android.widget.Toast;import AICore.AI;
import AICore.KnowledgeBase;
import AICore.Move;
import AICore.TransformTable;
import ChessMove.Rule;
import CustomDialog.CommonDialog;
import CustomDialog.RetryDialog;
import CustomDialog.SettingDialog_PvM;
import CustomView.RoundView;
import Info.ChessInfo;
import Info.InfoSet;
import Info.Pos;
import Info.SaveInfo;
import CustomView.ChessView;import static AICore.AI.getBestMove;
import static com.example.a77304.chessgame.HomeActivity.MIN_CLICK_DELAY_TIME;
import static com.example.a77304.chessgame.HomeActivity.backMusic;
import static com.example.a77304.chessgame.HomeActivity.checkMusic;
import static com.example.a77304.chessgame.HomeActivity.clickMusic;
import static com.example.a77304.chessgame.HomeActivity.curClickTime;
import static com.example.a77304.chessgame.HomeActivity.lastClickTime;
import static com.example.a77304.chessgame.HomeActivity.playEffect;
import static com.example.a77304.chessgame.HomeActivity.playMusic;
import static com.example.a77304.chessgame.HomeActivity.selectMusic;
import static com.example.a77304.chessgame.HomeActivity.setting;
import static com.example.a77304.chessgame.HomeActivity.sharedPreferences;
import static com.example.a77304.chessgame.HomeActivity.stopMusic;
import static com.example.a77304.chessgame.HomeActivity.winMusic;public class PvMActivity extends AppCompatActivity implements View.OnTouchListener, View.OnClickListener {public RelativeLayout relativeLayout;public ChessInfo chessInfo;public InfoSet infoSet;public ChessView chessView;   // 自定义的View,用于绘制棋盘、棋子public RoundView roundView;   // 自定义View(显示 红方回合、黑方回合)public static KnowledgeBase knowledgeBase;public static TransformTable transformTable;public Thread AIThread = new Thread(new Runnable() {@Overridepublic void run() {AIMove(chessInfo.IsRedGo, chessInfo.status);}});@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_pvm);relativeLayout = (RelativeLayout) findViewById(R.id.relativeLayout);chessInfo = new ChessInfo();infoSet = new InfoSet();transformTable = new TransformTable();knowledgeBase = new KnowledgeBase();roundView = new RoundView(this, chessInfo);//添加View(红方回合、黑方回合)relativeLayout.addView(roundView);RelativeLayout.LayoutParams paramsRound = (RelativeLayout.LayoutParams) roundView.getLayoutParams();paramsRound.addRule(RelativeLayout.CENTER_IN_PARENT);paramsRound.addRule(RelativeLayout.ALIGN_PARENT_TOP);paramsRound.setMargins(30, 30, 30, 30);roundView.setLayoutParams(paramsRound);roundView.setId(R.id.roundView);chessView = new ChessView(this, chessInfo);chessView.setOnTouchListener(this);//添加View(绘制棋盘、棋子)relativeLayout.addView(chessView);RelativeLayout.LayoutParams paramsChess = (RelativeLayout.LayoutParams) chessView.getLayoutParams();paramsChess.addRule(RelativeLayout.BELOW, R.id.roundView);chessView.setLayoutParams(paramsChess);chessView.setId(R.id.chessView);LayoutInflater inflater = LayoutInflater.from(this);RelativeLayout buttonGroup = (RelativeLayout) inflater.inflate(R.layout.button_group, relativeLayout, false);//添加View(新局、悔棋、设置、返回)relativeLayout.addView(buttonGroup);RelativeLayout.LayoutParams paramsV = (RelativeLayout.LayoutParams) buttonGroup.getLayoutParams();paramsV.addRule(RelativeLayout.BELOW, R.id.chessView);buttonGroup.setLayoutParams(paramsV);for (int i = 0; i < buttonGroup.getChildCount(); i++) {Button btn = (Button) buttonGroup.getChildAt(i);btn.setOnClickListener(this);}}/*** 屏幕监听* @param view* @param event* @return*/@Overridepublic boolean onTouch(View view, MotionEvent event) {lastClickTime = System.currentTimeMillis();if (lastClickTime - curClickTime < MIN_CLICK_DELAY_TIME) {return false;}curClickTime = lastClickTime;if (event.getAction() == MotionEvent.ACTION_DOWN) {float x = event.getX();float y = event.getY();if (chessInfo.status == 1) {if (x >= 0 && x <= chessView.Board_width && y >= 0 && y <= chessView.Board_height) {chessInfo.Select = getPos(event);Pos realPos = Rule.reversePos(new Pos(chessInfo.Select[0], chessInfo.Select[1]), chessInfo.IsReverse);int i = realPos.x, j = realPos.y;if (i >= 0 && i <= 8 && j >= 0 && j <= 9) {if (chessInfo.IsRedGo == true && setting.isPlayerRed == true) {if (chessInfo.IsChecked == false) {if (chessInfo.piece[j][i] >= 8 && chessInfo.piece[j][i] <= 14) {chessInfo.prePos = new Pos(i, j);chessInfo.IsChecked = true;chessInfo.ret = Rule.PossibleMoves(chessInfo.piece, i, j, chessInfo.piece[j][i]);playEffect(selectMusic);}} else {if (chessInfo.piece[j][i] >= 8 && chessInfo.piece[j][i] <= 14) {chessInfo.prePos = new Pos(i, j);chessInfo.ret = Rule.PossibleMoves(chessInfo.piece, i, j, chessInfo.piece[j][i]);playEffect(selectMusic);} else if (chessInfo.ret.contains(new Pos(i, j))) {int tmp = chessInfo.piece[j][i];chessInfo.piece[j][i] = chessInfo.piece[chessInfo.prePos.y][chessInfo.prePos.x];chessInfo.piece[chessInfo.prePos.y][chessInfo.prePos.x] = 0;if (Rule.isKingDanger(chessInfo.piece, true)) {chessInfo.piece[chessInfo.prePos.y][chessInfo.prePos.x] = chessInfo.piece[j][i];chessInfo.piece[j][i] = tmp;Toast toast = Toast.makeText(PvMActivity.this, "帅被将军", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();} else {chessInfo.IsChecked = false;chessInfo.IsRedGo = false;chessInfo.curPos = new Pos(i, j);chessInfo.updateAllInfo(chessInfo.prePos, chessInfo.curPos, chessInfo.piece[j][i], tmp);try {infoSet.pushInfo(chessInfo);} catch (CloneNotSupportedException e) {e.printStackTrace();}playEffect(clickMusic);int key = 0;if (Rule.isKingDanger(chessInfo.piece, false)) {key = 1;}if (Rule.isDead(chessInfo.piece, false)) {key = 2;}if (key == 1) {playEffect(checkMusic);Toast toast = Toast.makeText(PvMActivity.this, "将军", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();} else if (key == 2) {playEffect(winMusic);chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "红方获得胜利", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();}if (chessInfo.status == 1) {if (chessInfo.peaceRound >= 60) {chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "双方60回合内未吃子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();} else if (chessInfo.attackNum_B == 0 && chessInfo.attackNum_R == 0) {chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "双方都无攻击性棋子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();} else if (infoSet.ZobristInfo.get(chessInfo.ZobristKeyCheck) >= 4) {chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "重复局面出现4次,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();}}AIThread = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(400);} catch (InterruptedException e) {e.printStackTrace();}chessInfo.isMachine = true;AIMove(chessInfo.IsRedGo, chessInfo.status);}});AIThread.start();}}}} else if (chessInfo.IsRedGo == false && setting.isPlayerRed == false) {if (chessInfo.IsChecked == false) {if (chessInfo.piece[j][i] >= 1 && chessInfo.piece[j][i] <= 7) {chessInfo.prePos = new Pos(i, j);chessInfo.IsChecked = true;chessInfo.ret = Rule.PossibleMoves(chessInfo.piece, i, j, chessInfo.piece[j][i]);playEffect(selectMusic);}} else {if (chessInfo.piece[j][i] >= 1 && chessInfo.piece[j][i] <= 7) {chessInfo.prePos = new Pos(i, j);chessInfo.ret = Rule.PossibleMoves(chessInfo.piece, i, j, chessInfo.piece[j][i]);playEffect(selectMusic);} else if (chessInfo.ret.contains(new Pos(i, j))) {int tmp = chessInfo.piece[j][i];chessInfo.piece[j][i] = chessInfo.piece[chessInfo.prePos.y][chessInfo.prePos.x];chessInfo.piece[chessInfo.prePos.y][chessInfo.prePos.x] = 0;if (Rule.isKingDanger(chessInfo.piece, false)) {chessInfo.piece[chessInfo.prePos.y][chessInfo.prePos.x] = chessInfo.piece[j][i];chessInfo.piece[j][i] = tmp;Toast toast = Toast.makeText(PvMActivity.this, "将被将军", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();} else {chessInfo.IsChecked = false;chessInfo.IsRedGo = true;chessInfo.curPos = new Pos(i, j);chessInfo.updateAllInfo(chessInfo.prePos, chessInfo.curPos, chessInfo.piece[j][i], tmp);try {infoSet.pushInfo(chessInfo);} catch (CloneNotSupportedException e) {e.printStackTrace();}playEffect(clickMusic);int key = 0;if (Rule.isKingDanger(chessInfo.piece, true)) {key = 1;}if (Rule.isDead(chessInfo.piece, true)) {key = 2;}if (key == 1) {playEffect(checkMusic);Toast toast = Toast.makeText(PvMActivity.this, "将军", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}} else if (key == 2) {playEffect(winMusic);chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "黑方获得胜利", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();}if (chessInfo.status == 1) {if (chessInfo.peaceRound >= 60) {chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "双方60回合内未吃子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();} else if (chessInfo.attackNum_B == 0 && chessInfo.attackNum_R == 0) {chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "双方都无攻击性棋子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();} else if (infoSet.ZobristInfo.get(chessInfo.ZobristKeyCheck) >= 4) {chessInfo.status = 2;Toast toast = Toast.makeText(PvMActivity.this, "重复局面出现4次,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();}}AIThread = new Thread(new Runnable() {@Overridepublic void run() {try {Thread.sleep(400);} catch (InterruptedException e) {e.printStackTrace();}chessInfo.isMachine = true;AIMove(chessInfo.IsRedGo, chessInfo.status);}});AIThread.start();}}}}}}}}return false;}public int[] getPos(MotionEvent e) {int[] pos = new int[2];double x = e.getX();double y = e.getY();int[] dis = new int[]{chessView.Scale(3), chessView.Scale(41), chessView.Scale(80), chessView.Scale(85)};x = x - dis[0];y = y - dis[1];if (x % dis[3] <= dis[2] && y % dis[3] <= dis[2]) {pos[0] = (int) Math.floor(x / dis[3]);pos[1] = (int) Math.floor(y / dis[3]);if (pos[0] >= 9 || pos[1] >= 10) {pos[0] = pos[1] = -1;}} else {pos[0] = pos[1] = -1;}return pos;}@Overridepublic void onClick(View view) {lastClickTime = System.currentTimeMillis();if (lastClickTime - curClickTime < MIN_CLICK_DELAY_TIME) {return;}curClickTime = lastClickTime;playEffect(selectMusic);switch (view.getId()) {case R.id.btn_retry:if (chessInfo.isMachine == true && chessInfo.status == 1) {Toast toast = Toast.makeText(PvMActivity.this, "请等待电脑思考", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();break;}final RetryDialog retryDialog = new RetryDialog(this);retryDialog.setOnClickBottomListener(new RetryDialog.OnClickBottomListener() {@Overridepublic void onPositiveClick() {playEffect(selectMusic);try {chessInfo.setInfo(new ChessInfo());infoSet.newInfo();transformTable.transformInfos.clear();} catch (CloneNotSupportedException e) {e.printStackTrace();}SharedPreferences.Editor editor = sharedPreferences.edit();if (setting.isPlayerRed != retryDialog.isPlayerRed) {setting.isPlayerRed = retryDialog.isPlayerRed;editor.putBoolean("isPlayerRed", retryDialog.isPlayerRed);editor.commit();}retryDialog.dismiss();chessInfo.IsReverse = (setting.isPlayerRed == true) ? false : true;if (chessInfo.IsReverse == true) {try {infoSet.curInfo.setInfo(chessInfo);} catch (CloneNotSupportedException e) {e.printStackTrace();}}if (setting.isPlayerRed == false) {try {Thread.sleep(400);} catch (InterruptedException e) {e.printStackTrace();}AIFirstGo();}}@Overridepublic void onNegtiveClick() {playEffect(selectMusic);retryDialog.dismiss();}});retryDialog.show();break;case R.id.btn_recall:if (chessInfo.isMachine == true && chessInfo.status == 1) {Toast toast = Toast.makeText(PvMActivity.this, "请等待电脑思考", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();break;}int cnt = 0;int total = 2;if (chessInfo.status == 2 && chessInfo.isMachine == true) {total = 1;}if (infoSet.preInfo.size() < total) {break;}while (!infoSet.preInfo.empty()) {ChessInfo tmp = infoSet.preInfo.pop();cnt++;try {infoSet.recallZobristInfo(chessInfo.ZobristKeyCheck);chessInfo.setInfo(tmp);infoSet.curInfo.setInfo(tmp);} catch (CloneNotSupportedException e) {e.printStackTrace();}if (cnt >= total) {break;}}break;case R.id.btn_setting:final SettingDialog_PvM settingDialog_pvm = new SettingDialog_PvM(this);settingDialog_pvm.setOnClickBottomListener(new SettingDialog_PvM.OnClickBottomListener() {@Overridepublic void onPositiveClick() {playEffect(selectMusic);SharedPreferences.Editor editor = sharedPreferences.edit();boolean flag = false;if (setting.isMusicPlay != settingDialog_pvm.isMusicPlay) {setting.isMusicPlay = settingDialog_pvm.isMusicPlay;if (setting.isMusicPlay) {playMusic(backMusic);} else {stopMusic(backMusic);}editor.putBoolean("isMusicPlay", settingDialog_pvm.isMusicPlay);flag = true;}if (setting.isEffectPlay != settingDialog_pvm.isEffectPlay) {setting.isEffectPlay = settingDialog_pvm.isEffectPlay;editor.putBoolean("isEffectPlay", settingDialog_pvm.isEffectPlay);flag = true;}if (setting.mLevel != settingDialog_pvm.mLevel) {setting.mLevel = settingDialog_pvm.mLevel;editor.putInt("mLevel", settingDialog_pvm.mLevel);flag = true;}if (flag) {editor.commit();}settingDialog_pvm.dismiss();}@Overridepublic void onNegtiveClick() {playEffect(selectMusic);settingDialog_pvm.dismiss();}});settingDialog_pvm.show();break;case R.id.btn_back:final CommonDialog backDialog = new CommonDialog(this, "返回", "确认要返回吗");backDialog.setOnClickBottomListener(new CommonDialog.OnClickBottomListener() {@Overridepublic void onPositiveClick() {playEffect(selectMusic);backDialog.dismiss();finish();}@Overridepublic void onNegtiveClick() {playEffect(selectMusic);backDialog.dismiss();}});backDialog.show();break;default:break;}}public void AIMove(boolean isRed, int status) {if (status != 1) return;int depth = setting.mLevel * 2;if (isRed == true) {// AI获取最佳走法Move move = knowledgeBase.readBestMoves(chessInfo.ZobristKey, chessInfo.ZobristKeyCheck, depth);if (move == null) {long t1 = System.currentTimeMillis();move = getBestMove(chessInfo.piece, true, depth, chessInfo.ZobristKey, chessInfo.ZobristKeyCheck, infoSet.ZobristInfo);long t2 = System.currentTimeMillis();Log.i("AI思考", "AI思考的时间:" + String.valueOf(t2 - t1) + "ms");knowledgeBase.saveBestMove(chessInfo.ZobristKey, chessInfo.ZobristKeyCheck, depth, move);}Pos fromPos = move.fromPos;Pos toPos = move.toPos;int tmp = chessInfo.piece[toPos.y][toPos.x];chessInfo.piece[toPos.y][toPos.x] = chessInfo.piece[fromPos.y][fromPos.x];chessInfo.piece[fromPos.y][fromPos.x] = 0;chessInfo.IsChecked = false;chessInfo.IsRedGo = false;chessInfo.Select = new int[]{-1, -1};chessInfo.ret.clear();chessInfo.prePos = new Pos(fromPos.x, fromPos.y);chessInfo.curPos = new Pos(toPos.x, toPos.y);chessInfo.updateAllInfo(chessInfo.prePos, chessInfo.curPos, chessInfo.piece[toPos.y][toPos.x], tmp);chessInfo.isMachine = false;try {infoSet.pushInfo(chessInfo);} catch (CloneNotSupportedException e) {e.printStackTrace();}playEffect(clickMusic);int key = 0;if (Rule.isKingDanger(chessInfo.piece, false)) {key = 1;}if (Rule.isDead(chessInfo.piece, false)) {key = 2;}if (key == 1) {playEffect(checkMusic);Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "将军", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();} else if (key == 2) {playEffect(winMusic);chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "红方获得胜利", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();}if (chessInfo.status == 1) {if (chessInfo.peaceRound >= 60) {chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "双方60回合内未吃子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();} else if (chessInfo.attackNum_B == 0 && chessInfo.attackNum_R == 0) {chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "双方都无攻击性棋子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();} else if (infoSet.ZobristInfo.get(chessInfo.ZobristKeyCheck) >= 4) {chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "重复局面出现4次,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();}}} else {Move move = knowledgeBase.readBestMoves(chessInfo.ZobristKey, chessInfo.ZobristKeyCheck, depth);if (move == null) {long t1 = System.currentTimeMillis();move = getBestMove(chessInfo.piece, false, depth, chessInfo.ZobristKey, chessInfo.ZobristKeyCheck, infoSet.ZobristInfo);long t2 = System.currentTimeMillis();Log.i("AI思考", "AI思考的时间:" + String.valueOf(t2 - t1) + "ms");knowledgeBase.saveBestMove(chessInfo.ZobristKey, chessInfo.ZobristKeyCheck, depth, move);}Pos fromPos = move.fromPos;Pos toPos = move.toPos;int tmp = chessInfo.piece[toPos.y][toPos.x];chessInfo.piece[toPos.y][toPos.x] = chessInfo.piece[fromPos.y][fromPos.x];chessInfo.piece[fromPos.y][fromPos.x] = 0;chessInfo.IsChecked = false;chessInfo.IsRedGo = true;chessInfo.Select = new int[]{-1, -1};chessInfo.ret.clear();chessInfo.prePos = new Pos(fromPos.x, fromPos.y);chessInfo.curPos = new Pos(toPos.x, toPos.y);chessInfo.updateAllInfo(chessInfo.prePos, chessInfo.curPos, chessInfo.piece[toPos.y][toPos.x], tmp);chessInfo.isMachine = false;try {infoSet.pushInfo(chessInfo);} catch (CloneNotSupportedException e) {e.printStackTrace();}playEffect(clickMusic);int key = 0;if (Rule.isKingDanger(chessInfo.piece, true)) {key = 1;}if (Rule.isDead(chessInfo.piece, true)) {key = 2;}if (key == 1) {playEffect(checkMusic);Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "将军", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();} else if (key == 2) {playEffect(winMusic);chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "黑方获得胜利", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();}if (chessInfo.status == 1) {if (chessInfo.peaceRound >= 60) {chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "双方60回合内未吃子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();} else if (chessInfo.attackNum_B == 0 && chessInfo.attackNum_R == 0) {chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "双方都无攻击性棋子,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();} else if (infoSet.ZobristInfo.get(chessInfo.ZobristKeyCheck) >= 4) {chessInfo.status = 2;Looper.prepare();Toast toast = Toast.makeText(PvMActivity.this, "重复局面出现4次,此乃和棋", Toast.LENGTH_SHORT);toast.setGravity(Gravity.CENTER, 0, 0);toast.show();Looper.loop();}}}}public void AIFirstGo() {Move[] firstMoves = new Move[8];firstMoves[0] = new Move(new Pos(1, 9), new Pos(2, 7));     //走马firstMoves[1] = new Move(new Pos(7, 9), new Pos(6, 7));     //走马firstMoves[2] = new Move(new Pos(2, 9), new Pos(4, 7));     //走相firstMoves[3] = new Move(new Pos(6, 9), new Pos(4, 7));     //走相firstMoves[4] = new Move(new Pos(1, 7), new Pos(4, 7));     //走炮firstMoves[5] = new Move(new Pos(7, 7), new Pos(4, 7));     //走炮firstMoves[6] = new Move(new Pos(2, 6), new Pos(2, 5));     //走兵firstMoves[7] = new Move(new Pos(6, 6), new Pos(6, 5));     //走兵int num = (int) (Math.random() * firstMoves.length);//Log.e("chen",String.valueOf(num));Move firstMove = firstMoves[num];Pos fromPos = firstMove.fromPos;Pos toPos = firstMove.toPos;int tmp = chessInfo.piece[toPos.y][toPos.x];chessInfo.piece[toPos.y][toPos.x] = chessInfo.piece[fromPos.y][fromPos.x];chessInfo.piece[fromPos.y][fromPos.x] = 0;chessInfo.IsChecked = false;chessInfo.IsRedGo = false;chessInfo.Select = new int[]{-1, -1};chessInfo.ret.clear();chessInfo.prePos = new Pos(fromPos.x, fromPos.y);chessInfo.curPos = new Pos(toPos.x, toPos.y);chessInfo.updateAllInfo(chessInfo.prePos, chessInfo.curPos, chessInfo.piece[toPos.y][toPos.x], tmp);try {infoSet.pushInfo(chessInfo);} catch (CloneNotSupportedException e) {e.printStackTrace();}playEffect(clickMusic);}@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event) {if (keyCode == KeyEvent.KEYCODE_BACK) {final CommonDialog backDialog = new CommonDialog(this, "返回", "确认要返回吗");backDialog.setOnClickBottomListener(new CommonDialog.OnClickBottomListener() {@Overridepublic void onPositiveClick() {playEffect(selectMusic);backDialog.dismiss();finish();}@Overridepublic void onNegtiveClick() {playEffect(selectMusic);backDialog.dismiss();}});backDialog.show();return true;}return super.onKeyDown(keyCode, event);}@Overrideprotected void onPause() {stopMusic(backMusic);super.onPause();}@Overrideprotected void onStop() {/* try {SaveInfo.SerializeChessInfo(chessInfo, "ChessInfo_pvm.bin");SaveInfo.SerializeInfoSet(infoSet, "InfoSet_pvm.bin");SaveInfo.SerializeKnowledgeBase(knowledgeBase, "KnowledgeBase.bin");SaveInfo.SerializeTransformTable(transformTable, "TransformTable.bin");} catch (Exception e) {Log.e("chen", e.toString());}*/super.onStop();}@Overrideprotected void onStart() {playMusic(backMusic);if (chessInfo.isMachine) {if (AIThread.isAlive() == false) {AIThread = new Thread(new Runnable() {@Overridepublic void run() {AIMove(chessInfo.IsRedGo, chessInfo.status);}});AIThread.start();}}super.onStart();}}

规则类 Rule.java


import android.util.Log;import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;import Info.Pos;public class Rule {public static int[][] area = new int[][]{{1, 1, 1, 2, 2, 2, 1, 1, 1},{1, 1, 1, 2, 2, 2, 1, 1, 1},{1, 1, 1, 2, 2, 2, 1, 1, 1},{1, 1, 1, 1, 1, 1, 1, 1, 1},{1, 1, 1, 1, 1, 1, 1, 1, 1},{3, 3, 3, 3, 3, 3, 3, 3, 3},{3, 3, 3, 3, 3, 3, 3, 3, 3},{3, 3, 3, 4, 4, 4, 3, 3, 3},{3, 3, 3, 4, 4, 4, 3, 3, 3},{3, 3, 3, 4, 4, 4, 3, 3, 3},};//走棋规则public static int[][] offsetX = new int[][]{{0, 0, 1, -1},             //帅 将{1, 1, -1, -1},            //仕 士{2, 2, -2, -2},            //相 象{1, 1, -1, -1},            //象眼{1, 1, -1, -1, 2, 2, -2, -2},  //马{0, 0, 0, 0, 1, 1, -1, -1},    //蹩马腿{0},                    //卒{-1, 0, 1},               //过河卒{0},                    //兵{-1, 0, 1},               //过河兵{1, 1, -1, -1, 1, 1, -1, -1},  //反向蹩马腿};public static int[][] offsetY = new int[][]{{1, -1, 0, 0},             //帅 将{1, -1, 1, -1},            //仕 士{2, -2, 2, -2},            //相 象{1, -1, 1, -1},            //象眼{2, -2, 2, -2, 1, -1, 1, -1},  //马{1, -1, 1, -1, 0, 0, 0, 0},    //蹩马腿{1},                    //卒{0, 1, 0},                //过河卒{-1},                   //兵{0, -1, 0},               //过河兵{1, -1, 1, -1, 1, -1, 1, -1},  //反向蹩马腿};//生成某个位置的棋子的所有可能走法的位置public static List<Pos> PossibleMoves(int[][] piece, int fromX, int fromY, int PieceID) {List<Pos> ret = new ArrayList<Pos>();int num;switch (PieceID) {case 1://黑将num = 0;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) == 2 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}Pos eatPos1 = flyKing(1, fromX, fromY, piece);if (eatPos1.equals(new Pos(-1, -1)) == false) {ret.add(eatPos1);}break;case 2://黑士num = 1;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) == 2 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}break;case 3://黑象num = 2;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];int blockX = fromX + offsetX[num + 1][i];int blockY = fromY + offsetY[num + 1][i];if (InArea(toX, toY) >= 1 && InArea(toX, toY) <= 2 && IsSameSide(PieceID, piece[toY][toX]) == false && piece[blockY][blockX] == 0) {ret.add(new Pos(toX, toY));}}break;case 4://黑马case 11://红马num = 4;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];int blockX = fromX + offsetX[num + 1][i];int blockY = fromY + offsetY[num + 1][i];if (InArea(toX, toY) != 0 && IsSameSide(PieceID, piece[toY][toX]) == false && piece[blockY][blockX] == 0) {ret.add(new Pos(toX, toY));}}break;case 5://黑车case 12: //红车for (int i = fromY + 1; i < 10; i++) {//向下走if (CanMove(1, fromX, fromY, fromX, i, piece)) { //可以走时ret.add(new Pos(fromX, i));} else {//不可以走时直接 breakbreak;}}for (int i = fromY - 1; i > -1; i--) {//向上走if (CanMove(1, fromX, fromY, fromX, i, piece)) {//可以走时ret.add(new Pos(fromX, i));} else {//不可以走时break;}}for (int j = fromX - 1; j > -1; j--) {//向走走if (CanMove(1, fromX, fromY, j, fromY, piece)) {//可以走时ret.add(new Pos(j, fromY));} else {//不可以走时break;}}for (int j = fromX + 1; j < 9; j++) {//向右走if (CanMove(1, fromX, fromY, j, fromY, piece)) {//可以走时ret.add(new Pos(j, fromY));} else {//不可以走时break;}}/*for (int i = 0; i < 9; i++) {for (int j = 0; j < 10; j++) {if (i != fromX || j != fromY) {if (CanMove(1, fromX, fromY, i, j, piece)) {ret.add(new Pos(i, j));}}}}*/break;case 6://黑炮case 13://红炮for (int i = fromY + 1; i < 10; i++) {//向下走if (CanMove(2, fromX, fromY, fromX, i, piece)) { //可以走时ret.add(new Pos(fromX, i));}}for (int i = fromY - 1; i > -1; i--) {//向上走if (CanMove(2, fromX, fromY, fromX, i, piece)) {//可以走时ret.add(new Pos(fromX, i));}}for (int j = fromX - 1; j > -1; j--) {//向走走if (CanMove(2, fromX, fromY, j, fromY, piece)) {//可以走时ret.add(new Pos(j, fromY));}}for (int j = fromX + 1; j < 9; j++) {//向右走if (CanMove(2, fromX, fromY, j, fromY, piece)) {//可以走时ret.add(new Pos(j, fromY));}}/*for (int i = 0; i < 9; i++) {for (int j = 0; j < 10; j++) {if (i != fromX || j != fromY) {if (CanMove(2, fromX, fromY, i, j, piece)) {ret.add(new Pos(i, j));}}}}*/break;case 7://黑卒if (InArea(fromX, fromY) == 1) {num = 6;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) != 0 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}} else {num = 7;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) != 0 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}}break;case 8://红帅num = 0;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) == 4 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}Pos eatPos2 = flyKing(2, fromX, fromY, piece);if (eatPos2.equals(new Pos(-1, -1)) == false) {ret.add(eatPos2);}break;case 9://红士num = 1;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) == 4 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}break;case 10://红象num = 2;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];int blockX = fromX + offsetX[num + 1][i];int blockY = fromY + offsetY[num + 1][i];if (InArea(toX, toY) >= 3 && InArea(toX, toY) <= 4 && IsSameSide(PieceID, piece[toY][toX]) == false && piece[blockY][blockX] == 0) {ret.add(new Pos(toX, toY));}}break;case 14://红兵if (InArea(fromX, fromY) == 3) {num = 8;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) != 0 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}} else {num = 9;for (int i = 0; i < offsetX[num].length; i++) {int toX = fromX + offsetX[num][i];int toY = fromY + offsetY[num][i];if (InArea(toX, toY) != 0 && IsSameSide(PieceID, piece[toY][toX]) == false) {ret.add(new Pos(toX, toY));}}}break;default:break;}return ret;}//判断将、帅是否已经被将军public static boolean isKingDanger(int[][] piece, boolean isRedKing) {int num = 4;int op_block_num = 10;if (isRedKing == true) {int x = 0, y = 0;boolean flag = false;for (y = 7; y <= 9; y++) {for (x = 3; x <= 5; x++) {if (piece[y][x] == 8) {flag = true;break;}}if (flag) break;}for (int i = 0; i < offsetX[num].length; i++) {     //马int toX = x + offsetX[num][i];int toY = y + offsetY[num][i];int blockX = x + offsetX[op_block_num][i];int blockY = y + offsetY[op_block_num][i];if (InArea(toX, toY) != 0 && piece[toY][toX] == 4 && piece[blockY][blockX] == 0) {return true;}}for (int i = 5; i <= 6; i++) {  //车 炮List<Pos> moves = PossibleMoves(piece, x, y, i + 7);Iterator<Pos> it = moves.iterator();while (it.hasNext()) {Pos pos = it.next();if (piece[pos.y][pos.x] == i) {return true;}}}if (flyKing(2, x, y, piece).equals(new Pos(-1, -1)) == false) { //将return true;}if (piece[y - 1][x] == 7 || piece[y][x - 1] == 7 || piece[y][x + 1] == 7) {return true;}} else {int x = 0, y = 0;boolean flag = false;for (y = 0; y <= 2; y++) {for (x = 3; x <= 5; x++) {if (piece[y][x] == 1) {flag = true;break;}}if (flag) break;}for (int i = 0; i < offsetX[num].length; i++) {     //马int toX = x + offsetX[num][i];int toY = y + offsetY[num][i];int blockX = x + offsetX[op_block_num][i];int blockY = y + offsetY[op_block_num][i];if (InArea(toX, toY) != 0 && piece[toY][toX] == 11 && piece[blockY][blockX] == 0) {return true;}}for (int i = 12; i <= 13; i++) {  //车 炮List<Pos> moves = PossibleMoves(piece, x, y, i - 7);Iterator<Pos> it = moves.iterator();while (it.hasNext()) {Pos pos = it.next();if (piece[pos.y][pos.x] == i) {return true;}}}if (flyKing(1, x, y, piece).equals(new Pos(-1, -1)) == false) { //将return true;}if (piece[y + 1][x] == 14 || piece[y][x - 1] == 14 || piece[y][x + 1] == 14) {return true;}}return false;}//判断将、帅是否已经被将军public static boolean isDead(int[][] piece, boolean isRedKing) {if (isRedKing == true) {for (int i = 0; i <= 9; i++) {for (int j = 0; j <= 8; j++) {if (piece[i][j] >= 8 && piece[i][j] <= 14) {List<Pos> moves = PossibleMoves(piece, j, i, piece[i][j]);Iterator<Pos> it = moves.iterator();while (it.hasNext()) {Pos pos = it.next();int tmp = piece[pos.y][pos.x];if (tmp == 1) {return false;}piece[pos.y][pos.x] = piece[i][j];piece[i][j] = 0;if (isKingDanger(piece, true) == false) {piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;return false;}piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;}}}}} else {for (int i = 0; i <= 9; i++) {for (int j = 0; j <= 8; j++) {if (piece[i][j] >= 1 && piece[i][j] <= 7) {List<Pos> moves = PossibleMoves(piece, j, i, piece[i][j]);Iterator<Pos> it = moves.iterator();while (it.hasNext()) {Pos pos = it.next();int tmp = piece[pos.y][pos.x];if (tmp == 8) {return false;}piece[pos.y][pos.x] = piece[i][j];piece[i][j] = 0;if (isKingDanger(piece, false) == false) {piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;return false;}piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;}}}}}return true;}//0 棋盘外 1 黑盘 2 黑十字(九宫) 3 红盘 4 红十字(九宫)public static int InArea(int x, int y) {if (x < 0 || x > 8 || y < 0 || y > 9) {return 0;}return area[y][x];}//判断棋子是否为同一方public static boolean IsSameSide(int fromID, int toID) {if (toID == 0) {return false;}if ((fromID <= 7 && toID <= 7) || (fromID >= 8 && toID >= 8)) {return true;} else {return false;}}//判断将、帅是否见面public static Pos flyKing(int id, int fromX, int fromY, int[][] piece) {int cnt = 0;boolean flag = false;int i;if (id == 1) {  //将for (i = fromY + 1; i <= 9; i++) {if (piece[i][fromX] > 0 && piece[i][fromX] != 8) {cnt++;} else if (piece[i][fromX] == 8) {flag = true;break;}}} else {       //帅for (i = fromY - 1; i >= 0; i--) {if (piece[i][fromX] > 0 && piece[i][fromX] != 1) {cnt++;} else if (piece[i][fromX] == 1) {flag = true;break;}}}if (cnt == 0 && flag == true) {return new Pos(fromX, i);} else {return new Pos(-1, -1);}}//判断是否可以移动public static boolean CanMove(int id, int fromX, int fromY, int toX, int toY, int[][] piece) {if (fromX == 10 || fromY == 10 || toX == 10 || toY == 10) {Log.e("chen", String.valueOf(fromX) + " " + String.valueOf(fromY) + " " + String.valueOf(toX) + " " + String.valueOf(toY));}if ((fromX != toX && fromY != toY) || IsSameSide(piece[fromY][fromX], piece[toY][toX]) == true) {return false;}if (id == 1) {  //车int start, finish;if (fromX == toX) {if (fromY < toY) {start = fromY + 1;finish = toY;} else {start = toY + 1;finish = fromY;}for (int i = start; i < finish; i++) {if (piece[i][fromX] != 0) {return false;}}} else {if (fromX < toX) {start = fromX + 1;finish = toX;} else {start = toX + 1;finish = fromX;}for (int i = start; i < finish; i++) {if (piece[fromY][i] != 0) {return false;}}}} else {   //炮if (piece[toY][toX] == 0) {int start, finish;if (fromX == toX) {if (fromY < toY) {start = fromY + 1;finish = toY;} else {start = toY + 1;finish = fromY;}for (int i = start; i < finish; i++) {if (piece[i][fromX] != 0) {return false;}}} else {if (fromX < toX) {start = fromX + 1;finish = toX;} else {start = toX + 1;finish = fromX;}for (int i = start; i < finish; i++) {if (piece[fromY][i] != 0) {return false;}}}} else {int start, finish;int count = 0;if (fromX == toX) {if (fromY < toY) {start = fromY + 1;finish = toY;} else {start = toY + 1;finish = fromY;}for (int i = start; i < finish; i++) {if (piece[i][fromX] != 0) {count++;}}} else {if (fromX < toX) {start = fromX + 1;finish = toX;} else {start = toX + 1;finish = fromX;}for (int i = start; i < finish; i++) {if (piece[fromY][i] != 0) {count++;}}}if (count != 1) {return false;}}}return true;}//判断是否为红方,如果不是,则反转。public static Pos reversePos(Pos pos, boolean IsReverse) {return (IsReverse == false) ? pos : new Pos(8 - pos.x, 9 - pos.y);}
}

AI.java


import Info.Pos;
import ChessMove.Rule;import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;import static com.example.a77304.chessgame.HomeActivity.zobrist;
import static com.example.a77304.chessgame.PvMActivity.transformTable;public class AI {//棋子力价值表public static int[][][] pieceValue = new int[][][]{//黑将{{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},},//黑士{{0, 0, 0, 20, 0, 20, 0, 0, 0},{0, 0, 0, 0, 23, 0, 0, 0, 0},{0, 0, 0, 20, 0, 20, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},},//黑象{{0, 0, 20, 0, 0, 0, 20, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{18, 0, 0, 0, 23, 0, 0, 0, 18},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 20, 0, 0, 0, 20, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},},//黑马{{88, 85, 90, 88, 90, 88, 90, 85, 88},{85, 90, 92, 93, 78, 93, 92, 90, 85},{93, 92, 94, 95, 92, 95, 94, 92, 93},{92, 94, 98, 95, 98, 95, 98, 94, 92},{90, 98, 101, 102, 103, 102, 101, 98, 90},{90, 100, 99, 103, 104, 103, 99, 100, 90},{93, 108, 100, 107, 100, 107, 100, 108, 93},{92, 98, 99, 103, 99, 103, 99, 98, 92},{90, 96, 103, 97, 94, 97, 103, 96, 90},{90, 90, 90, 96, 90, 96, 90, 90, 90},},//黑车{{194, 206, 204, 212, 200, 212, 204, 206, 194},{200, 208, 206, 212, 200, 212, 206, 208, 200},{198, 208, 204, 212, 212, 212, 204, 208, 198},{204, 209, 204, 212, 214, 212, 204, 209, 204},{208, 212, 212, 214, 215, 214, 212, 212, 208},{208, 211, 211, 214, 215, 214, 211, 211, 208},{206, 213, 213, 216, 216, 216, 213, 213, 206},{206, 208, 207, 214, 216, 214, 207, 208, 206},{206, 212, 209, 216, 233, 216, 209, 212, 206},{206, 208, 207, 213, 214, 213, 207, 208, 206},},//黑炮{{96, 96, 97, 99, 99, 99, 97, 96, 96},{96, 97, 98, 98, 98, 98, 98, 97, 96},{97, 96, 100, 99, 101, 99, 100, 96, 97},{96, 96, 96, 96, 96, 96, 96, 96, 96},{95, 96, 99, 96, 100, 96, 99, 96, 95},{96, 96, 96, 96, 100, 96, 96, 96, 96},{96, 99, 99, 98, 100, 98, 99, 99, 96},{97, 97, 96, 91, 92, 91, 96, 97, 97},{98, 98, 96, 92, 89, 92, 96, 98, 98},{100, 100, 96, 91, 90, 91, 96, 100, 100},},//黑卒{{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{7, 0, 7, 0, 15, 0, 7, 0, 7},{7, 0, 13, 0, 16, 0, 13, 0, 7},{14, 18, 20, 27, 29, 27, 20, 18, 14},{19, 23, 27, 29, 30, 29, 27, 23, 19},{19, 24, 32, 37, 37, 37, 32, 24, 19},{19, 24, 34, 42, 44, 42, 34, 24, 19},{9, 9, 9, 11, 13, 11, 9, 9, 9},},//红帅{{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0},{0, 0, 0, 8888, 8888, 8888, 0, 0, 0}},//红士{{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 20, 0, 20, 0, 0, 0},{0, 0, 0, 0, 23, 0, 0, 0, 0},{0, 0, 0, 20, 0, 20, 0, 0, 0}},//红象{{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 20, 0, 0, 0, 20, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{18, 0, 0, 0, 23, 0, 0, 0, 18},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 20, 0, 0, 0, 20, 0, 0}},//红马{{90, 90, 90, 96, 90, 96, 90, 90, 90},{90, 96, 103, 97, 94, 97, 103, 96, 90},{92, 98, 99, 103, 99, 103, 99, 98, 92},{93, 108, 100, 107, 100, 107, 100, 108, 93},{90, 100, 99, 103, 104, 103, 99, 100, 90},{90, 98, 101, 102, 103, 102, 101, 98, 90},{92, 94, 98, 95, 98, 95, 98, 94, 92},{93, 92, 94, 95, 92, 95, 94, 92, 93},{85, 90, 92, 93, 78, 93, 92, 90, 85},{88, 85, 90, 88, 90, 88, 90, 85, 88}},//红车{{206, 208, 207, 213, 214, 213, 207, 208, 206},{206, 212, 209, 216, 233, 216, 209, 212, 206},{206, 208, 207, 214, 216, 214, 207, 208, 206},{206, 213, 213, 216, 216, 216, 213, 213, 206},{208, 211, 211, 214, 215, 214, 211, 211, 208},{208, 212, 212, 214, 215, 214, 212, 212, 208},{204, 209, 204, 212, 214, 212, 204, 209, 204},{198, 208, 204, 212, 212, 212, 204, 208, 198},{200, 208, 206, 212, 200, 212, 206, 208, 200},{194, 206, 204, 212, 200, 212, 204, 206, 194}},//红炮{{100, 100, 96, 91, 90, 91, 96, 100, 100},{98, 98, 96, 92, 89, 92, 96, 98, 98},{97, 97, 96, 91, 92, 91, 96, 97, 97},{96, 99, 99, 98, 100, 98, 99, 99, 96},{96, 96, 96, 96, 100, 96, 96, 96, 96},{95, 96, 99, 96, 100, 96, 99, 96, 95},{96, 96, 96, 96, 96, 96, 96, 96, 96},{97, 96, 100, 99, 101, 99, 100, 96, 97},{96, 97, 98, 98, 98, 98, 98, 97, 96},{96, 96, 97, 99, 99, 99, 97, 96, 96}},//红兵{{9, 9, 9, 11, 13, 11, 9, 9, 9},{19, 24, 34, 42, 44, 42, 34, 24, 19},{19, 24, 32, 37, 37, 37, 32, 24, 19},{19, 23, 27, 29, 30, 29, 27, 23, 19},{14, 18, 20, 27, 29, 27, 20, 18, 14},{7, 0, 13, 0, 16, 0, 13, 0, 7},{7, 0, 7, 0, 15, 0, 7, 0, 7},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0},{0, 0, 0, 0, 0, 0, 0, 0, 0}}};public static final int INF = 0x3f3f3f3f;   //正无穷大public static final int Win = 88888;public static final int hashfEXACT = 1;public static final int hashfALPHA = 2;public static final int hashfBETA = 3;public static boolean isMachineRed;public static int ZobristKey;public static long ZobristKeyCheck;public static int maxDepth;public static int goodValue;public static int[][][][] historyTable = new int[9][10][9][10];  //历史表public static int searchCnt = 0;public AI() {}//迭代加深public static Move getBestMove(int[][] piece, boolean isRedGo, int depth, int startZobristKey, long startZobristKeyCheck, Map<Long, Integer> ZobristInfo) {int[][] pieceClone = new int[10][9];for (int i = 0; i <= 9; i++) {pieceClone[i] = piece[i].clone();}searchCnt = 0;Move goodMove = new Move(new Pos(-1, -1), new Pos(-1, -1));Move bestMove = new Move(new Pos(-1, -1), new Pos(-1, -1));clearHistory();for (int i = 2; i <= depth; i += 2) {goodMove = getGoodMove(pieceClone, isRedGo, i, startZobristKey, startZobristKeyCheck, ZobristInfo);if (goodValue >= -Win / 2) {bestMove = goodMove;}}if (bestMove.fromPos.equals(new Pos(-1, -1)) == true) {bestMove = getLegalMove(pieceClone, isRedGo);}//Log.i("博弈树搜索算法比对","搜索结点数:"+String.valueOf(searchCnt));return bestMove;}//PVS+置换表+历史表public static Move getGoodMove(int[][] piece, boolean isRedGo, int depth, int startZobristKey, long startZobristKeyCheck, Map<Long, Integer> ZobristInfo) {Move goodMove = new Move(new Pos(-1, -1), new Pos(-1, -1));isMachineRed = isRedGo;boolean FoundPv = false;int value = -INF;int alpha = -INF, beta = INF;boolean isKingAlive = true;ZobristKey = startZobristKey;ZobristKeyCheck = startZobristKeyCheck;maxDepth = depth;LinkedList<Move> sortedMoves = allPossibleMoves(piece, isRedGo, depth, alpha, beta);Iterator<Move> it = sortedMoves.iterator();while (it.hasNext()) {Move move = it.next();Pos fromPos = move.fromPos;Pos toPos = move.toPos;int pieceID = piece[toPos.y][toPos.x];piece[toPos.y][toPos.x] = piece[fromPos.y][fromPos.x];piece[fromPos.y][fromPos.x] = 0;updateZobrist(fromPos, toPos, piece[toPos.y][toPos.x], pieceID);if (pieceID == 1 || pieceID == 8) {isKingAlive = false;}if (ZobristInfo.get(ZobristKeyCheck) != null) {value = -INF;} else {if (FoundPv) {value = -PVS(piece, (isRedGo == true) ? false : true, depth - 1, -alpha - 1, -alpha, isKingAlive);if ((value > alpha) && (value < beta)) {value = -PVS(piece, (isRedGo == true) ? false : true, depth - 1, -beta, -alpha, isKingAlive);}} else {value = -PVS(piece, (isRedGo == true) ? false : true, depth - 1, -beta, -alpha, isKingAlive);}}updateZobrist(fromPos, toPos, piece[toPos.y][toPos.x], pieceID);piece[fromPos.y][fromPos.x] = piece[toPos.y][toPos.x];piece[toPos.y][toPos.x] = pieceID;if (pieceID == 1 || pieceID == 8) {isKingAlive = true;}if (value > alpha) {alpha = value;FoundPv = true;goodMove = new Move(fromPos, toPos);}}goodValue = alpha;addHistory(goodMove.fromPos, goodMove.toPos, (maxDepth - depth + 1) * (maxDepth - depth + 1));return goodMove;}//通过算法获得最佳结果public static int PVS(int[][] piece, boolean isRedGo, int depth, int alpha, int beta, boolean isKingAlive) {int value = transformTable.readTransformTable(ZobristKey, ZobristKeyCheck, maxDepth - depth, alpha, beta);   //局面评分if (value != INF) {return value;}if (isKingAlive == false) {if (isMachineRed == true && isRedGo == true) {return -Win + (maxDepth - depth);} else if (isMachineRed == true && isRedGo == false) {return Win - (maxDepth - depth);} else if (isMachineRed == false && isRedGo == true) {return Win - (maxDepth - depth);} else {return -Win + (maxDepth - depth);}}if (depth <= 0) {searchCnt++;if (Rule.isDead(piece, isMachineRed)) {value = -Win + (maxDepth - depth + 2);} else {value = evaluate(piece);}return value;}boolean FoundPv = false;int hashf = hashfALPHA;int fatherZobristKey = ZobristKey;long fatherZobristKeyCheck = ZobristKeyCheck;value = -INF;Move goodMove = new Move(new Pos(-1, -1), new Pos(-1, -1));LinkedList<Move> sortedMoves = allPossibleMoves(piece, isRedGo, depth, alpha, beta);Iterator<Move> it = sortedMoves.iterator();while (it.hasNext()) {Move move = it.next();Pos fromPos = move.fromPos;Pos toPos = move.toPos;int pieceID = piece[toPos.y][toPos.x];if (maxDepth == 6 && depth == 1 && pieceID == 0) continue;piece[toPos.y][toPos.x] = piece[fromPos.y][fromPos.x];piece[fromPos.y][fromPos.x] = 0;updateZobrist(fromPos, toPos, piece[toPos.y][toPos.x], pieceID);if (pieceID == 1 || pieceID == 8) {isKingAlive = false;}if (FoundPv) {value = -PVS(piece, (isRedGo == true) ? false : true, depth - 1, -alpha - 1, -alpha, isKingAlive);if ((value > alpha) && (value < beta)) {value = -PVS(piece, (isRedGo == true) ? false : true, depth - 1, -beta, -alpha, isKingAlive);}} else {value = -PVS(piece, (isRedGo == true) ? false : true, depth - 1, -beta, -alpha, isKingAlive);}updateZobrist(fromPos, toPos, piece[toPos.y][toPos.x], pieceID);piece[fromPos.y][fromPos.x] = piece[toPos.y][toPos.x];piece[toPos.y][toPos.x] = pieceID;if (pieceID == 1 || pieceID == 8) {isKingAlive = true;}if (value >= beta) {transformTable.saveTransformTable(fatherZobristKey, fatherZobristKeyCheck, maxDepth - depth, beta, hashfBETA);addHistory(fromPos, toPos, (maxDepth - depth + 1) * (maxDepth - depth + 1));return beta;}if (value > alpha) {alpha = value;FoundPv = true;hashf = hashfEXACT;goodMove = new Move(fromPos, toPos);}}transformTable.saveTransformTable(fatherZobristKey, fatherZobristKeyCheck, maxDepth - depth, alpha, hashf);if (hashf == hashfEXACT) {addHistory(goodMove.fromPos, goodMove.toPos, (maxDepth - depth + 1) * (maxDepth - depth + 1));}return alpha;}//生成所有可能走法public static LinkedList<Move> allPossibleMoves(int[][] piece, boolean isRedGo, int depth, int alpha, int beta) {LinkedList<Move> sortedMoves = new LinkedList<Move>();LinkedList<Move> transformMoves = new LinkedList<Move>();LinkedList<Move> eatMoves = new LinkedList<Move>();LinkedList<Move> historyMoves = new LinkedList<Move>();//遍历整个棋盘for (int i = 0; i <= 9; i++) {for (int j = 0; j <= 8; j++) {if ((isRedGo == false && piece[i][j] >= 1 && piece[i][j] <= 7) || (isRedGo == true && piece[i][j] >= 8 && piece[i][j] <= 14)) {List<Pos> ret = Rule.PossibleMoves(piece, j, i, piece[i][j]);  //某个位置的棋子的全部走法Pos fromPos = new Pos(j, i);Iterator<Pos> it = ret.iterator();while (it.hasNext()) {Pos toPos = it.next();updateZobrist(fromPos, toPos, piece[fromPos.y][fromPos.x], piece[toPos.y][toPos.x]);if (transformTable.readTransformTable(ZobristKey, ZobristKeyCheck, maxDepth - depth, alpha, beta) != INF) {transformMoves.add(new Move(fromPos, toPos));} else {if (piece[toPos.y][toPos.x] != 0) {eatMoves.add(new Move(fromPos, toPos));} else {if (historyMoves.isEmpty()) {historyMoves.add(new Move(fromPos, toPos));} else {Move firstMove = historyMoves.getFirst();int firstVal = getHistory(firstMove.fromPos, firstMove.toPos);int curVal = getHistory(fromPos, toPos);if (curVal >= firstVal) {historyMoves.addFirst(new Move(fromPos, toPos));} else {historyMoves.addLast(new Move(fromPos, toPos));}}}}updateZobrist(fromPos, toPos, piece[fromPos.y][fromPos.x], piece[toPos.y][toPos.x]);}}}}sortedMoves.addAll(transformMoves);sortedMoves.addAll(eatMoves);sortedMoves.addAll(historyMoves);return sortedMoves;}public static void clearHistory() {for (int i = 0; i < 9; i++) {for (int j = 0; j < 10; j++) {for (int k = 0; k < 9; k++) {for (int p = 0; p < 10; p++) {historyTable[i][j][k][p] = historyTable[i][j][k][p] = 0;}}}}}public static int getHistory(Pos fromPos, Pos toPos) {return historyTable[fromPos.x][fromPos.y][toPos.x][toPos.y];}public static void addHistory(Pos fromPos, Pos toPos, int val) {historyTable[fromPos.x][fromPos.y][toPos.x][toPos.y] += val;}public static void updateZobrist(Pos fromPos, Pos toPos, int fromID, int toID) {ZobristKey = ZobristKey ^ zobrist.ZobristTable[fromID - 1][fromPos.y][fromPos.x];ZobristKeyCheck = ZobristKeyCheck ^ zobrist.ZobristTableCheck[fromID - 1][fromPos.y][fromPos.x];ZobristKey = ZobristKey ^ zobrist.ZobristTable[fromID - 1][toPos.y][toPos.x];ZobristKeyCheck = ZobristKeyCheck ^ zobrist.ZobristTableCheck[fromID - 1][toPos.y][toPos.x];if (toID > 0) {ZobristKey = ZobristKey ^ zobrist.ZobristTable[toID - 1][toPos.y][toPos.x];ZobristKeyCheck = ZobristKeyCheck ^ zobrist.ZobristTableCheck[toID - 1][toPos.y][toPos.x];}}//局面评分public static int evaluate(int[][] piece) {int score = 0;for (int i = 0; i <= 9; i++) {for (int j = 0; j <= 8; j++) {if (piece[i][j] >= 1 && piece[i][j] <= 7) {score += pieceValue[piece[i][j] - 1][i][j];} else if (piece[i][j] >= 8 && piece[i][j] <= 14) {score -= pieceValue[piece[i][j] - 1][i][j];}}}if (isMachineRed) score *= -1;return score;}//判断是否有杀招走法public static Move getLegalMove(int piece[][], boolean isRedKing) {   //参数true表示红棋if (isRedKing == true) {for (int i = 0; i <= 9; i++) {for (int j = 0; j <= 8; j++) {if (piece[i][j] >= 8 && piece[i][j] <= 14) {//生成某个位置的棋子的所有走法的位置List<Pos> moves = Rule.PossibleMoves(piece, j, i, piece[i][j]);Iterator<Pos> it = moves.iterator();while (it.hasNext()) {Pos pos = it.next();int tmp = piece[pos.y][pos.x]; //标记可以走的位置的其他棋子号if (tmp == 1) {  //当前棋子下一步可以吃掉黑方将return new Move(new Pos(j, i), pos);   //返回杀招的走法}piece[pos.y][pos.x] = piece[i][j];piece[i][j] = 0;if (Rule.isKingDanger(piece, true) == false) {  //非当前棋子的可以吃掉将piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;return new Move(new Pos(j, i), pos);   //返回杀招的走法}piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;}}}}} else {    //参数false表示黑棋for (int i = 0; i <= 9; i++) {for (int j = 0; j <= 8; j++) {if (piece[i][j] >= 1 && piece[i][j] <= 7) {List<Pos> moves = Rule.PossibleMoves(piece, j, i, piece[i][j]);Iterator<Pos> it = moves.iterator();while (it.hasNext()) {Pos pos = it.next();int tmp = piece[pos.y][pos.x];if (tmp == 8) {return new Move(new Pos(j, i), pos);}piece[pos.y][pos.x] = piece[i][j];piece[i][j] = 0;if (Rule.isKingDanger(piece, false) == false) {piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;return new Move(new Pos(j, i), pos);}piece[i][j] = piece[pos.y][pos.x];piece[pos.y][pos.x] = tmp;}}}}}return new Move(new Pos(-1, -1), new Pos(-1, -1));}
}

未完......

点击下载资源

Android studio中国象棋,下棋思路与代码实现相关推荐

  1. android飞机大战项目描述,Android studio 飞机大战项目思路和代码

    整体思路 先背景 绘制玩家飞机,玩家飞机随触摸点移动 绘制boss飞机,自动移动 绘制子弹,分别从玩家飞机和boss飞机发射 绘制爆装效果,由子弹触发 绘制血量,玩家血量为0触发死亡画面,boss血量 ...

  2. 朋友写的一个中国象棋游戏,JAVA代码

    朋友写的一个中国象棋游戏,JAVA代码.有兴趣的可以这里下载:中国象棋下载 (1)地址,不知现在还能下否....中国象棋历史悠久,吸引了无数的人研究,现对中国象棋的对战和实现棋谱的制作做如下的设计和说 ...

  3. Android Studio使用小技巧:提取方法代码片段

    今天,讲讲android studio使用的小技巧.把代码直接提取一个函数. 有些时候我们在一个方法内部写了过多的代码,然后想要把一些代码提取出来再放在一个单独的方法里,通常我们的做法是复制粘贴,现在 ...

  4. Android课程---Android Studio使用小技巧:提取方法代码片段

    这篇文章主要介绍了Android Studio使用小技巧:提取方法代码片段,本文分享了一个快速复制粘贴方法代码片段的小技巧,并用GIF图演示,需要的朋友可以参考下 今天来给大家介绍一个非常有用的Stu ...

  5. android登录操作代码,Android Studio实现第三方QQ登录操作代码

    来看看效果图吧 实现QQ登录了, 新建一个项目工程 ,然后把我们刚才下载的SDK解压将jar文件夹中的jar包拷贝到我们的项目libs中 导入一个下面架包就可以 项目结构如下 打开我们的清单文件And ...

  6. 如何将Android Studio与华为软件开发云代码仓库无缝对接(二)

    上篇文章:如何将Android Studio与华为软件开发云代码仓库无缝对接(一) 上一章讲了,如何用Android Studio以软件开发云代码仓库为基础,新建一个项目.接下来,这一章继续讲建好项目 ...

  7. Android Studio在xml文件中编写代码时,关键词没有代码提示补全

    问题描述: Android Studio在xml文件中编写代码时,无法自动补全 例如在TextView中输入textSize,没有出现任何代码提示 解决方式: File->Project Str ...

  8. Android游戏: 中国象棋-局域网版

    实现环境: android studio 3.2.1, 手机分辨率为: 1920 * 1080 局域网 UDP 连接 分主活动类,棋类,主机类 代码如下: 清单文件要添加的权限: <uses-p ...

  9. android studio mvpplugin,MVPHelper Android Studio 插件,一键生成 MVP 代码接口以及实现类。 @codeKK Android开源站...

    一款适用于 Intellij IDEA 和 Android Studio 的插件, 可用于为 MVP 架构生成接口以及实现类, 解放双手. 欢迎 Issue Report, 欢迎 Feature Re ...

最新文章

  1. JS 总结之原型继承的几种方式
  2. laravel 项目迁移_在Laravel迁移
  3. Spring的两种代理方式:JDK动态代理和CGLIB动态代理
  4. django-模型类字段选项
  5. Python使用Queue对象实现多线程同步小案例
  6. api es7 删除所有数据_【Elasticsearch7.0】文档接口之查询delete接口
  7. H5活动页面抽奖源码
  8. EXCEL日期格式不一致设置统一显示格式的方法
  9. 同样是VPS,为什么RAKsmart更受欢迎
  10. [英语] 自建专业词典
  11. 2020 全国大学生数学建模竞赛C题思路+代码
  12. 寻找鲁菜——美食江山寻味记之三·胶东人家
  13. UE4 C++ 动态读取图片
  14. 电机编码器的使用方法
  15. PostgresQL窗口函数 last_value未返回预期结果原因排查
  16. 周庄王,姬佗(公元前696年—公元前682年在位)
  17. list.toArray()方法
  18. 计算机课代表专业演讲稿,课代表发言稿优秀范文3篇
  19. 做时间的记录者—手机摄影达人20天养成计划
  20. 打印机故障处理【以MP 3054sp 打印机为例】

热门文章

  1. k8s高可用集群安装
  2. Cloudreve自建云盘实站:容量和速度自己来决定
  3. KnowHowChain(脑海链)进度报告——9月15日-9月30日
  4. 2020年全球网速排名
  5. C++ Primer读书笔记
  6. 市面所有民营电信运营商套餐资费
  7. ABBYY FineReader 12激活教程
  8. 用JQuery写出农场的小游戏
  9. Web3D发展趋势以及Web3D应用场景
  10. 微信公众号网页授权登录的超简单实现步骤