package com.company;
import javax.swing.*;
public class ChessMainBehavior extends JLabel {//Java中所有图像的显示都是基于JLabel实现故需要继承
boolean died=false;//初始时刻棋子的状态
ChessMainBehavior(Icon image){//构造方法继承自JLabel类:创建具有指定图像的JLabel实例
super(image);//调用image的构造器可以正常调用image会完成image的初始化
}
public void playSounds(){//点击棋子可以放出声音的功能
}
}
首先是该ChessMainBehavior类的定义该类继承了JLabel类便于调用对于Java中的图像显示的相关方法,该类实际上是建立象棋32个棋子所在的类,便于创建32个棋子对象,其内的构造函数的参数为Icon image表示对应要传入的具体图像,来实现对于32个棋子图像的设定,该构造器内部还包含image的构造器,同样能够完成对于棋子图像image的改变。
package com.company;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.List;
public class ChessMainframe extends JFrame implements ActionListener, MouseListener,Runnable {//implments为接口一旦定义则该类里面必须有接口
//JFrame可以提供相应的框架
//后面所有的类里面的方法的重写ActionListener为按钮点击 MouseListener为鼠标点击 Runnable为多线程
ChessMainBehavior play[]=new ChessMainBehavior[32];//定义象棋中的32个棋子图片
JLabel image;//定义一个JLabel类对象image用来显示棋盘
Container con;//定义一个内容显示对象即为一个容器可以将其它图片和按钮放在上边Container为容器类
JToolBar jmain;//定义一个工具栏用来显示(装载)相应的按钮
JButton anew,repent,exit;//定义三个按钮新游戏,重新游戏,退出游戏
JLabel text;//定义文本提示框
int chessPlayClick=2;//表示谁走1表示黑棋走2表示红旗走3表示谁都无法走
boolean chessManClick;//判断是否点击了棋子未点就是false点了就变成true
Thread tmain;//线程变量用来实现棋子闪烁过程中的子线程
static int Man;//用来判断点的是哪个棋子
boolean gameIsOver;//判断游戏是否结束为true则游戏结束
ChessRule chessRule;//运用定义的ChessRule类定义出的对象chessRule来通过调用规则与吃子方法来实现操作
List regretList;//用于进行悔棋操作的记录
public ChessMainframe(String title){//编写构造函数即为构造方法作用:当该类被new为对象时,对象需要声明的一些变量的构造声明主要为初始化
con=this.getContentPane();//获取内容面板由于JFrame类无法直接添加组件只能通过该方法获取内容面板并赋给con显示对象实现初始化
con.setLayout(null);//设置窗口的布局为绝对布局之后再次基础上添加按钮或图片可以按位置大小添加
this.setTitle(title);//将本页面的标题设置为传递进来的字符串title
jmain=new JToolBar();//进行jmain的初始化
text=new JLabel("欢迎使用象棋对弈系统");//完成文本提示框的初始化
text.setToolTipText("信息提示");//当鼠标在该Label上停留时的显示信息
anew=new JButton("新游戏");//设计该按钮上的名字
anew.setToolTipText("重新开始新的一局游戏");//设计停留在该按钮上时显示信息
exit=new JButton("退出");
exit.setToolTipText("退出象棋博弈系统");
repent=new JButton("悔棋");
repent.setToolTipText("返回上次走棋的位置");
jmain.setLayout(new GridLayout(0,4));//设置用户界面上的屏幕组件的格式布局常用有五种这是之一创建rows行cols列的GridLayout对象
jmain.add(anew);
jmain.add(repent);
jmain.add(exit);
jmain.add(text);//工具栏(一行四列)包含三个按钮和一个提示信息
jmain.setBounds(0,0,558,30);//设置该工具栏起始位置为(0,0)宽为558像素,高为30像素
con.add(jmain);//将设定好的工具栏添加到内容面板里面
drawChessMain();//只是初始化32个棋子的图片以及位置方便调用但是如果不添加到显示对象con中则无法显示出来
for(int i=0;i<32;i++){//依次将32个棋子图片添加到显示对象con中
con.add(play[i]);
play[i].addMouseListener(this);//每个棋子都有点击事件以及鼠标落下的事件所有将所有棋子都加入一个鼠标事件监听器
}
//之所以采用先添加棋子和按钮而非先添加背景板的原因是:绝对布局中先添加的永远显示在最上方
con.add(image=new JLabel(new ImageIcon("image/main.gif")));//类似于下面的依次添加过程括号内的new ImageIcon("image/main.gif")
//相当于之前的in而new JLabel(新in)也与new ChessMainBehavior(in);相似因为ChessMainBehavior是继承了JLabel类之后再赋值给image对象(play[i]也是该类型)
//再作为add的参数加入con中即实现方式一致
image.setBounds(0,30,558,620);//之所以y从30开始是因为工具栏占据了30像素
image.addMouseListener(this);//因为其上方棋子会随着鼠标事件而移动所以棋盘也要加入鼠标事件
Dimension screenSize=Toolkit.getDefaultToolkit().getScreenSize();//得到当前屏幕的大小赋值给抽象类Dimension对象screenSize
this.setLocation(screenSize.width/2-280,screenSize.height/2-350);//将组件移到新位置用x与y确定新位置的左上角,来保证该组件中间对齐
this.setIconImage(new ImageIcon("image/红将.gif").getImage());//实际上功能(添加一个小图标)与下方添加是一致的具体自己理解
this.setResizable(false);//令窗体无法改变大小
this.setSize(558,676);//为当前窗体总大小固定住要加上工具栏和标题栏的高度与宽度
this.setVisible(true);//使该窗体可见默认为不可见的必须设置为true!
gameIsOver=false;//初始化表示该游戏没有结束仍在继续
regretList=new ArrayList();//将之初始化为一元素只能为ChessRegret模式的空列表
chessRule=new ChessRule();
this.addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {//控制窗口关闭的重写函数
super.windowClosing(e);
System.exit(0);//至此程序将直接关闭
}
});//用于控制退出程序
anew.addActionListener(this);
repent.addActionListener(this);
exit.addActionListener(this);//对三个按钮分别都加上动作
}
public void drawChessMain(){//画棋盘的函数避免构造函数过长
int i,k;
Icon in=null;//目的是为了显示图片
//首先显示黑方对象
//用play[0][1]放黑车
in=new ImageIcon("image/黑车.gif");//从指定位置得到该图片赋给in对象
for(i=0,k=24;i<2;i++,k+=456){
play[i]=new ChessMainBehavior(in);//将黑车的图片加载赋值给play[i]对象此循环一共执行两次表示构造两次黑车的位置二者位置之差为456
play[i].setBounds(k,56,55,55);//定义其位置x为横坐标纵坐标已求出play[0][1]放黑车
play[i].setName("车1");//所有黑方均为1后缀
}
//显示黑马
in=new ImageIcon("image/黑马.gif");
//用play[4][5]放黑马i即为其中的4 5
for(i=4,k=81;i<6;i++,k+=342){
play[i]=new ChessMainBehavior(in);//新建一个内容为in的ChessMainBehaviour对象赋值给play[i]完成初始化
play[i].setBounds(k,56,55,55);
play[i].setName("马1");
}
//显示黑象
in=new ImageIcon("image/黑象.gif");
//用play[8][9]放黑象
for(i=8,k=138;i<10;i++,k+=228){
play[i]=new ChessMainBehavior(in);//新建一个内容为in的ChessMainBehaviour对象赋值给play[i]完成初始化
play[i].setBounds(k,56,55,55);
play[i].setName("象1");
}
//显示黒士
in=new ImageIcon("image/黑士.gif");
//用play[12][13]放黑士
for(i=12,k=195;i<14;i++,k+=114){
play[i]=new ChessMainBehavior(in);//新建一个内容为in的ChessMainBehaviour对象赋值给play[i]完成初始化
play[i].setBounds(k,56,55,55);
play[i].setName("士1");
}
//显示黑卒
in=new ImageIcon("image/黑卒.gif");
//用paly[16][17][18][19][20]放黑卒
for(i=16,k=24;i<21;i++,k+=114){
play[i]=new ChessMainBehavior(in);
play[i].setBounds(k,227,55,55);
play[i].setName("卒1"+i);//setName的名字允许重复
}
//显示黑炮
in=new ImageIcon("image/黑炮.gif");
//用play[26][27]放黑炮
for(i=26,k=81;i<28;i++,k+=342){
play[i]=new ChessMainBehavior(in);
play[i].setBounds(k,170,55,55);
play[i].setName("炮1"+i);
}
//显示黑将
in=new ImageIcon("image/黑将.gif");
//用play[30]放黑将
play[30]=new ChessMainBehavior(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 ChessMainBehavior(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 ChessMainBehavior(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 ChessMainBehavior(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 ChessMainBehavior(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 ChessMainBehavior(in);
play[i].setBounds(k,398,55,55);
play[i].setName("卒2"+i);
}
//显示红炮
in=new ImageIcon("image/红炮.gif");
for(i=28,k=81;i<30;i++,k+=342){
play[i]=new ChessMainBehavior(in);
play[i].setBounds(k,455,55,55);
play[i].setName("炮2"+i);
}
//显示红将
in=new ImageIcon("image/红将.gif");
play[31]=new ChessMainBehavior(in);
play[31].setBounds(252,569,55,55);
play[31].setName("帅2");
}
此行代码是对于框架类ChessMainFrame类的定义,该类继承了Frame类(对于框架设计都需要使用的类)同时还使用了接口
ActionListener, MouseListener,Runnable用来实现相应的事件的响应,这接口对应的三个类分别为
ActionListener为按钮点击 MouseListener为鼠标点击 Runnable为多线程的作用,当Idea接口定义完毕后就会自动重写完成该三个接口所需要的各个方法(最后会讲解)
这就是具体的参数情况,之后根据这些参数进行坐标系的建立
还要设定每个棋子的长度和宽度均为55像素
由图片可得每个象棋棋子之间间隔为2像素且横坐标从0纵坐标要算上工具栏的高度30
对于该框架类,定义了一个大小为32的ChessMainBehavior类数组play[32]用来存储32个棋子,还有image为棋盘con为空容器作用是将所有的框架加在它上面,jmain为设定的工具栏用于装载对应的三个按钮和一个提示栏,之后在该类的构造器内完成了相关变量和对象的初始化,首先对于con是利用this.getContentPane()来获得暂时为空的组件完成初始化,标题的设定则按照传入的String title来设定,对于text为工具栏最右侧的文字提示栏其为JLabel("欢迎使用象棋对弈系统")来完成上方名字的初始化,之后的text.setToolTipText("信息提示")是当鼠标落在该文字栏时显示的文字,按同样方法完成3个按钮(JButton)的问题与提示符,之后进行标题栏的格式布局设定为GridLayout(0,4)即包含一行和四列的格式,之后将三个按钮和文字提示符都加到工具栏jmain上即完成工具栏的初始化,之后对工具栏的位置进行设置为jmain(0,0,558,30)即该工具栏最左上角坐标为(0,0)其宽度为558高度为30并将该工具栏添加到空组件con上con.add(jmain).
之后调用drawChessMain()方法完成32个棋子的初始化,以其中的黑车为例子,根据坐标图可得最左边黑车左上角坐标为(24,56)最右边黑车的左上角坐标为(480,56)56为工具栏高度加棋盘最上方空白处,可以先完成play[0]=new ChessMainBehavior(in)其中in=new ImageIcon("image/黑马.gif")即In为image文件下的黑马.gif图片,并按照ChessMainBehavior(in)该构造方法完成play[0]的构造之后对play[0]的左上角坐标进行设定为play[0].setBounds(24,56,55,55),按此原理完成32个棋子的定位与初始化,之后利用com.add(play[i])将32个棋子加到容器内。
此时整个框架只差棋盘没有完成设定,于是利用代码
con.add(image=new JLabel(new ImageIcon("image/main.gif")));完成棋盘初始化其具体与棋子的初始化类似JLabel可以认为是之前的ChessMainBehavior,其括号内相当于in完成了该棋盘(image)的初始化并加到con上.
之后社定con的坐标为(0,30)宽度与高度为558与620,之所以先加棋子与工具栏最后加棋盘是因为该窗口con的布局是绝对布局,先放在上面的就位于最上方,注意由于棋子和棋盘都会受到鼠标的点击所以二者都需要添加鼠标监听事件来实现鼠标操作是能够感应到image.addMouseListener(this).最后利用Dimension获取整个屏幕的大小并赋值给screenSize之后利用setLocation来设定该屏幕位于中心位置,setResizeable(false)来使得该屏幕大小不可改变,最后设定窗体的总大小为(558,676)也是由之前的图片得到,并令this.setVisible(true)即令该窗口为可见的。
至此暂时ChessMainFrame框架类定义完成。
package com.company;
public class Main {
public static void main(String[] args) {
// write your code here
ChessMainframe chessMainframe=new ChessMainframe("象棋对弈系统");//前方的ChessMainframe为类名使用后方的ChessMainframe()为此类对应的构造方法
}
}
在主函数中调用该框架构造类的对象chessMainframe并传入实参为象棋对弈系统,于是该系统的最上方标题即为此.运行该主函数就能得到该象棋的主框架如下图所示
至此页面设计到此完毕。
之后为了对于棋子点击后能够显示出其处于被点击的情况,要实现点击后令棋子处于闪烁状态(主要通过线程来实现)首先在之前的ChessMainbehavior类中加上boolean属性died为false即表示32个棋子均未死(被吃)
在主框架类中多定义变量chessPlayClick为1时表示轮到黑棋走,为1时表示轮到红旗走,tmain变量为线程变量就是用来实现棋子闪烁的子线程,定义变量Man用来判断点的是哪个棋子以及chessManClick当为false时表示没有棋子被点击为true时表示有棋子处于被点击状态。
之后由于闪烁是要通过鼠标点击来实现于是要对于鼠标点击方法mouseClicked(Mouseevent e)的修改来实现其主要代码如下(有关吃子的操作暂不处理)
public void mouseClicked(MouseEvent e) {//实现代码闪烁主要是通过鼠标的点击事件
int ex=0;
int ey=0;
if(tmain==null){//当tmain为null则进行启动子线程
tmain=new Thread(this);//将当前的类实例化为一个进程并对tmain初始化
tmain.start();//启动该进程
}
if(gameIsOver)
return;//表示如果游戏已经结束则直接结束鼠标点击事件鼠标无法再点击
if(e.getSource().equals(image)){//e为定义的鼠标事件,若其得到的资源事件等于image(为棋盘对象)即点中了棋盘而非棋子
if(chessPlayClick==2&&play[Man].getName().charAt(1)=='2'){//表示当前为红旗走且点击的也是红棋
ex=play[Man].getX();
ey=play[Man].getY();//Man为当前首次点击的棋子
if (Man >= 0 && Man < 4) {
System.out.println("移动红车");
chessRule.cannoRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 4 && Man < 8) {
System.out.println("移动红马");
this.chessRule.horseRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 8 && Man < 12) {
System.out.println("移动红象");
this.chessRule.elephantRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 12 && Man <= 15) {
System.out.println("移动红士");
this.chessRule.chapRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 16 && Man < 26) {
System.out.println("移动红兵");
this.chessRule.soilderRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 25 && Man < 30) {
System.out.println("移动红炮");
this.chessRule.cannonRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man == 30 || Man == 31) {
System.out.println("移动红帅");
this.chessRule.masterRule(this.play[Man], this.play, e, this.regretList, Man);
}
if(ex==play[Man].getX() && ey==play[Man].getY()){//看走之前的坐标与走之后的坐标是否一致即是否是要进行换棋子走的操作
text.setText(" 红旗走棋");
chessPlayClick=2;
}else {
if(chessRule.masterMeet(play)==1){
JOptionPane.showMessageDialog(this,"游戏结束,黑棋胜利!!!");
gameIsOver=true;
return;
}
text.setText(" 黑棋走棋");
chessPlayClick=1;//表示要黑棋走了
chessManClick=false;//表示变回未点击状态
}
}else if(chessPlayClick==1 && play[Man].getName().charAt(1)=='1'){
ex=play[Man].getX();
ey=play[Man].getY();
if (Man >= 0 && Man < 4) {
System.out.println("移动黑车");
this.chessRule.cannoRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 4 && Man < 8) {
System.out.println("移动黑马");
this.chessRule.horseRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 8 && Man < 12) {
System.out.println("移动黑象");
this.chessRule.elephantRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 12 && Man <= 15) {
System.out.println("移动黑士");
this.chessRule.chapRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 16 && Man < 26) {
System.out.println("移动黑兵");
this.chessRule.soilderRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man >= 25 && Man < 30) {
System.out.println("移动黑炮");
this.chessRule.cannonRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (Man == 30 || Man == 31) {
System.out.println("移动黑将");
this.chessRule.masterRule(this.play[Man], this.play, e, this.regretList, Man);
}
if (ex == this.play[Man].getX() && ey == this.play[Man].getY()) {//判断是否重新点击了黑棋即换棋操作即没有执行上述的任何一个规则坐标没有改变
this.text.setText(" 黑棋走棋");
this.chessPlayClick = 1;
} else {//没有重新点击黑棋已经走完要判断是结束了游戏还是要红旗去走
if (this.chessRule.masterMeet(this.play) == 1) {//将帅相遇了
JOptionPane.showMessageDialog(this, "游戏结束,黑棋赢了!!!");
this.text.setText("游戏结束,黑棋赢了!!!");
this.chessManClick = false;
this.gameIsOver = true;
return;
}
this.text.setText(" 红棋走棋");
this.chessPlayClick = 2;
this.chessManClick = false;
}
}
}else{//单击的就一定是棋子
int iClick=-1;
for(int i=0;i<32;i++){
if(e.getSource().equals(play[i])){
iClick=i;//代表找到了点击的是第几个棋子并退出该循环
break;
}
}
if(chessPlayClick==2){//表示为红旗要走
if(play[iClick].getName().charAt(1)=='2'){//如果目的地是红棋
Man=iClick;//用来当点击为黑棋时候吃子后要悔棋时便于找到上一次点击时候的红棋是什么
chessManClick=true;//表明现在已经有棋子被点击且红棋一定先被点击故而就激活之后就一直处于改状态
return;//结束该方法
}
int judge=play[Man].getName().charAt(1)-'0';//判断棋子类型是1还是2转换为整形变量
if(play[iClick].getName().charAt(1)=='1' && judge==2){//表示点击的为黑棋而要动的是红旗(1为黑2为红即要吃子判断)
if (Man >= 0 && Man < 4) {//为要进行吃子判断与操作
System.out.println("车吃子判断");
this.chessRule.careat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 4 && Man < 8) {
System.out.println("马吃子判断");
this.chessRule.horseEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 8 && Man < 12) {
System.out.println("象吃子判断");
this.chessRule.elephantEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 12 && Man < 16) {
System.out.println("士吃子判断");
this.chessRule.chapEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 16 && Man < 26) {
System.out.println("士兵吃子判断");
this.chessRule.soliderEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 26 && Man < 30) {
System.out.println("炮吃子判断");
this.chessRule.cannonEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 30 && Man < 32) {
System.out.println("BOSS吃子判断");
this.chessRule.masterEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
//如果吃子成功,则棋子和被吃的子的坐标会相同因为棋子将移动到被吃子的位置
if (this.play[iClick].getX() == this.play[Man].getX() && this.play[iClick].getY() == this.play[Man].getY()) {
if (this.chessRule.masterMeet(this.play) == 1) {
JOptionPane.showMessageDialog(this, "游戏结束,黑棋赢了!!!");
this.text.setText("游戏结束,黑棋赢了!!!");
this.chessManClick = false;
this.gameIsOver = true;
return;
}
if (!this.play[30].isVisible()) {
JOptionPane.showMessageDialog(this, "游戏结束,红棋赢了!!!");
this.text.setText("游戏结束,红棋赢了!!!");
this.chessManClick = false;
this.gameIsOver = true;
return;
}
this.chessPlayClick = 1;
this.text.setText(" 黑棋走棋");//红旗吃子结束轮到黑棋运动
this.chessManClick = false;
}
}
}else if(chessPlayClick==1){//表示为黑棋要走也有两种情况,点击的是黑棋还是红棋
if(play[iClick].getName().charAt(1)=='1') {//表明先点击的是黑棋具体与上方类似
Man = iClick;
chessManClick = true;
return;
}
int judge=play[Man].getName().charAt(1)-'0';
if(play[iClick].getName().charAt(1)=='2' && judge==1){//注意iclick为当前的点击对象而Man是某对象二次点击时,其上一次的点击对象
//要进行黑棋的吃子判断与操作
if (Man >= 0 && Man < 4) {
System.out.println("车吃子判断");
this.chessRule.careat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 4 && Man < 8) {
System.out.println("马吃子判断");
this.chessRule.horseEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 8 && Man < 12) {
System.out.println("象吃子判断");
this.chessRule.elephantEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 12 && Man < 16) {
System.out.println("士吃子判断");
this.chessRule.chapEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 16 && Man < 26) {
System.out.println("士兵吃子判断");
this.chessRule.soliderEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 26 && Man < 30) {
System.out.println("炮吃子判断");
this.chessRule.cannonEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (Man >= 30 && Man < 32) {
System.out.println("BOSS吃子判断");
this.chessRule.masterEat(this.play[Man], this.play, this.play[iClick], this.regretList, Man, iClick);
}
if (this.play[iClick].getX() == this.play[Man].getX() && this.play[iClick].getY() == this.play[Man].getY()) {
if (this.chessRule.masterMeet(this.play) == 1) {
JOptionPane.showMessageDialog(this, "游戏结束,红棋赢了!!!");
this.text.setText("游戏结束,红棋赢了!!!");
this.chessManClick = false;
this.gameIsOver = true;
return;
}
if (!this.play[31].isVisible()) {
JOptionPane.showMessageDialog(this, "游戏结束,黑棋赢了!!!");
this.text.setText("游戏结束,黑棋赢了!!!");
this.chessManClick = false;
this.gameIsOver = true;
return;
}
this.chessPlayClick = 2;
this.text.setText(" 红棋走棋");
this.chessManClick = false;
}
}
}
}
}
首先判断子线程tmain是否为空如果为空则直接将其初始化为该类的子线程类型,并通过tmain.start()来启动该类的子线程,之后进行判断点击的是否为棋盘image若为棋盘则表明应为移动操作即要移动某棋子到达棋盘上某处,暂时不进行讲解,之后else即此时点击的不是棋盘而是棋子,之后for循环32个棋子判断此刻点击的棋子的编号是多少并记录在变量iClick中,之后先利用chessPlayClick==2来判别此时轮到红方进行操作,在红方进行操作的前提下判断点击的棋子为红旗则将,该棋子的编号存入Man变量中(Man变量的作用始终为存储进行操作前一步的棋子的状态便于悔棋时进行恢复)并令chessManClick为true即令现在有棋子处于被点击状态。之后再次判断再次点击时候的棋子是否为黑棋若是则进行吃子判断与相关操作(暂时不讲)。 此时红方先走的情况已经判断完毕之后按照相似思想进行黑方走棋时的判别即先判断点击的是否为棋盘看是否要进行移动棋子操作,之后看点击的是否为黑棋,之后判断再次点击时是否为红棋若是进行吃子判断。
最后对于棋子闪烁要求的线程函数run(所有定义的线程的实现都是靠它实现)进行书写
@Override
public void run() {//线程对应的方法,只要有线程就会执行
while (true){
if(chessManClick){//表示如果此时有棋子处于被点击的状态
play[Man].setVisible(false);
//之所以用Man是因为Man为第一次点击的棋子使它保持闪烁即可实现功能不能为iclick因为它一定会有两次点击如红方走时,先点击红方棋子,再点击空白或者黑方棋子
try{
tmain.sleep(200);//要监控的代码块
}catch (Exception e){//若发生异常则抛出下方的异常情况,否则正常执行(即隔200ms停止线程)主要是为了使棋子可见与不可见操作相隔200ms实现棋子闪烁功能
e.printStackTrace();
}
play[Man].setVisible(true);
for(int i=0;i<32;i++){
if(i!=Man && play[i].died==false){
play[i].setVisible(true);//也就是在保持点击的棋子闪烁的同时也要保持其它棋子可见
}
}
}else{//此时没有棋子被点击于是文本提示要进行闪烁
text.setVisible(false);
try{
tmain.sleep(250);
}catch (Exception e){
e.printStackTrace();
}
text.setVisible(true);
}
try{//其实根本不会执行到此只是为了保证安全
tmain.sleep(350);
}catch (Exception e){
e.printStackTrace();
}
}
}//显示棋盘的主框架需要继承JFrame类
直接设定一个死循环通过,当有棋子被点击的时候,令对应棋子不可见以及令进程休眠的不断循环来实现棋子的闪烁功能,同时,设定棋子不可见与可见的过程之后还要对32个棋子中非该棋子的棋子均设置为可见,否则可能出现当仅有一个棋子在闪烁其它棋子因它影响而不可见。如果没有棋子处于被点击状态,则令工具栏的文字提示框进行闪烁来提醒玩家尽快进行相关操作。
至此就实现了棋子的闪烁功能。