Einführung
2048 ist ein beliebtes Zahlenrätselspiel, bei dem das Ziel darin besteht, die Kachel mit der Zahl 2048 zu erreichen, indem man benachbarte Kacheln mit der gleichen Zahl zusammenführt. In diesem Projekt lernst du, wie man ein einfaches 2048-Spiel in C erstellt. Wir geben schrittweise Anweisungen, um das Spiel zu entwickeln, von der Initialisierung des Spielfelds bis zur Implementierung der Spiel Logik und zum Ausführen des Spiels.
👀 Vorschau

🎯 Aufgaben
In diesem Projekt wirst du lernen:
- Wie man die Projekt Dateien erstellt
- Wie man Konstanten für das Spiel definiert
- Wie man die
main()-Funktion implementiert, um die Spielschleife auszuführen - Wie man das Spielfeld initialisiert
- Wie man Funktionen implementiert, um den Spielzustand zu überprüfen
- Wie man die Logik für das Bewegen der Kacheln erstellt
- Wie man das Spielfeld anzeigt
- Wie man das Spiel kompiliert und testet
🏆 Errungenschaften
Nach Abschluss dieses Projekts kannst du:
- Ein C-Programm für ein Spiel erstellen
- Arrays verwenden, um das Spielfeld darzustellen
- Spiel Logik für das Zusammenführen von Kacheln implementieren
- Das Spielfeld anzeigen
- Spieler Eingaben verarbeiten
- Überprüfen, ob das Spiel vorbei ist oder ob die Gewinnbedingung erfüllt ist
Erstellen Sie die Projekt-Dateien
Zuerst erstelle eine neue Datei mit dem Namen 2048.c und öffne sie in deinem bevorzugten Code-Editor.
cd ~/project
touch 2048.c
Definieren Sie Konstanten
Zuerst müssen wir den C-Code schreiben. Der erste Schritt besteht darin, die Header-Dateien einzubinden:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
Bevor wir die main()-Funktion schreiben, lassen Sie uns einige grundlegende Aufgaben erledigen, um einige Konstanten zu definieren:
#define SIZE 4
#define WIN_SCORE 2048
int board[SIZE][SIZE];
int score = 0;
Hauptfunktion (main Function)
int main() {
srand(time(NULL));
init_board();
print_board();
while (1) {
if (is_won()) {
printf("You won!\n");
break;
}
if (is_full() &&!can_move()) {
printf("Game over!\n");
break;
}
int direction;
printf("Enter the move direction (0-Up, 1-Down, 2-Left, 3-Right): ");
scanf("%d", &direction);
if (move(direction)) {
// Print the board after the move
print_board();
}
}
return 0;
}
init_board(): Dieser Funktionsaufruf initialisiert das Spielfeld, setzt alle Zellen des Spielfelds auf 0 und generiert dann zwei anfängliche Zufallszahlen (2 oder 4) an zufälligen Positionen.print_board(): Diese Funktion wird verwendet, um den aktuellen Zustand des Spielfelds anzuzeigen, einschließlich des aktuellen Punktestands und der Zahl in jeder Zelle.while (1): Dies ist eine Endlosschleife, die das Spiel ausführt, bis die Spiel-Endbedingung erfüllt ist.
Der Hauptablauf des 2048-Spiels wird hier implementiert, einschließlich der Initialisierung des Spielfelds, des Verschiebens der Zahlenblöcke, der Beurteilung des Spielsiegs oder -niedergangs und des Wartens auf die Spieler Eingabe zur Steuerung des Spielverlaufs.
Initialisieren Sie das Spielfeld
Um das Spielfeld zu initialisieren, erstellen wir eine Funktion init_board, die das Spielfeld einrichtet und zwei anfängliche Zufallszahlen generiert.
void init_board() {
// Initialize the board by setting all cells to 0
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
board[i][j] = 0;
}
}
// Generate two initial random numbers
for (int k = 0; k < 2; k++) {
int i = rand() % SIZE;
int j = rand() % SIZE;
int value = (rand() % 2 + 1) * 2; // Generate 2 or 4 randomly
board[i][j] = value;
}
}
Was diese Funktion tut, ist, dass zu Beginn des Spiels alle Zellen auf dem Spielfeld geleert werden und zwei anfängliche Zufallsblöcke mit Zahlen an zufälligen Positionen generiert werden, um dem Spieler einen anfänglichen Spielzustand zu bieten.
Implementieren Sie Funktionen zur Überprüfung des Spielzustands
Wir benötigen Funktionen, um zu überprüfen, ob der Spieler gewonnen hat, ob das Spielfeld voll ist und ob noch gültige Züge möglich sind. Hier sind die Funktionen:
int is_full() {
// Check if the board is full
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == 0) {
return 0; // Board is not full
}
}
}
return 1; // Board is full
}
int is_won() {
// Check if the player has won
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == WIN_SCORE) {
return 1; // Player has won
}
}
}
return 0; // Player has not won
}
int can_move() {
// Check if there are any valid moves left
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
if (board[i][j] == 0) {
return 1; // There are still empty cells to move
}
if (j > 0 && board[i][j] == board[i][j - 1]) {
return 1; // Can move left
}
if (j < SIZE - 1 && board[i][j] == board[i][j + 1]) {
return 1; // Can move right
}
if (i > 0 && board[i][j] == board[i - 1][j]) {
return 1; // Can move up
}
if (i < SIZE - 1 && board[i][j] == board[i + 1][j]) {
return 1; // Can move down
}
}
}
return 0; // No valid moves left
}
int is_full(): Diese Funktion wird verwendet, um zu überprüfen, ob das Spielfeld voll ist, d. h., ob alle Zellen belegt sind.int is_won(): Diese Funktion überprüft, ob der Spieler gewonnen hat, d. h., ob es eine Zelle mit dem Wert vonWIN_SCORE(normalerweise 2048) für den Sieg im Spiel gibt.int can_move(): Diese Funktion wird verwendet, um zu überprüfen, ob es noch gültige Züge gibt, um sicherzustellen, dass das Spiel fortgesetzt werden kann.
Erstellen Sie die Logik zum Bewegen von Kacheln
Implementieren Sie die Logik zum Verschieben von Kacheln in der move-Funktion. Diese Funktion behandelt die Züge des Spielers in vier Richtungen: nach oben, unten, links und rechts. Sie überprüft auch, ob der Zug gültig ist, aktualisiert den Punktestand und generiert eine neue Zufallszahl.
int move(int dir) {
int moved = 0;
// Store the current board state
int prev_board[SIZE][SIZE];
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
prev_board[i][j] = board[i][j];
}
}
// Move upwards
if (dir == 0) {
for (int j = 0; j < SIZE; j++) {
for (int i = 1; i < SIZE; i++) {
if (board[i][j]!= 0) {
int k = i;
while (k > 0 && board[k - 1][j] == 0) {
board[k - 1][j] = board[k][j];
board[k][j] = 0;
k--;
moved = 1;
}
if (k > 0 && board[k - 1][j] == board[k][j]) {
board[k - 1][j] *= 2;
score += board[k - 1][j];
board[k][j] = 0;
moved = 1;
}
}
}
}
}
// Move downwards
else if (dir == 1) {
for (int j = 0; j < SIZE; j++) {
for (int i = SIZE - 2; i >= 0; i--) {
if (board[i][j]!= 0) {
int k = i;
while (k < SIZE - 1 && board[k + 1][j] == 0) {
board[k + 1][j] = board[k][j];
board[k][j] = 0;
k++;
moved = 1;
}
if (k < SIZE - 1 && board[k + 1][j] == board[k][j]) {
board[k + 1][j] *= 2;
score += board[k + 1][j];
board[k][j] = 0;
moved = 1;
}
}
}
}
}
// Move left
else if (dir == 2) {
for (int i = 0; i < SIZE; i++) {
for (int j = 1; j < SIZE; j++) {
if (board[i][j]!= 0) {
int k = j;
while (k > 0 && board[i][k - 1] == 0) {
board[i][k - 1] = board[i][k];
board[i][k] = 0;
k--;
moved = 1;
}
if (k > 0 && board[i][k - 1] == board[i][k]) {
board[i][k - 1] *= 2;
score += board[i][k - 1];
board[i][k] = 0;
moved = 1;
}
}
}
}
}
// Move right
else if (dir == 3) {
for (int i = 0; i < SIZE; i++) {
for (int j = SIZE - 2; j >= 0; j--) {
if (board[i][j]!= 0) {
int k = j;
while (k < SIZE - 1 && board[i][k + 1] == 0) {
board[i][k + 1] = board[i][k];
board[i][k] = 0;
k++;
moved = 1;
}
if (k < SIZE - 1 && board[i][k + 1] == board[i][k]) {
board[i][k + 1] *= 2;
score += board[i][k + 1];
board[i][k] = 0;
moved = 1;
}
}
}
}
}
// Check if the move was successful
if (moved) {
// Generate a new random number
int i = rand() % SIZE;
int j = rand() % SIZE;
while (board[i][j]!= 0) {
i = rand() % SIZE;
j = rand() % SIZE;
}
board[i][j] = (rand() % 2 + 1) * 2; // Generate 2 or 4
// Print the board after the move
print_board();
}
// Check if the move was successful
if (moved) {
return 1;
} else {
// If the move failed, restore the previous board state
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
board[i][j] = prev_board[i][j];
}
}
return 0;
}
}
Zunächst wird eine Variable
moveddefiniert, um zu markieren, ob ein Zug erfolgt ist. Der Anfangswert ist 0, was bedeutet, dass keine Bewegung stattgefunden hat. Ein temporäres 2D-Array namensprev_boardwird erstellt, um den aktuellen Zustand des Spielfelds zu speichern, damit es bei einem fehlgeschlagenen Zug in den vorherigen Zustand zurückgesetzt werden kann.Der aktuelle Zustand des Spielfelds wird in
prev_boardkopiert, um den aktuellen Zustand des Spielfelds im Falle eines fehlgeschlagenen Zuges zu sichern.Entsprechend dem Wert des Parameters
dir(0 für oben, 1 für unten, 2 für links, 3 für rechts) wird die entsprechende Verschiebungsoperation ausgeführt.Wenn eine Verschiebung oder ein Zusammenführen erfolgt, wird die
moved-Flagge auf 1 gesetzt, was bedeutet, dass sich der Spielzustand geändert hat. Wenn die Verschiebungs- oder Zusammenführungsoperation erfolgreich ausgeführt wird, wird eine neue Zufallszahl generiert, die verwendet wird, um einen neuen Zahlenblock an einem leeren Platz auf dem Spielfeld zu generieren. Schließlich gibt die Funktion 1 zurück, wenn eine Bewegung erfolgt ist (movedist 1), was bedeutet, dass der Zug erfolgreich war. Wenn der Zug fehlschlägt (es gibt keine Verschiebungs- oder Zusammenführungsoperation), wird das Spielfeld in seinen vorherigen Zustand zurückgesetzt und 0 zurückgegeben, was bedeutet, dass der Zug fehlgeschlagen ist.
Zeige das Spielfeld an
Um das Spielfeld anzuzeigen, erstellen wir eine print_board-Funktion, die das Terminal leert und den aktuellen Zustand des Spielfelds ausgibt.
void print_board() {
// Clear the terminal
system("clear");
printf("Score: %d\n", score);
for (int i = 0; i < SIZE; i++) {
for (int j = 0; j < SIZE; j++) {
printf("%4d", board[i][j]);
}
printf("\n");
}
}
Der Hauptzweck hier ist es, den Terminalbildschirm zu leeren, dann den aktuellen Punktestand oben auf dem Bildschirm anzuzeigen und anschließend den Zustand des Spielfelds auf dem Bildschirm auszugeben, damit der Spieler die Zahlenblöcke auf dem Spielfeld und den Punktestand deutlich sehen kann. Dies hilft, eine benutzerfreundliche Schnittstelle bereitzustellen, die es den Spielern ermöglicht, den aktuellen Spielzustand zu kennen.
Kompilieren und Testen
Geben Sie den folgenden Befehl im Terminal ein, um zu kompilieren und auszuführen:
cd ~/project
gcc -o 2048 2048.c
./2048

Zusammenfassung
In diesem Projekt haben Sie gelernt, wie man ein einfaches 2048-Spiel in C erstellt. Sie haben das Spielfeld initialisiert, Funktionen zur Überprüfung des Spielzustands implementiert, die Logik zum Verschieben von Kacheln erstellt, das Spielfeld angezeigt und das Spiel gestartet. Viel Spaß beim Spielen und beim weiteren Verbessern Ihres 2048-Spiels!



