0

0

怎么用Java实现中国象棋游戏

PHPz

PHPz

发布时间:2023-05-12 18:58:04

|

1905人浏览过

|

来源于亿速云

转载

一、界面

下棋的棋盘首先要准备好,这就是一个合适大小合适比例合适位置的界面,然后在窗体上画上(没错drawline的那种画上)n条直线和斜线,具体数值根据你的界面大小设置。这样画出的界面整齐好看~

public void paint(Graphics g){
        
        super.paint(g);//重写画图函数
        Font f=new Font("微软雅黑",Font.BOLD,30);
        g.setFont(f);
        
        g.drawRect(60, 50, 500, 560);//外圈
        g.drawRect(70, 60, 480, 540);//内圈
        //横线部分
        int length=60;
        for(int i=0;i<9;i++){
            g.drawLine(70, length, 550, length);
            length+=60;
        }
        //中间汉字
        g.drawString("楚河", 160, 340);
        g.drawString("汉界", 400, 340);
        //竖线部分
        length=130;
        for(int i=0;i<7;i++){
            //上半部分竖线
            g.drawLine( length,60, length,300);
            //下半部分竖线
            g.drawLine( length,360, length,600);
            length+=60;
        }
        //上半部分九宫格斜线
        g.drawLine(250, 60, 370, 180);
         g.drawLine(370, 60, 250, 180);
         //下半部分九宫格斜线
         g.drawLine(250, 480, 370, 600);
         g.drawLine(250, 600, 370, 480);
     
    }

二、按钮

画好棋盘之后加上功能按钮,这个时候的功能暂时不考虑实现,可以根据喜好随意添加。这里推荐将按钮类型设置成数组,便于及时增删。

//添加到面板上
        String[] type = {"开始游戏","重新开始","认 输","悔 棋"};
        for(int i=0;i

怎么用Java实现中国象棋游戏

这个时候你会发现在加按钮的地方贴的十分紧凑,我的解决办法是在这一块面板上再加一个面板设置为白色覆盖在上面,这样根据面板的流式布局按钮就会下移,调整空白面板的宽度可以改变按钮的位置。

三、加棋子

将找到的棋子图片加到棋盘交叉的位置上才是给棋盘注入灵魂,将所有的十四类图片加到package中以便程序之后可以在其他电脑上运行(这里推荐png格式,jpg格式会有方形边框)。
接下来分三步走

立即学习Java免费学习笔记(深入)”;

1.创建一个10行9列的整数数组,用来存储每个位置的数据;
2.创建一个长度为14的Image数组,用来与棋子类型对应;
3.遍历整数数组画出对应的棋子;

这是棋盘的直观图,也就是我们的整数数组的初始值:

怎么用Java实现中国象棋游戏

将Image与棋子图片对应:

//初始化给每个chess定义
        for(int k=0; k<14; k++){
            chess[k] = new ImageIcon(this.getClass().getResource((k+1)+".png")).getImage();
        }

遍历画图:

//根据棋盘布局
        for(int i=0;i0){
                    bg.drawImage(chess[place[i][j]-1], chessX+60*j, chessY+60*i, 50, 50, null); 
                }
            }
        }

四、实现棋子的移动

通过函数获得鼠标拖动前后两个点所代表的棋盘上的位置,并将这两个位置的二维数组的值交换,然后重新绘图实现棋子的移动。

int x1, y1, x2, y2;
public void mousePressed(MouseEvent e) {
        
            x1 = e.getX();
            y1 = e.getY();
            x1 = getj(x1);
            y1 = geti(y1);
    }
    public void mouseReleased(MouseEvent e) {
        
            x2 = e.getX();
            y2 = e.getY();
            x2 = getj(x2);
            y2 = geti(y2);
    }
    //根据点的坐标得到其代表的位置,具体参数可以微调,我的格子是60x60大小
    public int getj(int x){
        return (x-50)/60;
    }
    public int geti(int y){
        return (y-40)/60;
    }

这个时候遇到的状况就是你每次移动一次之后,整个界面都要重绘一次,而画面是直接画在窗体上的,数据会直接传到电脑硬件,这样一来画图速度就慢了,所以会出现每走一步界面就闪烁一次的情况,这种情况下,我们可以将画面先存在缓存中,就不经过硬件直接画出来,这样效率就可以明显提高。

