[JAVA] Meine Gedanken zur Zukunft [Vorbereitung]

1. 1. Einleitung (selbst sprechend benannt)

Als ich ein Gymnasiast war, war ich in der Schule ein wenig im Go Shogi Club eingeschrieben. Ich habe lange Zeit weder Go noch Shogi gespielt, aber ich war daran interessiert, von Manga beeinflusst zu werden. Infolgedessen war ich nicht wirklich gut darin und wollte die schwächste Position im Verein. Aus irgendeinem Grund gab es auch ein Othello-Board im Clubraum des Go Shogi-Clubs, und nachdem ich von anderen Mitgliedern mit Shogi durcheinander gebracht worden war, machte ich zur Abwechslung auch Othello. Othello hat einfachere Regeln als Go und Shogi, daher gibt es natürlich Schwierigkeiten, aber ich weiß nicht, wo ich die mit Shogi aufgenommenen Teile verwenden soll oder wann Go als das Ende angesehen wird. Für mich war es eine sehr einfache Veranstaltung. Nun, es war immer noch holprig. Übrigens scheint es auf der Welt wilde Menschen zu geben, die die Codierung von Othello im Bereich von 7 Zeilen $ × $ 79 Zeichen durchführen können, aber ich kann es nicht einmal mit 700 Zeilen tun, geschweige denn mit 70 Zeilen, was 10-mal so viel ist. Da es wie ein Körper funktioniert, habe ich mich entschlossen, diesmal die Implementierung von Othello in Frage zu stellen, ohne die Anzahl der Zeichen zu begrenzen. Eigentlich habe ich das stärkste Othello-Programm angestrebt, wie der Titel andeutet, indem ich einen Algorithmus entwickelt habe, um zu bestimmen, wo der Stein am besten platziert werden kann, aber wie ich erwartet hatte, werde ich es zu einer Situation machen, in der Othello überhaupt normal durchgeführt werden kann. Es war alles was ich tun konnte. Also werde ich dieses Mal als [Vorbereitung] über den Prozess schreiben, bis Othello vorerst spielen konnte.

2. Problemstellung (Entschuldigung genannt)

Diesmal wäre es schön, wenn Othello gemacht werden könnte! Ich werde sagen. Ich kann jedoch momentan nichts erstellen, was im Browser funktioniert. Daher werde ich jedes Mal etwas erstellen, das auf der vertrauten Konsole funktioniert. Bitte verzeihen Sie __not __ etwas, das Sie tun und spielen können.

3. 3. Implementierung ① Anzeige der Othello-Karte

Grundsätzlich wird die gesamte Othello-Verarbeitung, die wir implementieren, in einer Klasse namens OthelloBoard geschrieben. OthelloBoard hat die folgenden Variablen und Arrays als Mitglieder:

class OthelloBoard {
	private int size;				//Eine Seite des Othello-Boards(8, 10, 12, 14, 16)
	private char[][] squares;		//Zustand jeder Masse(B:schwarz, W:Weiß, N:Kein Stein)
	private char playerColor;		//Spieler Steinfarbe
	private char otherColor;		//Die Farbe des Steins des Gegners
	private int turnCounter;		//Zählen Sie die Anzahl der Umdrehungen
	private final String alphabets = "abcdefghijklmnop";
}

Die variable Größe des Typs int gibt die Anzahl der Steine an, die auf einer Seite des Othello-Bretts platziert werden können. In dem später beschriebenen Konstruktor wird die allgemeine 8 zugewiesen, aber wenn Sie damit spielen, können Sie auch mit der Größe madness von 16 Quadraten $ × $ 16 Quadrate spielen. Ich habe es versucht, aber ich war früh frustriert. ~~ Ich bin verrückt ~~ othello2.png Hmmm, dieses Gefühl der Verzweiflung.

…… Gib die Geschichte zurück. Die zweidimensionalen Array-Quadrate vom Typ char sind ein Array, das den Status jeder Zelle darstellt. Sie können sehen, ob sich auf dem Platz ein Stein befindet, und wenn ja, ob es sich um einen schwarzen oder einen weißen Stein handelt, oder ihn aktualisieren. Die folgenden Zeichenvariablen playerColor und otherColor enthalten entweder 'B'or'W', wenn der Spieler zu Beginn des Spiels entweder Kuroishi oder Shiraishi auswählt. Die letzte Zeichenfolge, Alphabete, enthält Alphabete, die die horizontalen Koordinaten darstellen, die zur Anzeige der Othello-Tafel verwendet werden. This.alphabets.charAt (x), wenn Sie sich auf das $ x $ -te Alphabet beziehen möchten, und umgekehrt, wenn Sie wissen möchten, welche Zahl der Buchstabe y ist (Sie möchten die horizontalen Koordinaten als numerischen Wert kennen). Sie können so etwas wie .alphabets.indexOf ("y") tun. Da diese Zeichenfolge in Zukunft nicht mehr geändert werden soll, wird der endgültige Modifikator hinzugefügt. Für diesen Bereich habe ich auf die Kommentare verwiesen, die ich in den vorherigen Artikeln erhalten habe. Vielen Dank an alle, die Kommentare abgegeben haben.

Von hier aus erkläre ich nun den Teil, der die Othello-Tafel anzeigt.

//Zeigen Sie die Othello-Karte auf der Konsole an
private void printBoard() {
	this.printBoardAlphabetLine();				//Alphabetzeile
	this.printBoardOtherLine("┏", "┳", "┓");		//Oberkante
	for (int y = 0; y < this.size - 1; y ++) {
		this.printBoardDiscLine(y);			//Linie, die Steine anzeigt
		this.printBoardOtherLine("┣", "╋", "┫");	//Zeilenabstand
	}
	this.printBoardDiscLine(this.size - 1);			//Linie, die Steine anzeigt
	this.printBoardOtherLine("┗", "┻", "┛");		//unteres Ende
}

