先贴效果图
规则
1、输入坐标来排除不是雷的部分
2、第一次不会死
收获
1、写类似程序思路要清楚,不能直接下手写,先画流程图,搞清楚游戏规则的实现
2、整个程序最不好思考的即扫雷函数,递归翻开周边为雷盘,写的过程中经常出现Stack Overflow,函数递归写的要仔细,不能马虎
代码
头文件部分(game.h)
#ifndef __GAME_H__
#define __GAME_H__
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define EASY_COUNT 20
#define HARD_COUNT 40
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set);//初始化棋盘
void PrintBoard(char board[ROWS][COLS], int row, int col);//打印雷盘
void FirstMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);//第一次移动不能死
void SetMine(char board[ROWS][COLS], int row, int col);//设置雷
int ClearMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);//扫雷的主要部分
int GetMineCount(char board[ROWS][COLS], int x, int y);//数雷的个数
#endif //__GAME_H__
主函数部分(code.c)
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
const int rows = 11;
const int cols = 11;
const int row = 9;
const int col = 9;
int x = 0, y = 0;
char set = '*';
int main()
{
int choice = 0;
char show[ROWS][COLS] = { 0 };
char mine[ROWS][COLS] = { 0 };
srand((unsigned)time(0));
while (1)
{
printf("1.玩一把 0.退出\n");
scanf("%d", &choice);
system("cls");
switch (choice)
{
case 1:
InitBoard(show, rows, cols, set);
PrintBoard(show, row, col);
SetMine(mine, row, col);
//PrintBoard(mine, row, col);//测试的时候用
FirstMove(show, mine, row, col);//第一次移动不会死
system("cls");
PrintBoard(show, row, col);
while (ClearMine(show, mine, row, col))
{
system("cls");
PrintBoard(show, row, col);
//PrintBoard(mine, row, col);//测试的时候用
}
PrintBoard(mine, row, col);
break;
case 0:
exit(0);
break;
}
}
return 0;
}
游戏函数部分(game.c)
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
int win = 0;//计算翻开的格子数
int n = 0;//难度
void FirstMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col);
void ShowSafeArea(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col, int x, int y);//翻开安全区域
void InitBoard(char board[ROWS][COLS], int rows, int cols, char set)
{
int i = 0;
int j = 0;//i、j循环变量
win = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
board[i][j] = set;
}
}
}
void SetMine(char board[ROWS][COLS], int row, int col)
{
int i = 0, j = 0;//i、j循环变量
int x = 0;
int y = 0;
int choice = 0;
printf("选择难度:1.简单 2.困难:>");
scanf("%d", &choice);
if (choice == 1)
{
n = EASY_COUNT;
}
else
{
n = HARD_COUNT;
}
//此部分初始化雷棋盘
for (i = 0; i < row + 2; i++)
{
for (j = 0; j < col + 2; j++)
{
board[i][j] = '0';
}
}
//埋雷部分
i = 0;
while (i < n)
{
while (1)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
break;
}
}
i++;
}
}
void PrintBoard(char board[ROWS][COLS], int row, int col)
{
int i = 0, j = 0;//i、j循环变量
//打印棋盘
for (i = 0; i <= row; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <= row; i++)
{
printf("%d", i);
for (j = 1; j <= col; j++)
{
printf(" %c", board[i][j]);
}
printf("\n");
}
}
void FirstMove(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int i = 0, j = 0;//i、j循环变量
int x = 0, y = 0;
printf("输入坐标:>");
scanf("%d%d", &x, &y);
while (x > row || y > col || x < 1 || y < 1)
{
printf("重新输入:>");
scanf("%d%d", &x, &y);
}
if (mine[x][y] == '1')//第一次碰到雷,把雷移走
{
do
{
i = rand() % row + 1;
j = rand() % col + 1;
}while (mine[i][j] != '0');
mine[x][y] = '0';
mine[i][j] = '1';
}
if (mine[x][y] == '0')//不是雷,正常步骤进行
{
ShowSafeArea(show, mine, row, col, x, y);
}
}
int ClearMine(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col)
{
int i = 0, j = 0;//i、j循环变量
int x = 0, y = 0;;
printf("输入坐标:>");
scanf("%d%d", &x, &y);
while (x > row || y > col || x < 1 || y < 1)
{
printf("重新输入:>");
scanf("%d%d", &x, &y);
}
if (mine[x][y] == '1')
{
printf("你输了!\n");
return 0;
}
if (mine[x][y] == '0')
{
ShowSafeArea(show, mine, row, col, x, y);
if (win == row * col - n)
{
printf("你赢了!\n");
return 0;
}
return 1;
}
}
void ShowSafeArea(char show[ROWS][COLS], char mine[ROWS][COLS], int row, int col, int x, int y)
{
int i = 0, j = 0;//i、j循环变量
if (show[x][y] != '*')
{
return;//已经翻开,返回
}
else
{
show[x][y] = '0' + GetMineCount(mine, x, y);//先翻开点的这一格
win++;
}
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if ((show[i][j] == '*') && (i > 0) && (i <= row) && (j > 0) && (j <= col))//如果show为*说明没有翻开
{
if (mine[i][j] == '1')
{
continue;
}
else if ((GetMineCount(mine, i, j) != 0) && (mine[i][j] == '0'))
{
show[i][j] = '0' + GetMineCount(mine, i, j);
win++;
}
if ((GetMineCount(mine, i, j) == 0) && (mine[i][j] == '0'))
{
ShowSafeArea(show, mine, row, col, i, j);
}
}
}
}
}
int GetMineCount(char mine[ROWS][COLS], int x, int y)
{
int i = 0, j = 0;//i、j循环变量
int count = 0;
for (i = x - 1; i <= x + 1; i++)//数雷的个数
{
for (j = y - 1; j <= y + 1; j++)
{
if (mine[i][j] == '1')
{
count++;
}
}
}
return count;
}