Heim  >  Artikel  >  Java  >  So implementieren Sie ein chinesisches Schachspiel mit Java

So implementieren Sie ein chinesisches Schachspiel mit Java

PHPz
PHPznach vorne
2023-05-12 18:58:041387Durchsuche

1. Schnittstelle

Das Schachbrett muss zunächst in geeigneter Größe, Proportion und Position vorbereitet werden. Zeichnen Sie dann n gerade Linien und diagonale Linien auf das Formular Der Wert wird entsprechend der Größe Ihrer Schnittstelle festgelegt. Die auf diese Weise gezeichnete Benutzeroberfläche ist ordentlich und schö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);
     
    }

2. Schaltflächen

Fügen Sie nach dem Zeichnen des Schachbretts Funktionsschaltflächen hinzu. Die Funktionen gelten derzeit nicht als implementiert. Sie können sie nach Belieben hinzufügen ganz nach Ihren Wünschen. Hier wird empfohlen, den Schaltflächentyp auf ein Array festzulegen, um zeitnahe Hinzufügungen und Löschungen zu ermöglichen.

//添加到面板上
        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);
        }

So implementieren Sie ein chinesisches Schachspiel mit Java

Zu diesem Zeitpunkt werden Sie feststellen, dass die Schaltflächen sehr kompakt sind. Meine Lösung besteht darin, diesem Bedienfeld ein weiteres Bedienfeld hinzuzufügen und es auf Weiß einzustellen, um es abzudecken, sodass die Schaltflächen entsprechend dem Fluss angeordnet sind Das Bedienfeld wird nach unten verschoben. Durch Anpassen der Breite des leeren Bedienfelds kann sich die Position der Schaltfläche ändern.

3. Schachfiguren hinzufügen

Fügen Sie die gefundenen Schachfigurenbilder zu den Schnittpunkten des Schachbretts hinzu, um dem Paket Seele zu verleihen, damit das Programm später auf anderen Computern ausgeführt werden kann PNG-Format, JPG-Format hat quadratische Ränder).
Die nächsten drei Schritte sind

1. Erstellen Sie ein ganzzahliges Array mit 10 Zeilen und 9 Spalten, um die Daten jeder Position zu speichern.
2. Erstellen Sie ein Bildarray mit einer Länge von 14, das dem Schachfigurentyp entspricht . Durchlaufen Sie das Ganzzahl-Array und zeichnen Sie die entsprechenden Schachfiguren.

Dies ist ein intuitives Bild des Schachbretts, das den Anfangswert unseres Ganzzahl-Arrays darstellt:

So implementieren Sie ein chinesisches Schachspiel mit Java

Korrespondieren Sie das Bild mit dem Schachfigurenbild:

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

Durchlaufen Sie die Zeichnung:

//根据棋盘布局
        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. Erkennen Sie die Bewegung von Schachfiguren. Verwenden Sie die Funktion, um die Positionen auf dem Schachbrett zu ermitteln, die durch die beiden Punkte vor und nach dem Ziehen der Maus dargestellt werden, und tauschen Sie die Werte der zweidimensionalen Arrays aus dieser beiden Positionen und zeichnen Sie dann neu, um die Bewegung der Schachfiguren zu realisieren.

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

Die Situation, auf die Sie derzeit stoßen, ist, dass bei jeder Bewegung die gesamte Schnittstelle neu gezeichnet wird, das Bild direkt auf dem Formular gezeichnet wird und die Daten direkt an die Computerhardware übertragen werden, sodass die Zeichengeschwindigkeit erhöht wird Es ist langsam, sodass die Benutzeroberfläche bei jedem Schritt flackert. In diesem Fall können wir das Bild zuerst im Cache speichern und es direkt zeichnen, ohne die Hardware zu durchlaufen, sodass die Effizienz erheblich verbessert werden kann .

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

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

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

5. Bestimmen Sie das Ergebnis. Schreiben Sie eine Funktion, um zu bestimmen, wer gewinnt und wer verliert. Gleichzeitig werden die Daten auf 0 gesetzt und bereiten Sie sich auf ein weiteres Spiel vor:

(showMessageDialog-Methode kann direkt verwendet werden. Springen Sie aus einer Box)

//判断游戏结束并显示胜局
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. Implementierung der Schaltflächen „Spiel starten“ und „Neustart“

Aktions-Listener hinzufügen

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

Die Init-Funktion hier ist Initialisieren Sie das ganzzahlige zweidimensionale Array am Anfang und durchlaufen Sie es dann, um den Schachfigurenstatus hinzuzufügen.

Sieben. Fügen Sie eine lange Liste von Regeln hinzu

rrree

Die Kanonen und Generäle müssen hier getrennt betrachtet werden. Die Kanonen haben zwei Möglichkeiten, sich direkt und einzeln zu bewegen, und Generäle sind noch mehr mühsam

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

Acht Runden

Rot und Schwarz spielen abwechselnd Schach

Ich habe eine separate Methode geschrieben, um zu bestimmen, ob sich die Generäle treffen, denn was die Generäle dazu veranlasst, sich zu treffen, ist nicht nur die Bewegung der Generäle selbst, sondern auch Die Bewegung anderer Schachfiguren ist also ebenfalls eine boolesche Funktion. Sie können sich nur gleichzeitig bewegen, wenn die vorherige Funktion und der Rückgabewert dieser Funktion erfüllt sind. Beim Verschieben habe ich einen Parameter definiert Auf diese Weise werden die Schachregeln umgesetzt.

9. Reueschach

Es ist unvermeidlich, dass es zu Fehlern kommt, und es ist besser, die Reueschachfunktion hinzuzufügen.
Wenn wir die Werte von zwei Punkten austauschen (oder im Fall der Erfassung eines Stücks), müssen wir den vorherigen Wert aufzeichnen und ihn dann zurück austauschen, wenn der Aktions-Listener auf „Repent“ klickt.

Sie können den Zug jeweils nur einmal bereuen, und Sie können den Zug nicht bereuen, wenn sich die Schachfigur am Anfang nicht bewegt hat.

10. Hintergrund und Tipps


Fügen Sie den Hintergrund Ihrer Wahl hinzu und markieren Sie, um das Schachspielen zu vereinfachen, welche Seite gerade an der Reihe ist.
Um einen Hintergrund hinzuzufügen, können Sie die gleiche Methode wie beim Zeichnen von Schachfiguren verwenden. Sie sollten ihn also vor dem Schachbrett zeichnen, um zu verhindern, dass er verdeckt wird.

Es gibt ein weiteres offensichtliches Problem beim Hinzufügen: Jedes Mal, wenn Sie die Schaltfläche rechts betätigen, verschwindet es und wird von Ihrem Hintergrundbild verdeckt. Was soll ich tun?

Also haben wir drei Methoden zusammengefasst:

1. Schreiben Sie die Schaltfläche in der oberen linken Ecke um;
3. Screenshot), einfach noch einmal zeichnen;

Darüber hinaus können Sie dem Hintergrundbild auch die Worte „aktueller Schachspieler“ hinzufügen und an der Seite Bilder der Generäle des aktuellen Schachspielers anzeigen.

Der Zählparameter wird hier ausgeliehen und an den Listener übergeben, und der Konstruktor wird neu geschrieben.

//判断将是否会面
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;//会面了
    }

Jedes Mal, wenn eine Figur gespielt wird, zählen Sie×(-1), markieren Sie die Seite, auf der sie sich befindet, und zeichnen Sie ein Bild.

Anbei ein Ergebnisbild:


Das obige ist der detaillierte Inhalt vonSo implementieren Sie ein chinesisches Schachspiel mit Java. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen