扫 雷 小 游 戏
掃雷游戲的實現的關鍵是要創建好兩個同樣大小二維數組,一個用來隨機生成雷,一個用來更新游戲界面.在創建游戲過程中應注意輸入坐標和數組下標之間的關系。為了增加游戲的樂趣,本游戲將使玩家第一步不會踩到雷,并且可以顯示周圍坐標雷的個數,還可以讓玩家是否標記出雷的位置,降低了游戲的難度.
將掃雷的代碼分為三部分:頭文件存放game.h (主要用來聲明各種函數,以便調用) ;源文件分別存放game.c(主要用來存放各種函數實現的代碼)以及test.c(主要用來實現整個游戲代碼框架)。
game.h代碼:
#ifndef __GAME_H__ #define __GAME_H__ #define ROWS 14 //宏定義行 #define COLS 14 //列 #define sweep 20 void Init_Interface(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols); //初始化掃雷棋盤 void display_board(int board2[ROWS][COLS], int rows, int cols); //打印掃雷棋盤 int play_move(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols); //玩家輸入坐標并判斷是否是雷 void pai_lei(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols); //玩家是否排雷 int win(int board2[ROWS][COLS], int rows, int cols); //判斷玩家輸贏 int error_sweep(int board2[ROWS][COLS], int rows, int cols); //判斷玩家掃雷錯誤數 int check_sweep(int board2[ROWS][COLS], int rows, int cols); //判斷雷陣是否填滿 void sweep_board(int board1[ROWS][COLS], int rows, int cols); //打印布雷棋盤 #endif //__GAME_H__game.c代碼:
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include "game.h" #include <string.h> #include <stdlib.h> #include <time.h>void Init_Interface(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols) //初始化掃雷棋盤,以及布雷其中0代表無雷,1代表有雷 {int i = 0;int j = 0;int x = 0;int y = 0;int count = 0;for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board1[i][j] = 0;}}for (i = 0; i < rows; i++){for (j = 0; j < cols; j++){board2[i][j] = '*';}}srand((unsigned int)time(NULL));while (count != sweep) //產生20個雷{int x = rand() % 10 + 2;int y = rand() % 10 + 2;if (board1[x][y] == 0){count++;board1[x][y] = 1;}}//初始化雷盤printf(" 1 2 3 4 5 6 7 8 9 10 \n");printf(" _________________________________________\n");for (i = 2; i < rows - 2; i++){if (i > 10){printf("%d | |", i - 1);}else if (i <= 10){printf("%d | |", i - 1);}for (j = 3; j < cols - 2; j++){printf(" |");}printf("\n");printf(" | %c |", board2[i][2]);for (j = 3; j < cols - 2; j++){printf(" %c |", board2[i][j]);}printf("\n");printf(" |___|");for (j = 3; j < cols - 2; j++){printf("___|");}printf("\n");}}void display_board(int board2[ROWS][COLS], int rows, int cols) //打印掃雷棋盤 {int i = 0;int j = 0;printf(" 1 2 3 4 5 6 7 8 9 10 \n");printf(" _________________________________________\n");for (i = 2; i < rows - 2; i++){if (i > 10){printf("%d | |", i - 1);}else if (i <= 10){printf("%d | |", i - 1);}for (j = 3; j < cols - 2; j++){printf(" |");}printf("\n");if ((board2[i][2] == '*') || (board2[i][2] == 'Y') || (board2[i][2] == 'N')){printf(" | %c |", board2[i][2]);}if ((board2[i][2] != '*') && (board2[i][2] != 'Y') && (board2[i][2] != 'N')){printf(" | %d |", board2[i][2]);}for (j = 3; j < cols - 2; j++){if ((board2[i][j] == '*') || (board2[i][j] == 'Y') || (board2[i][j] == 'N'))printf(" %c |", board2[i][j]);if (((board2[i][j] != '*') && (board2[i][j] != 'Y')) && (board2[i][j] != 'N'))printf(" %d |", board2[i][j]);}printf("\n");printf(" |___|");for (j = 3; j < cols - 2; j++){printf("___|");}printf("\n");} }int play_move(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols) //玩家輸入坐標 {int x = 0;int y = 0;int i = 0;int j = 0;int static first_move = 0; //定義一個靜態變量,判斷first_move是不是第一步棋子int count = 0;printf("請輸入坐標:");while (1){scanf("%d%d", &x, &y);x++;y++;if ((x >= 2) && (x <= rows - 3) && (y >= 2) && (y <= cols - 3)){first_move++;if (1 == first_move){if (board1[x][y] == 1) //第一步是雷,并轉移{for (i = 2; i < rows - 2; i++){for (j = 2; j < cols - 2; j++){if (board1[i][j] == 0){board1[i][j] = 1;board1[x][y] = 0;break;}}break;}}//統計第一步周圍雷的情況count = board1[x - 1][y] + board1[x - 1][y + 1] + board1[x - 1][y - 1]+ board1[x + 1][y] + board1[x + 1][y + 1] + board1[x + 1][y - 1]+ board1[x][y + 1] + board1[x][y - 1];board2[x][y] = count;if (board1[x][y - 1] != 1){count = 0;count = board1[x - 1][y - 1] + board1[x - 1][y] + board1[x - 1][y - 2]+ board1[x + 1][y - 1] + board1[x + 1][y] + board1[x + 1][y - 2]+ board1[x][y] + board1[x][y - 2];board2[x][y - 1] = count;}if (board1[x][y + 1] != 1){count = 0;count = board1[x - 1][y + 1] + board1[x - 1][y + 2] + board1[x - 1][y]+ board1[x + 1][y + 1] + board1[x + 1][y + 2] + board1[x + 1][y]+ board1[x][y + 2] + board1[x][y];board2[x][y + 1] = count;}if (board1[x + 1][y] != 1){count = 0;count = board1[x][y] + board1[x][y + 1] + board1[x][y - 1]+ board1[x + 2][y] + board1[x + 2][y + 1] + board1[x + 2][y - 1]+ board1[x + 1][y + 1] + board1[x + 1][y - 1];board2[x + 1][y] = count;}if (board1[x - 1][y] != 1){count = 0;count = board1[x - 2][y] + board1[x - 2][y + 1] + board1[x - 2][y - 1]+ board1[x][y] + board1[x][y + 1] + board1[x][y - 1]+ board1[x - 1][y + 1] + board1[x - 1][y - 1];board2[x - 1][y] = count;}if (board1[x + 1][y - 1] != 1){count = 0;count = board1[x][y - 1] + board1[x][y] + board1[x][y - 2]+ board1[x + 2][y - 1] + board1[x + 2][y] + board1[x + 2][y - 2]+ board1[x + 1][y] + board1[x + 1][y - 2];board2[x + 1][y - 1] = count;}if (board1[x - 1][y - 1] != 1){count = 0;count = board1[x - 2][y - 1] + board1[x - 2][y] + board1[x - 2][y - 2]+ board1[x][y - 1] + board1[x][y] + board1[x][y - 2]+ board1[x - 1][y] + board1[x - 1][y - 2];board2[x - 1][y - 1] = count;}if (board1[x - 1][y + 1] != 1){count = 0;count = board1[x - 2][y + 1] + board1[x - 2][y + 2] + board1[x - 2][y]+ board1[x][y + 1] + board1[x][y + 2] + board1[x - 2][y]+ board1[x - 1][y + 2] + board1[x - 1][y];board2[x - 1][y + 1] = count;}if (board1[x + 1][y + 1] != 1){count = 0;count = board1[x][y + 1] + board1[x][y + 2] + board1[x][y]+ board1[x + 2][y + 1] + board1[x + 2][y + 2] + board1[x + 2][y]+ board1[x + 1][y + 2] + board1[x + 1][y];board2[x + 1][y + 1] = count;}return -2;}if (board2[x][y] == '*'){board2[x][y] = 1;if (board1[x][y] == board2[x][y]){return -1; //證明踩到雷了}else{int count = 0;count = board1[x - 1][y] + board1[x - 1][y + 1] + board1[x - 1][y - 1]+ board1[x + 1][y] + board1[x + 1][y + 1] + board1[x + 1][y - 1]+ board1[x][y + 1] + board1[x][y - 1];board2[x][y] = count;return count;}}}printf("\n輸入錯誤,請重新輸入坐標:");} }void sweep_board(int board1[ROWS][COLS], int rows, int cols) //打印布好雷的圖 {int i = 0;int j = 0;printf(" 1 2 3 4 5 6 7 8 9 10 \n");printf(" _________________________________________\n");for (i = 2; i < rows - 2; i++){if (i > 10){printf("%d | |", i - 1);}else if (i <= 10){printf("%d | |", i - 1);}for (j = 3; j < cols - 2; j++){printf(" |");}printf("\n");printf(" | %d |", board1[i][2]);for (j = 3; j < cols - 2; j++){printf(" %d |", board1[i][j]);}printf("\n");printf(" |___|");for (j = 3; j < cols - 2; j++){printf("___|");}printf("\n");} }int win(int board2[ROWS][COLS], int rows, int cols) //判斷玩家是否掃雷成功 {int i = 0;int j = 0;int count = 0;for (i = 2; i <= rows - 3; i++){for (j = 2; j <= cols - 3; j++){if (board2[i][j] == 'Y')count++;}}return count; }void pai_lei(int board1[ROWS][COLS], int board2[ROWS][COLS], int rows, int cols) //玩家是否排雷 {int x = 0;int y = 0;printf("請輸入要排雷的坐標:");while (1){scanf("%d%d", &x, &y);x++;y++;if ((x >= 2) && (x <= rows - 3) && (y >= 2) && (y <= cols - 3)){if ((board1[x][y] == 1) && (board2[x][y] == '*')){board2[x][y] = 'Y';break;}else if ((board1[x][y] == 0) && (board2[x][y] == '*')){board2[x][y] = 'N';break;}}printf("\n輸入錯誤,請重新輸入坐標:");} }int error_sweep(int board2[ROWS][COLS], int rows, int cols) {int i = 0;int j = 0;int count = 0;for (i = 2; i <= rows - 3; i++){for (j = 2; j <= cols - 3; j++){if (board2[i][j] == 'N')count++;}}return count; }int check_sweep(int board2[ROWS][COLS], int rows, int cols) {int i = 0;int j = 0;for (i = 2; i <= rows - 3; i++){for (j = 2; j <= cols - 3; j++){if (board2[i][j] == '*')return 0;}}return 1; }test.c代碼:
#include <stdio.h> #include "game.h" enum {EXIT, /*枚舉元素本身由系統定義了一個表示序號的數值,從0開始順序定義為0,1,2…。EXIT的值為0,PLAY的值為1*/PLAY }; void menu() {printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n");printf("☆☆☆☆☆ 1.PLAY ☆☆☆☆☆\n");printf("☆☆☆☆☆ 0.EXIT ☆☆☆☆☆\n");printf("☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆☆\n"); } void game() {int ret = 0;int k = 0; //用來判斷玩家是否輸入雷的坐標int board1[ROWS][COLS] = { 0 }; //第一張棋盤作為埋好雷的棋盤int board2[ROWS][COLS] = { 0 }; //第二張棋盤作為統計雷的棋盤Init_Interface(board1, board2, ROWS, COLS); //初始化掃雷棋盤while (1){int ret1 = play_move(board1, board2, ROWS, COLS); //玩家輸入坐標{if (ret1 == -1){printf("\n踩雷成功,光榮犧牲.\n");sweep_board(board1, ROWS, COLS); //打印布雷棋盤break;}display_board(board2, ROWS, COLS);//排雷過程k = 0;printf("☆☆☆☆☆☆☆☆☆☆☆☆☆\n");printf("☆☆☆ 輸入0: 排雷 ☆☆☆\n");printf("☆☆☆ 輸入1: 不排雷☆☆☆\n");printf("☆☆☆☆☆☆☆☆☆☆☆☆☆\n");printf("請選擇:\n");while (k == 0){scanf("%d", &k);switch (k) //判斷是否需要排雷{case 0:pai_lei(board1, board2, ROWS, COLS);break;case 1:break;default:k = 0;printf("輸入錯誤\n");break;}if (k == 0){printf("請選擇是否繼續排雷:");}}//結束int ret2 = win(board2, ROWS, COLS);{if (ret2 == sweep) //返回的值為雷的個數則成功{printf("恭喜掃雷成功.\n");sweep_board(board1, ROWS, COLS); //打印布雷棋盤break;}else{printf("您已經成功的掃出%d顆雷\n", ret2);}}int ret3 = error_sweep(board2, ROWS, COLS); //判斷掃錯雷的個數{printf("您已經錯誤的掃出%d顆雷\n", ret3);}int ret4 = check_sweep(board2, ROWS, COLS); //檢查雷陣是否填滿if (ret4 == 1){printf("沒能成功找出所有的雷,很遺憾");break;}}display_board(board2, ROWS, COLS);}} int main() {int input = 0;do{menu();printf("請輸入你的選擇:");scanf("%d", &input); //switch (input){case PLAY:game();break;case EXIT:break;default:printf("您的輸入有誤,請重新輸入.\n");break;}} while (input);return 0; }部分游戲運行界面:
總結
- 上一篇: Google 黑板报: 哀悼与团结的曲线
- 下一篇: C语言——链表拆分,奇数组成一个链表,偶