在C中使用递归函数的扫雷问题

时间:2014-03-21 22:45:32

标签: c recursion minesweeper

我试图在C中为编程类创建游戏扫雷的终端版本。我只是在项目的一部分,我遇到了一个我似乎无法解决的问题。我试图创建一个函数,当一个位置,揭开正方形,然后递归调用自己来揭开任何不包含地雷的相邻正方形。该功能似乎有效,除了它有时会隐藏一个没有被任何地雷包围的方块。

以下是问题的一个例子,在这种情况下,当地雷数量真的很低时,它似乎只是一个问题4:

enter image description here

这是我的源代码,如果它不是最好的我只是学习C,请原谅我。

//
//  main.c
//  Minesweeper
//
//  

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include "game.h"
#include "io.h"

int X=20;
int Y=20;
int M=4;

int main(int argc,char **argv)
{
    time_t t;
    srand((unsigned) time(&t));

    int **intboard = allocateBoard(X,Y,M); // initalizes board X by Y and randomly places M mines.

    numberBoard(intboard, X, Y); // assigns numbers of mines around each square.

    char **charboard = allocateVisableBoard(X,Y); // allocates a board which keeps track of what is visable and what is not. '-' = not visible ' ' = visable

    display(intboard, charboard, X, Y); // function which displays values that are visable

    system("clear");

    int **checkboard = initCheckboard(X,Y); // board which is used by reveal function so it knows which squares have already been checked

    int status = reveal(intboard, charboard,checkboard, X, Y, 5, 5,0); // reveals the value at 5,5 and recursively reveals squares as necessary

    display(intboard, charboard, X, Y);

    if (status == 1) //displays loosing screen if mine is chosen
        boom();

    if ( 1 == endofgame(intboard, charboard, X, Y))
        printf("you win!");

    return 0;
}

//
//game.c
//Minesweeper
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "game.h"

#define MVALUE -1 //minevalue
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KYEL  "\x1B[33m"
#define KBLU  "\x1B[34m"
#define KMAG  "\x1B[35m"
#define KCYN  "\x1B[36m"
#define KWHT  "\x1B[37m"
#define BOARD  "\x1B[37;44m"
#define RESET   "\033[0m"

int **allocateBoard(int X, int Y, int M) /* Allocates board X by Y with M mines  */
{
    /* Check if allocation succeeded. (check for NULL pointer) */
    int i,j,x,y,**board;

    board = malloc(X*sizeof(int *));
    for(i = 0 ; i < X ; i++)
        board[i] = malloc(Y*sizeof(int));

    /*int modulo = (X*Y)/(double) M;    

    printf("modulo: %d\n", modulo);
    */

   for(i = 0 ; i < X ; i++)
        for(j = 0 ; j < Y ; j++)
            board[i][j] = 0;

    int r = (rand() % (X*Y));
    for(i = 0; i < M;)
    {
        y = r/Y;
        x = r %X;
        if(board[x][y] == 0)
        {
            board[x][y] = MVALUE;
            i++;
        }

        r =rand() % (X*Y);
    }
    return board;
}

int adjacentMines(int **board,int X, int Y, int x, int y)
{
    int count = 0;
    if(x < X-1)
        if(board[y][x+1]== MVALUE)
            count++;
    if(x > 0)
        if(board[y][x-1] == MVALUE)
            count++;
    if(y < Y-1)
        if(board[y+1][x]== MVALUE)
            count++;
    if(y > 0)
        if(board[y-1][x]== MVALUE)
            count++;
    if(x < X-1 && y < Y-1)
        if(board[y+1][x+1]== MVALUE)
            count++;
    if(x > 0 && y < Y-1)
        if(board[y+1][x-1]== MVALUE)
            count++;
    if(x < X-1 && y > 0)
        if(board[y-1][x+1]== MVALUE)
            count++;
    if(x > 0 && y > 0)
        if(board[y-1][x-1]== MVALUE)
            count++;

    // TESTING CODE
    /*
    printf("x:%d y:%d mines adjacent:%d\n",x,y,count);    
    */
    return count;
}

void printIntBoard(int **board,int X,int Y)
{
    int i,j;
    system("clear");
    printf("       ");
    for(i=0; i < X; i++)
        printf("[%.3d] ",i);
    printf("\n\n ");

    for(i=0;i < Y; i++)
    {
        printf("[%.3d] ",i);

        for(j=0; j < X; j++)
        {
            if(board[i][j] == -1)
            {
                printf("  *  ");
            }
            else
                printf("  %d  ",board[i][j]);
                printf(" ");
        }
        printf("\n\n ");

    }
}

void printCharBoard(char **board,int X,int Y)
{
    int i,j;

    printf("       ");

    for(i = 0; i < X; i++)
        printf("[%.3d] ",i);

    printf("\n\n ");

    for(i=0;i < Y; i++)
    {
        printf("[%.3d] ",i);

        for(j = 0; j < X; j++)
        {
            printf("  %c  ",board[i][j]);
            printf(" ");
        }
        printf("\n\n ");

    }
}

void numberBoard(int **board,int X, int Y)
{
    int i,j;
    for (i = 0; i < X; i++) {
        for (j = 0; j < Y ; j++)
        {
            if(board[j][i]!= -1)
                board[j][i]=adjacentMines(board, X, Y, i, j);
        }
    }
}

char **allocateVisableBoard(int X, int Y) /* Allocates Visable board X by Y completely hidden */
{
    int i,j;
    char **board;

    board = malloc(X*sizeof(char *));
    for(i = 0 ; i < X ; i++)
        board[i] = malloc(Y*sizeof(char));

    for(i = 0 ; i < X ; i++)
        for(j = 0 ; j < Y ; j++)
            board[i][j] = '-';

    return board;
}

void showBoard(int **iboard, char **cboard,int X, int Y)
{
    int i,j;

    for(i = 0; i < X; i++)
        {
            for (j=0; j<Y; j++) {
                printf("  %c  ",cboard[j][i]);
            }
            printf("\n");
        }
}

int **initCheckboard(int X,int Y)
{
    int i,j, **checkboard;

    checkboard = malloc(X *sizeof(int *));
    for (i = 0; i < X; i++) {
        checkboard[i]= malloc(Y *sizeof(int));
    }

    for(i = 0 ; i < X ; i++)
        for(j = 0 ; j < Y ; j++)
            checkboard[i][j] = 0;

    return checkboard;
}


int reveal(int **iboard,char **cboard,int **checkboard, int X, int Y, int x, int y,int count)
{
    if(count == 0 && iboard[x][y]== MVALUE)
    {
        cboard[x][y] = ' ';
        checkboard[x][y] = 1;
        return 1;
    }


    if (iboard[y][x] > 0)
    {
        cboard[y][x] = ' ';
        checkboard[y][x] = 1;
        return 0;
    }

    else if(iboard[y][x] == 0)
    {
        checkboard[y][x] = 1;
        count ++;

        if(x < X-1 && checkboard[y][x+1] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y][x+1] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x+1, y,count);
        }
        if(y < Y-1 && checkboard[y+1][x] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y+1][x] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x, y+1,count);
        }
        if(x > 0 && checkboard[y][x-1] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y][x-1] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x-1, y,count);
        }
        if(y > 0 && checkboard[y-1][x] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y-1][x] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x, y-1,count);
        }
        if(x < X-1 && y < Y-1 && checkboard[y+1][x+1] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y+1][x+1] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x+1, y+1,count);
        }
        if(x < X-1 && y > 0 && checkboard[y-1][x+1] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y-1][x+1] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x+1, y-1,count);
        }
        if(x > 0 && y > 0 && checkboard[y-1][x-1] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y-1][x-1] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x-1, y-1,count);
        }
        if(x > 0 && y < Y-1 && checkboard[y+1][x-1] == 0)
        {
            cboard[y][x]= ' ';
            checkboard[y+1][x-1] = 1;
            reveal(iboard, cboard, checkboard, X, Y, x-1, y+1,count);
        }

    }
        return 0;
}

int endofgame(int **iboard,char **cboard,int X,int Y)
{
    int i,j;
    int count = 0;

    for (i = 0; i < Y; i++)
    {
        for (j = 0; j < X; j++)
        {
            if(cboard[i][j] == '-')
            {
                if (iboard[i][j] != MVALUE)
                    count++;
            }
        }
    }
    if (count == 0)
        return 1; // win

    else
        return 0; // keep going
}

void resetcheck(int **checkboard,int X, int Y)
{
    int i,j;
    for(i = 0 ; i < X ; i++)
        for(j = 0 ; j < Y ; j++)
            checkboard[i][j] = 0;


}

//
//  io.c
//  Minesweeper
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "game.h"
#include "scanner.h"

void boom(void)
{
    system("clear");
    printf("Boom!");                                                                                                                                                                                                        

}

void display(int **iboard, char **cboard,int X,int Y)
{
    int i,j;

    printf("      ");
    for (i =0 ;i < X; i++)
        printf("[%.3d]",i);

    printf("\n\n");

    for (i = 0; i < Y; i++) {
        printf("[%.3d]",i);
        for (j = 0; j < X; j++) {
            if (cboard[i][j]==' ') {
                if (iboard[i][j] == -1)
                    printf("  *  ");

                //else if(iboard[i][j] == 0)
                //printf("      ");

                else
                    printf("  %d  ",iboard[i][j]);
            }
            else
                printf("  %c  ",cboard[i][j]);
        }
        printf("\n\n");
    }

}

//
//  mine.h
//  Minesweeper
//

extern int **allocateBoard(int X, int Y, int M);
extern int adjacentMines(int **board,int X, int Y, int x, int y);
extern void printIntBoard(int **board,int X,int Y);
extern void numberBoard(int **board,int X, int Y);
extern char **allocateVisableBoard(int X, int Y);
extern void printCharBoard(char **board,int X,int Y);
extern int **initCheckboard(int X,int Y);
extern int reveal(int **iboard,char **cboard,int **checkboard, int X, int Y, int x, int y,int count);
extern int endofgame(int **iboard,char **cboard,int X,int Y);
extern void resetcheck(int **checkboard,int X, int Y);
extern void showBoard(int **iboard, char **cboard,int X, int Y);

//
//  io.h
//  Minesweeper
//

extern void display(int **iboard, char **cboard,int X,int Y);
extern void boom(void);

问题应该在于我的揭示功能,即251到324行。

1 个答案:

答案 0 :(得分:1)

在您的显示功能(和其他)中,您正在使用[x] [y]和[y] [x]对同一阵列进行切换。