Java国际象棋 棋子的走法和吃法

知识创造技术 技术改变世界

------ Oracle中文开发者社区 ------

二维码 二维码 二维码 二维码 二维码 二维码

如果你想要学习编程,关注本博客,持续获得技术支持,持续获得技术咨询


java开发·企业官方账号 Oracle中国官方账号 Java中国管理部 全网粉丝30万+ 华为云享专家 阿里专家博主 CSDN内容合伙人 CSDN原力计划作者 51CTO专家博主 CSDN博客V账号 毕业于四川大学新闻与文学学院 精通java,Python,HTML,掌握了PHP,C语言,C++,C#,JavaScript,Visual Basic等二十余种编程语言的技巧,会分享一些编程心得、面试技巧和编程方法。


其他链接

主页 官网 社区 论坛

文章目录


Hello!大家好!今天我们来写国际象棋棋子的一些走法和吃法,其中主要包括以下几种规则:

  1. 车走直线,象走斜线,马走日字,后走直线和斜线,王也是走直线和斜线但只能走一格。
  2. 兵一开始可以往前走两格或者一格,但之后只能往前走一格,而且兵不能后退。
  3. 兵吃子的时候只能吃斜上方一格的棋子,其他棋子吃法与走法相同。
  4. 两种兵的特殊走法:
    1. 升变
    2. 吃过路兵

在开始写规则之前,我们要引入两个函数,跟斗兽棋一样,我们要判断出棋子的种类和所属一方。具体的方法我在之前写斗兽棋的时候也有介绍过,就是

 private static String getname(MyIcon icon) {判断棋子的种类(不分黑白)if(icon.getPath()==paths[0]||(icon.getPath()==paths[1])) {return "pawn";}if(icon.getPath()==paths[2]||(icon.getPath()==paths[7])) {return "rook";}if(icon.getPath()==paths[3]||(icon.getPath()==paths[8])) {return "knight";}if(icon.getPath()==paths[4]||(icon.getPath()==paths[9])) {return "bishop";}if(icon.getPath()==paths[5]||(icon.getPath()==paths[10])) {return "queen";}if(icon.getPath()==paths[6]||(icon.getPath()==paths[11])) {return "king";}return "";}
