首页 > 解决方案 > (C++) 我必须使用幻数在数组中的正确位置显示值。我怎样才能摆脱它?

问题描述

对不起,如果代码太长。我只是想详细描述一下我所面临的情况

我正在编写一个名为 Battle Ship 的游戏。下面的代码是一个更简单的版本,我确实消除了所有不必要的逻辑,因为我只想用幻数来说明问题。

这是我的结构和枚举

// the dimension of the 10 + 2 game grid for detection of the neighboring ship 
// (its usage comes later in the game, not at this stage)
const int SIZE = 12;

// the number of warships
const int NBSHIP = 5;

string ships[NBSHIP] = {"Carrier", "Cruiser", "Destroyer", "Submarine", "Torpedo" };

// available warships and their size on the grid
enum Ship {
  CARRIER=5,
  CRUISER=4,
  DESTROYER=3,
  SUBMARINE=3,
  TORPEDO=2,
  NONE=0
};

// the different states that a grid cell can take and their display
enum State {
  HIT='x',
  SINK='#',
  MISS='o',
  UNSHOT='~'
};

// a grid cell
// the ship present on the space
// the state of the box
struct Cell {
  Ship ship;
  State state;
};

// the player with
// his name
// his score to determine who lost
// his game grid
struct Player {
  string name;
  int score;
  Cell grid[SIZE][SIZE];
};

// the coordinates of the cell on the grid
// its column from 'A' to 'J'
// its line from 1 to 10
struct Coordinate {
  char column;
  int line;
};

// the placement of the ship on the grid
// its coordinates (E5)
// its direction 'H' horizontal or 'V' vertical from the coordinate
struct Placement {
  Coordinate coordi;
  char direction;
};

基本上,在游戏开始时,我必须为每个单元格初始化一个具有适当状态的网格(在本例中为 UNSHOT 和 NONE)。然后我必须显示网格并开始放置船只。这里奇怪的是我必须根据玩家的输入使用“魔术数字”将船只放置在正确的位置。但我什至不知道为什么我需要它以及如何摆脱它。

幻数的利用出现在placeShip 函数中。

void initializeGrid (Cell aGrid[][SIZE])
{
    for (int i = 0; i < SIZE - 2; i++)
    {
        for (int j = 0; j < SIZE - 2; j++)
        {
          aGrid[i][j].ship = NONE;
          aGrid[i][j].state = UNSHOT;
        }
    }
}

void displayGrid(Player aPlayer)
{
    cout << endl;
    cout << setw(10) << aPlayer.name << endl;

    // Letter coordinates
    char a = 'A';
    cout << "  "; 
    for (int i = 0; i < SIZE - 2 ; i++)
    {
        cout << " " << char (a+i);
    }
    cout << endl;

    // Number coordinates
    for (int i = 0; i < SIZE - 2; i++)
    {
        // Player
        if(i + 1 >= 10) // To align the first column
            cout << i + 1;
        else
            cout << " " << i + 1;

        for (int j = 0; j < SIZE - 2; j++)
        {
            if (aPlayer.grid[i][j].ship) // Check if there are ships
                cout << " " << (aPlayer.grid[i][j].ship);
            else
                cout << " " << char (aPlayer.grid[i][j].state);
        }
        cout << endl;
    }
}

void placeShip(Cell aGrid[][SIZE], Placement aPlace, Ship aShip)
{
    if (aPlace.direction == 'h' || aPlace.direction == 'H')
    {
        for (int i = 0; i < aShip; i++) // To change the value of a cell according to the size of the boat
        {
          // Utilization of magic number
          aGrid[aPlace.coordi.line - 9][aPlace.coordi.column + i - 1].ship = aShip; // Horizontal so we don't change the line
        }
    }
    else if (aPlace.direction == 'v' || aPlace.direction == 'V')
    {
        for (int i = 0; i < aShip; i++)
        {
          // Utilization of magic number
          aGrid[aPlace.coordi.line + i - 9][aPlace.coordi.column - 1].ship = aShip; // Vertical so we don't change the column
        }
    }
}

void askPlayerToPlace(Player& aPlayer)
{
    Ship battleships[NBSHIP] = { CARRIER, CRUISER, DESTROYER, SUBMARINE, TORPEDO};

    for (int i = 0; i < NBSHIP; i++)
    {
        string stringPlace;
        string stringShip = ships[i];
        Ship aShip = battleships[i];
        string inputDirection;
        Coordinate coordi;

        cout << "\n" << aPlayer.name << ", time to place your carrier of length " 
        << to_string(battleships[i]) 
        << " (" << ships[i] << ")\n" 
        << "Enter coordinates (i.e. B5): ";
        cin >> stringPlace;
        coordi = { stringPlace[0], int(stringPlace[1]) - 48 };

        cout << "Direction: ";
        cin >> inputDirection;
  
        Placement aPlace = {
            coordi,
            inputDirection[0]
        };

        placeShip(aPlayer.grid, aPlace, aShip);
        displayGrid(aPlayer);
    }
}

int main()
{
    Player aPlayer;

    cout << "Player's name: ";
    getline (cin, aPlayer.name);

    initializeGrid(aPlayer.grid);
    displayGrid(aPlayer);

    askPlayerToPlace(aPlayer);

    return 0;
}

标签: c++arraysmagic-numbers

解决方案


这里奇怪的是我必须根据玩家的输入使用“魔术数字”将船只放置在正确的位置。

如果这些是经常出现的数字,您应该为这些定义另一个常量,例如:

const int GRID_SIZE_MARGIN = 2;

并使用它

void initializeGrid (Cell aGrid[][SIZE]) {
    for (int i = 0; i < SIZE - GRID_SIZE_MARGIN; i++) {
        for (int j = 0; j < SIZE - GRID_SIZE_MARGIN; j++) {
          aGrid[i][j].ship = NONE;
          aGrid[i][j].state = UNSHOT;
        }
    }
}

如果还有其他数字出现在计算中,但无法合理命名,则保留数值即可。我会试着给你一个例子:

从弧度计算度数的公式是

deg = rad * 180° / π

对于 π,我们有一个常数定义 ( PI),但是180一个神奇的数字值得一个常数定义吗?
我们应该如何命名它?HUNDREDEIGHTY_DEGREES??

因此,摆脱出现在代码中的数字常量并不总是合理的。


但我什至不知道为什么我需要它以及如何摆脱它。

这可能是任务的一部分,要找出答案。


推荐阅读