用GridView做国际象棋

xiaoxiao2021-02-28  20

     最近写了一个国际象棋,写之前一直参考网上的例子,发现基本上都是运用画布,画笔等工具写的。自己也试了一试,但是因为自己本身是一名软件行业的新手,能力有限,并没有成功,见笑了。。。

    最后痛定思痛,捋清思路,运用GridView成功的写了出来,集思广益,有些不严谨的地方或者有bug希望指出来,直接上代码。

    首先将每个国际象棋的黑白格看作是一个item,那么势必需要一个适配器,所以这里我写了一个ChessAdapter,数据源是List<ChessPiece>,然后每个种类的棋子类作为子类并继承这个象棋类(ChessPiece)的父类(具体的看代码,一看便懂)。

   我们在ChessActivity中定义一个集合作为adapter的数据源,并进行数据的加载,分别存放黑白棋的标识、棋子图片、每个棋子独有的标识、是否移动过的标识(因国际象棋规则需要)。

/** * 加载数据 */ private void loadData() { chessPieceList.add(new ChessPiece("1", R.drawable.blackrook, 1, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackknight, 2, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackbishop, 3, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackqueen, 4, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackking, 5, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackbishop, 3, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackknight, 2, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackrook, 1, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 101, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 102, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 103, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 104, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 105, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 106, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 107, 0)); chessPieceList.add(new ChessPiece("1", R.drawable.blackpawn, 108, 0)); for (int i = 0; i < 32; i++) { chessPieceList.add(new ChessPiece("0", 22, 0, 0)); } chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 201, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 202, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 203, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 204, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 205, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 206, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 207, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitepawn, 208, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whiterook, 6, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whiteknight, 7, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitebishop, 8, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitequeen, 9, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whiteking, 10, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whitebishop, 8, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whiteknight, 7, 0)); chessPieceList.add(new ChessPiece("2", R.drawable.whiterook, 6, 0)); }

之后在item的点击事件里分别记下选择棋子和确定落子时的坐标StartX,StartY,endX,endY并找到他们与position之间的关系

startY = position / 8; startX = position - 8 * startY;

并分别将坐标值StartX,StartY传递到象棋的子类中去

mPawn.startCoordinate(startX, startY); mKnight.startCoordinate(startX, startY); mBishop.startCoordinate(startX, startY); mQueen.startCoordinate(startX, startY); mRook.startCoordinate(startX, startY); mKing.startCoordinate(startX, startY); mChessAdapter.notifyDataSetChanged();

同理将endX,endY传递进去

mPawn.endCoordinate(endX, endY); mQueen.endCoordinate(endX, endY); mKnight.endCoordinate(endX, endY); mBishop.endCoordinate(endX, endY); mRook.endCoordinate(endX, endY); mKing.endCoordinate(endX, endY);

这时我们需要针对不同棋子的规则进行编写,分别车,马,象,兵,王和王后

车:

