用java编国际象棋4之判断赢棋与和棋,实现自定义棋盘

该博客介绍了如何使用Java编程实现国际象棋中赢棋与和棋的判断,包括将杀的判断逻辑,并实现自定义棋盘功能。博主分享了判断将军的三种应对方法:吃子、垫子和移王,并详细解释了各个判断过程。此外,还提到了无子可动的和棋判断,但未涵盖所有和棋条件。最后,讨论了如何实现清空棋盘和展示棋盘在JFrame中的功能。
摘要由CSDN通过智能技术生成

Hello!大家好!今天我们来讲解国际象棋的最后一个部分,判断赢棋与和棋,并实现自定义棋盘的功能。

在国际象棋比赛中,判断赢棋的方式有三种:将杀,认输和超时。在这里认输属于主观判断,而我这次也没有把计时功能写进去,所以就只写了一个判断将死的函数。

当然了,写这一个就已经很费事了。大家还记得我们在上一期当中是如何应对将军等一系列问题的吗?我采取的方法是不直接在走棋之前处理这些问题,而是在走完棋之后对这个棋盘进行将军的判断,如果走棋一方仍然处于被将军的状态,则自动悔棋。虽然这个方法在当时确实帮我避免了很多复杂的逻辑处理,但是现在在判断将杀的时候我意识到之前悔棋方法的局限性。因为我们不能简单地判断被将军的一方是否有合法走棋,按照我们的逻辑只要不违背最基本的走子规则都不算违例,因此即使被将杀他还是有很多“合法”的棋可以走。即使应用我之前的方法,也只是不停地被悔棋,电脑是不会知道你已经没棋可走了,让电脑自动执行move()函数更是天方夜谭,因为move()函数本身就是建立在鼠标监听器下的。

在这种情况下我们有什么样的解决办法呢?我在这里还是会用到我处理将军的方法。只不过方式大有不同,要写的辅助函数也有很多。

在国际象棋规则中,当一方被将军时,它有三种应对的方法:
1.吃掉对方将军的棋子
2.在对方的棋子和自己的王中间点上自己的棋子
3.移走自己的王
如果以上三种方式都避免不了将军的话,那他就算是被将死了。

这样,我的思路也随之出来了。那就是在将军的时候对以上三种方法分别判断,然后取一个并集。
在进入主体代码之前,先介绍两个实现自动走棋和悔棋的函数。

这是实现自动走棋的函数
private static MyLabel[][] trymove(MyLabel a,MyLabel b,MyLabel[][] c) {
  MyLabel[][] answer=c;我在这里做了一个浅拷贝,不过好像并没有什么用
  MyIcon icon=(MyIcon) a.getIcon();
  capturedpiece2=(MyIcon) b.getIcon();————capturedpiece2是一个新的全局变量,
  作用相当于手动走棋当中的capturedpiece
  answer[b.row][b.col].setIcon(icon);把目标格子设置上起始格子的图标
  answer[a.row][a.col].setIcon(null);把起始格子的图标取消
  return answer;
 }

在这里我没有考虑到吃过路兵的情况,不过我是真的不想考虑这种情况,太极端了,几乎不会出现。王车移位的情况不需要考虑,因为之前的逻辑已经限制住了(被将军的时候不能移位)。

这是手动悔棋函数,要注意它的参数多了一个MyIcon
private static MyLabel[][] undo2(MyLabel a,MyLabel b,MyLabel[][] c,MyIcon piece){
  MyIcon icon=(MyIcon) b.getIcon();
  c[b.row][b.col].setIcon(piece);把原目标格子设置上原来棋子的图标,
  在这里就是指capturedpiece2
  c[a.row][a.col].setIcon(icon);把原起始格子设置上走动的棋子
  return c;  
 }

写完这两个函数,我们就开始判断被将军的一方是否可以移走他的王

private static boolean canrun() {
  if(ischecking2(labels)) {首先这个函数只适用于被将军的时候,而且是判断走棋之前被将军,
  因此要用到ischecking2
   for(int i=1;i<rows+1;i++) {
    for(int j=1;j<cols+1;j++) {
     MyIcon icon=(MyIcon) labels[i][j].getIcon();
     if(icon!=null&&getside(icon)==sidetomove&&getname(icon)=="king") {找到被将军的王
      for(int x=1;x<rows+1;x++) {
       for(int y=1;y<cols+1;y++) {
        if(islegalmove(labels[i][j],labels[x][y])) {判断走棋是否合法
         MyLabel[][] resultboard=trymove(labels[i][j],labels[x][y],labels);  
          这时候我们会用到我们自动走棋的函数trymove,试着把王走到那一个格子中

        if(!ischecking2(resultboard)) {然后判断走完棋之后是否被仍然将军,
        注意,自动走棋的函数并没有转换sidetomove,所以还是要用ischecking2来检查
          resultboard=undo2(labels[i][j],labels[x][y],labels,capturedpiece2);
          在检查完了之后,不管判断的结果如何,一定要手动悔棋,还原棋盘。
          return true;
         }
         resultboard=undo2(labels[i][j],labels[x][y],labels,capturedpiece2);
        }
       }
      }
     }
    }
   }
   return false;
  }
  return true;
 }

然后是判断吃和垫两个方法,与直接把王逃走的方法不同,如果对方将军的棋子有两个的话,这两种方法都是行不通的。所以我们还要引入一个判断有几个子将军的函数

priva
  • 12
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 45
    评论
评论 45
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值