以下为本人十几天之前写的扫雷代码,没有看教程,从构思到完成全是自己做的(很有成就感)
当时Expand扩展函数那里总是出错,老是栈溢出还找不到哪里错了
今天突然发现错了一行代码,改了之后果然能正常运行了
不做其他介绍(因为太懒了),有的介绍文字都在注释里,大家自己看吧
(ps.本代码没有写插旗函数)
test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu()
{
printf("*************************************************\n");
printf("*************************************************\n");
printf("***** 1.play ************ 0.exit *****\n");
printf("*************************************************\n");
printf("*************************************************\n");
}
void game()
{
//设定二维数组
char board[ROW][COL] = { 0 };
char minesboard[ROW][COL] = { 0 };
//初始化
InitBoard(board, ROW, COL);
InitMinesBoard(minesboard, ROW, COL);
//生成雷
GenerateMines(minesboard, ROW, COL, MINES);
//打印表盘
DisplayBoard(board, ROW, COL);
//扫雷
SweepMines(board,minesboard,ROW,COL);
}
void test()
{
srand((unsigned int)time(NULL));
int input;
do
{
menu();
printf("请选择>\t");
scanf("%d", &input);
printf("\n");
switch (input)
{
case 1:
game();
break;
case 0:
printf("退出游戏\n");
break;
default:
printf("输入错误,请重新输入\n");
break;
}
} while (input);
}
int main()
{
test();
}
game.h
#pragma once
#define ROW 10 //行
#define COL 10 //列
#define MINES 10 //雷数
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<windows.h>
void InitBoard(char board[ROW][COL], int row, int col);//初始化表盘
void InitMinesBoard(char minesboard[ROW][COL], int row, int col);//初始化雷盘
void DisplayBoard(char board[ROW][COL], int row, int col);//打印表盘
void GenerateMines(char minesboard[ROW][COL], int row, int col, int mines);//生成雷
void SweepMines(char board[ROW][COL], char minesboard[ROW][COL], int row, int col);//扫雷
char Count(char minesboard[ROW][COL], int x, int y);//数雷
void Expand(char board[ROW][COL],char minesboard[ROW][COL], int x, int y);
int Win(char board[ROW][COL],int row,int col);//判断是否胜利
game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void InitBoard(char board[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
board[i][j] = '@';
}
}
}
void InitMinesBoard(char minesboard[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
minesboard[i][j] = '0';
}
}
}
void DisplayBoard(char board[ROW][COL], int row, int col)
{
system("cls");//每次打印之前清屏一遍
int i = 0;
for (i = 0; i < row; i++)
{
int j = 0;
for (j = 0; j < col; j++)
{
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
for (j = 0; j < col; j++)
{
if (i < row - 1)
{
printf("---");
if (j < col - 1)
printf("|");
}
}
printf("\n");
}
}
void GenerateMines(char minesboard[ROW][COL], int row, int col, int mines)
{
int n = 0;
for (n = 0; n < mines; n++)
{
int i = rand() % row;
int j = rand() % col;
if (minesboard[i][j] == '1')//防止重复布雷
{
n--;
continue;
}
minesboard[i][j] = '1';
}
}
void SweepMines(char board[ROW][COL], char minesboard[ROW][COL], int row, int col)
{
int x, y;
while (Win(board,ROW,COL))
{
printf("请输入您要扫的坐标>\n");
scanf("%d%d", &x, &y);
if (x - 1 >= 0 && x - 1 <= row && y - 1 >= 0 && y - 1 <= col)
{
if (minesboard[x - 1][y - 1] == '1')
{
DisplayBoard(minesboard, ROW, COL);
printf("很遗憾,您被炸死了!\n");
Sleep(2000);
break;
}
else
{
Expand(board, minesboard, x-1, y-1);
DisplayBoard(board, ROW, COL);
}
}
else
{
printf("非法坐标,请重新输入!\n");
}
}
}
char Count(char minesboard[ROW][COL], int x, int y)
{
int count = 0;
if (minesboard[x + 1][y + 1] == '1')
{
count++;
}
if (minesboard[x + 1][y] == '1')
{
count++;
}
if (minesboard[x + 1][y - 1] == '1')
{
count++;
}
if (minesboard[x][y + 1] == '1')
{
count++;
}
if (minesboard[x][y - 1] == '1')
{
count++;
}
if (minesboard[x - 1][y + 1] == '1')
{
count++;
}
if (minesboard[x - 1][y] == '1')
{
count++;
}
if (minesboard[x - 1][y - 1] == '1')
{
count++;
}
return count+'0';
}
int Win(char board[ROW][COL], int row, int col)
{
int i = 0, j = 0;
int o = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (board[i][j] != '@')
{
o++;
}
}
}
if (o == row * col - MINES)
{
printf("游戏结束,扫雷成功!\n");
return 0;
}
else
{
return 1;
}
}
void Expand(char board[ROW][COL], char minesboard[ROW][COL], int x, int y)
{
if (Count(minesboard, x, y) == '0')
{
board[x][y] = ' ';
int i = 0, j = 0;
for (i = x - 1; i <= x + 1; i++)
{
for (j = y - 1; j <= y + 1; j++)
{
if (i >= 1 && i <= ROW && j >= 1 && j <= COL)
{
if (board[i][j] == '@')//???改了半天就差在这一行条件代码上???(原代码是minesboard[i][j]=='0',总是导致栈溢出)
{ //原来如此,minesboard[i][j]=='0'并不是必要的条件,因为最上面的if已经限定了只有不是雷的时候才能进入循环,这就说明只要进入递归了,就一定不会是雷,而board[i][j]=='@'却是必要条件,因为如果没有这个条件,那么Expand函数就会反复递归所有已经递归过的格子,最终导致栈溢出,虽然我在改代码的时候曾经尝试加上 i=x,j=y 就不进行递归的条件,但仍然无法限制住,因为在扩展到一定的数量的格子之后,会有重叠的格子,这些格子也会造成无限递归
Expand(board, minesboard, i, j);
}
}
}
}
}
else
{
board[x][y] = Count(minesboard, x, y);
}
}
希望对您有所帮助,如有学术问题敬请纠正。
|