C语言 战舰游戏不与浮动和下沉工作

63lcw9qa  于 2023-03-22  发布在  其他
关注(0)|答案(1)|浏览(91)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

//Define the board size 
#define ROWS 10
#define COLS 10

//Define the ships
#define BABY_SHIP 'B'
#define SIMPLE_SHIP 'S'
#define RUGGED_SHIP 'R'
#define VALENCIA_SHIP 'V'
#define GIANT_SHIP 'G'

//Define the ship sizes
#define BABY_SHIP_SIZE 2
#define SIMPLE_SHIP_SIZE 3
#define RUGGED_SHIP_SIZE 3
#define VALENCIA_SHIP_SIZE 4
#define GIANT_SHIP_SIZE 5

//Define the ship struct
struct ship {
    char type;
    int size;
    int hits;
    int row;
    int col;
    int is_horizontal;
};

//Function prototypes
void initialize_board(int board[ROWS][COLS]);
void getBoard(int board[ROWS][COLS]);
void randomizeShips(int board[ROWS][COLS], struct ship* s);
int check_location_valid(int board[ROWS][COLS], struct ship* s);
void fire_missile(int board[ROWS][COLS], int row, int col, struct ship ships[]);
int check_ship_sunk(int board[ROWS][COLS], struct ship* s);
void print_ship_status(struct ship ships[]);
void save_game(int board[ROWS][COLS], struct ship ships[]);
void loadGame(int board[ROWS][COLS], struct ship ships[]);

int main()
{
    // Seed the random number generator
    srand(time(NULL));
    int board[ROWS][COLS] = { 0 };
    // Declare the array of ships
    struct ship ships[5];
    int check = 0;
    // Define the ships
    ships[0].type = BABY_SHIP;
    ships[0].size = BABY_SHIP_SIZE;
    ships[0].hits = 0;

    ships[1].type = SIMPLE_SHIP;
    ships[1].size = SIMPLE_SHIP_SIZE;
    ships[1].hits = 0;

    ships[2].type = RUGGED_SHIP;
    ships[2].size = RUGGED_SHIP_SIZE;
    ships[2].hits = 0;

    ships[3].type = VALENCIA_SHIP;
    ships[3].size = VALENCIA_SHIP_SIZE;
    ships[3].hits = 0;

    ships[4].type = GIANT_SHIP;
    ships[4].size = GIANT_SHIP_SIZE;
    ships[4].hits = 0;

    // Initialize the board
    initialize_board(board);

    // Place the ships
    for (int i = 0; i < 5; i++)
    {
        randomizeShips(board, &ships[i]);
    }

    // Print the board
    getBoard(board);

    // Start the game
    int missiles = 0;
    int ships_sunk = 0;

    while (ships_sunk < 5)
    {
        // Get the row and column from the player
        char row_c;
        int col;
        printf("Missiles Fired: %d\n", missiles);
        printf("Enter row and column (ex. A5) or QQ to quit: ");
        scanf(" %c%d", &row_c, &col);

        // Check if the player wants to quit
        if (row_c == 'Q' || row_c == 'q')
        {
            save_game(board, ships);
            check++;
            break;
        }

        // Convert the row to an int
        int row = row_c - 'A';

        // Fire the missile
        fire_missile(board, row, col, ships);

        // Increment the missile count
        missiles++;
        // Check to see if any ships have been sunk
        for (int i = 0; i < 5; i++)
        {
            if (check_ship_sunk(board, &ships[i]))
            {
                ships_sunk++;
            }
        }

        // Print the board
        getBoard(board);
        // Print ship status
        print_ship_status(ships);
    }

    // Print the win message
    if (check = 1)
    {
        printf("See you next time :)");
    }
    else
    {
        printf("You win! You sunk all the ships in %d missiles.\n", missiles);
    }
    return 0;
}

// Function implementations

// Initializes the board with all 0s
void initialize_board(int board[ROWS][COLS])
{
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLS; j++)
        {
            board[i][j] = 0;
        }
    }
}

// Prints the board to the console
void getBoard(int board[ROWS][COLS])
{
    printf("  ");

    // Print the column numbers
    for (int i = 0; i < COLS; i++)
    {
        printf("%d ", i);
    }

    printf("\n");

    // Print the board
    for (int i = 0; i < ROWS; i++)
    {
        printf("%c ", 'A' + i);

        for (int j = 0; j < COLS; j++)
        {
            if (board[i][j] == 0)
            {
                printf(". ");
            }
            else if (board[i][j] == BABY_SHIP || board[i][j] == SIMPLE_SHIP || board[i][j] == RUGGED_SHIP || board[i][j] == VALENCIA_SHIP || board[i][j] == GIANT_SHIP)
            {
                printf(". ");
            }
            else
            {
                printf("%c ", board[i][j]);
            }
        }

        printf("\n");
    }
}

// Places a ship on the board
void randomizeShips(int board[ROWS][COLS], struct ship* s)
{
    // Generate a random row, column, and orientation
    s->row = rand() % ROWS;
    s->col = rand() % COLS;
    s->is_horizontal = rand() % 2;

    // Check to make sure the location is valid
    while (!check_location_valid(board, s))
    {
        s->row = rand() % ROWS;
        s->col = rand() % COLS;
        s->is_horizontal = rand() % 2;
    }

    // Place the ship
    for (int i = 0; i < s->size; i++)
    {
        if (s->is_horizontal == 0)
        {
            board[s->row][s->col + i] = s->type;
        }
        else
        {
            board[s->row + i][s->col] = s->type;
        }
    }
}

// Checks to make sure the location is valid
int check_location_valid(int board[ROWS][COLS], struct ship* s)
{
    // Check to make sure the ship is inside the board
    if (s->is_horizontal == 0 && (s->col + s->size) > COLS)
    {
        return 0;
    }

    if (s->is_horizontal == 1 && (s->row + s->size) > ROWS)
    {
        return 0;
    }

    // Check to make sure the ship is not overlapping another ship
    for (int i = 0; i < s->size; i++)
    {
        if (s->is_horizontal == 0)
        {
            if (board[s->row][s->col + i] != 0)
            {
                return 0;
            }
        }
        else
        {
            if (board[s->row + i][s->col] != 0)
            {
                return 0;
            }
        }
    }

    return 1;
}

// Fires a missile at the specified row and column
void fire_missile(int board[ROWS][COLS], int row, int col, struct ship ships[])
{
    if (row < 0 || row >= ROWS || col < 0 || col >= COLS)
    {
        printf("Invalid location.\n");
        printf("You missed that bad huh... dumbass.\n");
        return;
    }

    if (board[row][col] == BABY_SHIP || board[row][col] == SIMPLE_SHIP || board[row][col] == RUGGED_SHIP || board[row][col] == VALENCIA_SHIP || board[row][col] == GIANT_SHIP)
    {
        printf("Hit!\n");
        board[row][col] = 'H';

        // Increment the hit count for the corresponding ship
        for (int i = 0; i < 5; i++)
        {
            if (ships[i].type == board[row][col])
            {
                ships[i].hits++;
                break;
            }
        }
    }
    if (board[row][col] == 'H' || board[row][col] == 'M')
    {
        printf("You already hit there idiot.\n");
    }
    else
    {
        printf("Miss!\n");
        board[row][col] = 'M';
    }
}

// Checks to see if a ship has been sunk
int check_ship_sunk(int board[ROWS][COLS], struct ship* s)
{
    if (s->hits == s->size)
    {
        printf("You sunk the %c ship!\n", s->type);

        for (int i = 0; i < s->size; i++)
        {
            if (s->is_horizontal == 0)
            {
                board[s->row][s->col + i] = s->type;
            }
            else
            {
                board[s->row + i][s->col] = s->type;
            }
        }

        return 1;
    }
    else
    {
        return 0;
    }
}

// Saves the game to a file
void save_game(int board[ROWS][COLS], struct ship ships[])
{
    // Open the file for writing
    FILE* f = fopen("battleship.txt", "w");

    // Write the board to the file
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLS; j++)
        {
            fprintf(f, "%d ", board[i][j]);
        }

        fprintf(f, "\n");
    }

    // Close the file
    fclose(f);

    printf("Game saved to battleship.txt\n");
}

void loadGame(int board[ROWS][COLS], struct ship ships[])
{
    FILE* file = fopen("battleship.txt", "rb");

    if (file == NULL)
    {
        printf("Warning: Could not open file.\n");
        return;
    }

    fread(board, sizeof(int) * ROWS * COLS, 1, file);
    fread(ships, sizeof(struct ship), 5, file);

    fclose(file);
} // ends loadGame

void print_ship_status(struct ship ships[])
{
    printf("Ship Status:\n");
    for (int i = 0; i < 5; i++)
    {
        printf("%c: %s\n", ships[i].type, ships[i].hits == ships[i].size ? "Sunk" : "Floating");
    }
    printf("\n");
}

在C写的战舰游戏.我有麻烦恢复游戏,以及使船舶实际沉没,并显示在标签上,它已经沉没.我还需要显示谁是“赢家”是通过显示以前的分数.另一个问题是,我必须改变字母的船舶字母,一旦它已被摧毁.图像显示的方向.没有全局变量或后藤.谢谢你提前:)。

lfapxunr

lfapxunr1#

在测试和调试你的代码时,我把注意力集中在那些看起来永远不会沉没的东西上。下面是你的代码的重构版本,它大约有99%是原来的。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>

//Define the board size
#define ROWS 10
#define COLS 10

//Define the ships
#define BABY_SHIP 'B'
#define SIMPLE_SHIP 'S'
#define RUGGED_SHIP 'R'
#define VALENCIA_SHIP 'V'
#define GIANT_SHIP 'G'

//Define the ship sizes
#define BABY_SHIP_SIZE 2
#define SIMPLE_SHIP_SIZE 3
#define RUGGED_SHIP_SIZE 3
#define VALENCIA_SHIP_SIZE 4
#define GIANT_SHIP_SIZE 5

//Define the ship struct
struct ship
{
    char type;
    int size;
    int hits;
    int row;
    int col;
    int is_horizontal;
};

//Function prototypes
void initialize_board(int board[ROWS][COLS]);
void getBoard(int board[ROWS][COLS]);
void randomizeShips(int board[ROWS][COLS], struct ship* s);
int check_location_valid(int board[ROWS][COLS], struct ship* s);
void fire_missile(int board[ROWS][COLS], int row, int col, struct ship ships[]);
int check_ship_sunk(int board[ROWS][COLS], struct ship* s);
void print_ship_status(struct ship ships[]);
void save_game(int board[ROWS][COLS], struct ship ships[]);
void loadGame(int board[ROWS][COLS], struct ship ships[]);

int main()
{
    // Seed the random number generator
    srand(time(NULL));
    int board[ROWS][COLS] = { 0 };
    // Declare the array of ships
    struct ship ships[5];
    int check = 0;
    // Define the ships
    ships[0].type = BABY_SHIP;
    ships[0].size = BABY_SHIP_SIZE;
    ships[0].hits = 0;

    ships[1].type = SIMPLE_SHIP;
    ships[1].size = SIMPLE_SHIP_SIZE;
    ships[1].hits = 0;

    ships[2].type = RUGGED_SHIP;
    ships[2].size = RUGGED_SHIP_SIZE;
    ships[2].hits = 0;

    ships[3].type = VALENCIA_SHIP;
    ships[3].size = VALENCIA_SHIP_SIZE;
    ships[3].hits = 0;

    ships[4].type = GIANT_SHIP;
    ships[4].size = GIANT_SHIP_SIZE;
    ships[4].hits = 0;

    // Initialize the board
    initialize_board(board);

    // Place the ships
    for (int i = 0; i < 5; i++)
    {
        randomizeShips(board, &ships[i]);
    }

    // Print the board
    getBoard(board);

    // Start the game
    int missiles = 0;
    int ships_sunk = 0;

    while (ships_sunk < 5)
    {
        // Get the row and column from the player
        char row_c;
        int col;
        printf("Missiles Fired: %d\n", missiles);
        printf("Enter row and column (ex. A5) or QQ to quit: ");
        scanf(" %c%d", &row_c, &col);

        // Check if the player wants to quit
        if (row_c == 'Q' || row_c == 'q')
        {
            save_game(board, ships);
            check++;
            break;
        }

        // Convert the row to an int
        int row = row_c - 'A';

        // Fire the missile
        fire_missile(board, row, col, ships);

        // Increment the missile count
        missiles++;
        // Check to see if any ships have been sunk
        ships_sunk = 0;                 /* Need to reset this after each ship is sunk */
        for (int i = 0; i < 5; i++)
        {
            if (check_ship_sunk(board, &ships[i]))
            {
                ships_sunk++;
            }
        }

        // Print the board
        getBoard(board);
        // Print ship status
        print_ship_status(ships);
    }

    // Print the win message
    if (check == 1)         /* Fixed this */
    {
        printf("See you next time :)");
    }
    else
    {
        printf("You win! You sunk all the ships in %d missiles.\n", missiles);
    }
    return 0;
}

// Function implementations

// Initializes the board with all 0s
void initialize_board(int board[ROWS][COLS])
{
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLS; j++)
        {
            board[i][j] = 0;
        }
    }
}

// Prints the board to the console
void getBoard(int board[ROWS][COLS])
{
    printf("  ");

    // Print the column numbers
    for (int i = 0; i < COLS; i++)
    {
        printf("%d ", i);
    }

    printf("\n");

    // Print the board
    for (int i = 0; i < ROWS; i++)
    {
        printf("%c ", 'A' + i);

        for (int j = 0; j < COLS; j++)
        {
            if (board[i][j] == 0)
            {
                printf(". ");
            }
            else if (board[i][j] == BABY_SHIP || board[i][j] == SIMPLE_SHIP || board[i][j] == RUGGED_SHIP || board[i][j] == VALENCIA_SHIP || board[i][j] == GIANT_SHIP)
            {
                printf("%c ", board[i][j]); /* Temporary to see where the ships actually are */
                //printf(". ");
            }
            else
            {
                printf("%c ", board[i][j]);
            }
        }

        printf("\n");
    }
}

// Places a ship on the board
void randomizeShips(int board[ROWS][COLS], struct ship* s)
{
    // Generate a random row, column, and orientation
    s->row = rand() % ROWS;
    s->col = rand() % COLS;
    s->is_horizontal = rand() % 2;

    // Check to make sure the location is valid
    while (!check_location_valid(board, s))
    {
        s->row = rand() % ROWS;
        s->col = rand() % COLS;
        s->is_horizontal = rand() % 2;
    }

    // Place the ship
    for (int i = 0; i < s->size; i++)
    {
        if (s->is_horizontal == 0)
        {
            board[s->row][s->col + i] = s->type;
        }
        else
        {
            board[s->row + i][s->col] = s->type;
        }
    }
}

// Checks to make sure the location is valid
int check_location_valid(int board[ROWS][COLS], struct ship* s)
{
    // Check to make sure the ship is inside the board
    if (s->is_horizontal == 0 && (s->col + s->size) > COLS)
    {
        return 0;
    }

    if (s->is_horizontal == 1 && (s->row + s->size) > ROWS)
    {
        return 0;
    }

    // Check to make sure the ship is not overlapping another ship
    for (int i = 0; i < s->size; i++)
    {
        if (s->is_horizontal == 0)
        {
            if (board[s->row][s->col + i] != 0)
            {
                return 0;
            }
        }
        else
        {
            if (board[s->row + i][s->col] != 0)
            {
                return 0;
            }
        }
    }

    return 1;
}

// Fires a missile at the specified row and column
void fire_missile(int board[ROWS][COLS], int row, int col, struct ship ships[])
{
    if (row < 0 || row >= ROWS || col < 0 || col >= COLS)
    {
        printf("Invalid location.\n");
        printf("You missed that bad huh... dumbass.\n");
        return;
    }

    if (board[row][col] == 'H' || board[row][col] == 'M')   /* This whole if/else block was reworked for proper sequence to avoid needless idiot declaration*/
    {
        printf("You already hit there idiot.\n");
    }
    else
    {
        if (board[row][col] == BABY_SHIP || board[row][col] == SIMPLE_SHIP || board[row][col] == RUGGED_SHIP || board[row][col] == VALENCIA_SHIP || board[row][col] == GIANT_SHIP)
        {
            printf("Hit!\n");
            //board[row][col] = 'H'; /* This needed to be placed down in the if block below */

            // Increment the hit count for the corresponding ship
            for (int i = 0; i < 5; i++)
            {
                if (ships[i].type == board[row][col])
                {
                    board[row][col] = 'H';      /* Needed to be placed here */
                    ships[i].hits++;
                    break;
                }
            }
        }
        else
        {
            printf("Miss!\n");
            board[row][col] = 'M';
        }
    }
}

// Checks to see if a ship has been sunk
int check_ship_sunk(int board[ROWS][COLS], struct ship* s)
{
    printf("Ship %c hits: %d\n", s->type, s->hits);
    if (s->hits == s->size)
    {
        printf("You sunk the %c ship!\n", s->type);

        for (int i = 0; i < s->size; i++)
        {
            if (s->is_horizontal == 0)
            {
                board[s->row][s->col + i] = s->type;
            }
            else
            {
                board[s->row + i][s->col] = s->type;
            }
        }

        return 1;
    }
    else
    {
        return 0;
    }
}

// Saves the game to a file
void save_game(int board[ROWS][COLS], struct ship ships[])
{
    // Open the file for writing
    FILE* f = fopen("battleship.txt", "w");

    // Write the board to the file
    for (int i = 0; i < ROWS; i++)
    {
        for (int j = 0; j < COLS; j++)
        {
            fprintf(f, "%d ", board[i][j]);
        }

        fprintf(f, "\n");
    }

    // Close the file
    fclose(f);

    printf("Game saved to battleship.txt\n");
}

void loadGame(int board[ROWS][COLS], struct ship ships[])
{
    FILE* file = fopen("battleship.txt", "rb");

    if (file == NULL)
    {
        printf("Warning: Could not open file.\n");
        return;
    }

    fread(board, sizeof(int) * ROWS * COLS, 1, file);
    fread(ships, sizeof(struct ship), 5, file);

    fclose(file);
} // ends loadGame

void print_ship_status(struct ship ships[])
{
    printf("Ship Status:\n");
    for (int i = 0; i < 5; i++)
    {
        printf("%c: %s\n", ships[i].type, ships[i].hits == ships[i].size ? "Sunk" : "Floating");
    }
    printf("\n");
}

为了直观地看到测试船只的位置,进行了修正和/或临时更改的地方使用vintage /* . . . */ comment方法进行了注解。以下是调整的关键部分。

  • 正如在上面的好的评论中所指出的,“if(check = 1)”语句本来是有问题的,所以被更正为“if(check == 1)”
  • 在测试被击沉的船只数量时,很明显,在运行“for”循环之前,需要将变量keeping count重置为零;否则汇点计数被累积并且将过早地调用赢家。
  • 董事会字符已暂时更改为打印船舶类型字符-这将需要更改回来。
  • “fire_missle”函数中的if/else块被修改,以便当第一次感觉到命中时,不会打印后续的“idiot”消息。
  • 在if/else块中,“H”字符的赋值被移动到与船舶命中数的增量相同的位置-否则“if(ships[i].type == board[row][col])”测试永远不会为真。

随着这些位的变化,下面是一个样本的游戏测试运行。

Ship B hits: 2
You sunk the B ship!
Ship S hits: 3
You sunk the S ship!
Ship R hits: 3
You sunk the R ship!
Ship V hits: 4
You sunk the V ship!
Ship G hits: 5
You sunk the G ship!
  0 1 2 3 4 5 6 7 8 9 
A . . . . . . . . . . 
B . . . . . . . . . . 
C . G G G G G . . . . 
D . . . . . . . . . . 
E . . . . . . . . . . 
F R . . . . . . . . . 
G R . . B . . . . . . 
H R . . B . . V V V V 
I . . . . . . . . . . 
J . . . . . . . S S S 
Ship Status:
B: Sunk
S: Sunk
R: Sunk
V: Sunk
G: Sunk

You win! You sunk all the ships in 18 missiles.

我将在文件保存/恢复位上尊重其他人,但是给予这些重构的调整,看看它是否符合您的项目的精神。

相关问题