BufferedImage buffer = new BufferedImage(this.getWidth(), this.getHeight(), BufferedImage.TYPE_INT_ARGB);
Graphics bg = buffer.getGraphics();

//这个中间写的是你画界面的方法,也就是上面提到的paint方法内部
//......

//绘制缓存到窗体上
g.drawImage(buffer, 0, 0, null);

五、判断胜负

率先吃掉对方帥或将的队伍获胜,写一个函数判断谁胜谁负显示胜局,同时将数据初始化为0,准备再来一局:
(showMessageDialog方法可以直接跳出一个框)

Morph Studio
Morph Studio

Morph Studio是一款领先的文字转视频AI平台,可以将用户输入的文字转化为精美视频。

下载
//判断游戏结束并显示胜局
public void isWine() {
        
        System.out.println(place[y1][x1]+" "+place[y2][x2]);
        if (place[y2][x2]==7&&place[y1][x1]!=0) {
            place[y2][x2] = place[y1][x1];
            place[y1][x1] = 0;
            UI.repaint();
            JOptionPane.showMessageDialog(null, "黑方  胜利!");
            again();
        } else if(place[y2][x2]==14&&place[y1][x1]!=0) {
            place[y2][x2] = place[y1][x1];
            place[y1][x1] = 0;
            UI.repaint();
            JOptionPane.showMessageDialog(null, "红方  胜利!");
            again();
        }
    }
    //游戏结束时要重绘
    public void again(){
          for(int i=0; i

六、按钮“开始游戏”和“重新开始”的实现

加动作监听器

public void actionPerformed(ActionEvent e) {
        
        type = e.getActionCommand();
        if("开始游戏".equals(type)||"重新开始".equals(type)){
            x=0;
            count = 1;//这里要把每次的走棋方刷新,认输时也需要刷新
            init();
            UI.repaint();
        }
    }
    //初始化place坐标
    public void init(){

        /*红兵 1.png
         *红炮 2.png
         *红車 3.png
         *红马 4.png
         *红相 5.png
         *红仕 6.png
         *红帥 7.png
         *黑卒 8.png
         *黑炮 9.png
         *黑車 10.png
         *黑马 11.png
         *黑象 12.png
         *黑士 13.png
         *黑将 14.png
         */
        
            
        for(int i=0;i

这里的init函数是给整数二维数组初始化为开局后遍历可以加上棋子的状态。

七、加规则

//规定各个棋子的移动规则
public boolean rule(int gi, int gj,int si, int sj){
        int x = place[gi][gj];
        int y = place[si][sj];
        int start, end;
        
        //判断为何种棋子
        //車:只能走直线
        if(x == 3||x == 10){
            
            if(gi != si&&gj != sj)    return false;
            else if(gi == si){
                start = Math.min(gj, sj);
                end = Math.max(gj, sj);
                for(int m = 1; m < end - start; m++){
                    if(place[gi][start+m] != 0)    return false;
                }
                return true;
            }
            else if(gj == sj){
                start = Math.min(gi, si);
                end = Math.max(gi, si);
                for(int m = 1; m < end - start; m++){
                    if(place[start+m][gj] != 0)    return false;
                }
                return true; 
            }
            else return true;
        }
        //马:走日,且某个位置不可以有棋子
        else if(x == 4||x == 11){
            //下
            if(si - gi == 2&&Math.abs(gj-sj) == 1&&place[gi+1][gj] == 0)    return true;
            //上
            else if(gi - si == 2&&Math.abs(gj-sj) == 1&&place[gi-1][gj] == 0)    return true;
            //右
            else if(sj - gj == 2&&Math.abs(gi-si) == 1&&place[gi][gj+1] == 0)    return true;
            //左
            else if(gj - sj == 2&&Math.abs(gi-si) == 1&&place[gi][gj-1] == 0)    return true;
            //否则不可以走
            else return false;
        }
        //相:走田,且不能过河
        else if(x == 5||x == 12){
            //左上
            if(gi - si == 2&&gj - sj == 2&&place[gi-1][gj-1] == 0){
                
                if((x == 5&&si >= 5)||(x == 12&&si < 5))    return true;
                else return false;
            }
            //右上
            else if(gi - si == 2&&sj - gj == 2&&place[gi-1][gj+1] == 0){
                
                if((x == 5&&si >= 5)||(x == 12&&si < 5))    return true;
                else return false;
            }
            //左下
            else if(si - gi == 2&&gj - sj == 2&&place[gi+1][gj-1] == 0){
                
                if((x == 5&&si >= 5)||(x == 12&&si < 5))    return true;
                else return false;
            }
            //右下
            else if(si - gi == 2&&sj - gj == 2&&place[gi+1][gj+1] == 0){
                
                if((x == 5&&si >= 5)||(x == 12&&si < 5))    return true;
                else return false;
            }
            else return false;
        }
        //士:斜着走不能出田字格
        else if(x == 6||x == 13){
            
            if(Math.abs(gj-sj)==1&&Math.abs(gi-si)==1){
                
                if(x == 6&&si >= 7&&sj >= 3&&sj <= 5)    return true;
                else if(x == 13&&si <= 2&&sj >= 3&&sj <= 5)    return true;
                else return false;
            }
            else return false;
        }
        //将:不能出田字格且不能会面
        else if(x == 7||x == 14){
            
            if((Math.abs(gj-sj)==1&&gi - si ==0)||(gj - sj ==0&&Math.abs(gi-si)==1)){
                
                if(x == 7&&si >= 7&&sj >= 3&&sj <= 5)    return true;
                else if(x == 14&&si <= 2&&sj >= 3&&sj <= 5)    return true;
                else return false;
            }
            else return false;
            
        }
        //炮:隔一个
        else if(x == 2||x == 9){
            
            //若要吃棋子,必须中间有且只有一枚棋子
            if(x*y!=0){
                int t = 0;
                if(gi == si){
                    for(int m = Math.min(gj, sj); m <= Math.max(gj, sj); m++){
                        if(place[gi][m] != 0)    t++;
                    }
                }
                else if(gj == sj){
                    for(int m = Math.min(gi, si); m <= Math.max(gi, si); m++){
                        if(place[m][gj] != 0)    t++;
                    }
                }
                if(t == 3)    return true;
                
            }    
                
            //若为不吃棋子的情况,中间不可以有其他棋子,且只能走直线
            else {
                int t = 0;
                if(gi == si){
                    for(int m = Math.min(gj, sj); m <= Math.max(gj, sj); m++){
                        if(place[gi][m] != 0)    t++;
                    }
                }
                else if(gj == sj){
                    for(int m = Math.min(gi, si); m <= Math.max(gi, si); m++){
                        if(place[m][gj] != 0)    t++;
                    }
                }
                if(t == 1) return true;
                else return false;
            }
        }
        //兵:不能后退,且过了河才可以左右移动
        else if(x == 1||x == 8){
            //判断是否过河
            if(x == 1){
                if(gi >=5){
                    if(gi - si == 1&&gj == sj)    return true;
                    else return false;
                }
                else if((gi - si == 1&&sj - gj == 0)||(gi - si == 0&&Math.abs(sj-gj) == 1))    return true;
                else return false;
            }
            else if(x == 8){
                if(gi <5){
                    if(si - gi == 1&&gj == sj)    return true;
                    else return false;
                }
                else if(((si - gi == 1&&sj - gj == 0))||(gi - si == 0&&Math.abs(sj-gj) == 1))    return true;
                else return false;
            }
            else return false;
        }
        
        return false;
    }

长长的一大串,这里对于炮和将需单独考虑,炮有直行和隔一个两种走法,需分开考虑,而将就更是麻烦

//判断将是否会面
public boolean meet(){
        int jiangi=0, jiangj=0, shuaii=0, shuaij=0, temp=0;
        for(int i=0; i<10; i++){
            for(int j=0; j<9; j++){
                if(place[i][j]==7){
                    shuaii = i;
                    shuaij = j;
                }
                else if(place[i][j]==14){
                    jiangi = i;
                    jiangj = j;
                }
            }
        }
        if(shuaij == jiangj){
            for(int i=jiangi+1; i

八、轮次

红黑轮流下棋
我单独写了一个方法判断将是否会面,因为导致将会面的不仅是将自身的移动导致,还可能是其他棋子的移动,所以也是一个boolean函数,只有同时满足前一个函数以及这个函数返回的是不会面,才可以移动,移动时我定义了一个参数x记录局数,根据他的奇偶判断轮到哪一方走。这样就实现了象棋的规则。

九、悔棋

难免会有失误,加上悔棋功能更合适。
我们在交换两个点的值时(或者吃子的情况)需记录下之前的值,然后当动作监听器监听到点击悔棋时又交换回来。
一次只能悔棋一次,且刚开始时棋子没有移动不能悔棋。

十、背景 及 提示

加上自己挑的背景,并为了方便下棋,标注轮到哪一方。
加背景可以用到画棋子同样的方法,所以要画在棋盘前面,防止被覆盖住。
这样加上去又有一个很明显的问题,就是你每操作一次右边的按钮都会消失,被你的背景图覆盖了,这怎么办呢?
于是乎,又总结出了三种方法:

1.重写按钮的paint方法;
2.将按钮以菜单的形式加在左上角;
3.将按钮直接p在背景图上(截图),再画就可以了;

此外你还可以在背景图上加上“当前下棋方”的字样,在边上显示当前下棋方将领的图片。
这里借用了count参数并将其传到了监听器中,重写了构造函数。

int count=1;

if(listener.count==1){
            //画帥
        bg.drawImage(chess[6], 708, 322, 50, 50, null); 
    }else if(listener.count==-1){
            //画将
        bg.drawImage(chess[13], 708, 322, 50, 50, null); 
}

每下一子,count×(-1),以此标记是哪一方并画图。

附一张成果图:

怎么用Java实现中国象棋游戏

相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
java
java

Java是一个通用术语,用于表示Java软件及其组件,包括“Java运行时环境 (JRE)”、“Java虚拟机 (JVM)”以及“插件”。php中文网还为大家带了Java相关下载资源、相关课程以及相关文章等内容,供大家免费下载使用。

831

2023.06.15

java正则表达式语法
java正则表达式语法

java正则表达式语法是一种模式匹配工具,它非常有用,可以在处理文本和字符串时快速地查找、替换、验证和提取特定的模式和数据。本专题提供java正则表达式语法的相关文章、下载和专题,供大家免费下载体验。

735

2023.07.05

java自学难吗
java自学难吗

Java自学并不难。Java语言相对于其他一些编程语言而言,有着较为简洁和易读的语法,本专题为大家提供java自学难吗相关的文章,大家可以免费体验。

733

2023.07.31

java配置jdk环境变量
java配置jdk环境变量

Java是一种广泛使用的高级编程语言,用于开发各种类型的应用程序。为了能够在计算机上正确运行和编译Java代码,需要正确配置Java Development Kit(JDK)环境变量。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

396

2023.08.01

java保留两位小数
java保留两位小数

Java是一种广泛应用于编程领域的高级编程语言。在Java中,保留两位小数是指在进行数值计算或输出时,限制小数部分只有两位有效数字,并将多余的位数进行四舍五入或截取。php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

398

2023.08.02

java基本数据类型
java基本数据类型

java基本数据类型有:1、byte;2、short;3、int;4、long;5、float;6、double;7、char;8、boolean。本专题为大家提供java基本数据类型的相关的文章、下载、课程内容,供大家免费下载体验。

446

2023.08.02

java有什么用
java有什么用

java可以开发应用程序、移动应用、Web应用、企业级应用、嵌入式系统等方面。本专题为大家提供java有什么用的相关的文章、下载、课程内容,供大家免费下载体验。

430

2023.08.02

java在线网站
java在线网站

Java在线网站是指提供Java编程学习、实践和交流平台的网络服务。近年来,随着Java语言在软件开发领域的广泛应用,越来越多的人对Java编程感兴趣,并希望能够通过在线网站来学习和提高自己的Java编程技能。php中文网给大家带来了相关的视频、教程以及文章,欢迎大家前来学习阅读和下载。

16925

2023.08.03

c++主流开发框架汇总
c++主流开发框架汇总

本专题整合了c++开发框架推荐,阅读专题下面的文章了解更多详细内容。

25

2026.01.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 2.4万人学习

C# 教程
C# 教程

共94课时 | 6.4万人学习

Java 教程
Java 教程

共578课时 | 44.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号