//Zeigen Sie das Alphabet an, das die Zeile der Othello-Tafel angibt
private void printBoardAlphabetLine() {
	String buf = "  ";
	for (int x = 0; x < this.size; x ++) {
		buf += "   " + this.alphabets.charAt(x);
	}
	System.out.println(buf);
}

//Zeigen Sie eine Linie mit Steinen auf dem Othello-Brett an
private void printBoardDiscLine(int y) {
	String buf = String.format("%2d┃", y+1);
	for (int x = 0; x < this.size; x ++) {
		if (this.squares[y][x] == 'B') {
			buf += "●┃";
		} else if (this.squares[y][x] == 'W') {
			buf += "○┃";
		} else {
			buf += " ┃";
		}
	}
	System.out.println(buf);
}

//Zeigen Sie eine Linie von Linien an, die den Rahmen der Othello-Tafel darstellen
private void printBoardOtherLine(String left, String middle, String right) {
	String buf = "  " + left;
	for (int x = 0; x < this.size - 1; x ++) {
		buf += "━" + middle;
	}
	System.out.println(buf + "━" + right);
}

Wenn Sie die Othello-Karte auf der Konsole anzeigen möchten, rufen Sie die erste printBoard-Methode auf. Um die Othello-Tafel anzuzeigen, müssen schwarze und weiße Kreise angezeigt werden, die Steine darstellen, Regellinien, die den Rahmen der Tafel darstellen usw. Die Teile mit demselben Ablauf werden in verschiedenen Methoden printBoardAlphabetLine, printBoardDiscLine und printBoardOtherLine zusammengestellt und aufgerufen. Übrigens, wenn Sie die obige Methode ausführen, sehen Sie so etwas (Größe ist 8 Quadrate $ x $ 8 Quadrate). othello.png

Die Alphabete oder Zahlen, die die Koordinaten darstellen, werden oben und links auf der Othello-Tafel ausgegeben. Wenn der Spieler beispielsweise die Stelle eingibt, an der der Stein platziert werden soll, geben Sie Alphabet + halbes Feld + Zahl wie "eine 1" ein.

4. Implementierung ② Spielereingabe

Als nächstes zeigen wir Ihnen, wie Sie mit Spielereingaben umgehen. Wie ich bereits geschrieben habe, müssen Sie den Stein mit "Alphabet + halber Breite + Zahl" platzieren. Sie müssen jedoch sicherstellen, dass die Eingabe korrekt ist. Die Inhalte, die bestätigt werden müssen, sind vorerst wie folgt.

  1. Existiert der Ort der eingegebenen Koordinaten tatsächlich? Beispielsweise wird ein unmöglicher Ort wie "z 15" oder ein Objekt, dessen Koordinaten nicht gelesen werden können, wie "syoukou 1234", nicht als Eingabe akzeptiert.
  2. Befinden sich an den eingegebenen Koordinaten noch andere Steine auf dem Quadrat?
  3. Befindet sich auf dem Quadrat kein anderer Stein mit den eingegebenen Koordinaten, aber ist es nicht möglich, einen der anderen Steine umzudrehen?

Der folgende Code implementiert den Prozess, um diese zu überprüfen.

//Akzeptieren Sie die Eingabe, bis der Ort für das Ablegen des Steins festgelegt ist
private void askNewCoordinates(char myColor, char enemyColor) {
	while (true) {
		//Eingang
		System.out.println("\n Entscheiden Sie, wo der Stein abgelegt werden soll.");
		System.out.println("[x-Koordinate y-Koordinate](Beispiela1):");
		Scanner sc = new Scanner(System.in);
		//Stellen Sie fest, ob es sich im Bereich des Othello-Boards befindet
		Coordinates newDisc = this.checkCoordinatesRange(sc.nextLine());
		if (newDisc.equals(-1, -1)) {
			//Wenn die Koordinaten falsch sind, geben Sie sie erneut ein
			System.out.println("Die Eingabe ist falsch.");
			continue;
		}
		if (this.squares[newDisc.y][newDisc.x] != 'N') {
			//Wenn ein Stein bereits platziert wurde, lassen Sie ihn erneut eingeben
			System.out.println("Ich habe schon einen Stein.");
			continue;
		}
		//Bestimmen Sie, ob der Stein des Gegners umgedreht werden kann
		ArrayList<Coordinates> discs = this.checkDiscsTurnedOverAllLine(
			myColor, enemyColor, newDisc, this.size*this.size);
		if (! discs.isEmpty()) {
			//Wenn es einen Stein gibt, der umgedreht werden kann, drehen Sie den Stein tatsächlich um
			this.putDisc(myColor, newDisc);
			this.turnOverDiscs(discs);
			this.printDiscsTurnedOver(discs);
			return;
		}
		System.out.println("Ich kann den Stein des Gegners nicht umdrehen.");
	}
}

//Stellen Sie fest, ob die vom Spieler eingegebenen Koordinaten im Bereich des Othello-Bretts liegen
//Wenn das Urteil erfolgreich ist, werden die Koordinaten verwendet, und wenn das Urteil fehlschlägt, werden die Koordinaten verwendet.(-1, -1)Gib es zurück
private Coordinates checkCoordinatesRange(String line) {
	String[] tokens = line.split(" ");
	//Lesen Sie die horizontalen Koordinaten aus dem ersten Buchstaben des Alphabets
	int x = this.alphabets.indexOf(tokens[0]);
	if (tokens[0].length() != 1 || x < 0 || this.size <= x) {
		return new Coordinates(-1, -1);
	}
	//Lesen Sie die vertikalen Koordinaten der verbleibenden Zeichen
	int y;
	try {
		y = Integer.parseInt(tokens[1]);
		if (y <= 0 || this.size < y) {
			return new Coordinates(-1, -1);
		}
	} catch (NumberFormatException e) {
		return new Coordinates(-1, -1);
	}
	return new Coordinates(x, y - 1);
}

