Maison  >  Article  >  Java  >  Comment implémenter un jeu d'échecs chinois en utilisant Java

Comment implémenter un jeu d'échecs chinois en utilisant Java

PHPz
PHPzavant
2023-05-12 18:58:041387parcourir

1. Interface

L'échiquier pour jouer aux échecs doit d'abord être préparé. Il s'agit d'une interface avec une taille, une proportion et un emplacement appropriés. Ensuite, tracez (oui, drawLine) des lignes droites et des lignes diagonales sur le formulaire. la valeur est définie en fonction de la taille de votre interface. L'interface dessinée de cette manière est soignée et belle ~

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);
     
    }

2. Boutons

Après avoir dessiné l'échiquier, ajoutez des boutons de fonction Les fonctions pour le moment ne sont pas considérées comme implémentées pour le moment. Vous pouvez les ajouter à volonté. selon votre préférence. Il est recommandé ici de définir le type de bouton sur un tableau pour faciliter les ajouts et suppressions en temps opportun.

//添加到面板上
        String[] type = {"开始游戏","重新开始","认 输","悔 棋"};
        for(int i=0;i<type.length;i++){
            Button btn = new Button(type[i]);
            btn.setPreferredSize(new Dimension(150,50));
            anniu.add(btn);
        }

Comment implémenter un jeu déchecs chinois en utilisant Java

À ce stade, vous constaterez que les boutons sont très compacts. Ma solution est d'ajouter un autre panneau à ce panneau et de le régler en blanc pour le recouvrir, de sorte que les boutons soient disposés en fonction du flux. Le panneau sera déplacé vers le bas. Le réglage de la largeur du panneau vierge peut modifier la position du bouton.

3. Ajouter des pièces d'échecs

Ajoutez les images des pièces d'échecs trouvées aux positions d'intersection de l'échiquier pour injecter de l'âme dans l'échiquier. Ajoutez les quatorze types d'images au package afin que le programme puisse fonctionner sur d'autres ordinateurs plus tard (recommandé). ici au format png, le format jpg aura des bordures carrées).
Les trois étapes suivantes sont

1. Créez un tableau d'entiers avec 10 lignes et 9 colonnes pour stocker les données de chaque position
2 Créez un tableau d'images d'une longueur de 14 pour correspondre au type de pièce d'échecs ; . Parcourez le tableau d'entiers et dessinez les pièces d'échecs correspondantes ;

Ceci est une image intuitive de l'échiquier, qui est la valeur initiale de notre tableau d'entiers :

Comment implémenter un jeu déchecs chinois en utilisant Java

Corrélez l'image avec l'image de la pièce d'échecs :

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

Parcourez le dessin :

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

4. Réalisez le mouvement des pièces d'échecs

Utilisez la fonction pour obtenir les positions sur l'échiquier représentées par les deux points avant et après avoir fait glisser la souris, échangez les valeurs des tableaux bidimensionnels de ces deux positions, puis redessinez pour réaliser le mouvement des pièces d'échecs.

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;
    }

La situation que vous rencontrez en ce moment est qu'à chaque fois que vous bougez, toute l'interface sera redessinée, et l'image sera dessinée directement sur le formulaire, et les données seront directement transmises au matériel informatique, donc la vitesse de dessin sera réduit. Il est lent, donc l'interface clignote à chaque fois que vous faites un pas. Dans ce cas, nous pouvons d'abord stocker l'image dans le cache et la dessiner directement sans passer par le matériel, ce qui permet d'améliorer considérablement l'efficacité. .

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

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

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

5. Déterminez le résultat

L'équipe qui prend la tête pour vaincre le général ou le général adverse gagne. Écrivez une fonction pour déterminer qui gagne et qui perd pour afficher la victoire. En même temps, initialisez les données à 0. et préparez-vous pour un autre jeu :

(la méthode showMessageDialog peut être utilisée directement Sauter hors d'une boîte)

//判断游戏结束并显示胜局
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<place.length; i++){
              
              for(int j=0; j<place[0].length; j++){
                  
                  place[i][j] = 0;
              }
         }
    }

6. Implémentation des boutons "Démarrer le jeu" et "Redémarrer"

