目录
扫雷小游戏
《扫雷》是一款大众类的益智小游戏,于1992年发行。游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
总纲
第一部分:程序源码
game.h
#define _CRT_SECURE_NO_WARNINGS 1 //progrom once #ifndef __GAME_H__ #define __GAME_H__ #include<stdio.h> #include<stdlib.h> #include<time.h> #include<string.h> #define ROW 9 #define COL 9 #define ROWS ROW+2 #define COLS COL+2 #define MINE_FUM 10 //雷的个数 //初始化棋盘 void InitBoard(char mineboard[ROWS][COLS], int rows, int cols, char ch); //展示棋盘 void ShowBoard(char findboard[ROWS][COLS]); //布雷 void SetMine(char mineboard[ROWS][COLS], int rows, int cols, int count); //计算周围雷的个数 void ShowRoundMine(char findboard[ROWS][COLS], char mineboard[ROWS][COLS] , int x,int y); //判断输赢 int IsWin(char findboard[ROWS][COLS], char mineboard[ROWS][COLS], int x, int y); //展开雷阵 void OpenMine(char findboard[ROWS][COLS], char mineboard[ROWS][COLS] , char textboard[ROWS][COLS], int x,int y); //排雷 void FindMine(char mineboard[ROWS][COLS], char findboard[ROWS][COLS] , char textboard[ROWS][COLS], int x,int y); #endif //__GAME_H__
test.c
#include"game.h" void menu() { printf("*****************************\n"); printf("****** 扫雷小游戏 *******\n"); printf("*****************************\n"); printf("****** 1.play *******\n"); printf("****** 2.exit *******\n"); printf("*****************************\n"); } void game() { volatile int x = 0; volatile int y = 0; int count = MINE_FUM; char mineboard[ROWS][COLS] = {0};//布雷的雷盘 char findboard[ROWS][COLS] = {0};//排雷的雷盘 char textboard[ROWS][COLS] = {0};//测试的雷盘 InitBoard(textboard, ROWS, COLS, '0'); InitBoard(mineboard, ROWS, COLS, '0'); InitBoard(findboard, ROWS, COLS, '*'); SetMine(mineboard, ROWS, COLS, count); FindMine(mineboard, findboard, textboard, x, y); } int main() { int input = 0; do { menu(); printf("请选择:"); scanf("%d",&input); switch(input) { case 1: game(); break; case 0: printf("退出游戏!\n"); break; default: printf("输入错误,请重新选择!\n"); break; } }while(input); return 0; }
game.c
#include"game.h" //初始化棋盘 void InitBoard(char board[ROWS][COLS], int rows, int cols, char ch) { memset(&board[0][0], ch, rows*cols*sizeof(board[0][0])); } //展示棋盘 void ShowBoard(char findboard[ROWS][COLS]) { int i = 0; int j = 0; for(j=0; j<=COL; j++) { printf(" %d |",j); if(9 == j) { printf("\n"); printf("---|---|---|---|---|---|---|---|---|---|\n"); } } for(i = 0; i<ROW; i++) { int a = i+1; printf(" %d ",a); printf("| %c | %c | %c | %c | %c | %c | %c | %c | %c |\n", findboard[i+1][1],findboard[i+1][2],findboard[i+1][3], findboard[i+1][4],findboard[i+1][5],findboard[i+1][6], findboard[i+1][7],findboard[i+1][8],findboard[i+1][9]); if(8 != i) { printf("---|---|---|---|---|---|---|---|---|---|\n"); } } printf("\n"); } //布雷 void SetMine(char mineboard[ROWS][COLS], int rows, int cols, int count) { int i = 0; int j = 0; srand((unsigned int)time(NULL)); while(count != 0) { i = rand()%9 + 1; j = rand()%9 + 1; if('0' == mineboard[i][j]) { mineboard[i][j] = '1'; count--; } } } //计算周围雷的个数 void ShowRoundMine(char findboard[ROWS][COLS], char mineboard[ROWS][COLS] , int x,int y) { findboard[x][y] = mineboard[x-1][y-1] + mineboard[x-1][y] + mineboard[x-1][y+1] + mineboard[x][y-1] + mineboard[x][y+1] + mineboard[x+1][y-1] + mineboard[x+1][y] + mineboard[x+1][y+1] - 7*'0';// -8*'0'+'0'以字符形式展示 } //展开雷阵 void OpenMine(char findboard[ROWS][COLS], char mineboard[ROWS][COLS] , char textboard[ROWS][COLS], int x,int y) { textboard[x][y] = '1'; if(x>0 && x<=ROW && y>0 && y<=COL) { ShowRoundMine(findboard, mineboard, x, y); if('0' == findboard[x][y]) { findboard[x][y] = ' '; ShowRoundMine(findboard, mineboard, x-1, y);//上 ShowRoundMine(findboard, mineboard, x, y-1);//左 ShowRoundMine(findboard, mineboard, x, y+1);//右 ShowRoundMine(findboard, mineboard, x+1, y);//下 if('0' == findboard[x-1][y]) { if('0' == textboard[x-1][y]) { OpenMine(findboard, mineboard,textboard, x-1, y); findboard[x-1][y] = ' '; textboard[x-1][y] = '1'; } }//上 if('0' == findboard[x][y-1]) { if('0' == textboard[x][y-1]) { OpenMine(findboard, mineboard,textboard, x, y-1); findboard[x][y-1] = ' '; textboard[x][y-1] = '1'; } }//左 if('0' == findboard[x][y+1]) { if('0' == textboard[x][y+1]) { OpenMine(findboard, mineboard,textboard, x, y+1); findboard[x][y+1] = ' '; textboard[x][y+1] = '1'; } }//右 if('0' == findboard[x+1][y]) { if('0' == textboard[x+1][y]) { OpenMine(findboard, mineboard,textboard, x+1, y); findboard[x+1][y] = ' '; textboard[x+1][y] = '1'; } }//下 } } } int IsWin(char mineboard[ROWS][COLS], char findboard[ROWS][COLS], int x, int y) { int i = 0; int j = 0; int num = 0; for(i = 1; i<ROWS-1; i++) { for(j = 1; j<COLS-1; j++) { if(mineboard[i][j] == '*') { ++num; } } } return num; } //排雷 void FindMine(char mineboard[ROWS][COLS], char findboard[ROWS][COLS] , char textboard[ROWS][COLS], int x,int y) { int count = 0; int Num = 0; ShowBoard(mineboard); printf("\n"); printf("****************************************\n"); printf("\n"); while(1) { if('0' == findboard[x][y]) { findboard[x][y] = ' '; } ShowBoard(findboard); printf("请输入坐标:"); scanf("%d%d",&x,&y); if(x>0 && x<=ROW && y>0 && y<=COL) { ++count; if('1' == mineboard[x][y]) { if(1 == count) { mineboard[x][y] = '0'; SetMine(mineboard, ROW, COL, count); ShowBoard(mineboard); OpenMine(findboard, mineboard, textboard, x, y); } else { printf("很遗憾,你被炸死了!\n"); ShowBoard(mineboard); break; } } else { OpenMine(findboard, mineboard, textboard, x, y); } } else { printf("输入坐标有误,请重新输入!\n"); } Num = IsWin(findboard, mineboard, x, y); printf("星星数:%d\n",Num); if(MINE_FUM == Num) { printf("恭喜你,游戏通关!\n"); ShowBoard(mineboard); break; } } }
第二部分:问题及解决方案
1.第一次不被炸死
mineboard[x][y] = '0'; SetMine(mineboard, ROW, COL, count); ShowBoard(mineboard); OpenMine(findboard, mineboard, textboard, x, y);
将该点设为由‘1’设置为‘0’,重新布雷(防止雷的数量!=设置的雷数)
字符‘1’设置为雷,‘0’为空,方便以后统计周围雷的数量
2.如何展开一片空白区
递归思想,展开上下左右
设置一个标记位,防止无限递归(走过的路就标记为1)
3.有了递归,如何判断输赢
统计‘*’的个数是否等于设置雷的数量
(如果没有递归思想,可以考虑 步数 = ROW*COL - 的数量)
第三部分:知识扩展
难度选择
棋盘设计