Wenn der Spieler die Position des zu platzierenden Steins eingeben soll, rufen Sie die erste askNewCoordinates-Methode auf. Mit der while-Anweisung tippt der Player immer wieder, bis er als korrekte Eingabe verarbeitet werden kann (es ist etwas beängstigend zu sagen). Das erste der oben genannten Bulletins wird nach der checkCoordinatesRange-Methode beurteilt. Da der Spieler das Alphabet der horizontalen Koordinaten und die Anzahl der vertikalen Koordinaten mit einem Raum halber Breite verbindet, teilen Sie es zuerst mit der Teilungsmethode. Bei vertikalen Koordinaten wird die parseInt-Methode verwendet, um die Zeichenfolge in einen numerischen Wert zu konvertieren. Wenn diese Methode jedoch fehlschlägt, wird eine Ausnahme namens NumberFormatException ausgelöst und das gesamte Programm wird zwangsweise beendet. Es ist. Verwenden Sie daher ~~ __ Exception Handling __, das Sie gerade untersucht haben, damit es nicht gewaltsam beendet wird, selbst wenn eine solche Ausnahme auftritt. Schließen Sie wie im obigen Code den Teil ein, in dem die Ausnahme im __try-Block __ auftreten kann, und schreiben Sie die Verarbeitung nach dem Abfangen der Ausnahme in den __catch-Block __ nach dem try-Block. Der try-Block ist wie das Platzieren eines Netzes an einer Stelle, an der eine Ausnahmeverarbeitung stattfinden kann, und es scheint, als ob die Verarbeitung, die auf die Ausnahme im Netz angewendet werden soll, im catch-Block geschrieben ist (Wenn Sie einen Fehler machen, wäre es hilfreich, wenn Sie einen Kommentar abgeben könnten). ). Das zweite Aufzählungszeichen kann leicht unter Bezugnahme auf die Array-Quadrate vom Typ char bestimmt werden. Die dritte Kugel, aber das ist nervig. Ob der Stein des Gegners umgedreht werden kann oder nicht, ist genau der Prozess, von dem man sagen kann, dass er die Grundlage von Othello ist. Die im obigen Code aufgerufene checkDiscsTurnedOverAllLine-Methode wird im nächsten Abschnitt ausführlich beschrieben.

5. Umsetzung ③ Beurteilung, ob der Stein des Gegners umgedreht werden kann

Zunächst werde ich die Koordinatenklasse erläutern, die in zukünftigen Verarbeitungen häufig vorkommt. Diese Koordinatenklasse ist einfach eine Klasse, die die x- und y-Koordinaten der Othello-Karte als numerische Werte speichert. Die Mitgliedsvariablen x und y werden veröffentlicht, um das Schreiben von Code zu vermeiden. Genau genommen sollte es privat sein und eine dedizierte öffentliche Methode sollte als Referenz und Aufgabe vorbereitet werden, aber diesmal habe ich dem Spaß Priorität eingeräumt. Es tut mir Leid. Es gibt auch eine Kopiermethode, die andere Koordinaten kopiert, und eine Gleichheitsmethode, die bestimmt, ob die Koordinaten den angegebenen Koordinaten entsprechen.

class Coordinates {
	public int x;
	public int y;

	Coordinates(int x, int y)  {
		this.x = x;
		this.y = y;
	}

	Coordinates(Coordinates c)  {
		this.x = c.x;
		this.y = c.y;
	}

	public void copy(Coordinates c) {
		this.x = c.x;
		this.y = c.y;
	}

	public boolean equals(int x, int y) {
		if (this.x == x && this.y == y) {
			return true;
		} else {
			return false;
		}
	}
}

Lassen Sie uns nun über den schlimmsten Teil dieses Programms sprechen, die Beurteilung, ob der Stein des Gegners umgedreht werden kann oder nicht. Lassen Sie uns zunächst klären, wie wir feststellen, ob wir den Stein des Gegners umdrehen können, wenn wir tatsächlich mit Othello spielen.

  1. Konzentrieren Sie sich auf die Quadrate, die keine Steine haben und noch nicht bemerkt wurden.
  2. Sehen Sie sich die __8 Richtungen __ von rechts, oben rechts, oben, oben links, links, unten links, unten rechts unten vom interessierenden Quadrat an. Wenn in jeder Richtung ein oder mehrere Steine des Gegners vom nächsten zum interessierenden Quadrat __1 und dann zu einem Ihrer eigenen Steine __ weitergehen, fahren Sie mit 3 fort. Wenn dies in keiner Richtung der Fall ist, kehren Sie zu 1 zurück.
  3. Drehen Sie in alle acht Richtungen das interessierende Quadrat und den Stein des Gegners um, der zwischen Ihren in 2. gefundenen Steinen liegt, um Ihren eigenen Stein herzustellen.

Es tut mir leid, dass es schwer zu verstehen ist, aber in Worten sieht es so aus. Der folgende Code hat also versucht, einen solchen Prozess zu implementieren.

//Bestimmen Sie, ob der Stein an den eingegebenen Koordinaten den Stein des Gegners umdrehen kann
//Gibt die Koordinaten des Steins zurück, der als Arraylist umgedreht werden kann
//Da der Maximalwert der Zahl, die umgedreht werden kann, durch das Argument countMax bestimmt werden kann,
//1 reicht aus, um zu beurteilen, ob ein Stein an dieser Koordinate platziert werden kann
//Größe, um alle Koordinaten eines Steins zurückzugeben, die umgedreht werden können*messen
private ArrayList<Coordinates> checkDiscsTurnedOverAllLine(
	char myColor, char enemyColor, Coordinates myCoordinates, int countMax)
{
	ArrayList<Coordinates> discs = new ArrayList<Coordinates>();
	//In jede Richtung scannen
	for (int d = 0; d < 8; d ++) {
		discs.addAll(this.checkDiscsTurnedOverOneLine(myColor, enemyColor, myCoordinates, d));
		//Wenn der Maximalwert des Steins, der umgedreht werden kann, überschritten wird, wird die Verarbeitung gestoppt.
		if (discs.size() > countMax) {
			break;
		}
	}
	return discs;
}