public boolean guize() { if (startY - endY == 0) {//横着走 return true; } else if (startX - endX == 0) {//竖着走 return true; } return false; }

马(不象中国象棋有蹩腿的限制,会简单一些):

public boolean guize() { //马走日 if (Math.abs(startX - endX) == 2 && Math.abs(startY - endY) == 1) { return true; } else if (Math.abs(startX - endX) == 1 && Math.abs(startY - endY) == 2) { return true; } return false; }

象:

public boolean guize() { if (Math.abs(startX - endX) == Math.abs(startY - endY)) {//斜着走 return true; } return false; }

兵(兵相对麻烦了写,因为走棋和吃子的方式时不同,但也觉得代码能更简单一些,不过有些短路,希望有更好的意见):

//白色兵走棋的规则 public boolean guizeWhiteFirst() { //白兵是第一次走的时候 if ((startX - endX == 0) && (StartY - endY <= 2)) {//兵的走法 return true; } return false; } //白色兵走棋的规则 public boolean guizeWhite() { //白兵移动过 if ((startX - endX == 0) && (StartY - endY == 1)) {//兵的走法 return true; } return false; } //白色兵吃子的规则 public boolean guizeWhiteEat() { if (Math.abs(startX - endX) == 1 && (StartY - endY == 1)) { return true; } return false; } //黑色兵走棋的规则 public boolean guizeBlackFirst() { //黑兵是第一次走的时候 if ((startX - endX == 0) && (endY - StartY <= 2)) { return true; } return false; } //黑色兵走棋的规则 public boolean guizeBlack() { //黑兵移动过 if ((startX - endX == 0) && (endY - StartY == 1)) { return true; } return false; } //黑色兵吃子的规则 public boolean guizeBlackEat() { if (Math.abs(startX - endX) == 1 && (endY - StartY == 1)) { return true; } return false; }

王(包含长短易位):

public boolean guize() { if (startY - endY == 0 && Math.abs(startX - endX) == 1) {//横着走 return true; } else if (startX - endX == 0 && Math.abs(startY - endY) == 1) {//竖着走 return true; } else if (Math.abs(startX - endX) == Math.abs(startY - endY) && Math.abs(startX - endX) == 1 && Math.abs(startY - endY) == 1) {//斜着走 return true; } return false; } //车王易位(长易位) public boolean longTranslocation() { if (startY - endY == 0 && startX - endX == 2) { return true; } return false; } //车王易位(短易位) public boolean shortTranslocation() { if (startY - endY == 0 && endX - startX == 2) { return true; } return false; }

王后(公认最厉害的棋子,看来国王也是妻管严):

public boolean guize() { if (Math.abs(startX - endX) == Math.abs(startY - endY)) {//斜着走 flage = 1; return true; } else if (startY - endY == 0) {//横着走 flage = 2; return true; } else if (startX - endX == 0) {//竖着走 flage = 2; return true; } return false; }

规则写好了,就要让棋子来按照规则进行移动了(包含了很多的判断,其中吃过路兵这个特殊走法比较复杂)

//落子 private boolean luozi(int position) { //黑色兵 if (chessPieceList.get(oldPosition).getChessPieceColor() == "1" && chessPieceList.get(oldPosition).getFlage() > 100 && chessPieceList.get(oldPosition).getFlage() < 200) { if (!(chessPieceList.get(position).getFlage() == 0)) {//有子 if (mPawn.guizeBlackEat()) {//黑兵吃子 pawnOrRookOrKing(oldPosition, position); return true; } } else if (chessPieceList.get(position).getFlage() == 0) {//无子 int positionLeft = 8 * 4 + (startX - 1); int positionRight = 8 * 4 + (startX + 1); if (chessPieceList.get(positionLeft).getFlage() > 200 && whitePawnFlage == 1 && oldPosition == mWhitePosition + 1) { if (startX - endX == 1 && mPawn.guizeBlackEat()) {//黑兵吃左侧过路兵 pawnOrRookOrKing(oldPosition, position); chessPieceList.get(positionLeft).setDrawable(22);//移除左侧白兵 chessPieceList.get(positionLeft).setChessPieceColor("0"); chessPieceList.get(positionLeft).setFlage(0); whitePawnFlage = 0; return true; } } else if (chessPieceList.get(positionRight).getFlage() > 200 && whitePawnFlage == 1 && oldPosition == mWhitePosition - 1) { if (endX - startX == 1 && mPawn.guizeBlackEat()) {//黑兵吃右侧过路兵 pawnOrRookOrKing(oldPosition, position); chessPieceList.get(positionRight).setDrawable(22);//移除右侧白兵 chessPieceList.get(positionRight).setChessPieceColor("0"); chessPieceList.get(positionRight).setFlage(0); whitePawnFlage = 0; return true; } } //黑兵是否是第一次移动 if (this.Pawn() && mPawn.guizeBlackFirst() && chessPieceList.get(oldPosition).getPawnFlage() == 0) {//当前兵的位置没移动过 pawnOrRookOrKing(oldPosition, position); return true; } else if (mPawn.guizeBlack() && chessPieceList.get(oldPosition).getPawnFlage() == 1) { pawnOrRookOrKing(oldPosition, position); return true; } } } //白色兵 if (chessPieceList.get(oldPosition).getChessPieceColor() == "2" && chessPieceList.get(oldPosition).getFlage() > 200) { if (!(chessPieceList.get(position).getFlage() == 0)) {//有子 if (mPawn.guizeWhiteEat()) {//白兵吃子 pawnOrRookOrKing(oldPosition, position); return true; } } else if (chessPieceList.get(position).getFlage() == 0) {//无子 int positionLeft = 8 * 3 + (startX - 1); int positionRight = 8 * 3 + (startX + 1); if ( chessPieceList.get(positionLeft).getFlage() > 100 && chessPieceList.get(positionLeft).getFlage() < 200 && blackPawnFlage == 1 && oldPosition == mBlackPosition + 1) { if (startX - endX == 1 && mPawn.guizeWhiteEat()) {//白兵吃左侧过路兵 pawnOrRookOrKing(oldPosition, position); chessPieceList.get(positionLeft).setDrawable(22);//移除左侧黑兵 chessPieceList.get(positionLeft).setChessPieceColor("0"); chessPieceList.get(positionLeft).setFlage(0); blackPawnFlage = 0; return true; } } else if (chessPieceList.get(positionRight).getFlage() > 100 && chessPieceList.get(positionRight).getFlage() < 200 && blackPawnFlage == 1 && oldPosition == mBlackPosition - 1) { if (endX - startX == 1 && mPawn.guizeWhiteEat()) {//白兵吃右侧过路兵 pawnOrRookOrKing(oldPosition, position); chessPieceList.get(positionRight).setDrawable(22);//移除右侧黑兵 chessPieceList.get(positionRight).setChessPieceColor("0"); chessPieceList.get(positionRight).setFlage(0); blackPawnFlage = 0; return true; } } //白兵是否是第一次移动 if (this.Pawn() && mPawn.guizeWhiteFirst() && chessPieceList.get(oldPosition).getPawnFlage() == 0) { pawnOrRookOrKing(oldPosition, position); return true; } else if (mPawn.guizeWhite() && chessPieceList.get(oldPosition).getPawnFlage() == 1) { pawnOrRookOrKing(oldPosition, position); return true; } } } //车 if (chessPieceList.get(oldPosition).getFlage() == 1 || chessPieceList.get(oldPosition).getFlage() == 6) { if (mRook.guize()) { if (this.verticallyAndHorizontally()) { pawnOrRookOrKing(oldPosition, position); return true; } } } //马 if (chessPieceList.get(oldPosition).getFlage() == 2 || chessPieceList.get(oldPosition).getFlage() == 7) { if (mKnight.guize()) { knightOrbishopOrqueen(oldPosition, position); return true; } } //象 if (chessPieceList.get(oldPosition).getFlage() == 3 || chessPieceList.get(oldPosition).getFlage() == 8) { if (mBishop.guize()) { if (this.oblique()) { knightOrbishopOrqueen(oldPosition, position); return true; } } } //王后 if (chessPieceList.get(oldPosition).getFlage() == 4 || chessPieceList.get(oldPosition).getFlage() == 9) { if (mQueen.guize()) { if (mQueen.flage == 1 && this.oblique()) { knightOrbishopOrqueen(oldPosition, position); return true; } else if (mQueen.flage == 2 && this.verticallyAndHorizontally()) { knightOrbishopOrqueen(oldPosition, position); return true; } } } //王 if (chessPieceList.get(oldPosition).getFlage() == 5 || chessPieceList.get(oldPosition).getFlage() == 10) { if (mKing.guize()) { pawnOrRookOrKing(oldPosition, position); return true; } else if (mKing.longTranslocation() && chessPieceList.get(oldPosition).getPawnFlage() == 0 && chessPieceList.get(56).getPawnFlage() == 0) {//长易位且王没有移动过 if (this.longTranslocation()) { pawnOrRookOrKing(oldPosition, position); int oldRookPosition = 8 * startY + startX - 4; int newRookPosition = 8 * startY + startX - 1; int rookDrawable = chessPieceList.get(oldRookPosition).getDrawable();//原来车的图片 chessPieceList.get(oldRookPosition).setDrawable(22);//原来车的图片为空 chessPieceList.get(newRookPosition).setDrawable(rookDrawable);//车的图片设置到本次newRookPosition上 int rookFlage = chessPieceList.get(oldRookPosition).getFlage();//上一次位置的标记 chessPieceList.get(newRookPosition).setFlage(rookFlage); chessPieceList.get(oldRookPosition).setFlage(0);//设置上一次位置的标记为0 String rookColor = chessPieceList.get(oldRookPosition).getChessPieceColor();//上一次位置的棋子颜色 chessPieceList.get(oldRookPosition).setChessPieceColor("0");//设置上一次位置的棋子颜色 chessPieceList.get(newRookPosition).setChessPieceColor(rookColor); chessPieceList.get(oldRookPosition).setPawnFlage(0);//设置上一次位置的标记为0 chessPieceList.get(newRookPosition).setPawnFlage(1);//设置本次位置的标记为1,证明车移动过了 return true; } } else if (mKing.shortTranslocation() && chessPieceList.get(oldPosition).getPawnFlage() == 0 && chessPieceList.get(63).getPawnFlage() == 0) {//短易位且王没有移动过 if (this.shortTranslocation()) { pawnOrRookOrKing(oldPosition, position); int oldRookPosition = 8 * startY + startX + 3; int newRookPosition = 8 * startY + startX + 1; int rookDrawable = chessPieceList.get(oldRookPosition).getDrawable();//原来车的图片 chessPieceList.get(oldRookPosition).setDrawable(22);//原来车的图片为空 chessPieceList.get(newRookPosition).setDrawable(rookDrawable);//车的图片设置到本次newRookPosition上 int rookFlage = chessPieceList.get(oldRookPosition).getFlage();//上一次位置的标记 chessPieceList.get(newRookPosition).setFlage(rookFlage); chessPieceList.get(oldRookPosition).setFlage(0);//设置上一次位置的标记为0 String rookColor = chessPieceList.get(oldRookPosition).getChessPieceColor();//上一次位置的棋子颜色 chessPieceList.get(oldRookPosition).setChessPieceColor("0");//设置上一次位置的棋子颜色 chessPieceList.get(newRookPosition).setChessPieceColor(rookColor); chessPieceList.get(oldRookPosition).setPawnFlage(0);//设置上一次位置的标记为0 chessPieceList.get(newRookPosition).setPawnFlage(1);//设置本次位置的标记为1,证明车移动过了 return true; } } } return false; }

那么在符合了规则的前提下又要进一步的判断(比如车走的时候前面是否有棋子之类,没有了这个限制,车就变成了中国象棋里的炮了)

//纵横方向有无子的判断 private boolean verticallyAndHorizontally() { //竖直方向 if (startX == endX) { if (endY > startY) { Toast.makeText(ChessActivity.this, "上至下", Toast.LENGTH_SHORT).show(); if (startY + 1 == endY) { verticallyAndHorizontally = true; } for (int i = startY + 1; i < endY; i++) { int positionMiddle = 8 * i + endX; if (!"0".equals(chessPieceList.get(positionMiddle).getChessPieceColor())) {//有棋子 Toast.makeText(ChessActivity.this, "上至下,此路不通" + " " + chessPieceList.get(positionMiddle).getChessPieceColor(), Toast.LENGTH_SHORT).show(); verticallyAndHorizontally = false; break; } else { verticallyAndHorizontally = true; } } } else if (endY < startY) { Toast.makeText(ChessActivity.this, "下至上", Toast.LENGTH_SHORT).show(); if (endY + 1 == startY) { verticallyAndHorizontally = true; } for (int i = endY + 1; i < startY; i++) { int positionMiddle = 8 * i + endX; if (!"0".equals(chessPieceList.get(positionMiddle).getChessPieceColor())) {//有棋子 Toast.makeText(ChessActivity.this, "下至上,此路不通" + " " + chessPieceList.get(positionMiddle).getChessPieceColor(), Toast.LENGTH_SHORT).show(); verticallyAndHorizontally = false; break; } else { verticallyAndHorizontally = true; } } } } else if (startY == endY) {//水平方向 if (endX > startX) { if (startX + 1 == endX) { verticallyAndHorizontally = true; } Toast.makeText(ChessActivity.this, "左至右", Toast.LENGTH_SHORT).show(); for (int i = startX + 1; i < endX; i++) { int positionMiddle = 8 * endY + i; if (!"0".equals(chessPieceList.get(positionMiddle).getChessPieceColor())) {//有棋子 Toast.makeText(ChessActivity.this, "左至右,此路不通" + " " + chessPieceList.get(positionMiddle).getChessPieceColor(), Toast.LENGTH_SHORT).show(); verticallyAndHorizontally = false; break; } else { verticallyAndHorizontally = true; } } } else if (endX < startX) { if (endX + 1 == startX) { verticallyAndHorizontally = true; } Toast.makeText(ChessActivity.this, "右至左", Toast.LENGTH_SHORT).show(); for (int i = endX + 1; i < startX; i++) { int positionMiddle = 8 * endY + i; if (!"0".equals(chessPieceList.get(positionMiddle).getChessPieceColor())) {//有棋子 Toast.makeText(ChessActivity.this, "右至左,此路不通" + " " + chessPieceList.get(positionMiddle).getChessPieceColor(), Toast.LENGTH_SHORT).show(); verticallyAndHorizontally = false; break; } else { verticallyAndHorizontally = true; } } } } return verticallyAndHorizontally; }

依次类推还有象的,王后的和车王易位(长易位和短易位)

这里就不一一贴出了。。。

另外我们在吃对方棋子或者是走棋的时候都将它看作时吃子的过程(这里提炼出个方法,分别引用,减少代码量,看着更简洁些)

//兵、车、王 private void pawnOrRookOrKing(int oldPosition, int position) { int drawable = chessPieceList.get(oldPosition).getDrawable();//上一次位置的图片 chessPieceList.get(oldPosition).setDrawable(22);//设置上一次位置图片为空 chessPieceList.get(position).setDrawable(drawable);//将上次位置的图片设置到本次position上 int flage = chessPieceList.get(oldPosition).getFlage();//上一次位置的标记 chessPieceList.get(oldPosition).setFlage(0);//设置上一次位置的标记为0 chessPieceList.get(position).setFlage(flage); String chessPieceColor = chessPieceList.get(oldPosition).getChessPieceColor();//上一次位置的棋子颜色 chessPieceList.get(oldPosition).setChessPieceColor("0");//设置上一次位置的棋子颜色 chessPieceList.get(position).setChessPieceColor(chessPieceColor); chessPieceList.get(oldPosition).setPawnFlage(0);//设置上一次位置的兵标记为0 chessPieceList.get(position).setPawnFlage(1);//设置本次位置的兵标记为1,证明兵移动过了 }

//马、象、王后 private void knightOrbishopOrqueen(int oldPosition, int position) { int drawable = chessPieceList.get(oldPosition).getDrawable();//上一次位置的图片 chessPieceList.get(oldPosition).setDrawable(22);//设置上一次位置图片为空 chessPieceList.get(position).setDrawable(drawable);//将上次位置的图片设置到本次position上 int flage = chessPieceList.get(oldPosition).getFlage();//上一次位置的标记 chessPieceList.get(oldPosition).setFlage(0);//设置上一次位置的标记为0 chessPieceList.get(position).setFlage(flage); String chessPieceColor = chessPieceList.get(oldPosition).getChessPieceColor();//上一次位置的棋子颜色 chessPieceList.get(oldPosition).setChessPieceColor("0");//设置上一次位置的棋子颜色 chessPieceList.get(position).setChessPieceColor(chessPieceColor); chessPieceList.get(oldPosition).setPawnFlage(0);//设置上一次位置的兵标记为0 chessPieceList.get(position).setPawnFlage(1);//设置本次位置的兵标记为1,证明兵移动过了 }

最后,既然是国际象棋就要有输有赢并且黑白之间交替走

//黑白棋交替并判断输赢 if ("1".equals(chessPieceList.get(oldPosition).getChessPieceColor())) {//黑棋 if (blackFlage == 0 && beforehand == 0 || whiteFlage == 1 && blackFlage == 1 || blackFlage == 1 && whiteFlage == 0 && beforehand > 0) {//白棋没走完 Toast.makeText(ChessActivity.this, "轮到白棋了...", Toast.LENGTH_SHORT).show(); blackFlage = 2; } else {//判断输赢 if (chessPieceList.get(position).getFlage() == 10) { piece = "黑棋"; yesOrNoDialog = new YesOrNoDialog(ChessActivity.this, "提示", piece + "获胜," + "再来一局!"); yesOrNoDialog.show(); dialog(); return; } else { if (luozi(position)) { blackPawm(oldPosition, position); blackFlage = 2; whiteFlage = 0; } else { blackFlage = 1; } } } } else if ("2".equals(chessPieceList.get(oldPosition).getChessPieceColor())) {//白棋 if (whiteFlage == 1 && blackFlage == 1 || whiteFlage == 1 && blackFlage == 0 && beforehand > 0) {//黑棋没走完 Toast.makeText(ChessActivity.this, "轮到黑棋了...", Toast.LENGTH_SHORT).show(); whiteFlage = 2; } else {//判断输赢 if (chessPieceList.get(position).getFlage() == 5) { piece = "白棋"; yesOrNoDialog = new YesOrNoDialog(ChessActivity.this, "提示", piece + "获胜," + "再来一局!"); yesOrNoDialog.show(); dialog(); return; } else { if (luozi(position)) { whitePawn(oldPosition, position); beforehand++; whiteFlage = 2; blackFlage = 0; } else { whiteFlage = 1; } } } }

这里我做了三个变量,分别是beforehand,whiteFlage,blackFlage,意义分别是让执白棋的先行,和黑白棋的两个标识,判断条件是我Debug一遍测试加理论实验出来的,有些绕口,一时也说不清,希望能看懂。

最后胜利的时候会提示一个自定义的Dialog。

以上就是对于国际象棋简单的总结,有兴趣的小伙伴可以下载下源码看看,我还是个新手,如果有问题希望能提出,大家一起进步,请多多指教=.=

转载请说明出处:

源码:http://download.csdn.net/download/qq_38179135/10105988

转载请注明原文地址: https://www.6miu.com/read-1249996.html

最新回复(0)