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