//Bestimmen Sie, ob der Stein an den eingegebenen Koordinaten den Stein des Gegners umdrehen kann
//Die Scanrichtung ändert sich abhängig von der Argumentrichtung
// 0:0 Grad, 1:45 Grad, 2:90 Grad, 3:135 Grad, 4:180 Grad, 5:225 Grad, 6:270 Grad, 7:315 Grad
private ArrayList<Coordinates> checkDiscsTurnedOverOneLine(
	char myColor, char enemyColor, Coordinates myCoordinates, int direction)
{
	//Scannen Sie einen Stein, der umgedreht werden kann
	Coordinates currentCoordinates = new Coordinates(myCoordinates);
	ArrayList<Coordinates> discs = new ArrayList<Coordinates>();
	//Scannen Sie weiter neben Ihnen, während die Steine Ihres Gegners weiterlaufen
	while (true) {
		//Finde die Koordinaten des nächsten Steins
		Coordinates nextDisc = this.getNextDiscCoordinates(currentCoordinates, direction);
		if (nextDisc.equals(-1, -1)) {
			//Gibt eine leere Liste zurück, wenn keine Steine zum Umdrehen vorhanden sind
			discs.clear();
			break;
		}
		if (this.squares[nextDisc.y][nextDisc.x] == enemyColor) {
			//Wenn sich neben dir ein Stein eines Gegners befindet, registriere ihn vorübergehend in der Flip-Liste
			discs.add(nextDisc);
		} else if (this.squares[nextDisc.y][nextDisc.x] == myColor) {
			//Wenn Sie einen eigenen Stein daneben haben, geben Sie die Liste zurück
			break;
		} else {
			//Wenn sich kein Stein daneben befindet, geben Sie eine leere Liste zurück
			discs.clear();
			break;
		}
		//Fahren Sie mit dem nächsten Stein fort
		currentCoordinates.copy(nextDisc);
	}
	return discs;
}

//neben an(Kommt auf die Richtung an)Gibt die Koordinaten des Steins in zurück
//Wenn die Koordinaten außerhalb des Bereichs liegen(-1, -1)Gib es zurück
private Coordinates getNextDiscCoordinates(Coordinates myDisc, int direction) {
	//x-Koordinate
	int x = myDisc.x;
	if (direction == 0 || direction == 1 || direction == 7) {
		x ++; //0 Grad,45 Grad,315 Grad
	} else if (direction == 3 || direction == 4 || direction == 5) {
		x --;  //135 Grad,180 Grad,225 Grad
	}
	//y-Koordinate
	int y = myDisc.y;
	if (direction == 1 || direction == 2 || direction == 3) {
		y --; //45 Grad,90 Grad,135 Grad
	} else if (direction == 5 || direction == 6 || direction == 7) {
		y ++;  //225 Grad,270 Grad,315 Grad
	}
	if (x < 0 || this.size <= x || y < 0 || this.size <= y) {
		//Wenn die Koordinaten außerhalb des Bereichs liegen
		return new Coordinates(-1, -1);
	}
	return new Coordinates(x, y);
}

Wenn Sie herausfinden möchten, ob Sie den Stein Ihres Gegners umdrehen können, rufen Sie zuerst die Methode checkDiscsTurnedOverAllLine auf. Ich werde alle acht Richtungen wie AllLine betrachten, aber ich wollte die Verarbeitung ähnlicher Teile zusammenfassen, deshalb habe ich beschlossen, die checkDiscsTurnedOverOneLine-Methode für jede Richtung aufzurufen. Diese checkDiscsTurnedOverOneLine-Methode verarbeitet wie in OneLine nur eine durch die Argumentrichtung angegebene Richtung. Für eine bestimmte Richtung werden die Koordinaten des nächsten Steins kontinuierlich von der Methode getNextDiscCoordinates abgerufen (die x- und y-Koordinaten werden durch Angabe der Richtung um 1 erhöht, dekrementiert oder unverändert). Wenn in der while-Anweisung die Steine des Gegners neben dem interessierenden Quadrat durchgehend sind, __ registrieren Sie __ vorübergehend in der Liste der Steinscheiben, die sie umdrehen können. Wenn Sie nach dem Stein des Gegners keinen eigenen Stein haben, den Sie möglicherweise umdrehen können, oder wenn Sie sich außerhalb der Reichweite des Othello-Bretts befinden, löschen Sie alle vorübergehend registrierten Listen. Letztendlich sind die Koordinaten in der Liste, die von der zu Beginn eingeführten checkDiscsTurnedOverAllLine-Methode zurückgegeben werden, die Liste der Steine, die wirklich umgedreht werden können.

6. Implementierung ④ Gesamtfluss von Othello

Abschließend werde ich kurz den Teil vorstellen, der den Ablauf des Othello-Spiels beschreibt.