Ajouter un écouteur d'action

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<place.length;i++){
                
            for(int j=0;j<place[0].length;j++){
                            
                place[i][j] = 0;
            }
        }
            place[0][0] = 10;    place[9][0] = 3;
            place[0][1] = 11;    place[9][1] = 4;
            place[0][2] = 12;    place[9][2] = 5;
            place[0][3] = 13;    place[9][3] = 6;
            place[0][4] = 14;    place[9][4] = 7;
            place[0][5] = 13;    place[9][5] = 6;
            place[0][6] = 12;    place[9][6] = 5;
            place[0][7] = 11;    place[9][7] = 4;
            place[0][8] = 10;    place[9][8] = 3;
            place[2][1] = 9;    place[7][1] = 2;
            place[2][7] = 9;    place[7][7] = 2;
            place[3][0] = 8;    place[6][0] = 1;
            place[3][2] = 8;    place[6][2] = 1;
            place[3][4] = 8;    place[6][4] = 1;
            place[3][6] = 8;    place[6][6] = 1;
            place[3][8] = 8;    place[6][8] = 1;
            
    }

La fonction init ici est pour initialiser le tableau bidimensionnel entier au début, puis parcourir pour ajouter le statut des pièces d'échecs.

Sept. Ajoutez une longue liste de règles

//规定各个棋子的移动规则
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;
    }

Les canons et les généraux doivent être considérés séparément ici. Les canons ont deux façons de se déplacer directement et une à la fois, qui doivent être considérées séparément, et les généraux le sont encore plus. gênant

//判断将是否会面
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<shuaii; i++){
                if(place[i][shuaij] != 0)    temp++;
            }
        }
        else return false;//没会面
        if(temp != 0)    return false;//没会面
        else return true;//会面了
    }

Huit tours

Les rouges et les noirs jouent aux échecs à tour de rôle

J'ai écrit une méthode distincte pour déterminer si les généraux se rencontreront, car ce qui provoque la rencontre des généraux n'est pas seulement le mouvement des généraux eux-mêmes, mais aussi le mouvement des autres pièces d'échecs, c'est donc aussi une fonction booléenne, seulement en même temps. Ce n'est que lorsque la fonction précédente et cette fonction ne renvoient aucune face que le joueur peut bouger. Lors du déplacement, j'ai défini un paramètre. De cette façon, les règles des échecs sont mises en œuvre.

9. Échecs à regret

Il est inévitable qu'il y ait des erreurs, et il est plus approprié d'ajouter la fonction d'échecs à regret.

Lorsque nous échangeons les valeurs de deux points (ou dans le cas de la capture d'un morceau), nous devons enregistrer la valeur précédente, puis la rééchanger lorsque l'auditeur d'action écoute pour cliquer sur le bouton de regret.
Vous ne pouvez regretter le coup qu'une fois à la fois, et vous ne pouvez pas regretter le coup si la pièce d'échecs n'a pas bougé au début.

10. Contexte et astuces

Ajoutez l'arrière-plan de votre choix et, pour faciliter le jeu d'échecs, marquez de quel côté c'est le tour.

Pour ajouter un arrière-plan, vous pouvez utiliser la même méthode que pour dessiner des pièces d'échecs, il doit donc être dessiné devant l'échiquier pour éviter qu'il ne soit recouvert.
Il y a un autre problème évident avec l'ajout de ceci, c'est-à-dire que chaque fois que vous appuyez sur le bouton de droite, il disparaîtra et sera recouvert par votre image d'arrière-plan. Que dois-je faire ?
Nous avons donc résumé trois méthodes :

1. Réécrivez la méthode de dessin du bouton ;

2 Ajoutez le bouton dans le coin supérieur gauche sous la forme d'un menu ;
3. capture d'écran ), dessinez simplement à nouveau ;

De plus, vous pouvez également ajouter les mots "joueur d'échecs actuel" à l'image d'arrière-plan et afficher des images des généraux du joueur d'échecs actuel sur le côté.

Le paramètre count est emprunté ici et transmis à l'écouteur, et le constructeur est réécrit.

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); 
}

Chaque fois qu'une pièce est jouée, comptez ×(-1), marquez de quel côté elle se trouve et faites un dessin.

Ci-joint une photo du résultat :

Comment implémenter un jeu déchecs chinois en utilisant Java

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer