Erstellen eines Vier-Gewinnt-Spiels in C

CCBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Projekt werden wir ein einfaches textbasiertes Gomoku-Spiel mit der Programmiersprache C erstellen. Gomoku ist ein Zwei-Spieler-Strategiespielfeldspiel, bei dem das Ziel ist, der erste zu sein, der fünf aufeinanderfolgende Steine in einer Reihe erhält, entweder horizontal, vertikal oder diagonal. Wir werden dieses Spiel mit einer 15x15 Spielfläche entwickeln.

👀 Vorschau

Gomoku Game

🎯 Aufgaben

In diesem Projekt lernen Sie:

  • Wie man eine Schachbrett mit einem zweidimensionalen Array in C entwirft und implementiert.
  • Wie man eine Hauptfunktion erstellt, um den Spielablauf zu steuern.
  • Wie man Funktionen implementiert, um das Spiel zu initialisieren, das Schachbrett auszugeben und den Spielern ihren Zug zu ermöglichen.
  • Wie man eine Funktion entwickelt, um die Gewinnbedingung im Spiel zu überprüfen.
  • Wie man das Programm kompiliert und ausführt.

🏆 Errungenschaften

Nach Abschluss dieses Projekts werden Sie in der Lage sein:

  • Mit zweidimensionalen Arrays in C umzugehen.
  • Ein Spielablauf mit Funktionen zu entwerfen und zu implementieren.
  • Gewinnbedingungen im Spiel zu überprüfen.
  • Ein C-Programm zu kompilieren und auszuführen.

Projekt-Dateien erstellen

Erstellen Sie zunächst eine neue Datei mit dem Namen gomoku.c und öffnen Sie sie in Ihrem bevorzugten Code-Editor.

cd ~/project
touch gomoku.c
✨ Lösung prüfen und üben

Entwurf eines Schachbretts

Verwenden von 'O' und 'X' zur Darstellung von Schachfiguren

Zunächst benötigen wir ein Schachbrett (15 * 15), um die "Situation" jeder Position auf dem Brett zu erfassen. Wir können daher ein Array chessboard[16][16] definieren. Warum nicht [15][15]? Dies ist, weil auf diese Weise die Koordinaten des Arrays genau mit den Zeilen und Spalten des Schachbretts übereinstimmen, was es einfacher macht, den nachfolgenden Code zu schreiben.

#include <stdio.h>

#define N 15

// Definiere ein Array und weise jedem Element den Anfangswert 0 zu.
int chessboard[N + 1][N + 1] = { 0 };
✨ Lösung prüfen und üben

Hauptfunktion

Bevor wir beginnen, die Hauptfunktion zu schreiben, betrachten wir kurz den typischen Ablauf eines Spiels. Zunächst betreten wir die Hauptschnittstelle des Spiels, klicken dann auf die Startschaltfläche, um das Spiel zu beginnen, und sehen dann das Spielbildschirm an. Danach bestimmen wir das Sieg- oder Niederlageergebnis und beenden das Spiel. Wie sieht nun der Ablauf eines Spiels wie Gomoku aus?

Zunächst betreten wir das Willkommensfenster des Spiels, geben dann Y ein, um das Spiel zu starten (nicht Y, um das Spiel zu beenden), sehen dann das Spielbrett an und lassen die beiden Spieler abwechselnd ihre Steine setzen. Danach bestimmen wir das Sieg- oder Niederlageergebnis (ob es fünf Steine in einer Reihe gibt).

// Es wird verwendet, um zu verfolgen, ob es der Reihe nach Spieler 1 oder Spieler 2 ist. Eine ungerade Zahl bedeutet, dass es Spieler 1s Zug ist, und eine gerade Zahl bedeutet, dass es Spieler 2s Zug ist.
int whoseTurn = 0;

int main(void)
{
	// Eine benutzerdefinierte Funktion, die das Spiel initialisiert, d.h. das Willkommensfenster anzeigt und das Spielbrett anzeigt.
	initGame();

	// Diese Schleife ist für die abwechselnden Züge der beiden Spieler.
	while (1)
	{
		// In jeder Schleifendurchlauf wird um 1 erhöht, sodass die beiden Spieler abwechselnd ziehen können.
		whoseTurn++;

		// Eine benutzerdefinierte Funktion, die einen Stein setzen.
		playChess();
	}

	return 0;
}
✨ Lösung prüfen und üben

initGame-Funktion

In dieser Funktion möchten wir die folgenden Funktionen implementieren:

  • Ein einfaches Willkommensfenster anzeigen.
  • Nach Eingabe von 'Y' das Schachbrett anzeigen.
void initGame(void)
{
	char c;

	printf("Bitte geben Sie 'y' ein, um das Spiel zu starten:");
	c = getchar();
	if ('y'!= c && 'Y'!= c)
		exit(0);

	//Löschen
	system("clear");

	//Hier rufen wir erneut eine benutzerdefinierte Funktion auf, deren Funktion es ist, das Schachbrett auszugeben.
	printChessboard();
}

In der initGame-Funktion verwenden wir die Funktionen exit und system, daher müssen wir die Headerdatei stdlib.h am Anfang des Programms einbinden.

#include <stdlib.h>
✨ Lösung prüfen und üben

printChessboard-Funktion

Ziel dieser Funktion ist es:

  • Die Zeilen- und Spaltennummern auszugeben und das Schachbrett auszugeben.
  • Wenn der Wert des Arrayelements 0 ist, einen Stern (*) auszugeben, um anzuzeigen, dass die Position leer ist.
  • Wenn der Wert des Arrayelements 1 ist, einen Vollkreis (X) auszugeben, was den Stein von Spieler 1 darstellt.
  • Wenn der Wert des Arrayelements 2 ist, einen leeren Kreis (O) auszugeben, was den Stein von Spieler 2 darstellt.
void printChessboard(void)
{
	int i, j;

	for (i = 0; i <= N; i++)
	{
		for (j = 0; j <= N; j++)
		{
			if (0 == i)		// Dies gibt die Spaltennummer aus.
				printf("%3d", j);
			else if (j == 0)	// Gibt die Zeilennummer aus.
				printf("%3d", i);
			else if (1 == chessboard[i][j])
				printf("  X");
			else if (2 == chessboard[i][j])
				printf("  O");
			else
				printf("  *");
		}
		printf("\n");
	}
}
✨ Lösung prüfen und üben

playChess-Funktion

In dieser Funktion möchten wir das Folgende erreichen:

  • Auffordern Sie den Spieler, die Position für das Setzen des Schachsteins einzugeben.
  • Wenn es derzeit Spieler 1s Zug ist, weisen Sie dem entsprechenden Element im Array den Wert 1 zu.
  • Wenn es derzeit Spieler 2s Zug ist, weisen Sie dem entsprechenden Element im Array den Wert 2 zu.
  • Nach jedem Zug bestimmen, ob der aktuelle Spieler gewonnen hat.
void playChess(void)
{
	int i, j, winner;

	// Bestimmen, ob es Spieler 1s Zug oder Spieler 2s Zug ist und weise dann dem entsprechenden Element im Array den Wert zu.
	if (1 == whoseTurn % 2)
	{
		printf("Spieler 1 ist am Zug. Bitte geben Sie die Position ein, das Format ist Zeilennummer + Leerzeichen + Spaltennummer: ");
		scanf("%d %d", &i, &j);
		chessboard[i][j] = 1;
	}
	else
	{
		printf("Spieler 2 ist am Zug. Bitte geben Sie die Position ein, das Format ist Zeilennummer + Leerzeichen + Spaltennummer: ");
		scanf("%d %d", &i, &j);
		chessboard[i][j] = 2;
	}

	// Drucken Sie das Brett erneut.
	system("clear");
	printChessboard();	// Diese Funktion wird erneut aufgerufen.

	/*
	* Der folgende Abschnitt ruft die benutzerdefinierte Funktion (die Prüfungsfunktion) auf.
	* Es wird verwendet, um zu bestimmen, ob der aktuelle Spieler mit diesem Zug gewonnen hat oder nicht.
	*/
	if (judge(i, j, whoseTurn))
	{
		if (1 == whoseTurn % 2)
			printf("Gewinner ist Spieler 1!\n");
		else
			printf("Gewinner ist Spieler 2!\n");
	}
}
✨ Lösung prüfen und üben

judge-Funktion

Funktionsparameter:

  • x: Die Zeilennummer des aktuellen Zuges
  • y: Die Spaltennummer des aktuellen Zuges

Rückgabewert:

  • 1 oder 0. 1 bedeutet, dass der aktuelle Spieler nach diesem Zug gewonnen hat.
int judge(int x, int y)
{
    int i, j;
    int t = 2 - whoseTurn % 2;
    const int step[4][2]={{-1,0},{0,-1},{1,1},{1,0}};
    for(int i=0;i<4;++i)
    {
        const int d[2]={-1,1};
        int count=1;
        for(int j=0;j<2;++j)
            for(int k=1;k<=4;++k){
                int row=x+k*d[j]*step[i][0];
                int col=y+k*d[j]*step[i][1];
                if( row>=1 && row<=N && col>=1 && col<=N &&
                    chessboard[x][y]==chessboard[row][col])
                    count+=1;
                else
                    break;
            }
        if(count>=5)
            return 1;
    }
    return 0;
}

In der judge-Funktion gibt es 3 geschachtelte for-Schleifen, und ihr Zweck ist es, zu bestimmen, ob es eine Reihe von fünf aufeinanderfolgenden Steinen gibt.

Eine Reihe von fünf Steinen kann entweder horizontal, vertikal oder diagonal verlaufen. Hier werden wir einen Versuch-und-Irrtum-Ansatz verwenden und nach aufeinanderfolgenden Steinen in horizontaler, vertikaler und diagonaler Richtung suchen. Nehmen wir als Beispiel:

Gomoku Game

Auf dem obigen Schachbrett erklären wir den Algorithmus zur Bestimmung, ob es eine Reihe von fünf Steinen gibt, basierend auf den Koordinaten (9, 10).

Zunächst überprüfen wir, ob es eine diagonale Reihe von fünf Steinen gibt, die bei (9, 10) beginnt. Der Prozess lautet wie folgt:

  • Beginnend bei (9, 10) suchen wir in die obere linke Richtung. Die Koordinaten, die die Bedingung erfüllen, sind (8, 9), (7, 8) und (6, 7). Da (5, 6) die Bedingung nicht erfüllt, gehen wir zum nächsten Schritt über.
  • Dann suchen wir in die untere rechte Richtung und finden (10, 11), die einzige Koordinate, die die Bedingung erfüllt.
  • Wir haben fünf Punkte in einer geraden Linie gefunden, also gewinnt Spieler 2.

Wenn es keine Reihe von fünf Steinen in diagonaler Richtung gibt, überprüfen wir dann die vertikale und horizontale Richtung. Wenn keine der beiden die Gewinnbedingung erfüllt, bedeutet das, dass der aktuelle Spieler nicht gewinnen kann und das Spiel fortgesetzt wird.

✨ Lösung prüfen und üben

Mein Schachstein wurde "aufgegessen"

Ich weiß nicht, ob jemand bemerkt hat, aber in unserem Vier Gewinnt-Spiel können wir sogar einen bereits belegten Platz "aufessen", wenn wir unseren eigenen Stein setzen.

Dies liegt daran, dass wir bei der Schreibung der playChess-Funktion die Position, an der wir den Stein setzen, nicht überprüft haben. Wir können unseren Code wie folgt ändern:

void playChess(void)
{
	int i, j, winner;
	if (1 == whoseTurn % 2)
	{
		printf("Spieler 1 ist am Zug. Bitte geben Sie die Position ein, das Format ist Zeilennummer + Leerzeichen + Spaltennummer: ");
		scanf("%d %d", &i, &j);
		//debug
		while(chessboard[i][j]!= 0)
		{
			printf("Dieser Platz ist bereits belegt. Bitte geben Sie die Position erneut ein: ");
			scanf("%d %d",&i, &j);
		}
		//debug
		chessboard[i][j] = 1;
	}
	else
	{
		printf("Spieler 2 ist am Zug. Bitte geben Sie die Position ein, das Format ist Zeilennummer + Leerzeichen + Spaltennummer: ");
		scanf("%d %d", &i, &j);
		//debug
		while(chessboard[i][j]!= 0)
		{
			printf("Dieser Platz ist bereits belegt. Bitte geben Sie die Position erneut ein: ");
			scanf("%d %d",&i, &j);
		}
		//debug
		chessboard[i][j] = 2;
	}

	system("clear");
	printChessboard();

	if (judge(i, j))
	{
		if (1 == whoseTurn % 2)
			printf("Der Gewinner ist Spieler 1!\n");
		else
			printf("Der Gewinner ist Spieler 2!\n");
	}
}

Wir haben in der Funktion eine Schleife hinzugefügt, sodass eine Aufforderung und eine neue Eingabe erfolgt, wenn der Platz bereits belegt ist.

✨ Lösung prüfen und üben

Warum gewinne ich nie endgültig?

Wenn es eine Reihe von fünf Steinen gibt und es daraufhin meldet, dass "Spieler 1" oder "Spieler 2" gewonnen hat, und dann daraufhin "Es ist Spieler *'s Zug, bitte geben Sie die Position Ihres Steins ein..." erscheint. Ist das nicht frustrierend? Eigentlich müssen wir nur eine Zeile Code hinzufügen!

	if (judge(i, j))
	{
		if (1 == whoseTurn % 2)
		{
			printf("Gewinner ist Spieler 1!\n");
			exit(0);	//debug
		}
		else
		{
			printf("Gewinner ist Spieler 2!\n");
			exit(0);	//debug
		}
	}
}

Neben der Meldung, wer gewonnen hat, beendet man das Spiel mit exit(0).

✨ Lösung prüfen und üben

Kompilieren und Ausführen

Führen Sie den Befehl gcc aus, um zu kompilieren:

cd ~/project
gcc -o gomoku gomoku.c
./gomoku
Gomoku Game
✨ Lösung prüfen und üben

Zusammenfassung

Herzlichen Glückwunsch! Sie haben ein einfaches Vier-Gewinnt-Spiel mit der C-Programmiersprache erstellt. Spieler können abwechselnd ihre Steine auf einem 15x15 Brett platzieren, und wenn ein Spieler fünf aufeinanderfolgende Steine hat, wird das Programm ihn zum Gewinner erklären. Freuen Sie sich beim Spielen dieses textbasierten Spiels mit Ihren Freunden!