//Starten Sie Othello
public void start() {
	//Entscheide dich für den Stein des Spielers
	this.askPlayerColor();
	//Bringen Sie das Othello-Board sofort nach dem Start in den Zustand
	this.initializeBoard();
	this.printBoard();
	this.turnCounter = 1;
	int turnCounterMax = this.size*this.size - 4;
	int skipCounter = 0;
	//Der erste Zug entscheidet, welcher
	boolean isPlayerTurn = true;
	if (this.playerColor == 'W') {
		isPlayerTurn = false;
	}
	//Verarbeitung jeder Runde
	System.out.println("Starten Sie Othello.");
	int playerDiscNum;
	int otherDiscNum;
	while (this.turnCounter <= turnCounterMax) {
		//Zeigen Sie die Anzahl der Steine im Moment an
		playerDiscNum = this.countDisc(this.playerColor);
		otherDiscNum = this.countDisc(this.otherColor);
		System.out.print("Sie= " + playerDiscNum + "  ");
		System.out.println("Gegner= " + otherDiscNum);
		if (isPlayerTurn) {
			//Spieler an der Reihe
			//Bestimmen Sie, ob der Spieler einen Stein legen kann
			if (! this.checkSquaresForNewDisc(this.playerColor, this.otherColor)) {
				//Spielerrunden werden übersprungen
				System.out.println("Ihr Zug wurde übersprungen.");
				if (skipCounter == 1) {
					//Wenn der Zug des Gegners bereits übersprungen wurde, endet das Spiel
					break;
				}
				isPlayerTurn = !isPlayerTurn;
				skipCounter ++;
				continue;
			}
			System.out.println("Turn " + turnCounter + ":Du bist dran.");
			skipCounter = 0;
			this.askNewCoordinates(this.playerColor, this.otherColor);
		} else {
			//Der Gegner ist an der Reihe
			//Bestimmen Sie, ob der Gegner einen Stein legen kann
			if (! this.checkSquaresForNewDisc(this.otherColor, this.playerColor)) {
				//Spielerrunden werden übersprungen
				System.out.println("Der Zug des Gegners wurde übersprungen.");
				if (skipCounter == 1) {
					//Wenn der Zug des Spielers bereits übersprungen wurde, endet das Spiel
					break;
				}
				isPlayerTurn = !isPlayerTurn;
				skipCounter ++;
				continue;
			}
			//Der Gegner ist an der Reihe
			System.out.println("Turn " + turnCounter + ":Ihr Gegner ist an der Reihe.");
			skipCounter = 0;
			this.askNewCoordinates(this.otherColor, this.playerColor);
		}
		this.printBoard();
		//Verarbeitung für die nächste Runde
		this.turnCounter ++;
		isPlayerTurn = !isPlayerTurn;
	}
	//Urteil über Sieg oder Niederlage
	playerDiscNum = this.countDisc(this.playerColor);
	otherDiscNum = this.countDisc(this.otherColor);
	System.out.print("Sie= " + playerDiscNum + "  ");
	System.out.println("Gegner= " + otherDiscNum);
	if (playerDiscNum > otherDiscNum) {
		System.out.println("Du gewinnst.");
	} else if (playerDiscNum == otherDiscNum) {
		System.out.println("Es ist eine Zeichnung.");
	} else {
		System.out.println("Du verlierst.");
	}
}

Abgesehen davon ist es nicht gut, 80 Zeilen in einer Methode wie der obigen Startmethode zu schreiben. Sie müssen einfach zu lesenden Code schreiben, indem Sie ähnliche Prozesse in verschiedene Methoden gruppieren oder einige Teile in verschiedene Methoden unterteilen. __ ist __, ich hatte diesmal nicht genug Zeit. Bitte vergib mir, ich werde es verbessern, wenn ich es das nächste Mal zeige.

Wenn Sie nun den Spielfluss steuern, gibt es eine wichtige Sache: __ Wenn Sie Ihren eigenen Stein überhaupt nicht setzen können, ist es ein Pass und Ihr Gegner ist an der Reihe __. Außerdem sollte beachtet werden, dass das Spiel endet, wenn weder Sie noch Ihr Gegner einen Stein legen können. Daher wird im obigen Code eine Variable vom Typ int vom Typ skipCounter erstellt und 1 hinzugefügt, wenn sich einer von Ihnen oder die andere Partei in einer Pass-Situation befindet. Wenn ein Stein platziert werden kann, wird er auf 0 zurückgesetzt. Dann endet das Spiel, wenn Sie und Ihr Gegner nacheinander passen (skipCounter == 2).

7. Implementierungszusammenfassung

Der Rest des Prozesses ist einfacher als der bisherige Inhalt, daher werde ich die Erklärung weglassen. Das gesamte diesmal implementierte Programm wird unten beschrieben.

Othello-Programm (zum Öffnen klicken)
import java.util.ArrayList;
import java.util.Scanner;

class OthelloBoardTest {
	public static void main(String args[]) {
		OthelloBoard ob = new OthelloBoard();
		ob.start();
	}
}

class OthelloBoard {
	private int size;				//Eine Seite des Othello-Boards(8, 10, 12, 14, 16)
	private char[][] squares;		//Zustand jeder Masse(B:schwarz, W:Weiß, N:Kein Stein)
	private char playerColor;		//Spieler Steinfarbe
	private char otherColor;		//Die Farbe des Steins des Gegners
	private int turnCounter;		//Zählen Sie die Anzahl der Umdrehungen
	private final String alphabets = "abcdefghijklmnop";
									//Alphabet mit horizontalen Koordinaten

	//Konstrukteur
	public OthelloBoard() {
		this.size = 8;
//		this.size = askBoardSize();
		this.squares = new char[this.size][this.size];
	}