private static String getside(MyIcon icon) {
//判断棋子所属一方if(icon.getPath()==paths[0]||icon.getPath()==paths[2]||icon.getPath()==paths[3]||icon.getPath()==paths[5]||icon.getPath()==paths[6]||icon.getPath()==paths[4]) {return "black";}if(icon.getPath()==paths[1]||icon.getPath()==paths[7]||icon.getPath()==paths[8]||icon.getPath()==paths[11]||icon.getPath()==paths[10]||icon.getPath()==paths[9]) {return "white";} return "";}

那我们先来写车的规则

private static boolean rooklegal(MyLabel a,MyLabel b) {MyIcon a1=(MyIcon) a.getIcon();起始格子上的棋子MyIcon b1=(MyIcon) b.getIcon();目标格子上的棋子(有可能是null

然后我们把两个格子所在的行与列分别取最小值和最大值

  int r1=Math.min(a.row, b.row);int r2=Math.max(a.row, b.row);int c1=Math.min(a.col, b.col);int c2=Math.max(a.col, b.col);if(a.row==b.row&&a.col==b.col) {//不能原地不动return false;}if(a.row==b.row) {  //这是在同一列的时候for(int i=c1;i<=c2;i++) {//查看他们之间的格子(行数从小到大)if(labels[a.row][i]!=a) {//不包括起始格子本身if(labels[a.row][i]==b&&b1!=null) {//如果循环到了目标格子,而且目标格子上有棋子的话,就要判断该棋子是否与被走棋子属于同一方。如果是同一方的话就违例了,如果是不同方的话就代表吃掉了对方的棋子。if(getside(a1)==getside(b1)) {return false;}}else if(labels[a.row][i].getIcon()!=null) {//如果没有循环到目标格子,就检查途径的格子上是否有棋子挡住,有的话也违例了。return false;}}}
//   如果一切正常就通过了。return true;}//接下来是考虑他们在同一行的情况,跟之前的方法完全相同,在这里不做过多的解释了。if(a.col==b.col) {  for(int i=r1;i<=r2;i++) {if(labels[i][a.col]!=a) {if(labels[i][a.col]==b&&b1!=null) {if(getside(a1)==getside(b1)) {return false;}}else if(labels[i][a.col].getIcon()!=null) {return false;}}}return true;}  //如果两个格子既不在同一行上也不在同一列上就违例了。return false;}

接下来写马的规则,马的规则是最简单的规则了,只要判断两个格子行的差距与列的差距是2和1或1和2就行。

 private static boolean knightlegal(MyLabel a,MyLabel b) {int r=Math.abs(a.row-b.row);//列的差距int c=Math.abs(a.col-b.col);  //行的差距MyIcon a1=(MyIcon) a.getIcon();MyIcon b1=(MyIcon) b.getIcon();if((r==1&&c==2)||(r==2&&c==1)) {//判断是否是2和1或1和2if(b1!=null) {return (getside(a1)!=getside(b1));//接下来判断目标格子上的棋子所属势力}return true;//如果目标格子为空则通过}return false;}

然后是象的规则,我先是写了一个判断两个格子是否在同一条斜线上的函数。

private static boolean samediagonal(MyLabel a,MyLabel b) {return (Math.abs(a.row-b.row)==Math.abs(a.col-b.col));}

然后再判断象的规则

private static boolean bishoplegal(MyLabel a,MyLabel b) {MyIcon a1=(MyIcon) a.getIcon();MyIcon b1=(MyIcon) b.getIcon();int r1=Math.min(a.row, b.row);int r2=Math.max(a.row, b.row);int c1=Math.min(a.col, b.col);int c2=Math.max(a.col, b.col);if(!samediagonal(a,b)) {判断是否在同一条斜线上return false;}if(r1==r2&&c1==c2) {不能原地不动return false;}
接下来的循环比较简单粗暴,实在一个被框起来的长方形里循环for(int i=r1;i<=r2;i++) {for(int j=c1;j<=c2;j++) {if(labels[i][j]!=a&&samediagonal(labels[i][j],a)) {被循环到的格子不能是起始格子本身,也必须和起始格子再同一斜线上if(labels[i][j]==b&&b1!=null) {判断吃子是否合法if(getside(a1)==getside(b1)) {return false;}}else if(labels[i][j].getIcon()!=null) {判断是否有棋子阻隔return false;}}}}return true;}

然后是后的规则,在写完象和车的规则之后,后的规则只不过是取一个并集罢了。没有特殊的代码。

然后是王的规则,在这里还牵扯到了一个特殊走法————王车移位,今天先不介绍他的写法。

private static boolean kinglegal(MyLabel a,MyLabel b) {MyIcon a1=(MyIcon) a.getIcon();MyIcon b1=(MyIcon) b.getIcon();if((Math.abs(a.row-b.row)+Math.abs(a.col-b.col)!=1)&&!(Math.abs(a.row-b.row)==1&&samediagonal(a,b))) {  判断是否走到了周围的一个格子return cancastle(a,b);如果不是的话去判断是否符合王车移位的条件}else {   判断吃子是否违规if(b1!=null) {return (getside(a1)!=getside(b1));}return true;}}

最后是兵的规则,虽然兵是最小的棋子,但它的规则却是最复杂的。
首先我们来写兵的走法

private static boolean pawnlegal(MyLabel a,MyLabel b) {MyIcon icon=(MyIcon) a.getIcon();MyIcon icon1=(MyIcon) b.getIcon();if(a.col==7&&getside(icon)=="white") {白兵如果刚开始走动if(b.row==a.row&&(b.col==5||b.col==6)) {可以向前走一格到两格for(int i=b.col;i<a.col;i++) {查看目标格子和途径格子上是否有棋子if(labels[a.row][i].getIcon()!=null) {return false;}}return true;}return pawneatlegal(a,b);如果不是往前走,去判断是否符合吃子的条件}if(a.col==2&&getside(icon)=="black") {黑兵如果刚开始走动,逻辑同上if(b.row==a.row&&(b.col==3||b.col==4)) {for(int i=b.col;i>a.col;i--) {if(labels[a.row][i].getIcon()!=null) {return false;}}return true;}return pawneatlegal(a,b);}else {兵如果不在起始的行上,那就只能往前走一格了if(a.row==b.row) {if(getside(icon)=="white") {return(a.col-b.col==1&&icon1==null);}else return(b.col-a.col==1&&icon1==null);}else {return pawneatlegal(a,b);}}}

接下来是兵的吃法

private static boolean pawneatlegal(MyLabel a,MyLabel b) {MyIcon a1=(MyIcon) a.getIcon();MyIcon b1=(MyIcon) b.getIcon();if(getside(a1)=="white") {白兵的情况,白兵向斜上方吃子的时候,所属的行数应该减一,列数应该加或减一。if(a.col-b.col==1&&Math.abs(a.row-b.row)==1) {if(b1!=null) {return (getside(b1)=="black");}return enpassant(a,b);如果斜上方没有棋子的话,判断是否符合吃过路兵的条件}return false;}if(getside(a1)=="black") {黑兵,逻辑同上if(a.col-b.col==1&&Math.abs(a.row-b.row)==1) {if(b1!=null) {return (getside(b1)=="white");}return enpassant(a,b);}return false;}return false;}

然后是过路兵的判断,如果有人不清楚过路兵是个什么概念,我在这里跟大家说一下。就是当一方的兵往前走了三格之后,这是对方旁边一列的兵往前走了两格,这时双方的兵就会在同一行上,原先的一方就可以用普通的兵的吃法来吃掉对方的兵,虽然目标格子上并没有棋子。而且过路兵只能当时吃掉,如果过了一步棋才决定吃就为时已晚。由此可见,在过路兵的判断上我们需要知道前一步棋到底走了什么,以此我在原先的move()函数里面加上了记录走棋的方法,大家可以去看一下我上一期发的代码。
接下来给大家看一下吃过路兵的判断。

private static boolean enpassant(MyLabel a,MyLabel b) {if(clickcount>2) {因为第一步棋不可能出现吃过路兵的情况,所以要默认为第二步棋以后,这样可以避免下面第一行出现空指针的情况MyLabel[] record=recordedmove.get(recordedmove.size()-1);//这一步是用来找到上一步走棋的记录MyIcon a1=(MyIcon) a.getIcon();MyIcon a2=(MyIcon) record[1].getIcon();if(getside(a1)=="white"&&a.col==4) {当轮到白棋走的时候,并且兵在第四行if(record[0].col==2&&record[1].col==4&&getname(a2)=="pawn"&&record[1].row==b.row&&getside(a2)=="black") {在这里我们要判断上一步棋是对方把兵往前走了两格,并且对方兵所处的列与走棋的目标格子所处的列相同return true;}}if(getside(a1)=="black"&&a.col==5) {黑方的判断逻辑同上if(record[0].col==7&&record[1].col==5&&getname(a2)=="pawn"&&record[1].row==b.row&&getside(a2)=="white") {return true;}}return false; }return false;}

既然吃过路兵的情况特殊,那么他的吃法的编写也是特殊的,我们不能用普遍的方法来完成吃子的过程,我们也需要一个专门的函数来完成这个过程

private static void eatenpassant(MyLabel a,MyLabel b){int r=b.row;MyIcon a1=(MyIcon) a.getIcon(); if(a.col==4) {这是白棋的情况MyIcon b1=(MyIcon) labels[r][4].getIcon();b.setIcon(a1);把目标格子设置上要走的棋子labels[r][4].setIcon(null);把兵旁边的那个格子上的图片(这里是黑兵)去掉capturedpiece=b1;记录被吃掉的子(之后写到悔棋的功能时要用到)}if(a.col==5) {黑棋的情况,同上MyIcon b1=(MyIcon) labels[r][4].getIcon();b.setIcon(a1);labels[r][5].setIcon(null);capturedpiece=b1;} }

最后的最后,我们只剩下兵升变了,国际象棋的兵在到达对方的底线后可以变成马,象,车或后。
这个函数跟之前所有函数的区别在于它的逻辑十分简单,可是编写起来却非常复杂,因为我们要引入新的JButton和JFrame

private static void promote(MyLabel jl) {这里的参数是兵升变的那个格子JFrame f=new JFrame();设置一个JFramef.setLayout(new FlowLayout());f.setSize(250, 250);Dimension a=new Dimension(100,100);这是每个棋子代表的JButton的大小JButton queen=new JButton();————后JButton bishop=new JButton();————象JButton knight=new JButton();————马JButton rook=new JButton();————车然后根据兵的颜色给JButton设置上相应的图片if(getside(movingpiece)=="white") {queen.setIcon(new MyIcon(paths[10]));bishop.setIcon(new MyIcon(paths[9]));knight.setIcon(new MyIcon(paths[8]));rook.setIcon(new MyIcon(paths[7]));} if(getside(movingpiece)=="black") {queen.setIcon(new MyIcon(paths[5]));bishop.setIcon(new MyIcon(paths[4]));knight.setIcon(new MyIcon(paths[3]));rook.setIcon(new MyIcon(paths[2]));}

这里为了方便起见,我把四个JButton放在了一个ArrayList里面,然后进行相同的操作。

ArrayList<JButton> buttons=new ArrayList<>();buttons.add(queen);buttons.add(bishop);buttons.add(knight);buttons.add(rook);for(int i=0;i<4;i++) {int x=i;buttons.get(x).setPreferredSize(a);buttons.get(x).setBorder(BorderFactory.createLineBorder(Color.BLACK));buttons.get(x).addActionListener(new ActionListener() {加上监听器@Overridepublic void actionPerformed(ActionEvent e) {jl.setIcon(buttons.get(x).getIcon());在该格子上设置上相应的图片f.dispose();在完成升变之后,这个JFrame就可以关掉了。}   });} f.add(queen);f.add(bishop);f.add(knight);f.add(rook);f.setVisible(true);}

今天就给大家讲到这里,其实在今天设计走棋的规则中我们还没有引入将军的概念,仅仅是限制了棋子基本的走法。下次我们将引入这一概念,同时也会加入另一大特殊走法————王车移位,以及加入悔棋的功能。


------- THE END -------

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/58692.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java 中国象棋

实现一个小游戏需要知道从哪里下手&#xff0c;一步步实现和完善&#xff0c;对于一个中国象棋的小游戏&#xff0c;我们可以按这样的顺序展开&#xff1a; 界面按钮加棋子实现棋子的移动判断胜负按钮“开始游戏”和“重新开始”的实现加规则轮次悔棋背景 及 提示 一、界面 …

简单的象棋开发

我们需要准备的知识是c语言基础和easyx图形: easyx官网&#xff1a; https://easyx.cn/ 首先头文件少不了: #include<stdio.h>(c语言的头文件) #include<graphics.h>&#xff08;easyx的&#xff09; #include<mmsystem.h>&#xff08;音乐播放的&#x…

中国象棋C++实现

使用C语言开发中国象棋的小游戏 Chess.cpp // includes #include<iostream> #include<graphics.h> using namespace std;// 使用到的 WCHAR 字符 class CKind{ public:WCHAR ROOKS *(_T("车"));WCHAR KNIGHTS *_T("马");WCHAR ELEPHANTS …

用C++实现中国象棋

项目介绍 最近学习到了STL库&#xff0c;了解到一些很实用的容器&#xff0c;同时我也是个象棋爱好者&#xff0c;想着能不能做个象棋的游戏小程序出来&#xff0c;运用一下所学到的知识点&#xff0c;于是动手做了这个项目&#xff0c;花了两天左右的时间基本完成&#xff0c;…

C++中国象棋

ssdut c的大作业&#xff0c;在控制台的界面实现人人对弈&#xff0c;比较适合初学&#xff0c;自己设计了一些简单算法&#xff0c;两百多行完成。 以下正文&#xff1a; 完成中国象棋游戏&#xff0c;实现如下功能&#xff1a; 1.实现人与人之间象棋的对弈。 2.每次走子之…

Java版本实现中国象棋

预览效果 中国象棋 游戏介绍&#xff1a;中国象棋是起源于中国的一种棋&#xff0c;属于二人对抗性游戏的一种&#xff0c;在中国有着悠久的历史&#xff0c;由于用具简单&#xff0c;趣味性强&#xff0c;成为流行极为广泛的棋艺活动。阿巴阿巴阿巴 代码结构&#xff1a;Butto…

数影周报:小米汽车供应商被罚100万,1688延迟下线“1688买家旺旺”

本周看点&#xff1a;小米汽车供应商被罚100万&#xff1b;特斯拉将在硅谷招聘AI 人才&#xff1b;阳光出行等25款 App涉违规收集使用个人信息等&#xff1b;1688延迟于2月8日下线“1688买家旺旺”&#xff1b;微蚁科技完成数千万元B轮融资...... 数据安全那些事 小米汽车供应商…

Coggle 30 Days of ML (23年7月)任务二:数据可视化

Coggle 30 Days of ML (23年7月&#xff09;任务二&#xff1a;数据可视化 任务二&#xff1a;对数据集字符进行可视化&#xff0c;统计标签和字符分布 说明&#xff1a;在这个任务中&#xff0c;需要使用Pandas库对数据集的字符进行可视化&#xff0c;并统计数据集中的标签和…

阿里云服务器ECS是什么?详细介绍

阿里云服务器ECS是什么&#xff1f;云服务器和传统的物理服务器有什么区别&#xff1f;云服务器有哪些优势&#xff1f;云服务器可以什么&#xff1f;云服务器架构及云服务器包含哪些功能组件&#xff1f;阿里云百科来详细说下什么是云服务器ECS&#xff1a; 目录 阿里云服务…

使用Chrome修改user agent模拟微信内置浏览器

很多时候&#xff0c;我们需要模拟微信内置浏览器&#xff0c;今天教大家用 chrome 简单模拟。如图设置&#xff1a; F12或者右键审查元素进入开发者模式&#xff0c;点击Emulation&#xff0c;然后点击Network&#xff0c;把Spoof user agent改成Other&#xff0c;并把下面…

数据分析案例-足球运动员分析

目录 加载数据 查看数据 数据详细 ​缺值处理 异常值处理 重复值处理 运动员身高和体重分布 左脚右脚使用数量 俱乐部球员评分分析 足球运动员数是否与出生日期相关 身高与体重是否具有相关性 加载数据 #加载足球运动员数据 import numpy as np import pandas as pd impor…

如何用算法预测世界杯?

预测2021欧洲世界杯 世界杯预测结果预测的原理是什么&#xff1f;周易算卦原理算命可以解决的问题善易者不卜 人工智能预测原理预测模型&#xff1a;逻辑回归算法可以预测的问题 可以单挑整个华尔街的算法现代足球 世界杯预测结果 预测2021年欧洲世界杯&#xff0c;也是一道考…

采用 Python 机器学习预测足球比赛结果

足球是世界上最火爆的运动之一,如何运用机器学习来预测足球比赛结果,是每一个足球爱好者所向往的! 本场 Chat 适合有 Python 基础的机器学习初学者,我们带你一起熟悉机器学习的开发流程,帮你快速建立起自己的英超比赛预测模型! 你将获取到如下内容: 人工智能在线建模平…

按键精灵移动端系列 - 按键精灵IOS版 之 网络已断开,请检查网络连接.解决方案.

由于很多网友对这种问题,不知道如何处理.因本人也曾遇到过这种情况.经过不懈努力终于解决了这个神奇的BUG.长话短说上操作流程.如果觉得给力,请三连 点赞. 收藏. 转发. 谢谢您的支持. ** 1 安装雷锋源: apt.abcydia.com 2安装好雷锋源, 搜索: conditionalwifi 更新到最新版 …

按键精灵助手无法连接模拟器解决方案【适用任何模拟器】

找到按键精灵安装地址 D:\ProgramData\按键精灵\按键精灵手机助手\android 找到木木安装地址&#xff0c;并搜索adb.exe,未找到 但是在D:\Program Files (x86)\MuMu\emulator\nemu\vmonitor\bin找到 adb_server.exe 以及另外两个.dll 复制着三个文件到按键精灵上述文件夹&#…

国行版苹果 ios 按键精灵无法联网问题处理

国行版苹果手机安装按键精灵后无法联网的问题&#xff1a; 操作步骤&#xff1a; &#xff08;1&#xff09;自行把苹果手机进行越狱&#xff0c;找到并打开越狱商店“Cydia” &#xff0c;其他商店同理&#xff0c;按照如下图步骤添加 “雷锋源”&#xff0c;源地址&#xff…

网易mumu显示无法连接服务器,网易MuMu无法连接网络_网易MuMu如何实现多开

网易MuMu是由网易全方面打造的一种非常具有精品特色的游戏服务平台&#xff0c;这款游戏服务平台在下载安装之后可以直接运行电脑上的各种不同游戏和应用程序&#xff0c;同时它的兼容性是比较强的&#xff0c;有着非常流畅的操作过程&#xff0c;还可以通过智能辅助等优秀特色…

网易mumu模拟器adb连接配置

一、 网易mumu模拟器下载 二、安装模拟器到本机指定目录 1、例如&#xff1a;D:\Program Files\MuMu 2、adb文配置相关文件位于&#xff1a;D:\Program Files\MuMu\emulator\nemu\vms\myandrovm_vbox86下&#xff0c;如下图所示&#xff1a; 3、打开myandrovm_vbox86.nemu文件…

uni-app 连接不上夜神模拟器

uni-app 连接不上夜神模拟器 第一步打开运行设置 设置端口号 第二步通过cmd命令去连接模拟器 我这利用的是HX 找到&#xff1a;HBuilderX.3.1.17.20210608.full\HBuilderX\plugins\launcher\tools\adbs 直接cmd 执行下面两个命令 adb connect 127.0.0.1:62001 adb devices…

夜神模拟器无法连接网络的解决办法

我们经常会在电脑上安装安卓模拟器来玩一些手机游戏或者运行手机软件&#xff0c;但是有时候可能由于网络不好等原因导致模拟器连接不上网络。比如夜神模拟器无法连接网络怎么办&#xff1f;下面就来看看解决的办法。 夜神模拟器无法连接网络怎么办&#xff1a; 1、同时按下“w…