Ausführliche Erklärung von 5 einfachen und leicht verständlichen Spielen in C-Sprache

Vorwort

Wir verwenden fünf leicht verständliche Minispiele, um unser Verständnis der C-Sprache zu stärken. Diese fünf Minispiele umfassen nicht nur Einzelspieler-Spiele, sondern auch Mensch-Maschine- und Jeder-Spieler-Spiele. Lasst uns nach dem Lernen ein spannendes Spiel spielen!

1. Vorbereitung

Wir werden 5 kleine Spiele erstellen und müssen für jedes der 5 kleinen Spiele eine Header-Datei und eine Quelldatei erstellen . Sie sind game1.h/game1.c, game2.h/game2.c, game3.h/game3.c, game4.h/game4.c, game5.h/game5.c. Der Zweck besteht darin, jedes Spiel separat zu erstellen, um Vorgänge wie die Rekonstruktion unseres Minispiels in der Zukunft zu erleichtern. Wir benötigen außerdem eine main.c, um die Header-Dateien dieser 5 kleinen Spiele einzubinden. Die Hauptfunktion ist nur für den Aufruf verantwortlich. Wir implementieren alle Codefunktionen des Minispiels in anderen Dateien und dekorieren sie mit statischer Aufladung, sodass Benutzer die Spielfunktion verwenden können, um den Code unseres Minispiels indirekt aufzurufen.

2. Spielmenü

Lassen Sie uns zuerst main.c erstellen:
1. Es muss die Header-Dateien von fünf kleinen Spielen enthalten.
2. Erstellen Sie unsere Hauptfunktion

#include"game1.h"//包含小游戏1的头文件
#include"game2.h"//包含小游戏2的头文件
#include"game3.h"//包含小游戏3的头文件
#include"game4.h"//包含小游戏4的头文件
#include"game5.h"//包含小游戏5的头文件
#include<time.h>
int main()
{
    
    
	srand((unsigned int)time(NULL));//用来生成随机数
	do
	{
    
    
		int optional = 0;//创建一个接收选择的变量
		menu();
		printf("请输入你的选项:\n");
		scanf("%d", &optional);
		switch (optional)
		{
    
    
		case 1:
			game1();
			break;
		case 2:
			game2();
			break;
		case 3:
			game3();
			break;
		case 4:
			game4();
			break;
		case 5:
			game5();
			break;
		case 0:
			printf("感谢你的游玩,欢迎下次使用。\n");
			exit(0);
		default:
			printf("你的选项输入有误,请重新输入:\n");
			break;
		}
	} while (1);
}

Wir verwenden eine Do-While-Schleife in der Hauptfunktion. Der Zweck besteht darin, dem Benutzer die Möglichkeit zu geben, eine Wahl zu treffen, und der Benutzer wird nicht beendet, bis er sich zum Beenden entscheidet oder einen Fehler macht.
Die Scanf-Funktion ist riskant. Wenn der Benutzer die eingegebenen Buchstaben durcheinander bringt, führt dies zu Pufferausnahmen. Also fügen wir die Auswahlvariable, die wir empfangen möchten, in die Schleife ein und geben ihr einen Anfangswert von 0, damit das Programm beendet wird, wenn der Benutzer einen Buchstaben eingibt.
Die Srand-Funktion wird zum Generieren von Zufallszahlen verwendet. Wenn wir nur die Rand-Funktion verwenden, bleiben die generierten Zufallszahlen unverändert, was unser wiederholtes Spielerlebnis verschlechtert.
Wir erstellen ein Menü für die Sammlung dieser Spiele, sodass Benutzer auswählen können, welches Spiel sie spielen möchten.

void menu()
{
    
    
	printf("*****************************\n");
	printf("*****1.猜数字   2.三子棋*****\n");
	printf("*****3.扫  雷   4.五子棋*****\n");
	printf("*****5.飞行棋   0.退  出*****\n");
	printf("*****************************\n");
}

Das Grundmenü ist fertig, wir betreten das Menü jedes Minispiels.
Erstellen wir zunächst die Header-Datei des Minispiels:

#pragma once
#include<stdio.h>
#include<stdlib.h>
void game1();

Die Minispiele entsprechen dem Spiel in den Headerdateien der Minispiele. Ich nehme Minispiel 1 als Beispiel, und die anderen vier Minispiele ähneln diesem.
Anschließend erstellen wir jeweils Quelldateien:

#include"game1.h"
static void menu1()
{
    
    
	printf("*****************************\n");
	printf("*****      猜数字       *****\n");
	printf("***** 1.Start the game ******\n");
	printf("***** 0.Exit the game  ******\n");
	printf("*****************************\n");
}
void game1()
{
    
    
	int optional = 0;//创建一个接收选择的变量
	do
	{
    
    
		optional = 0;
		menu1();
		printf("请输入你的选项:\n");
		scanf("%d", &optional);
		switch (optional)
		{
    
    
		case 1:
			//game();
			break;
		case 0:
			printf("猜数字小游戏以退出。\n");
			break;
		default:
			printf("你的选项输入有误,请重新输入:\n");
			break;
		}
	} while (optional);
}

Nehmen Sie immer noch Spiel1 als Beispiel. Die Optionen in anderen Minispielen sind die gleichen wie in Spiel1. Ändern Sie nur den Namen des Minispiels in der Menüfunktion. Die Spielfunktion in der Schleife wird verwendet, um in diesem kleinen Spiel die Kompositionsfunktion aufzurufen.
Lassen Sie uns es jetzt ausführen, um zu testen, ob der Code unseren Erwartungen entspricht. Der
Fügen Sie hier eine Bildbeschreibung ein
Test kann normal nach unseren Vorstellungen durchgeführt werden. Lassen Sie uns nun jedes kleine Spiel formal schreiben.

3. Spielinhalte

1. Erraten Sie die Zahl

Idee: Das System generiert zufällig eine Zufallszahl. Durch den Vergleich der von uns eingegebenen Zahl mit der generierten Zahl können wir raten, ob sie zu groß oder zu klein ist.

static void game()
{
    
    
	int num = rand() % 100 + 1;//创建一个变量,用来存放随机数。
	int guess = 0;//创建一个变量,用来存放所猜的数字。	
	//rand函数是用来生成随机数的,我们用rand函数生成的随机数对100取模并加1,可以产生1~100的随机数
	while(1)
	{
    
    
		printf("请输入你猜测的数字:");
		scanf("%d", &guess);
		if (guess == num)
		{
    
    
			printf("恭喜你,猜对了!\n");
			break;
		}
		else if (guess > num)
		{
    
    
			printf("你猜的数字过大,请重新猜测吧!\n");
		}
		else if (guess < num)
		{
    
    
			printf("你猜的数字过小,请重新猜测吧!\n");
		}
	}
	return;
}

Lassen Sie es uns einfach ausführen!
Fügen Sie hier eine Bildbeschreibung ein
Es funktioniert gut und wir können es wiederholt abspielen.

2. Backgammon

Idee: Verwenden Sie ein Array, um unsere Schachfiguren zu speichern und zu beurteilen, ob wir gewinnen.
1. Drucken Sie das Schachbrett aus
. 2. Der Spieler spielt Schach.
3. Bestimmen Sie, ob der Spieler gewinnt.
4. Der Computer spielt Schach.
5. Bestimmen Sie, ob der Computer gewinnt.
Wir definieren zunächst zwei Makros: Sie werden verwendet, um die Größe des Schachbretts zu bestimmen, die wir festlegen können.

#define ROW 3  //行
#define COL 3  //列

Wir beginnen mit dem Aufbau der Spielfunktion, um zu sehen, welche Module zur Unterstützung der Spielidee benötigt werden:

static void game()
{
    
    
	char win;//创建一个变量,存放判段获胜条件的字符。
	//我们把C代表继续,D代表平局,*代表玩家获胜,#代表电脑获胜
	char checkerboard[ROW][COL] = {
    
     0 };//创建一个数组,用来存放棋盘信息
	initialization(checkerboard,ROW,COL);//初始化数组,把数组中的每个元素初始化为空格
	ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	while(1)
	{
    
    
		Player(checkerboard, ROW, COL, '*');//玩家下棋,玩家的标志为 *
		win = Iswin(checkerboard, ROW, COL);//判断是否获胜
		if (win != 'C')
		{
    
    
			break;
		}
		ptintinitialization(checkerboard, ROW, COL);//打印棋盘
		Computer(checkerboard, ROW, COL, '#');//电脑下棋,电脑的标志为 #
		win = Iswin(checkerboard, ROW, COL);
		if (win != 'C')
		{
    
    
			break;
		}
		ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	}
	if (win == 'D')
	{
    
    
		printf("平局\n");
		ptintinitialization(checkerboard, ROW, COL);
	}
	else if (win == '*')
	{
    
    
		printf("恭喜你获得胜利\n");
		ptintinitialization(checkerboard, ROW, COL);
	}
	else
	{
    
    
		printf("很遗憾,你输掉了比赛\n");
		ptintinitialization(checkerboard, ROW, COL);
	}
}

Wir erstellen zunächst das Array, das wir verwenden, und eine Variable, die beurteilen kann, ob wir gewinnen oder verlieren. Wir initialisieren das Array und drucken es aus, um dem Spieler die Position mitzuteilen, an der er Schach spielen kann. Der Kampf zwischen Mensch und Maschine wird durch das Schach des Spielers realisiert Funktion und die Schachfunktion des Computers. .
Array-Funktion initialisieren:

static void initialization(char arr[ROW][COL],int row,int col)//初始化数组
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			arr[i][j] = ' ';//把数组中的每个元素赋值为空格
		}
	}
}

Schachbrettfunktion drucken:

static void ptintinitialization(char arr[ROW][COL], int row, int col)//打印棋盘
{
    
    
	int i = 0;
	for (i = 0; i < row; i++)
	{
    
    
		int j = 0;
		for (j = 0; j < col; j++)
		{
    
    
			if (j < col - 1)
			{
    
    
				printf(" %c |", arr[i][j]);//打印棋盘,如果为列中的最后一个元素,则不打印|
			}
			else
			{
    
    
				printf(" %c ", arr[i][j]);
			}
		}
		printf("\n");
		if(i < row-1)//打印棋盘,如果为行中的最后一个元素,则不打印---
		{
    
    
			for (j = 0; j < col; j++)
			{
    
    
				if (j < col)
				{
    
    
					printf("--- ");
				}
			}
		}
		printf("\n");
	}
}

Fügen Sie hier eine Bildbeschreibung ein
Der Druckeffekt ist in der Abbildung dargestellt.
Wenn wir das Makro ändern in:

#define ROW 9  //行
#define COL 9  //列

Fügen Sie hier eine Bildbeschreibung ein
Wir können sehen, dass sich das gedruckte Schachbrett ausdehnt. Dies ist der Vorteil von Makros, bei denen wir nicht den Wert in jeder Funktion ändern müssen. Ändern Sie einfach den vom Makro definierten Wert, um die Größe unseres Schachbretts zu ändern.

Spielerschachfunktion:

static void Player(char arr[ROW][COL], int row, int col, char ch)//玩家下棋函数
{
    
    
	int x = 0;
	int y = 0;
	while(1)
	{
    
    
		printf("请输入你要下棋的坐标:");
		scanf("%d %d", &x, &y);
		if (x<1 || x>row || y<1 || y>col)//判断坐标是否合法
		{
    
    
			printf("你输入的坐标不合法,请重新输入。\n");
		}
		else if (arr[x - 1][y - 1] != ' ')//判断输入坐标是否被占用
		{
    
    
			printf("你输入的坐标已被占用,请重新输入。\n");
		}
		else
		{
    
    
			arr[x - 1][y - 1] = ch;//数组下标从0开始,所以玩家的真实坐标要进行减1
			break;
		}
	}
}

Computerschachfunktion:

static void Computer(char arr[ROW][COL], int row, int col, char ch)
{
    
    
	while (1)
	{
    
    
		int x = rand() % 3;//产生0~2的数字
		int y = rand() % 3;
		if (arr[x][y] == ' ')//如果坐标未被占用,则电脑下棋,否则产生新的坐标进行判断
		{
    
    
			arr[x][y] = ch;//电脑的坐标的下标和数组下标对应,不需要进行减1操作
			break;
		}
	}
}

Beurteilung, ob die Funktion gewonnen werden soll:

static char Iswin(char arr[ROW][COL], int row, int col)//判断是否获胜
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)//判断每一排中是否有人获胜
	{
    
    
		if (arr[i][0] == arr[i][1] && arr[i][1] == arr[i][2] && arr[i][1] != ' ')
		{
    
    
			return arr[i][1];
		}
	}
	for (i = 0; i < col; i++)//判断每一列中是否有人获胜
	{
    
    
		if (arr[0][i] == arr[1][i] && arr[1][i] == arr[2][i] && arr[1][i] != ' ')
		{
    
    
			return arr[1][i];
		}
	}
	if ((arr[0][0] == arr[1][1] && arr[1][1] == arr[2][2] && arr[1][1] != ' ') || 
		(arr[0][2] == arr[1][1] && arr[1][1] == arr[2][0] && arr[1][1] != ' '))//判断对角线上是否有人获胜
	{
    
    
		return arr[1][1];
	}
	for (i = 0; i < row; i++)
	{
    
    
		for (j = 0; i < col; i++)
		{
    
    
			if (arr[i][j] == ' ');//判断是否还有空位
			{
    
    
				return 'C';
			}
		}
	}
	return 'D';
}

Lassen Sie es uns ausführen und das Ergebnis sehen!
Fügen Sie hier eine Bildbeschreibung ein
Hinweis:
1. Der von uns verwendete Scanf ist nicht sicher. Sie können die entsprechende Lösung finden, um zu verstehen, warum er nicht sicher ist.
2. Achten Sie bei der Initialisierung des verwendeten Arrays auf das Intervall. Achten Sie bei der Übergabe eines Array-Parameters darauf, ob die Typen des formalen Parameters und des tatsächlichen Parameters konsistent sind. Wir verwenden ein Array vom Typ char. Was passiert, wenn das formaler Parameter wird von int akzeptiert? Jeder kann hingehen und es versuchen.
3. Sie können diesen Code umgestalten und jeder kann gegen jeden spielen. Hier wird nur der Kampf zwischen Mensch und Maschine gezeigt. Lassen Sie uns ihn umgestalten und uns dem Kampf zwischen Mensch und Maschine anschließen.
Wenn der formale Parameter von int akzeptiert wird, führt dies dazu, dass das Array außerhalb der Grenzen liegt und einen Stapelfehler verursacht.

3. Minensuchboot

Idee: Verwenden Sie ein Array, um die Informationen von Minen zu speichern und durch Untersuchungen herauszufinden, wo sich keine Minen befinden.
1. Drucken Sie die Karte aus.
2. Der Spieler führt eine Minenräumung durch.
3. Bestimmen Sie, ob der Spieler auf Minen tritt.
4. Aktualisieren Sie die Karte.
Analyse:
Fügen Sie hier die Bildbeschreibung ein. Das Fügen Sie hier eine Bildbeschreibung ein
obige Bild ist eine 9*9-Minenräumkarte. Wenn wir das Rot beurteilen wollen Ort, wir müssen die Umgebung beurteilen Es wird zwangsläufig zu einem Zugang außerhalb der Grenzen führen. Wie kann dieses Problem gelöst werden?
Wir erweitern das Array um eine Zeile nach oben, unten, links und rechts, damit die Beurteilung nicht dazu führt, dass das Array den zulässigen Bereich überschreitet. Lassen Sie uns das Problem des Druckens von Arrays durch Code analysieren.
Wir richten zwei Arrays ein, eines dient zum Speichern von Karteninformationen und das andere zur Anzeige für den Spieler. Das dem Spieler angezeigte Array muss den sicheren Ort auf der Karte durch Speichern des Arrays mit Karteninformationen beurteilen.
Wir definieren zunächst fünf Makros: Bestimmen Sie jeweils die Größe der Karte, die wir festlegen können, und die Größe unserer gedruckten Karte. Das letzte Makro wird zum Speichern der Anzahl unserer Minen verwendet, was auch für spätere Tests praktisch ist.

#define ROW 9  //显示的行
#define COL 9  //显示的列
#define ROWS ROW+2  //真实数组的行
#define COLS COL+2  //真实数组的列
#define MINENUM 10  //地雷的个数

Dann fügen Sie unsere Spielfunktion hinzu, um die konkreten Ideen zu sehen:

static void game()
{
    
    
	int winnum = ROW * COL - MINENUM;//设置一个变量,用来存放还有多少个安全的地方
	char minemap[ROWS][COLS] = {
    
     0 };//雷分布的地图
	char showmap[ROWS][COLS] = {
    
     0 };//向玩家展示的地图
	Initialization(minemap, showmap, ROWS, COLS);//初始化数组,把雷分布随机分布在地图中,并且把向玩家展示的地图全部替换为 * 
	//Ptintinitialization(minemap, ROW, COL);//测试代码,用来打印地图
	while (winnum)
	{
    
    
		int x = 0;
		int y = 0;
		Ptintinitialization(showmap, ROW, COL);//打印展示地图
		printf("请输入排雷坐标:");
		scanf("%d %d", &x, &y);
		if (x<1 || x>ROW || y<1 || y>COL)//判断坐标是否合法
		{
    
    
			printf("你输入的坐标不合法,请重新输入。\n");
		}
		else if (showmap[x][y] != '*')//判断坐标是否已被排查过
		{
    
    
			printf("你输入的坐标已被排过雷了,请重新输入。\n");
		}
		else 
		{
    
    
			if (!Determine(minemap, x, y))//!Determine(minemap, x, y)用来判断是否踩到雷
			{
    
    
				Ptintinitialization(minemap, ROW, COL);//打印地雷地图,让玩家知道地雷在哪里。
				break;
			}
			Renewmap(minemap, showmap, x, y);//用来更新向玩家展示的地图
			winnum--;//对安全的地方进行减1
		}
	}
	if(winnum == 0)//当安全地方为0时,证明排雷成功
	{
    
    
		printf("恭喜你排雷成功!\n");
		Ptintinitialization(showmap, ROW, COL);//打印展示地图,让玩家知道自己获胜地图
	}
}

Array-Funktion initialisieren:

static void Initialization(char minemap[ROWS][COLS], char showmap[ROWS][COLS], int rows, int cols)
{
    
    
	int count = MINENUM;//创建一个变量,用来计算放置的雷的数量
	int i = 0;
	int j = 0;
	for (i = 0; i < rows; i++)//把地雷地图全部赋值为字符0
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			minemap[i][j] = '0';
		}
	}
	while (count)//把雷分布随机分布在地雷地图中
	//我们把0代表安全,1代表雷区
	{
    
    
		int x = rand() % ROW + 1;//创建随机变量范围在1~9
		int y = rand() % COL + 1;//创建随机变量范围在1~9
		if (minemap[x][y] == '0')//判断该位置是否已有雷
		{
    
    
			minemap[x][y] = '1';//放置地雷
			count--;
		}
	}
	for (i = 0; i < rows; i++)//把展示地图全部赋值为字符*
	{
    
    
		for (j = 0; j < cols; j++)
		{
    
    
			showmap[i][j] = '*';
		}
	}
}

Fügen Sie hier eine Bildbeschreibung ein
Die von uns angezeigte Kartenzeile ist 1 ~ ROW und die Spalte ist 1 ~ COL, sodass die Koordinaten der generierten Minen innerhalb dieses Bereichs gesteuert werden.
Kartenfunktion drucken:

static void Ptintinitialization(char showmap[ROWS][COLS], int row, int col)//打印地图
{
    
    
	int i = 1;
	int j = 1;
	for (i = 1; i <= row; i++)
	{
    
    
		if (i == 1)//当i为1时,需要多一个空格,目的为了和地图对齐
		{
    
    
			printf(" ");
		}
		printf(" %d", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++)//打印我们所需要的地图
	{
    
    
		printf("%d", i);
		for (j = 1; j <= col; j++)
		{
    
    
			printf(" %c", showmap[i][j]);
		}
		printf("\n");
	}
}

Wir beginnen mit dem Drucken bei 1, drucken bis ROW und drucken nur dort, wo wir es brauchen.
Um zu beurteilen, ob ich auf meine treten soll:

static bool Determine(char minemap[ROWS][COLS],int x,int y)
{
    
    
	if (minemap[x][y] == '1')
	{
    
    
		printf("排雷失败,你已死亡!\n");
		return false;
	}
	else
	{
    
    
		return true;
	}
}

Aktualisieren Sie die angezeigte Karte:

static void Renewmap(char minemap[ROWS][COLS], char showmap[ROWS][COLS], int x, int y)
{
    
    
	showmap[x][y] = (minemap[x - 1][y - 1] + minemap[x - 1][y] + minemap[x - 1][y + 1]
				  + minemap[x][y - 1] + minemap[x][y + 1]
				  + minemap[x + 1][y - 1] + minemap[x + 1][y] + minemap[x + 1][y + 1]) - 8*'0' + '0';
}

Fügen Sie hier eine Bildbeschreibung ein
Aktualisieren Sie die dem Spieler angezeigte Karte, um die Anzahl der umliegenden Minen zu addieren und sie durch die entsprechende Zahl zu ersetzen. Wir verwenden ein Zeichenarray, das Zeichen 1 und Zeichen 0 speichert. Daher müssen wir den ASCLL-Codewert 0 subtrahieren, um eine Ganzzahl zu erhalten, diese addieren, um die Anzahl der Minen an 8 Stellen um dieses Quadrat darzustellen, und schließlich addieren Der ASCLL-Codewert 0 erhält die entsprechende Zeichennummer.
Testen wir es: Wir kommentieren den Testcode aus und setzen die durch unser Makro definierte Anzahl von Minen auf einen größeren Wert. Ich habe sie zuerst auf 79 eingestellt. Sie können sie je nach Schwierigkeitsgrad, den Sie spielen möchten, ändern, wenn Sie tatsächlich spielen. Nehmen wir es Ein Blick auf die Minenräumung.
Fügen Sie hier eine Bildbeschreibung ein
Ob der Fehler normal angezeigt wird:
Fügen Sie hier eine Bildbeschreibung ein
Der Fehler bei der Minenräumung wird ebenfalls normal angezeigt.
Hinweis:
1. scanf ist nicht sicher.
2. Achten Sie beim Initialisieren des verwendeten Arrays auf das Intervall und achten Sie beim Zugriff auf das Array darauf, ob es außerhalb der Grenzen liegt.
3. Rekonstruktionsideen: Sie können eine erweiterte Karte hinzufügen (Sie können sie erweitern, wenn in den umliegenden 8 Orten keine Minen vorhanden sind, bis Sie wissen, dass sich um ein Gitter herum eine Mine befindet), eine kleine Flagge hinzufügen (den Ort ersetzen). Wird als Mine mit einer kleinen Flagge betrachtet und kann nur die kleine Flagge löschen, um sie zu ändern. Minesweeper kann nur an der Position ausgeführt werden. Zeit hinzufügen (wenn die Zeit abgelaufen ist und nicht alle Minen geräumt sind, endet das Spiel). , usw.

4. Backgammon

Ideen: Bestimmen Sie, welcher Spieler fünf aufeinanderfolgende Schachfiguren gespielt hat (eine Reihe oder eine Spalte oder eine diagonale Linie mit 5 aufeinanderfolgenden Figuren derselben Schachfiguren). 1. Drucken Sie das
Brett aus.
2. Spieler 1 spielt Schach
. 3. Bestimmen Sie, ob Spieler 1 gewinnt.
4 . Spieler 2 geht weiter. Spielen Sie Schach
5. Bestimmen Sie, ob Spieler 2 gewinnt
oder nicht. Wir verwenden immer noch Makros, um zuerst die Größe des Bretts zu definieren:

#define ROW 9  //棋盘的行
#define COL 9  //棋盘的列

Schauen Sie sich die Spielidee noch einmal an:

static void game()
{
    
    
	char win;//创建一个变量,存放判段获胜条件的字符。
	//我们把C代表继续,D代表平局,白棋(@)代表玩家1获胜,黑棋(O)代表玩家2获胜
	char checkerboard[ROW][COL] = {
    
     0 };//棋盘数组
	Initialization(checkerboard, ROW, COL);//初始化数组,把棋盘的所有位置都赋值为 *
	Ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	while (1)
	{
    
    
		Player(checkerboard, ROW, COL, '@');//玩家1下棋,玩家1的标志为 @
		win = Iswin(checkerboard, ROW, COL);//判断是否获胜
		if (win != 'C')
		{
    
    
			break;
		}
		Ptintinitialization(checkerboard, ROW, COL);//打印棋盘
		Player(checkerboard, ROW, COL, 'O');//玩家2下棋,玩家2的标志为 O
		win = Iswin(checkerboard, ROW, COL);//判断是否获胜
		if (win != 'C')
		{
    
    
			break;
		}
		Ptintinitialization(checkerboard, ROW, COL);//打印棋盘
	}
	if (win == 'D')
	{
    
    
		printf("平局\n");
		Ptintinitialization(checkerboard, ROW, COL);
	}
	else if (win == '@')
	{
    
    
		printf("玩家1获胜\n");
		Ptintinitialization(checkerboard, ROW, COL);
	}
	else
	{
    
    
		printf("玩家2获胜\n");
		Ptintinitialization(checkerboard, ROW, COL);
	}
}

Die Idee von Backgammon ist genau die gleiche wie die von Backgammon, außer dass der Computer durch einen anderen Spieler ersetzt wird. Der Spielfunktionscode hat sich also im Grunde nicht wesentlich geändert. Die Spieler denken beim Schachspielen gleich, daher benötigen wir nur eine Funktion, um die Denkweise zweier Spieler beim Schachspielen zu lösen.
Array-Funktion initialisieren:

static void Initialization(char arr[ROW][COL], int row, int col)//初始化数组,把棋盘的所有位置都赋值为 *
{
    
    
	int i = 0;
	int j = 0;
	for (i = 0; i < row; i++)//把展示地图全部赋值为字符*
	{
    
    
		for (j = 0; j < col; j++)
		{
    
    
			arr[i][j] = '*';
		}
	}
}

Die Idee, das Array zu initialisieren, ist genau die gleiche wie die Karte, die dem Spieler in Minesweeper angezeigt wird.
Kartenfunktion drucken:

static void Ptintinitialization(char arr[ROW][COL], int row, int col)//打印棋盘
{
    
    
	int i = 0;
	int j = 0;
	for (i = 1; i <= row; i++)
	{
    
    
		if (i == 1)//当i为1时,需要多两个空格,目的为了和地图对齐
		{
    
    
			printf("  ");
		}
		if (i < 9)//当i小于9时,需要多一个个空格,目的为了和地图对齐
		{
    
    
			printf(" %d ", i);
		}
		else//当i大于于9时,不需要多一个个空格
		{
    
    
			printf(" %d", i);
		}
	}
	printf("\n");
	for (i = 0; i < row; i++)//打印我们所需要的地图
	{
    
    
		printf("%2d", i + 1);
		for (j = 0; j < col; j++)
		{
    
    
			printf(" %c ", arr[i][j]);//需要多一个个空格,目的为了和地图对齐
		}
		printf("\n");
	}
}

Die Backgammon-Karte kann nach Belieben vergrößert und verkleinert werden, und Sie müssen darauf achten, ob die Karte mit den Zeilen und Spalten darüber ausgerichtet ist.
Spielerschachfunktion:

int x = 0;//用来接收玩家下棋的坐标
int y = 0;//用来接收玩家下棋的坐标
static void  Player(char arr[ROW][COL], int row, int col, char ch)//玩家下棋函数,通过ch来判断是玩家1还是玩家2
{
    
    
	int player = 0;//创建一个变量来确定是玩家几
	if (ch == '@')//如果ch为白棋(@),则代表玩家1
	{
    
    
		player = 1;
	}
	else//反之则为玩家2
	{
    
    
		player = 2;
	}
	while (1)
	{
    
    
		printf("请玩家 %d 输入要下棋的坐标:",player);
		scanf("%d %d", &x, &y);
		if (x<1 || x>row || y<1 || y>col)//判断坐标是否合法
		{
    
    
			printf("你输入的坐标不合法,请重新输入。\n");
		}
		else if (arr[x - 1][y - 1] != '*')//判断输入坐标是否被占用
		{
    
    
			printf("你输入的坐标已被占用,请重新输入。\n");
		}
		else
		{
    
    
			arr[x - 1][y - 1] = ch;//数组下标从0开始,所以玩家的真实坐标要进行减1
			break;
		}
	}
}

Wir legen die Koordinaten des Schachspiels des Spielers als globale Variable fest, damit wir beurteilen können, ob es bei fünf Söhnen hintereinander der Fall ist.
Beurteilung, ob die Funktion gewonnen werden soll:
Fügen Sie hier eine Bildbeschreibung ein

enum Direction
{
    
    
	LEFT,
	RIGHT,
	UP,
	DOWN,
	LEFTUP,
	RIGHTDOWN,
	RIGHTUP,
	LEFTDOWN
};
static char Iswin(char arr[ROW][COL], int row, int col)//判断是否获胜
{
    
    
	static chessnum = 0;//创建一个静态变量,用来存放棋盘中使用的格数
	chessnum++;//每进行一次判断调用就对棋盘使用格数进行+1
	int winnum1 = 1 + Wincount(arr, ROW, COL, LEFT) + Wincount(arr, ROW, COL, RIGHT);
	//确定左和右共计多少相同个棋子,需要加上自身的棋子
	int winnum2 = 1 + Wincount(arr, ROW, COL, UP) + Wincount(arr, ROW, COL, DOWN);
	//确定上和下共计多少相同个棋子,需要加上自身的棋子
	int winnum3 = 1 + Wincount(arr, ROW, COL, LEFTUP) + Wincount(arr, ROW, COL, RIGHTDOWN);
	//确定左上和右下共计多少相同个棋子,需要加上自身的棋子
	int winnum4 = 1 + Wincount(arr, ROW, COL, RIGHTUP) + Wincount(arr, ROW, COL, LEFTDOWN);
	//确定右上和左下共计多少相同个棋子,需要加上自身的棋子
	if (winnum1 >= 5 || winnum2 >= 5 || winnum3 >= 5 || winnum4 >= 5)//判断是否获胜
	{
    
    
		return arr[x - 1][y - 1];//返回获胜棋子的字符
	}
	else
	{
    
    
		if (chessnum == ROW * COL)//如果棋盘使用格数等于棋盘的格数,证明平局
		{
    
    
			return 'D';
		}
		else//如果棋盘使用格数不等于棋盘的格数,证明还有空位,继续进行比赛
		{
    
    
			return 'C';
		}
	}
}

Wir müssen in diesen 8 Richtungen die gleiche Anzahl an Schachfiguren zählen. Es wird keine 5 aufeinanderfolgende *-Situationen geben und die Adresse, die wir speichern, ist immer die Adresse des letzten Spielers. Mit dem Menütyp stellen wir die 8 Richtungen dar.

static int Wincount(char arr[ROW][COL], int row, int col, enum Direction dir)
{
    
    
	int count = 0;//记录相同棋子个数
	int _x = x - 1;//要对坐标进行减1,因为我们的棋盘从1开始,数组下标从0开始
	int _y = y - 1;//要对坐标进行减1,因为我们的棋盘从1开始,数组下标从0开始
	//用局部变量保存,避免在这里修改全局变量的值
	while (1)
	{
    
    
		switch (dir)
		{
    
    
		case LEFT:
			_y--;//对中心坐标的列坐标进行减1
			break;
		case RIGHT:
			_y++;//对中心坐标的列坐标进行加1
			break;
		case UP:
			_x++;
			break;
		case DOWN:
			_x--;
			break;
		case LEFTUP:
			_y--;
			_x++;
			break;
		case RIGHTDOWN:
			_y++;
			_x--;
			break;
		case RIGHTUP:
			_y++;
			_x++;
			break;
		case LEFTDOWN:
			_y--;
			_x--;
			break;
		default:
			break;
		}
		if (_x < 0 || _x > ROW || _y < 0 || _y>COL)//判断位置是否合法
		{
    
    
			return count;
		}
		else if(arr[_x][_y] != arr[x-1][y-1])//判断是否和上一个玩家的棋子相同
		{
    
    
			return count;
		}
		else
		{
    
    
			count++;
		}
	}
}

Wir legen es als Endlosschleife fest, um die spezifische Anzahl von Schachfiguren in derselben Richtung zu bestimmen. Der Menütyp unterscheidet sich von den Parametern, die wir übergeben, daher nehmen wir im Switch-Zweig unterschiedliche Routen.
Hinweis:
Array außerhalb der Grenzen. Rekonstruktion von Ideen
zur Beurteilung von Wuzilianzhu : Sie können dem Netzwerk beitreten, Online-Kämpfe durchführen, Sie können die Funktion zum Bedauern von Schach usw. hinzufügen.

5. Ludo

So wird gespielt: 1. Abgesehen davon, dass die Startposition dieselbe ist, kommt es in den restlichen Fällen, in denen die Position eines Spielers mit der Position eines anderen Spielers übereinstimmt, zu einem Ansturm.
2. Wenn der Spieler auf die Requisiten tritt, führen Sie die entsprechende Requisitenoperation aus.
3. Der Spieler, der zuerst das Ende erreicht, ist die Gewinneridee
:
1. Verwenden Sie ein Array zum Speichern von Karteninformationen
. 2. Verwenden Sie eine Struktur zum Erstellen von Spielerinformationen
. 3. Verwenden Sie eine Struktur Arrays zum Speichern von Spielerinformationen
4. Verwenden Sie Zufallsfunktionen, um Siebvorgänge zu simulieren.
Konstruieren wir zunächst die Spielidee:

int map[100];//创建一个地图大小为100的地图。并且把地图元素全部初始化为0
//为了对数组进行方便的操作,我们把数组设置为全局变量,使每个函数可以直接访问数组
static void game()
{
    
    
	struct Player play[2];//创建一个玩家数组,里面存放玩家信息
	Initializationmap();//初始化地图数组,把地图相应位置填上道具元素,
	//我们把地图数组设置为了全局函数,所以不要需要传参
	Initializationplay(play);//初始化玩家数组,加入玩家信息,并把玩家位置置于地图开始位置
	Ptintinitialization(play);//打印棋盘,地图数组为全局函数,所以不要对地图传参。
	//需要玩家信息来判断地图要填的字符,所以要对玩家进行传参
	while (1)//使玩家交替进行游玩,直到产生胜利者
	{
    
    
		if (play[0].flags == false)//判断玩家1是否处于暂停回合。
		{
    
    
			Play(&play[0], &play[1],play);//玩家1进行游戏
			Ptintinitialization(play);//打印棋盘
		}
		else//处于暂停回合,把暂停回合改为继续
		{
    
    
			play[0].flags = false;
		}
		if (play[0].position >= 99)//判断玩家1是否获胜
		{
    
    
			printf("%s侥幸赢了%s\n", play[0].name, play[1].name);
			break;
		}
		if (play[1].flags == false)//判断玩家2是否处于暂停回合。
		{
    
    
			Play(&play[1], &play[0],play);//玩家2进行游戏
			Ptintinitialization(play);//打印棋盘
		}
		else
		{
    
    
			play[1].flags = false;//更改暂停选项
		}
		if (play[1].position >= 99)//判断玩家2是否获胜
		{
    
    
			printf("%s侥幸赢了%s\n", play[1].name, play[0].name);
			break;
		}
	}
}

Der Einfachheit halber legen wir das Kartenarray als globales Array fest, wodurch die Parameterübergabe reduziert wird. Und das Array muss nach der Initialisierung nicht geändert werden. Wir haben auch ein Strukturarray eingerichtet, um Spielerinformationen zu speichern (Position, ob er sich in einer Pausenposition befindet).
Initialisieren Sie die Kartenfunktion:

static void Initializationmap()//初始化地图数组
//地图数组中
//0代表什么都没有
//1代表道具1(幸运轮盘),2代表道具2(地雷),3代表道具3(暂停),4代表道具4(时空隧道)
{
    
    
	int luckyturn[] = {
    
    1, 20, 45, 60, 75, 90};//在相应的位置放入 幸运轮盘
	for (int i = 0; i < sizeof(luckyturn) / sizeof(luckyturn[0]); i++)
	//sizeof(luckyturn) / sizeof(luckyturn[0])用来求出数组元素的个数
	{
    
    
		map[luckyturn[i]] = 1;
	}
	int Landmine[] = {
    
     3, 6, 19, 25, 36, 49, 69, 70, 80 };//在相应的位置放入 地雷
	for (int i = 0; i < sizeof(Landmine) / sizeof(Landmine[0]); i++)
	{
    
    
		map[Landmine[i]] = 2;
	}
	int puse[] = {
    
     2, 11, 26, 35, 44, 59, 71, 88 };//在相应的位置放入 暂停
	for (int i = 0; i < sizeof(puse) / sizeof(puse[0]); i++)
	{
    
    
		map[puse[i]] = 3;
	}
	int timetunnel[] = {
    
     5, 15, 30, 50, 77 };//在相应的位置放入 时空隧道
	for (int i = 0; i < sizeof(timetunnel) / sizeof(timetunnel[0]); i++)
	{
    
    
		map[timetunnel[i]] = 4;
	}
}

Der anfängliche Kartenvorgang ermöglicht es uns, die entsprechenden Requisiten an der gewünschten Position zu platzieren, und die Position der Requisiten kann entsprechend unseren Vorlieben geändert werden.
Player-Funktion initialisieren:

static void Initializationplay(struct Player *play)
{
    
    
	printf("请输入玩家A的姓名\n");
	scanf("%s", &(play[0].name));
	while (!strcmp(play[0].name,""))//判断玩家A的姓名是否为空
	{
    
    
		printf("玩家姓名不能为空,请重新输入玩家A的姓名\n");
		scanf("%s", &(play[0].name));
	}
	printf("请输入玩家B的姓名\n");
	scanf("%s", &(play[1].name));
	while (1)
	{
    
    
		if (!strcmp(play[1].name, ""))//判断玩家B的姓名是否为空
		{
    
    
			printf("玩家姓名不能为空,请重新输入玩家B的姓名\n");
			scanf("%s", &(play[1].name));
		}
		else if(!strcmp(play[1].name, play[0].name))//判断玩家B的姓名和玩家A是否相同
		{
    
    
			printf("玩家姓名不能一致,请重新输入玩家B的姓名\n");
			scanf("%s", &(play[1].name));
		}
		else
		{
    
    
			break;
		}
	}
	play[0].position = 0;//把玩家A的位置置于0位置(地图开始位置)
	play[0].flags = false;//把玩家A的暂停条件置为假。
	play[1].position = 0;//把玩家B的位置置于0位置(地图开始位置)
	play[1].flags = false;//把玩家B的暂停条件置为假。
}

In dieser Funktion haben wir einen String-Vergleich durchgeführt. Sie können == nicht direkt für den String-Vergleich verwenden. Sie müssen die Funktion strcmp verwenden,
um die Kartenfunktion anzuzeigen:

extern char Drawstrmap(const struct Player* play, int i);//对Drawstrmap函数进行声明
static void Ptintinitialization(const struct Player* play) //打印棋盘
//由于不会对玩家信息进行更改,我们把参数设置为const,防止在函数中误改
{
    
    
		printf("图例:幸运轮盘:#    地雷:@    暂停:I     时空隧道:>     \n");//向玩家展示道具信息
		//第一段
		for (int i = 0; i < 30; i++)
		{
    
    
			printf("%c ", Drawstrmap(play, i));
		}
		printf("\n");
		//第一竖列
		for (int i = 30; i < 35; i++)
		{
    
    
			for (int j = 0; j <= 28; j++)
			{
    
    
				printf("  ");
			}
			printf("%c ", Drawstrmap(play, i));
			printf("\n");
		}
		//第二段
		for (int i = 64; i >= 35; i--)//地图为从前向后打打印
		{
    
    
			printf("%c ", Drawstrmap(play, i));
		}
		printf("\n");
		//第二数列
		for (int i = 65; i <= 69; i++)
		{
    
    
			printf("%c ", Drawstrmap(play, i));
			printf("\n");
		}
	    //第三行竖列
		for (int i = 70; i <= 99; i++)
		{
    
    
			printf("%c ", Drawstrmap(play, i));
		}
		printf("\n");//画完地图换行
}

static char Drawstrmap(const struct Player* play, int i)//打印地图元素
{
    
    
	char ch;
	if (play[0].position == play[1].position && play[0].position == i)
	//当玩家1和玩家2的位置处于起始位置时
	{
    
    
		ch = 'M';
	}
	else if (play[0].position == i)//当玩家1位于当前位置时
	{
    
    
		ch = 'A';
	}
	else if (play[1].position == i)//当玩家2位于当前位置时
	{
    
    
		ch = 'B';
	}
	else
	{
    
    
		switch (map[i])
		{
    
    
		case 0://地图数组元素为0时
			ch = 'O';
			break;
		case 1:
			ch = '#';
			break;
		case 2:
			ch = '@';
			break;
		case 3:
			ch = 'I';
			break;
		case 4:
			ch = '>';
			break;
		}
	}
	return ch;
}

Fügen Sie hier eine Bildbeschreibung ein
Hier erstellen wir eine Drawstrmap-Funktion. Der Zweck besteht darin, die ganzzahligen Elemente im Kartenarray in die von uns benötigten Zeichenelemente umzuwandeln. Wir übergeben den Speicherort der Karte, um zu bestimmen, welche Zeichen gedruckt werden sollen, und ändern unser Kartenarray nicht.
Spielfunktion:

static void Play(struct Player *play1, struct Player* play2, struct Player* play)
//play1为当前玩家,play2为另一名玩家,play为玩家数组,传玩家数组方便进行位置判断
{
    
    
	int points = rand() % 6 + 1;//设置随机变量,范围为1~6
	printf("%s请按任意键开始致筛子\n", play1->name);
	system("pause");//暂停屏幕
	printf("%s筛到了%d,前进%d格,", play1->name, points, points);
	system("pause");
	play1->position += points;//对玩家位置进行更新
	Weizhi(play);//判断玩家位置是否在合法的范围内
	if (play1->position == play2->position)//现在玩家的位置和另一名玩家位置相同时
	{
    
    
		printf("%s踩到了%s,%s退6格,", play1->name, play2->name, play2->name);
		system("pause");
		play2->position -= 6;//对另一名玩家位置进行更新
		Weizhi(play);//判断玩家位置是否在合法的范围内
		printf("%s已退6格,", play2->name);
		system("pause");
	}
	else
	{
    
    
		switch (map[play1->position])//检查本位玩家是否进行到道具位置
		{
    
    
		case 0:
			printf("%s踩到了方块,安全,", play1->name);
			system("pause");
			break;
		case 1:
		{
    
    
			printf("%s踩到了幸运转盘,1————交换位置,2————轰炸对方,请选择按键\n", play1->name);
			int a = 0;//用来接收用户的选择
			scanf("%d", &a);
			while (1)
			{
    
    
				if (a == 1)
				{
    
    
					printf("%s选择了交换位置,", play1->name);
					system("pause");
					int b = play1->position;
					play1->position = play2->position;
					play2->position = b;
					Weizhi(play);//判断玩家位置是否在合法的范围内
					printf("交换完成,");
					system("pause");
					break;
				}
				else if (a == 2)
				{
    
    
					printf("%s选择了轰炸对方,%s向后退6格,", play1->name, play2->name);
					system("pause");
					play2->position -= 6;
					Weizhi(play);
					printf("执行成功,\n");
					system("pause");
					break;
				}
				else
				{
    
    
					printf("输入不正确,请重新输入");
					int ch;
					while ((ch = fgetc(stdin)) != EOF && ch != '\n');
					//清除缓冲区,防止缓冲区问题使程序不能正常进行
					scanf("%d", &a);
				}
			}
		}
			break;
		case 2:
			printf("%s踩到了地雷,退6格,", play1->name);
			system("pause");
			play1->position -= 6;
			Weizhi(play);
			break;
		case 3:
			printf("%s踩到了暂停,下一回合禁止行动", play1->name);
			system("pause");
			play1->flags = true;
			break;
		case 4:
			printf("%s踩到了时空隧道,前进十格", play1->name);
			system("pause");
			play1->position += 10;
			Weizhi(play);
			break;
		}
	}
	Weizhi(play);
	system("cls");//清除屏幕
}

Wir simulieren das Sieb und nutzen Requisiten in der Spielfunktion. Wir setzen den Clear-Puffer, um das Pufferproblem der Scanf-Funktion zu lösen und eine Endlosschleife zu vermeiden.
Hinweis:
Array außerhalb der Grenzen. Wir möchten sicherstellen, dass die Position jedes Spielers innerhalb der Karte liegt.
Ideen für die Rekonstruktion von String-Vergleichen
: 1. Es kann dem Netzwerk beitreten, um Online-Schlachten zu realisieren. 2. Das Glücks-Roulette separat in eine Funktion kapseln. 3. Fügen Sie weitere Requisiten hinzu. 4. Treten Sie anderen Spielern bei. Es können 5 Punkte hinzugefügt und Punkte gegen Requisiten eingetauscht werden.

Zusammenfassen

Unsere fünf Minispiele sind alle fertig. Bei der Erstellung kleiner Spiele sind die folgenden Punkte zu beachten:
Die Funktion scanf ist nicht sicher. Wir können eine sichere Funktion finden, um sie zu ersetzen oder das Sicherheitsproblem von scanf zu lösen. Geben Sie sowohl
Arrays als auch ganzzahlige Arrays ein, achten Sie auf Arrays außerhalb der Grenzen liegen und auf Array-Parameter achten.
Konstruieren Sie häufig verwendete Codes als Funktionen, um die Coderedundanz zu reduzieren.

Ich denke du magst

Origin blog.csdn.net/2301_76986069/article/details/130986103
Empfohlen
Rangfolge