Hilfe: Java-Code?

2 Antworten

Von Experte ralphdieter bestätigt

Für eine ausführliche Erklärung fehlt mir im Moment die Zeit, das könnte bei Bedarf später nachgeholt werden (das würde aber ein ziemlich langer Text werden).

Kurzform: das ist eine "tricky" Methode, ein Spielfeld durch die Bits eines Ganzzahlwertes darzustellen.

Wenn man nicht gerade Hunderttausende von Spielfeldern gleichzeitig bearbeiten muss, ist das im Zeitalter des Gigabyte-RAMS erstens überflüssig und zweitens kontraproduktiv (nicht wegen der paar Nanosekunden, die die Berechnungen länger dauern als ein direkter Zugriff auf Array-Elemente, sondern wegen der verlorenen Wartbarkeit des Codes).

Woher ich das weiß:Berufserfahrung – Software-Entwickler
PWolff  13.12.2022, 14:16

Erst wollte ich schreiben, dass das so aussieht, als hätte da jemand ein Tic-Tac-Toe-Programm für einen 4-Bit-Microcontroller mit so um die 16 bis 64 Byte Arbeitsspeicher 1:1 in Java umgesetzt, aber das passt nicht zum (wenigstens) 32-Bit-Integer spielInt. (So breit muss das Ding wenigstens sein nach dem Code, den du, Mathematik2000, im Kommentar gepostet hast.)

Also beruht das vermutlich auf einer Aufgabe, ein Tic-Tac-Toe-Spiel mit möglichst wenig permanentem Speicher zu realisieren - hier kommt man mit einem einzigen 32-Bit-Integer aus, mit dem man den kompletten Spielstand sichern kann, um später weiterspielen zu können. (Wer am Zug ist, kann man aus den Belegungen errechnen oder notfalls irgendwo in den höheren Bits speichern.)

-----

Ein wenig zum Code im Einzelnen:

int index = zeile*3+spalte;

setzt die beiden Indices für ein 3x3-Feld in einen Index für ein eindimensionales Array um:

0,0    0,1    0,2
1,0    1,1    1,2
2,0    2,1    2,2

wird übersetzt in

0    1    2
3    4    5
6    7    8

-----

spielInt wird als Bit-Array aufgefasst, das ist nichts Unübliches, kombinierbare Ja-/Nein-Optionen werden oft in dieser Weise dargestellt ("Flags"). Allerdings kommt hier als Besonderheit hinzu, dass hier nicht einzelne Bits als Element betrachtet werden, sondern Gruppen von je 2 Bits. (Um die drei Zustände leer, Spieler_1 und Spieler_2 unterscheiden zu können, braucht man ja mindestens 2 Bits.)

(spielInt>>>2*index & 0b11)

zieht die Bit-Gruppe mit dem Index index heraus.

value>>offset

bzw.

value>>>offset