	//Starten Sie Othello
	public void start() {
		//Entscheide dich für den Stein des Spielers
		this.askPlayerColor();
		//Bringen Sie das Othello-Board sofort nach dem Start in den Zustand
		this.initializeBoard();
		this.printBoard();
		this.turnCounter = 1;
		int turnCounterMax = this.size*this.size - 4;
		int skipCounter = 0;
		//Der erste Zug entscheidet, welcher
		boolean isPlayerTurn = true;
		if (this.playerColor == 'W') {
			isPlayerTurn = false;
		}
		//Verarbeitung jeder Runde
		System.out.println("Starten Sie Othello.");
		int playerDiscNum;
		int otherDiscNum;
		while (this.turnCounter <= turnCounterMax) {
			//Zeigen Sie die Anzahl der Steine im Moment an
			playerDiscNum = this.countDisc(this.playerColor);
			otherDiscNum = this.countDisc(this.otherColor);
			System.out.print("Sie= " + playerDiscNum + "  ");
			System.out.println("Gegner= " + otherDiscNum);
			if (isPlayerTurn) {
				//Spieler an der Reihe
				//Bestimmen Sie, ob der Spieler einen Stein legen kann
				if (! this.checkSquaresForNewDisc(this.playerColor, this.otherColor)) {
					//Spielerrunden werden übersprungen
					System.out.println("Ihr Zug wurde übersprungen.");
					if (skipCounter == 1) {
						//Wenn der Zug des Gegners bereits übersprungen wurde, endet das Spiel
						break;
					}
					isPlayerTurn = !isPlayerTurn;
					skipCounter ++;
					continue;
				}
				System.out.println("Turn " + turnCounter + ":Du bist dran.");
				skipCounter = 0;
				this.askNewCoordinates(this.playerColor, this.otherColor);
			} else {
				//Der Gegner ist an der Reihe
				//Bestimmen Sie, ob der Gegner einen Stein legen kann
				if (! this.checkSquaresForNewDisc(this.otherColor, this.playerColor)) {
					//Spielerrunden werden übersprungen
					System.out.println("Der Zug des Gegners wurde übersprungen.");
					if (skipCounter == 1) {
						//Wenn der Zug des Spielers bereits übersprungen wurde, endet das Spiel
						break;
					}
					isPlayerTurn = !isPlayerTurn;
					skipCounter ++;
					continue;
				}
				//Der Gegner ist an der Reihe
				System.out.println("Turn " + turnCounter + ":Ihr Gegner ist an der Reihe.");
				skipCounter = 0;
				this.askNewCoordinates(this.otherColor, this.playerColor);
			}
			this.printBoard();
			//Verarbeitung für die nächste Runde
			this.turnCounter ++;
			isPlayerTurn = !isPlayerTurn;
		}
		//Urteil über Sieg oder Niederlage
		playerDiscNum = this.countDisc(this.playerColor);
		otherDiscNum = this.countDisc(this.otherColor);
		System.out.print("Sie= " + playerDiscNum + "  ");
		System.out.println("Gegner= " + otherDiscNum);
		if (playerDiscNum > otherDiscNum) {
			System.out.println("Du gewinnst.");
		} else if (playerDiscNum == otherDiscNum) {
			System.out.println("Es ist eine Zeichnung.");
		} else {
			System.out.println("Du verlierst.");
		}
	}

	//Drehen Sie den Stein um
	public void turnOverDiscs(ArrayList<Coordinates> discs) {
		for (int i = 0; i < discs.size(); i ++) {
			int x = discs.get(i).x;
			int y = discs.get(i).y;
			if (this.squares[y][x] == 'B') {
				this.squares[y][x] = 'W';
			} else if (this.squares[y][x] == 'W') {
				this.squares[y][x] = 'B';
			}
		}
	}

	//Platz zum Ablegen von Steinen(Ein Ort, an dem Sie andere Steine umdrehen können)Bestimmen Sie, ob es gibt
	private boolean checkSquaresForNewDisc(char myColor, char enemyColor) {
		for (int y = 0; y < this.size; y ++) {
			for (int x = 0; x < this.size; x ++) {
				if (this.squares[y][x] != 'N') {
					continue;
				}
				ArrayList<Coordinates> discs = this.checkDiscsTurnedOverAllLine(
						myColor, enemyColor, new Coordinates(x, y), 1);
				if (discs.size() >= 1) {
					return true;
				}
			}
		}
		return false;
	}

	//Akzeptieren Sie die Eingabe, bis der Ort für das Ablegen des Steins festgelegt ist
	private void askNewCoordinates(char myColor, char enemyColor) {
		while (true) {
			//Eingang
			System.out.println("\n Entscheiden Sie, wo der Stein abgelegt werden soll.");
			System.out.println("[x-Koordinate y-Koordinate](Beispiela1):");
			Scanner sc = new Scanner(System.in);
			//Stellen Sie fest, ob es sich im Bereich des Othello-Boards befindet
			Coordinates newDisc = this.checkCoordinatesRange(sc.nextLine());
			if (newDisc.equals(-1, -1)) {
				//Wenn die Koordinaten falsch sind, geben Sie sie erneut ein
				System.out.println("Die Eingabe ist falsch.");
				continue;
			}
			if (this.squares[newDisc.y][newDisc.x] != 'N') {
				//Wenn ein Stein bereits platziert wurde, lassen Sie ihn erneut eingeben
				System.out.println("Ich habe schon einen Stein.");
				continue;
			}
			//Bestimmen Sie, ob der Stein des Gegners umgedreht werden kann
			ArrayList<Coordinates> discs = this.checkDiscsTurnedOverAllLine(
				myColor, enemyColor, newDisc, this.size*this.size);
			if (! discs.isEmpty()) {
				//Wenn es einen Stein gibt, der umgedreht werden kann, drehen Sie den Stein tatsächlich um
				this.putDisc(myColor, newDisc);
				this.turnOverDiscs(discs);
				this.printDiscsTurnedOver(discs);
				return;
			}
			System.out.println("Ich kann den Stein des Gegners nicht umdrehen.");
		}
	}

	//Stellen Sie fest, ob die vom Spieler eingegebenen Koordinaten im Bereich des Othello-Bretts liegen
	//Wenn das Urteil erfolgreich ist, werden die Koordinaten verwendet, und wenn das Urteil fehlschlägt, werden die Koordinaten verwendet.(-1, -1)Gib es zurück
	private Coordinates checkCoordinatesRange(String line) {
		String[] tokens = line.split(" ");
		//Lesen Sie die horizontalen Koordinaten aus dem ersten Buchstaben des Alphabets
		int x = this.alphabets.indexOf(tokens[0]);
		if (tokens[0].length() != 1 || x < 0 || this.size <= x) {
			return new Coordinates(-1, -1);
		}
		//Lesen Sie die vertikalen Koordinaten der verbleibenden Zeichen
		int y;
		try {
			y = Integer.parseInt(tokens[1]);
			if (y <= 0 || this.size < y) {
				return new Coordinates(-1, -1);
			}
		} catch (NumberFormatException e) {
			return new Coordinates(-1, -1);
		}
		return new Coordinates(x, y - 1);
	}

