1. 程式人生 > >掃雷(第一次不能炸死及展開)

掃雷(第一次不能炸死及展開)

C語言小程式————掃雷

學習了一段時間的C語言,寫一個掃雷小遊戲練習一下!
大概思路是這樣的:1.列印地圖,2.埋雷,3,排雷,4.判斷遊戲結果。
首先列印地圖:在這裡用一個二維陣列來表示我們的地圖,在這裡我們建立兩個二維陣列,一個11 * 11用於埋雷和排雷,只有在遊戲結束後才對玩家顯示該陣列,一個9 * 9用於向玩家展示每一步操作後的結果,.為什麼要建立這樣的兩個陣列呢?這和掃雷的遊戲規則有關,遊戲規則:玩家任意點開一個方框,若不是雷 ,則在這個方框上顯示周圍8個格子類雷的個數總和。
在這裡插入圖片描述
假如玩家點開標號為1的這個方格,我們就要統計其周圍8個格子裡面的雷的個數。這必然會遇到陣列越界的問題 ,因此我們建立一個1111的陣列用於埋雷和排雷,這顯然就巧妙的解決了這個問題。然後將顯示展示在9

9的陣列上。
列印地圖的程式碼如下:首先初始化這兩個陣列,第一個用字元0初始化,第二個用*號初始化。

#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9

void init_arr(char mine[ROWS][COLS], char show[ROW][COL])
{
	memset(mine, '0', ROWS*COLS);
	memset(show, '*', ROW*COL);
}

然後,列印地圖:

void display_mine(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= y; i++)
	{
		printf("%d ", i );
		for (j = 1; j <= y; j++)
		{
			printf("%c ", mine[i][j]);
		}
		printf("\n");
	}
}


void display_show(char show[ROW][COL], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 0; i < x; i++)
	{
		printf("%d ", i + 1);
		for (j = 0; j < y; j++)
		{
			printf("%c ", show[i][j]);
		}
		printf("\n");
	}
}

第二步就是埋雷了:在這裡我們採用隨機數的方式進行埋雷,程式碼如下:

void set_mine(char mine[ROWS][COLS], int x, int y)
{
	int count = Count;
	int i = 0;
	int j = 0;
	while (count)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		//printf("(%d,%d)\n", x, y);
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}

我們總共埋10個雷,x,y的取值範圍為1–9,我們在第一個數組裡面進行埋雷,因為起初初始化為字元0,因此只要那個位置的元素是字元0,我們就能 在此埋一個雷,同時雷數減減,迴圈結束則已經成功布雷。
第三步;雷埋完之後就該玩家排雷了,排雷的要求是第一次不能被炸死,而且可以實現雷區展開。程式碼如下

void swap_mine(char mine[ROWS][COLS], char show[ROW][COL] ,int row, int col)//排雷
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int count = 0;
	int tmp = 1;
	while (count!=row*col-Count)
	{
		printf("請輸入座標;");
		scanf("%d%d", &x, &y);
		//printf("%c\n", mine[x][y]);
		if ((x<1 || x>9) | (y<1 || y>9))
		{
			printf("座標不合法");
			continue;
		}
		else if (mine[x][y] == '1')
		{
			if (tmp == 1)
			{
				avoid(mine, x, y);
				expand(mine, show, x, y);
				tmp++;
				//display_mine(mine, ROW, COL);
				ret = get_count(mine, x, y);
				show[x-1][y - 1] = ret + '0';
				system("cls");
				display_show(show, ROW, COL);
				count++;
			}
			else if (mine[x][y] == '1')
			{
				printf("踩雷了!\n");
				//system("cls");
				display_mine(mine, ROW, COL);
				return;
			}		
		}
		else if (mine[x][y] == '0')
		{
			expand(mine, show, x, y);
			tmp++;
			ret = get_count(mine, x, y);
			show[x - 1][y - 1] = ret + '0';
			//open_mine(mine, show, x-1 , y-1);
			system("cls");
			display_show(show, ROW, COL);
			count++;
		}
	}
	printf("恭喜你,你贏了\n");
	//system("cls");
	display_mine(mine, ROW, COL);
}

怎樣排雷呢?首先玩家輸入座標,判斷玩家輸入的座標是否合法,不合法提醒玩家重新輸入,座標合法後,判斷是不是第一次輸入,且判斷是不是第一次就遇到雷,如果是雷的話我們就呼叫移雷函式,將這個雷移去其他地方 ,如果不是遊戲繼續,然後呢對玩家每次輸入的座標進行判斷,如果是雷,則告訴玩家踩雷了,列印雷陣列遊戲結束,如果地圖上所剩的方格中*號的數目等於雷的數目的話則說明,排雷結束,列印雷陣列玩家勝利。
移雷函式程式碼:

void avoid(char mine[ROWS][COLS], int x, int y)//防止第一次被炸死
{
	if (mine[x][y] == '1')
	{
		mine[x][y] = '0';
		while (1)
		{
			int x1 = rand() % 9 + 1;
			int y1 = rand() % 9 + 1;
			if (mine[x1][y1] == '0' && ((x1 != x ) && (y1 != y)))
			{
				mine[x1][y1] = '1';
				break;
			}
		}
	}
}

統計雷 的數目的函式程式碼:

int get_count(char mine[ROWS][COLS],int x,int y)//獲取周圍雷的數目
{
	int ret = 0;
	ret = (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]
		+ mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1]) - 48 * 8;
	return ret;
}

遞迴實現雷區展開的函式程式碼:

void expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//雷區展開
{
	if ((x >= 1) && (y >= 1) && (x <= ROW) && (y <= COL))
	{
		if (get_count(mine, x, y) == 0)
		{
			show[x][y] =' ';
			if (show[x - 1][y - 1] == '*')
			{
				expand(mine, show, x - 1, y - 1);
			}
			if (show[x - 1][y] == '*')
			{
				expand(mine, show, x - 1, y);
			}
			if (show[x - 1][y + 1] == '*')
			{
				expand(mine, show, x - 1, y + 1);
			}
			if (show[x][y + 1] == '*')
			{
				expand(mine, show, x, y + 1);
			}
			if (show[x + 1][y + 1] == '*')
			{
				expand(mine, show, x + 1, y + 1);
			}
			if (show[x + 1][y] == '*')
			{
				expand(mine, show, x + 1, y);
			}
			if (show[x + 1][y - 1] == '*')
			{
				expand(mine, show, x + 1, y - 1);
			}
			if (show[x][y - 1] == '*')
			{
				expand(mine, show, x, y - 1);
			}

		}
	}
}

完整遊戲程式碼:
game.h

#define _CRT_SECURE_NO_WARNINGS 2
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
#define Count 10
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
void menu();
void init_arr(char mine[ROWS][COLS],char show[ROW][COL]);//陣列初始化
void display_show(char show[ROW][COL],int x,int y);//地圖列印
void display_mine(char mine[ROWS][COLS], int x, int y);//地圖列印
void set_mine(char mine[ROWS][COLS], int x, int y);//埋雷
void swap_mine(char mine[ROWS][COLS],char show[ROW][COL], int row, int col);//排雷
int get_count(char  mine[ROWS][COLS],int x,int y);//統計周圍累的數目
void avoid(char mine[ROWS][COLS], int x, int y);//防止第一次被炸死
void expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);//雷區展開

game.c

#include"game.h"
void menu()
{
	printf("******************************\n");
	printf("**********1. P L A Y**********\n");
	printf("**********0. E X I T**********\n");
	printf("******************************\n");
}
void init_arr(char mine[ROWS][COLS], char show[ROW][COL])
{
	memset(mine, '0', ROWS*COLS);
	memset(show, '*', ROW*COL);
}
void display_show(char show[ROW][COL], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 0; i < x; i++)
	{
		printf("%d ", i + 1);
		for (j = 0; j < y; j++)
		{
			printf("%c ", show[i][j]);
		}
		printf("\n");
	}
}
void display_mine(char mine[ROWS][COLS], int x, int y)
{
	int i = 0;
	int j = 0;
	printf("%d ", 0);
	for (i = 1; i <= x; i++)
	{
		printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= y; i++)
	{
		printf("%d ", i );
		for (j = 1; j <= y; j++)
		{
			printf("%c ", mine[i][j]);
		}
		printf("\n");
	}
}
void set_mine(char mine[ROWS][COLS], int x, int y)
{
	int count = Count;
	int i = 0;
	int j = 0;
	while (count)
	{
		x = rand() % 9 + 1;
		y = rand() % 9 + 1;
		//printf("(%d,%d)\n", x, y);
		if (mine[x][y] == '0')
		{
			mine[x][y] = '1';
			count--;
		}
	}
}
void swap_mine(char mine[ROWS][COLS], char show[ROW][COL] ,int row, int col)//排雷
{
	int x = 0;
	int y = 0;
	int ret = 0;
	int count = 0;
	int tmp = 1;
	while (count!=row*col-Count)
	{
		printf("請輸入座標;");
		scanf("%d%d", &x, &y);
		//printf("%c\n", mine[x][y]);
		if ((x<1 || x>9) | (y<1 || y>9))
		{
			printf("座標不合法");
			continue;
		}
		else if (mine[x][y] == '1')
		{
			if (tmp == 1)
			{
				avoid(mine, x, y);
				expand(mine, show, x, y);
				tmp++;
				//display_mine(mine, ROW, COL);
				ret = get_count(mine, x, y);
				show[x-1][y - 1] = ret + '0';
				system("cls");
				display_show(show, ROW, COL);
				count++;
			}
			else if (mine[x][y] == '1')
			{
				printf("踩雷了!\n");
				//system("cls");
				display_mine(mine, ROW, COL);
				return;
			}		
		}
		else if (mine[x][y] == '0')
		{
			expand(mine, show, x, y);
			tmp++;
			ret = get_count(mine, x, y);
			show[x - 1][y - 1] = ret + '0';
			system("cls");
			display_show(show, ROW, COL);
			count++;
		}
	}
	printf("恭喜你,你贏了\n");
	//system("cls");
	display_mine(mine, ROW, COL);
}
int get_count(char mine[ROWS][COLS],int x,int y)//獲取周圍雷的數目
{
	int ret = 0;
	ret = (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1]
		+ mine[x + 1][y] + mine[x + 1][y + 1] + mine[x][y + 1] + mine[x - 1][y + 1]) - 48 * 8;
	return ret;
}
void avoid(char mine[ROWS][COLS], int x, int y)//防止第一次被炸死
{
	if (mine[x][y] == '1')
	{
		mine[x][y] = '0';
		while (1)
		{
			int x1 = rand() % 9 + 1;
			int y1 = rand() % 9 + 1;
			if (mine[x1][y1] == '0' && ((x1 != x ) && (y1 != y)))
			{
				mine[x1][y1] = '1';
				break;
			}
		}
	}
}
void expand(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//雷區展開
{
	if ((x >= 1) && (y >= 1) && (x <= ROW) && (y <= COL))
	{
		if (get_count(mine, x, y) == 0)
		{
			show[x][y] =' ';
			if (show[x - 1][y - 1] == '*')
			{
				expand(mine, show, x - 1, y - 1);
			}
			if (show[x - 1][y] == '*')
			{
				expand(mine, show, x - 1, y);
			}
			if (show[x - 1][y + 1] == '*')
			{
				expand(mine, show, x - 1, y + 1);
			}
			if (show[x][y + 1] == '*')
			{
				expand(mine, show, x, y + 1);
			}
			if (show[x + 1][y + 1] == '*')
			{
				expand(mine, show, x + 1, y + 1);
			}
			if (show[x + 1][y] == '*')
			{
				expand(mine, show, x + 1, y);
			}
			if (show[x + 1][y - 1] == '*')
			{
				expand(mine, show, x + 1, y - 1);
			}
			if (show[x][y - 1] == '*')
			{
				expand(mine, show, x, y - 1);
			}

		}
	}
}

test.c

#define _CRT_SECURE_NO_WARNINGS 2
#include"game.h"
void game()
{
	char mine[ROWS][COLS] = { 0 };
	char show[ROW][COL] = { 0 };
	init_arr(mine, show);//***
	set_mine(mine, ROW, COL);
	//display_mine(mine, ROW, COL);
	system("cls");
	display_show(show, ROW, COL);
	swap_mine(mine,show, ROW, COL);
	
}
int main()
{
	srand((unsigned)time(NULL));
	int num = 0;
	do
	{
		menu();
		printf("請選擇:");
		scanf("%d", &num);
		switch (num)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出遊戲\n");
			break;
		default:
			printf("請重新選擇\n");
			break;
		}
	} while (num);

	system("pause");
	return 0;
}