verschiebt die Bits von value um offset stellen nach rechts. (Vgl. etwa https://stackoverflow.com/questions/12176280/java-operator)

Die Operatoren &, | und (irgendwas)= setze ich mal als bekannt voraus.

"0b" leitet eine Binärzahl ein - es folgen die Binärziffern (Bit = binary digit = Binärziffer) der Zahl, wie auf "0x" die Hexadezimalziffern folgen.

0b11 nimmt man hier, weil damit deutlich wird, dass die beiden niederwertigsten (am weitesten rechts liegenden) Bits gesetzt sind.

Mit Gruppen zu je 2 Bits bekommt man eine Darstellung im 4er-System, wie man mit Gruppen zu je 4 Bits eine Darstellung im 16-er System bekommt. Das Verfahren zieht also die Ziffer im 4er-System an einer bestimmten Stelle heraus. (Für das Dezimalsystem vgl. z. B. https://www.gutefrage.net/frage/zahlenreihe-in-excel-durchsuchen)

-----

value<<offset

schiebt die Bits von values nach links. Damit wird die Ziffer im 4er-System an die richtige Stelle geschoben.

mit & ~(Maske) werden die Bits auf 0 gesetzt, die in Maske auf 1 gesetzt sind, d. h. die 4er-Ziffer an dieser Stelle wird auf 0 gesetzt. (Dezimale Entsprechung: alter_Wert = 123456; Maske = 900; neuer_Wert = 123056)

spielInt |= (spieler+1) << 2*index;

setzt schließlich die 4er-Ziffer an der angegebenen Stelle auf den gewünschten Wert.

0
Mathematik2000 
Fragesteller
 14.12.2022, 08:33
@PWolff

Ich habe immer noch diese Zeile nicht verstanden habe, können Sie noch einfacher erklären?

Was meinen Sie mit die beiden niederwertigsten (am weitesten rechts liegenden) Bits und was ist hier 2 und warum schieben wir nach rechts >>>?

(spielInt>>>2*index & 0b11)

0
PWolff  14.12.2022, 10:14
@Mathematik2000

Die 4er-zahl

1230

entspricht der 2er-Zahl

01101100

Wenn ich aus der 1230 die 2 herausziehen will, muss ich die Zahl durch 100_4 teilen (das Komma um 2 Stellen nach links schieben), die Nachkommastellen abschneiden und die niedrigste Ziffer herausnehmen: 1230 -> 12,30 -> 12 -> 2

Die 2 als Verschiebung kommt daher, dass die Ziffer 2 an der Stelle für 4^2 steht.

In Binärdarstellung entspricht das

01101100 -> 0110,1100 -> 0110 -> 10

Hier muss man um 4 Stellen verschieben, weil ja jede 4er-Stelle genau 2 2er-Stellen entspricht.

Beim Bit-Schieben lässt man die Nachkommastellen sofort fallen - das ist auf Prozessorebene sehr viel einfacher zu realisieren.

spielInt >>> 2*index

verschiebt die Bits (2er-Ziffern) von spielInt gerade so weit nach rechts, dass die gewünschte 4er-Ziffer ganz rechts steht.

Das "& 0b11" filtert die letzten beiden 2er-Ziffern heraus, und das ist die gewünschte 4er-Ziffer. Wie "&" funktioniert, weißt du?

0
Mathematik2000 
Fragesteller
 14.12.2022, 20:06
@PWolff

Warum &3 bei ( spielInt>>>2*index & 0b11)? Was bedeutet hier &3, was steckt unter 3? 3 Werte?

0
Mathematik2000 
Fragesteller
 15.12.2022, 09:00
@PWolff

Aber warum &3 und nicht &2 oder &1? Was präsentiert 3? Drei Zuständen?

0
PWolff  15.12.2022, 14:14
@Mathematik2000

Es hat schon seinen Sinn, dass hier die Binärdarstellung verwendet wird und nicht die äquivalente 3. Damit soll deutlich gemacht werden, dass es hier auf die Bits ankommt und nicht auf den Zahlenwert.

Die 0b11 ist diejenige Zahl, bei der die beiden niederwertigsten (ganz rechts liegenden) Bits gesetzt sind und alle anderen Bits nicht gesetzt sind.

Für den Rest braucht man Verständnis des "bitweisen Und". Ich würde empfehlen, gezielt nach einer Erklärung dieses Operators zu suchen oder/und hier danach zu fragen.

0
ralphdieter  14.12.2022, 21:11

@PWolff:

das würde aber ein ziemlich langer Text werden

Oh ja! Der Code in der Frage stammt nämlich von mir :-/

Jetzt, wo ich diese Frage lese, gebe ich auf und wünsche Dir etwas mehr Glück.

1

Dafür muss man Schift-Operatoren verstehen:

https://www.straub.as/java/certify/shift.html

0b11 ist die Binärzahl 11.

Hier nochmal alle möglichen Java-Operatoren:

https://de.wikibooks.org/wiki/Java_Standard:_Operatoren

Kann einer mir diesen Code ausführlich erklären?

Im Detail verstehe ich es leider auch nicht. Aber vielleicht hilft dir die Beschreibung der Operatoren auch weiter.

Woher ich das weiß:Studium / Ausbildung – Informatik studiert und mit PCs & Technik beschäftigt
Mathematik2000 
Fragesteller
 13.12.2022, 12:14

Der Code war eigentlich so, können Sie es vielleicht ausführlich erklären?

 Write a description of class SpielfeldInteger here.
 *
 * @author (your name)
 * @version (a version number or a date)
 */
public class SpielfeldInteger implements Spielfeld
{
    private int spielInt;
    
    /**
     * Initialisiert ein neues, leeres Spielfeld.
     */
    public SpielfeldInteger() {
        spielInt = 0x00000;//2AAAA
        // 0000 0000 0000 0000 0000;
    }


    /**
     * Gibt den Besitzer der angegebenen Position auf dem Spielfeld.
     * 
     * @param zeile  vertikale Position (0-2)
     * @param spalte horizontale Position (0-2)
     * @return 0 (unbesetzt), 1 (Spieler 1), 2 (Spieler 2)
     */
    public int gibBesitzer(int zeile, int spalte) {
        int schiebung = (zeile*3*2)+(spalte*2);
        int geschobenerInt = spielInt>>>schiebung;
        //System.out.println(Integer.toBinaryString(geschobenerInt));
        
        //System.out.println((geschobenerInt&3));
        if((geschobenerInt&3) == 2) {
            return 1;
        } else if((geschobenerInt&3) == 3) {
            return 2;
        } else {
            return 0;
        }
    }


    /**
     * Besetzt die angegebene Position auf dem Spielfeld fuer einen Spieler.
     * 
     * @param zeile   vertikale Position (0-2)
     * @param spalte  horizontale Position (0-2)
     * @param spieler 0 (leer), 1 (Spieler 1), 2 (Spieler 2)
     */
    public void besetzePosition(int zeile, int spalte, int spieler) {
        int setzung;
        if(spieler == 1 || spieler == 2) {
            setzung = (spieler+1)<<(zeile*3*2)+(spalte*2);
            spielInt = spielInt|setzung;
        }
        else if(spieler == 0) {
            setzung = ~(3<<(zeile*3*2)+(spalte*2));
            spielInt = spielInt&setzung;
        }
        
        
    }


    /**
     * Gibt an, ob das Spielfeld an allen Positionen belegt ist.
     */
    public boolean istVoll() {
        return ((spielInt&0x2AAAA) == 0x2AAAA);
    }
}
0
ranger1111  13.12.2022, 12:16
@Mathematik2000

Das braucht ein bisschen mehr Zeit, um sich damit zu beschäftigen. Mir geht's aber gerade nicht so gut. Was ich dir aber sagen kann, ist, dass das keine typische Art und Weise ist, Java-Code zu schreiben. Da werden vielleicht sogar Leute besser helfen können, die sich mit C und Maschinensprachen auskennen.

2