	//Bestimmen Sie, ob der Stein an den eingegebenen Koordinaten den Stein des Gegners umdrehen kann
	//Gibt die Koordinaten des Steins zurück, der als Arraylist umgedreht werden kann
	//Da der Maximalwert der Zahl, die umgedreht werden kann, durch das Argument countMax bestimmt werden kann,
	//1 reicht aus, um zu beurteilen, ob ein Stein an dieser Koordinate platziert werden kann
	//Größe, um alle Koordinaten eines Steins zurückzugeben, die umgedreht werden können*messen
	private ArrayList<Coordinates> checkDiscsTurnedOverAllLine(
		char myColor, char enemyColor, Coordinates myCoordinates, int countMax)
	{
		ArrayList<Coordinates> discs = new ArrayList<Coordinates>();
		//In jede Richtung scannen
		for (int d = 0; d < 8; d ++) {
			discs.addAll(this.checkDiscsTurnedOverOneLine(myColor, enemyColor, myCoordinates, d));
			//Wenn der Maximalwert des Steins, der umgedreht werden kann, überschritten wird, wird die Verarbeitung gestoppt.
			if (discs.size() > countMax) {
				break;
			}
		}
		return discs;
	}
	
	//Bestimmen Sie, ob der Stein an den eingegebenen Koordinaten den Stein des Gegners umdrehen kann
	//Die Scanrichtung ändert sich abhängig von der Argumentrichtung
	// 0:0 Grad, 1:45 Grad, 2:90 Grad, 3:135 Grad, 4:180 Grad, 5:225 Grad, 6:270 Grad, 7:315 Grad
	private ArrayList<Coordinates> checkDiscsTurnedOverOneLine(
		char myColor, char enemyColor, Coordinates myCoordinates, int direction)
	{
		//Scannen Sie einen Stein, der umgedreht werden kann
		Coordinates currentCoordinates = new Coordinates(myCoordinates);
		ArrayList<Coordinates> discs = new ArrayList<Coordinates>();
		//Scannen Sie weiter neben Ihnen, während die Steine Ihres Gegners weiterlaufen
		while (true) {
			//Finde die Koordinaten des nächsten Steins
			Coordinates nextDisc = this.getNextDiscCoordinates(currentCoordinates, direction);
			if (nextDisc.equals(-1, -1)) {
				//Gibt eine leere Liste zurück, wenn keine Steine zum Umdrehen vorhanden sind
				discs.clear();
				break;
			}
			if (this.squares[nextDisc.y][nextDisc.x] == enemyColor) {
				//Wenn sich neben dir ein Stein eines Gegners befindet, registriere ihn vorübergehend in der Flip-Liste
				discs.add(nextDisc);
			} else if (this.squares[nextDisc.y][nextDisc.x] == myColor) {
				//Wenn Sie einen eigenen Stein daneben haben, geben Sie die Liste zurück
				break;
			} else {
				//Wenn sich kein Stein daneben befindet, geben Sie eine leere Liste zurück
				discs.clear();
				break;
			}
			//Fahren Sie mit dem nächsten Stein fort
			currentCoordinates.copy(nextDisc);
		}
		return discs;
	}
	
	//neben an(Kommt auf die Richtung an)Gibt die Koordinaten des Steins in zurück
	//Wenn die Koordinaten außerhalb des Bereichs liegen(-1, -1)Gib es zurück
	private Coordinates getNextDiscCoordinates(Coordinates myDisc, int direction) {
		//x-Koordinate
		int x = myDisc.x;
		if (direction == 0 || direction == 1 || direction == 7) {
			x ++; //0 Grad,45 Grad,315 Grad
		} else if (direction == 3 || direction == 4 || direction == 5) {
			x --;  //135 Grad,180 Grad,225 Grad
		}
		//y-Koordinate
		int y = myDisc.y;
		if (direction == 1 || direction == 2 || direction == 3) {
			y --; //45 Grad,90 Grad,135 Grad
		} else if (direction == 5 || direction == 6 || direction == 7) {
			y ++;  //225 Grad,270 Grad,315 Grad
		}
		if (x < 0 || this.size <= x || y < 0 || this.size <= y) {
			//Wenn die Koordinaten außerhalb des Bereichs liegen
			return new Coordinates(-1, -1);
		}
		return new Coordinates(x, y);
	}

	//Akzeptiert Eingaben, bis die Größe des Othello-Boards festgelegt ist
	//Diese Methode ist der Konstruktor dafür.Wenn Sie es auf der rechten Seite der Größe einfügen,
	//Sie können einen Prozess hinzufügen, um die Größe der Othello-Karte einzugeben
	private int askBoardSize() {
		while (true) {
			System.out.println("");
			System.out.println("Bitte bestimmen Sie die Länge einer Seite des Othello-Boards.");
			System.out.print("[8, 10, 12, 14,Jeder von 16]:");
			Scanner sc = new Scanner(System.in);
			String line = sc.nextLine();
			if ("8".equals(line) || "10".equals(line) || "12".equals(line) ||
				"14".equals(line) || "16".equals(line)) {
				System.out.println("Die Länge einer Seite des Othello-Bretts beträgt" + line + "ist.");
				return Integer.parseInt(line);
			}
			System.out.println("Die Eingabe ist falsch.");
		}
	}

	//Akzeptiere die Eingabe, bis die Farbe des Spielers festgelegt ist
	private void askPlayerColor() {
		while (true) {
			System.out.println("\n Entscheide dich für deinen Stein.");
			System.out.println("[b (schwarz), w (Weiß)Irgendein von]:");
			Scanner sc = new Scanner(System.in);
			String line = sc.nextLine();
			if ("b".equals(line)) {
				System.out.println("Dein Stein ist schwarz.");
				this.playerColor = 'B';
				this.otherColor = 'W';
				return;
			} else if ("w".equals(line)) {
				System.out.println("Dein Stein ist weiß.");
				this.playerColor = 'W';
				this.otherColor = 'B';
				return;
			}
			System.out.println("Die Eingabe ist falsch.");
		}
	}

