象棋 Java设计(java课程设计)计算机科学与技术

本文档详细介绍了基于JAVA技术的中国象棋游戏的设计与实现,包括棋盘界面、棋子规则、功能需求分析以及项目亮点。游戏采用多线程处理棋子的闪烁,使用监听器处理棋子移动,实现悔棋、新游戏等功能,并遵循中国象棋的行棋规则,如马走日、车走直、象走田等。同时,游戏支持人人对战,具备保存和读取棋局的能力,以及背景音乐和音效。通过精确的坐标计算确保每个棋子的合法移动,实现了完整的象棋游戏体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

文章目录

  • 系列文章目录
  • 前言
  • 一、象棋的整个程序的架框
  • 功能需求分析及项目采用技术
  • 三、象棋项目设计思路
  • 四、项目技术亮点
  • 五、棋盘界面的java设计
  • 六、棋盘规则所使用代码
  • 七、棋盘界面的测试以及主要功能演示截图
  • 八、团队成员负责模块
  • 总结


前言

      结合JAVA和中国象棋方面的实践经验,在分析了中国象棋游戏需求基础上,设计并实现了中国象棋系统。该系统为人人对战。人人对战规则明确,包含了中国象棋所有的招法。方便了不同水平人群的不同选择。设计和开发好中国象棋游戏,对与提高Java开发水平和系统的设计能力有极大的帮助。

     主要研究基于JAVA技术的中国象棋游戏的分析与设计,对中国象棋游戏特殊的行棋规则给予了细致的分析与理解,设计出了一种实时可行的行棋规则,从移动范围、移动方向和穿越障碍几个方面重新描述行棋规则,基于Java 技术通过计算机模拟实现了中国象棋特殊的行棋规则算法,设计出了一种可行的方法,使每个棋子的行棋路线都严格遵循本身的行棋规则,游戏的实战对弈得以实现。

     本软件设计的主要功能如下:(1)实现象棋的规则;(2)能够实现下棋期间保存棋盘,以及读取已有的棋盘;(3)能够在开始游戏时播放背景音乐,以及行棋时播放走棋的音效;(4)任一方获胜后,游戏结束,提示某一方获得胜利。

、象棋的整个程序的架框

二、功能需求分析及项目采用技术

功能分析

1.使用鼠标对棋子进行控制,让棋子按规则运动。

2.棋子移动可以周期性闪烁来突出棋子移动。

3.初始场景棋子按照规则摆放,每次落子没有时间限制。

4.可以进行人人对战,按照规则判断胜负 

项目采用技术

1. 实现Runnable接口,启用多线程实现棋子的周期性闪烁。
2.使用List列表进行棋子的移动储存,方便进行悔棋。
3.界面采用了绝对布局,防止界面变化影响棋局。
4.棋子使用鼠标监视器获取坐标在进行算法处理以达到吃子、行子的目的。

5.界面”新游戏”按钮通过函数重置进行新的一局游戏。

三、象棋项目设计思路

     这个程序的关键是棋子的行走规则和判断胜负的条件,每个棋子都有自己的移动规则, 游戏利用接口监视器通过鼠标点击控制。

四、项目技术亮点

1.棋子的悔棋处理

2.棋子移动的闪烁处理

3.棋子的行走规则及吃子判断

4判断游戏的胜利规则

5绘制制作棋盘界面和棋子

五、棋盘界面的java设计

       构建Java程序Main.class来实现棋盘的界面展示与ChessFrame.class来利用棋盘设计框架,利用java.swing中主要的方法如按钮的设计,需要设计多个按钮,如悔棋,新游戏等。利用前面我们设计的棋盘中棋子的大小,从而可以完成棋盘的总体设计。主要依靠java.awt Container(容器),GridLayout棋盘的设计框架。设计棋子大小后,棋盘的长于宽分别使用558与676的大小。然后利用我们前面设计的棋子走向来镶嵌入我们所创建出的棋盘。主要需要两个监视器如ActionListenerMouseListener接口来分别观察按钮和观察鼠标。

package com.chess;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferedImage;

public class ChessMainframe extends JFrame implements ActionListener, MouseListener,Runnable {
    ChessManBehavior play[] = new ChessManBehavior[32];
    JLabel image;
    Container con;
    JToolBar jmain;
    JButton anew, repent, exit;
    JLabel text;

    public ChessMainframe(String title) {
        con = this.getContentPane();
        con.setLayout(null);
        this.setTitle(title);
        jmain = new JToolBar();
        text = new JLabel("欢迎来到象棋荣耀");
        text.setToolTipText("信息提示");
        anew = new JButton("新游戏");
        anew.setToolTipText("重新开始新的一局");
        exit = new JButton("退出");
        exit.setToolTipText("退出象棋对弈系统");
        repent = new JButton("悔棋");
        repent.setToolTipText("返回上次走棋的位置");
        jmain.setLayout(new GridLayout(0, 4));
        jmain.add(anew);
        jmain.add(repent);
        jmain.add(exit);
        jmain.add(text);
        jmain.setBounds(0, 0, 558, 30);
        con.add(jmain);
        draeChessMain();
        for(int i=0;i<32;i++)
        {
            con.add(play[i]);
            play[i].addMouseListener(this);
        }
        con.add(image=new JLabel(new ImageIcon("image/main.gif")));
        image.setBounds(0,30,558,620);
        image.addMouseListener(this);
        Dimension screeSize=Toolkit.getDefaultToolkit().getScreenSize();
        this.setLocation(screeSize.width/2-228,screeSize.height/2-350);
        this.setIconImage(new ImageIcon("image/红将.gif").getImage());
        this.setResizable(false);
        this.setSize(558,676);
        this.setVisible(true);
    }

    public void draeChessMain() {
        int i, k;
        Icon in = null;
        in = new ImageIcon("image/黑车.gif");
        for (i = 0, k = 24; i < 2; i++, k += 456) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 56, 55, 55);
            play[i].setName("车1");
        }
        in = new ImageIcon("image/黑马.gif");
        for (i = 4, k = 81; i < 6; i++, k += 342) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 56, 55, 55);
            play[i].setName("马1");
        }
        in = new ImageIcon("image/黑象.gif");
        for (i = 8, k = 138; i < 10; i++, k += 228) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 56, 55, 55);
            play[i].setName("象1");
        }
        in = new ImageIcon("image/黑士.gif");
        for (i = 12, k = 195; i < 14; i++, k += 114) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 56, 55, 55);
            play[i].setName("士1");
        }
        in = new ImageIcon("image/黑卒.gif");
        for (i = 16, k = 24; i < 21; i++, k += 114) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 227, 55, 55);
            play[i].setName("卒1" + i);
        }
        in = new ImageIcon("image/黑炮.gif");
        for (i = 26, k = 81; i < 28; i++, k += 342) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 170, 55, 55);
            play[i].setName("炮1" + i);
        }
        in = new ImageIcon("image/黑将.gif");
        play[30] = new ChessManBehavior(in);
        play[30].setBounds(252, 56, 55, 55);
        play[30].setName("将1");

        in = new ImageIcon("image/红车.gif");
        for (i = 2, k = 24; i < 4; i++, k += 456) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 569, 55, 55);
            play[i].setName("车2");
        }
        in = new ImageIcon("image/红马.gif");
        for (i = 6, k = 81; i < 8; i++, k += 342) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 569, 55, 55);
            play[i].setName("红马2");
        }
        in = new ImageIcon("image/红象.gif");
        for (i = 10, k = 138; i < 12; i++, k += 228) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 569, 55, 55);
            play[i].setName("红象2");
        }
        in = new ImageIcon("image/红士.gif");
        for (i = 14, k = 195; i < 16; i++, k += 114) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 569, 55, 55);
            play[i].setName("红士2");
        }
        in = new ImageIcon("image/红卒.gif");
        for (i = 21, k = 24; i < 26; i++, k += 114) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 398, 55, 55);
            play[i].setName("红卒" + i);
        }
        in = new ImageIcon("image/红炮.gif");
        for (i = 28, k = 81; i < 30; i++, k += 342) {
            play[i] = new ChessManBehavior(in);
            play[i].setBounds(k, 455, 55, 55);
            play[i].setName("炮2" + i);
        }
        in=new ImageIcon("image/红将.gif");
            play[31] = new ChessManBehavior(in);
            play[31].setBounds(252, 569, 55, 55);
            play[31].setName("帅");
    }

    @Override
    public void actionPerformed(ActionEvent e) {

    }

    @Override
    public void mouseClicked(MouseEvent e) {

    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }

    @Override
    public void run() {

    }
}

六、棋盘规则所使用部分代码

      在第一部分(象棋的界面的 )完成后,继而开始规范每一个棋子的走向,利用Runnable接口的方法来实现棋子的周期性闪烁,利用前面界面设计,对每个棋子的步骤都清晰的写出来,利用两个监视器来触动事件的发生,经过精密的坐标计算,从而计算出每个棋子的每一种方法,进而可以将给每一个棋子的运动轨迹做记录。

中国象棋规则介绍:

Ⅰ棋盘
      棋子活动的场所叫做“棋盘”,在长方形的平面上,绘有9条平行的竖线和10条平行的横线相交组成,共90个交叉点,棋子摆在这些交叉点上。中间第5根横线和第6根横线之间未画竖线的空白地带,叫做“楚河 汉界”,整个棋盘就以“楚河 汉界”分为相等的两部分;两方将帅坐阵,画有“米”字方格的地方叫做“九宫”。
Ⅱ棋子
      象棋的棋子共32个,分为红黑两组,各16个,由对弈双方各执一组,每组兵种是一样的,各分为七种。
红方:帅、仕、相、车、马、炮、兵;
黑方:将、士、象、车、马、炮、卒。
其中帅和将、士和仕、相和象、兵和卒的作用完全相同,仅仅是为了区分红棋和黑棋。
Ⅲ各棋子走法说明
①将或帅
移动范围:它只能在九宫内移动
移动规则:它每一步只可以水平或垂直移动一点
特殊说明:红方帅和黑方将不能直接见面,即帅和将中间必须有其他棋子间隔,否则构成“老将见面”情况;
假如现在是红方执子,此时构成“老将见面”状况,那么玩家可以移动帅直接吃掉对方的将,红方获胜。
②士或仕
移动范围:它只能在九宫内移动
移动规则:它每一步只能沿对角线方向移动一点
③象或相
移动范围:“楚河 汉界”的一侧
移动规则:它每一步只能沿对角线走两点(走田字),另外,移动的对角线方向上一点不能有其他棋子(不能被堵象眼)。
④马
移动范围:任何位置
移动规则:它每一步只能走曰字并且不能被绊马脚(斜着走,横位移量*纵位移量等于2)。
⑤车
移动范围:任何位置
移动规则:它可以水平或垂直方向移动任意个无阻碍的点。
⑥炮
移动范围:任何位置
移动规则:移动跟车很相似,它既可以像车一样水平或垂直方向移动任意无阻碍的点,也可以通过隔一个棋子吃掉对方一个棋子的方式进行移动。
⑦卒或兵
移动范围:过河后可以走过河后的一侧的任何位置,未过河只能走该棋子向上方向的直线区域
移动规则:它每步只能移动一个点,它未过河时只能向前移动,如果它过河了,增加向左向右移动的能力。
Ⅳ胜负说明
对局中,如果一方玩家认输或者该玩家的“将”或“帅”被对方棋子吃掉,该玩家算输,对方算赢
Ⅱ棋子信息存储及显示
棋子设计成对应的类,每种棋子都有自己对应的棋子图案;
中国象棋一共有32个棋子,这里可以将32个棋子对象数组存储到一个棋子对象数组chess。chess[i]中下标i的值如果是前两个表示黑方棋子,紧接着表示的是红方棋子,黑色棋子与红色棋子交替;
      棋子初始化时根据玩家执子颜色和棋子上的字获取指定棋子图案,根据x,y的值,将棋子的位置信息初始化到第x行第y列;
游戏开始时根据双方执子颜色初始化棋盘信息(红方和黑方棋子放置位置会不同);
游戏保证了执子方一定处于棋盘下方,判棋规则目前都是基于我方下棋去判断的,如果我方下棋符合下棋规则,先将下棋信息进行坐标转换,然后发送给对方;接收到对方的下棋信息时,直接按照对方下棋信息对棋盘和棋子信息进行变更即可(发送之前坐标已经转换,无需再次转换)。
Ⅲ走棋规则
对于中国象棋来说,有马走日、象走田等一系列规则。
根据不同的棋子,按不同的规则进行走法判断。
判断是否能走棋的算法如下:
①如果棋子为“帅”或“将”,检查是否走直线并且走一步,以及走一步是否超出范围(老将碰面情况需要提前特殊处理)
②如果棋子为“仕”或“士”,检查是否沿斜对角线走一步,以及走一步是否超过范围
③如果棋子为“象”或“象”,检查是否走“田”字,是否被堵象眼,走一步是否超出范围
④如果棋子为“马”,检查是否走“日”字,是否被绊马脚
⑤如果棋子为“车”,检查是否走直线,移动前的位置和移动后的位置中间是否还有其他子
⑥如果棋子为“炮”,检查是否走直线,判断是否吃子,如果吃子判断中间是否只有一个棋子,否则判断中间是否还有其他子
⑦如果棋子为“卒”或“兵”,检查是否走直线,走一步;如果棋子没有过河,判断棋子是否向前走;如果棋子已经过河,判断是否向前、左、右移动
 

package com.chess;

import java.awt.event.MouseEvent;
import java.util.List;
import javax.swing.JLabel;

public class ChessRule {
    public ChessRule() {
    }

    public void cannonRule(ChessManBehavior play, JLabel[] playQ, MouseEvent me, List<ChessRegret> chessRegretList, int man) {
        int count = 0;
        int cx = me.getX();
        int cy = me.getY() + 30;
        int i;
        int j;
        int k;
        ChessRegret chessRegret;
        if (cx - play.getX() >= 0 && cx - play.getX() < 57) {
            for(i = 56; i <= 569; i += 57) {
                if (cy - i >= 0 && cy - i < 57) {
                    for(j = 0; j < 32; ++j) {
                        if (playQ[j].getX() == play.getX() && play.getName() != playQ[j].getName() && playQ[j].isVisible()) {
                            for(k = i; k < play.getY(); k += 57) {
                                if (playQ[j].getY() == k) {
                                    ++count;
                                }
                            }

                            for(k = play.getY(); k < i; k += 57) {
                                if (playQ[j].getY() == k) {
                                    ++count;
                                }
                            }
                        }
                    }

                    if (count == 0) {
                        chessRegret = new ChessRegret();
                        chessRegret.man = man;
                        chessRegret.cx = play.getX();
                        chessRegret.cy = play.getY();
                        chessRegretList.add(chessRegret);
                        play.setBounds(play.getX(), i, 55, 55);
                        return;
                    }
                }
            }
        }

        if (me.getY() - play.getY() + 30 >= 0 && me.getY() - play.getY() + 30 <= 56) {
            for(i = 24; i <= 480; i += 57) {
                if (me.getX() - i >= 0 && me.getX() - i < 57) {
                    for(j = 0; j < 32; ++j) {
                        if (playQ[j].getY() == play.getY() && play.getName() 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值