	//Zähle Steine der angegebenen Farbe
	private int countDisc(char myColor) {
		int count = 0;
		for (int y = 0; y < this.size; y ++) {
			for (int x = 0; x < this.size; x ++) {
				if (this.squares[y][x] == myColor) {
					count ++;
				}
			}
		}
		return count;
	}

	//Bringen Sie das Othello-Board sofort nach dem Start in den Zustand
	private void initializeBoard() {
		for (int y = 0; y < this.size; y ++) {
			for (int x = 0; x < this.size; x ++) {
				squares[y][x] = 'N';
			}
		}
		//Legen Sie Steine nur in die zentralen 4 Felder
		this.putDisc('B', this.size/2 - 1, this.size/2 - 1);
		this.putDisc('B', this.size/2, this.size/2);
		this.putDisc('W', this.size/2, this.size/2 - 1);
		this.putDisc('W', this.size/2 - 1, this.size/2);
	}

	//Platziere einen Stein an den angegebenen Koordinaten auf dem Othello-Brett
	private void putDisc(char discColor, int x, int y) {
		this.squares[y][x] = discColor;
	}
	private void putDisc(char discColor, Coordinates c) {
		this.putDisc(discColor, c.x, c.y);
	}

	//Zeige alle Koordinaten der umgedrehten Steine
	private void printDiscsTurnedOver(ArrayList<Coordinates> discs) {
		System.out.println("Ich drehte den nächsten Stein um.");
		int count = 0;
		for (int i = 0; i < discs.size(); i ++) {
			System.out.print(this.alphabets.substring(discs.get(i).x, discs.get(i).x + 1) +
				(discs.get(i).y + 1) + " ");
			count ++;
			if (count == 8) {
				System.out.println("");
				count = 0;
			}
		}
		System.out.println("");
	}

	//Zeigen Sie die Othello-Karte auf der Konsole an
	private void printBoard() {
		this.printBoardAlphabetLine();					//Alphabetzeile
		this.printBoardOtherLine("┏", "┳", "┓");		//Oberkante
		for (int y = 0; y < this.size - 1; y ++) {
			this.printBoardDiscLine(y);					//Linie, die Steine anzeigt
			this.printBoardOtherLine("┣", "╋", "┫");	//Zeilenabstand
		}
		this.printBoardDiscLine(this.size - 1);			//Linie, die Steine anzeigt
		this.printBoardOtherLine("┗", "┻", "┛");		//unteres Ende
	}

	//Zeigen Sie das Alphabet an, das die Zeile der Othello-Tafel angibt
	private void printBoardAlphabetLine() {
		String buf = "  ";
		for (int x = 0; x < this.size; x ++) {
			buf += "   " + this.alphabets.charAt(x);
		}
		System.out.println(buf);
	}

	//Zeigen Sie eine Linie mit Steinen auf dem Othello-Brett an
	private void printBoardDiscLine(int y) {
		String buf = String.format("%2d┃", y+1);
		for (int x = 0; x < this.size; x ++) {
			if (this.squares[y][x] == 'B') {
				buf += "●┃";
			} else if (this.squares[y][x] == 'W') {
				buf += "○┃";
			} else {
				buf += " ┃";
			}
		}
		System.out.println(buf);
	}

	//Zeigen Sie eine Linie von Linien an, die den Rahmen der Othello-Tafel darstellen
	private void printBoardOtherLine(String left, String middle, String right) {
		String buf = "  " + left;
		for (int x = 0; x < this.size - 1; x ++) {
			buf += "━" + middle;
		}
		System.out.println(buf + "━" + right);
	}
}

class Coordinates {
	public int x;
	public int y;

	Coordinates(int x, int y)  {
		this.x = x;
		this.y = y;
	}

	Coordinates(Coordinates c)  {
		this.x = c.x;
		this.y = c.y;
	}

	public void copy(Coordinates c) {
		this.x = c.x;
		this.y = c.y;
	}

	public boolean equals(int x, int y) {
		if (this.x == x && this.y == y) {
			return true;
		} else {
			return false;
		}
	}
}

8. Versuche zu rennen

Da das Othello-Brett jedes Mal angezeigt wird, wenn Sie eine Koordinate eingeben, wird nur ein Bildschirm angezeigt, anstatt das gesamte Spiel träge anzuzeigen.  othello3.png

Ganz am Ende haben sowohl Sie als auch Ihr Gegner bestanden, sodass das Spiel beendet wurde. Was schwierig ist, ist, dass wir die Verarbeitung der anderen Partei (PC) noch nicht implementiert haben, daher müssen wir derzeit die Koordinaten bis zum Stein der anderen Partei eingeben __. Dieses traurige __ selbst gemachte Gefühl __. Was mache ich seit Sonntag tagsüber ………

9. Zukünftige Aufgaben

Zur Zeit bin ich jetzt in einem Zustand, in dem ich zumindest Othello kann, also werde ich in Zukunft die Denkroutine der anderen Partei umsetzen. Am Anfang fühlt es sich an, als würde man zufällig aus der Stelle auswählen, an der man den Stein platzieren kann. Nehmen Sie zum Beispiel zu Beginn des Spiels nicht zu viel Stein, zielen Sie auf eine klebrige Ecke im mittleren Teil und lassen Sie die Berechnungsgeschwindigkeit im letzten Teil mit Ihnen sprechen Ich möchte einen __- Algorithmus erstellen, der im frühen, mittleren und späten Stadium keine Lücken aufweist, z. B. beim Vorlesen.

Es tut mir leid, dass die Erklärung dieses Mal aufgrund des langen Quellcodes überflüssig wurde. Trotzdem vielen Dank an alle, die bisher gelesen haben.

Recommended Posts

Meine Gedanken zur Zukunft [Vorbereitung]
Meine Gedanken zur Equals-Methode (Java)
Othello meiner Gedanken [Denkroutine 2]
Othello meiner Gedanken [Denkroutine 1]
Scala läuft auf einer JVM