Battleship

0

Witam :-)
W ostatnim czasie zaczęłam pisać w konsoli grę w statki. Jest to jak na razie jeden z moich większych projektów (uczę się programowania raczej od niedawna).
Pisząc grę miałam głównie przećwiczyć używanie wskaźników oraz posługiwanie się strukturami danych, w tym typem wyliczeniowym enum.
Kiedy doszłam do momentu, gdzie zaczęło mieć sens odpalenie gry i obejrzenie efektów swojej pracy- kompilator pokazał mi pierdyliard błędów... :-(
No nic- mimo tego, że jest ich aż tak dużo, wciąż żywię nadzieję, że będę to w stanie jakoś naprawić.
Zanim napisałam ten wątek, spędziłam kilka godzin naprawiając te błędy, które póki co naprawić potrafiłam- i komunikatów jest znacząco mniej niż na początku (musicie mi uwierzyć na słowo :-b).
Ale niestety doszłam do wniosku, że z moim dotychczasowym poziomem umiejętności ze wszystkim sobie sama nie poradzę :-( - dlatego uprzejmie proszę o pomoc.

A więc, po pierwsze:
-nigdy wcześniej w większym projekcie nie posługiwałam się enum, więc nie wiem, jak prawidłowo powinnam to rozdzielić na plik z nagłówkami (spis treści) i część zawierającą całe implementacje klas i funkcji.

-po drugie:
próbując załączyć pliki z nagłówkami pisałam na początku pliku z rozszerzeniem .h:
#ifndef __ BATTLESHIP_H__ #define __BATTLESHIP_H__
kompilator pokazuje mi błąd: unterminated ifndef- jest to dla mnie zupełnie coś nowego i nie wiem, co mam z tym zrobić :-(

  • po trzecie: cała reszta- prawie wszystko to skutki błędów w kodzie, jakie popełniłam przy tworzeniu struktur (wcześniej nie miałam wielu okazji, żeby tego używać)
    Zrobiłam zrzut ekranu i umieściłam w załączniku.

Projekt nieskończonej gry składa się z 6 plików: main.cpp, Battleship.cpp, Battleshipi.h, Instruction.cpp (ten plik to akurat jeden wielki komentarz z pseudokodem, planem tworzenia gry), Utils.cpp i Utils.h (dwa ostatnie zawierają funcje korygujące dane wprowadzane z klawiatury przez użytkownika- użyłam tego w nieco zmienionej formie przy tworzeniu gry w wisielca(poprzedni wpis)).

main.cpp:

include <iostream>
#include "Battleship.h"

using namespace std;

int main()
{
    const char * INPUT_ERROR_STRING = "input error! Please, try again.";

    Player player1;
    Player player2;

    InitializePlayer(player1, "Player1");
    InitializePlayer(player2, "Player2");

    do
    {
        PlayGame(player1, player2);
    }while(WantToPlayAgain());

    return 0;
}

Battleship.h:

enum SizeType
{
    AIRCRAFT_CARRIER_SIZE = 5,
    BATTLESHIP_SIZE = 4,
    CRUISER_SIZE = 3,
    DESTROYER_SIZE = 2,
    SUBMARINE_SIZE = 1,

    BOARD_SIZE = 10,
    NUM_SHIPS = 5,
    PLAYER_NAME_SIZE = 8, // Player1, Player2
    MAX_SHIP_SIZE = AIRCRAFT_CARRIER_SIZE
};

enum ShipType
{
    ST_NONE = 0,
    ST_AIRCRAFT_CARRIER,
    ST_BATTLESHIP,
    ST_CRUISER,
    ST_DESTROYER,
    ST_SUBMARINE
};

enum ShipOrientationType
{
    SO_HORIZONTAL = 0,
    SO_VERTICAL
};

struct ShipPositionType
{
    int row;
    int col;
};

struct Ship
{
    ShipType shipType;
    int shipSize;
    ShipOrientationType orientation;  //stworzylam tutaj typ, ale on sam nie definiuje zadnej kokrenej zmiennej =>
    ShipPositionType position;          // miszê ustawiæ wszystkie statki dla kazdego gracza
};

enum GuessType
{
    GT_NONE = 0,
    GT_MISSED,
    GT_HIT
};

struct ShipPartType
{
    ShipType shipType;
    bool isHit;
};

struct Player
{
    char playerName[PLAYER_NAME_SIZE];
    Ship ships[NUM_SHIPS];                  // musze ustawic wszystkie statki poprawnie i przekazac graczowi jeden typ statku do
    GuessType guessBoard[BOARD_SIZE][BOARD_SIZE];   // kazdego z poszczegolnych elementow tablicy
    ShipPartType shipBoard[BOARD_SIZE][BOARD_SIZE];
};

Battleship.cpp

#include <iostream>
#include <cstring>
#include <cctype>
#include "Battleship.h"
#include "Utils.h"

using namespace std;

const char * INPUT_ERROR_STRING = "input error! Please, try again.";

void InitializePlayer(Player & player, const char * playerName)
{
    if(playerName != nullptr && strlen(playerName)>0)
    {
        {
            strcpy(player, playerName);
        }

        InitializeShip(player.ships[0], AIRCRAFT_CARRIER_SIZE, ST_AIRCRAFT_CARRIER);
        InitializeShip(player.ships[1], BATTLESHIP_SIZE, ST_BATTLESHIP);
        InitializeShip(player.ships[2], CRUISER_SIZE, ST_CRUISER);
        InitializeShip(player.ships[3], DESTROYER_SIZE, ST_DESTROYER);
        InitializeShip(player.ships[4], SUBMARINE_SIZE, ST_SUBMARINE);
    }
}

void InitializeShip(Ship & ship, int shipSize, ShipType shipType)
{
        ship.shipType = ST_AIRCRAFT_CARRIER;
        ship.shipSize = AIRCRAFT_CARRIER_SIZE;
        ship.position.row = 0;
        ship.position.col = 0;
        ship.orientation = SO_HORIZONTAL;
}

void PlayGame(Player& player1, Player&player2)
{
    SetUpBoards(player1);
    SetUpBoards(player2);
}

bool WantToPlayAgain()
{
    char input;
    const char validInput[2] = {'y','n'};
    input = GetCharacter("Would you like to play again? (y/n)", INPUT_ERROR_STRING, validInput, 2, CC_LOWER_CASE);
    return input == 'y';
}

void SetUpBoards(Player& player)
{
    ClearBoards(player);
    DrawBoards(player);
}

void ClearBoards(Player&player)
{
    for(int r=0; r<BOARD_SIZE; r++)
    {
        for(int c=0; c<BOARD_SIZE; c++)
        {
            player.guessBoard[r][c] = GT_NONE;
            player.shipBoard[r][c].shipType = ST_NONE;// no ship here
            player.shipBoard[r][c].isHit = false;

        }
    }
}

void DrawBoards(const Player&player)
{
    DrawColumnsRow();
    DrawColumnsRow();
    cout<<endl;

    for(int r=0; r<BOARD_SIZE; r++)
    {
        DrawSeparatorLine();
        cout<<" ";

        DrawSeparatorLine();
        cout<<endl;

        DrawShipBoardRow(player, r);
        cout<<" ";

        DrawGuessBoardRow(player, r);
        cout<<endl;
    }
    DrawSeparatorLine();
    cout<<" ";
    DrawSeparatorLine();
    cout<<endl;

}

void DrawSeparatorLine()
{
    cout<<" ";

    for(int c=0; c<BOARD_SIZE; c++)
    {
        cout<<"+---";
    }
    cout<<"+";
}

void DrawColumnsRow()
{
    cout<<"  ";
    for(int c=0; c<BOARD_SIZE; c++)
    {
        int columnName = c+1;
        cout<<" "<<columnName<<"  ";
    }
    cout<<"+";
}

char GetShipReprezentation(const Player& player, int row, int col)
{
    if(player.guessBoard[row][col].isHit)
    {
        return '*';// represents hit
    }

    if(player.shipBoard[row][col].shipType == ST_AIRCRAFT_CARRIER)
    {
        return 'A';
    }
    else if(player.shipBoard[row][col].shipType == ST_BATTLESHIP)
    {
        return 'B';
    }
    else if(player.shipBoard[row][col].shipType == ST_CRUISER)
    {
        return 'C';
    }
    else if(player.shipBoard[row][col].shipType == ST_DESTROYER)
    {
        return 'D';
    }
    else if(player.shipBoard[row][col].shipType == ST_SUBMARINE)
    {
        return 'S';
    }
    else return ' ';
}

char GetGuessRepresentationAt(const Player& player, int row, int col)
{
    if(player.guessBoard[row][col] == GT_HIT)
    {
        return '*';
    }
    else if(player.guessBoard[row][col == GT_MISSED])
    {
        return 'o';
    }
    else return ' ';
}

void DrawShipBoardRow(const Player& player, int row)
{
    char rowName = row + 'A';
    cout<<rowName<<"|";

    for(int c=0; c<BOARD_SIZE; c++)
    {
        cout<<" "<<GetShipReprezentation(player, row, c)<<" ";
    }
}

void DrawGuessBoardRow(const Player& player, int row)
{
    char rowName = row + 'A';
    cout<<rowName<<"|";

    for(int c=0; c<BOARD_SIZE; c++)
    {
        cout<<" "<<GetGuessRepresentationAt(player, row, c)<<" ";    // tu trzeba uzupelnic reprezentacja kazdego statku
    }
}

Instruction.cpp:

/*
    InitPlayer(player1, "Player1");
    InitPlayer(player2, "Player2");

    do
    {
        PlayGame(player1, player2);
    } while(WantToPlayAgain());

    PlayGame()
    {
        SetupBoard(Player1);
        SetupBoard(Player2);

        do
        {
            DrawBoards(currentPlayer)

            do
            {
                Prompt the current player for a guess
                guess = GetGuess()
            } while(!IsGuessIsValid(guess, currentPlayer));

            UpdateBoards(guess, currentPlayer, otherPlayer);
            DrawBoard(currentPlayer) // to see the result of the guess

            if(a ship was sunk on currentPlayer's turn)
            {
                output that the current player sunk that ship
            }
            WatForKeyPress

            SwitchPlayers()

        } while(!GameIsOver());

        DisplayWinner();
    }

    SetUpBoards(player)
    {
        ClearBoards(player)

        for(all the ships)
        {
            DrawBoards(player)

            currentShip = Get the current ship

            // sprawdzam, czy statek zostal umieszczony poprawnie

            do
            {
                Get Board Position for the head of the ship
                Get the ship orientation

                isValidPlacement = IsValidPlacement(currenShip, position, orientation, player)
                if (!isValidPlacement)
                {
                    output to the player that it was not a valid placement
                }
            } while(!isValidPlacement)

            PlaceShipOnBoard(currenShip, position, orientation, player)
        }
    }

    IsValidPlacement(currentShip, position, orientation, player)
    {
        if(orientatin == HO0RIZONTAL)
        {
            for(all the columns the currentShip would take up)
            {
                if(ship will overlap another ship or the ship will be off the board horizontally)
                {
                    return false
                }
            }
        }
        else
        {
            for(all the rows the currentShip would take up)
            {
                if(ship will overlap another ship or the ship will be off the board vertically)
                {
                    return false
                }
            }
        } return true
    }

    PlaceShipOnBoard(currentShip, position, orientation, player)
    {
        ship.position = position
        ship.orientation = orientation

        if(orientation == HORIZONTAL)
        {
            for(all the columns the ship would take up)
            {
                set the ship part on the board at position.row and current column
            }
        }
        else
        {
            for(all the rows that the ship would take up)
            {
                set the ship part on the board at current row and position.col
            }
        }
    }

    UpdateBoards(guess, currentPlayer, otherPlayer)
    {
        if(otherPlayer's ship board at guess is a ship)
        {
            // hit
               set hit on the currentPlayer's guess board
               apply damage to the otherPlayer's shipBoard
               return shipType
        }
        else
        {
            set miss on the currentPlayer's guess board
            return ST_NONE
        }
    }

    IsGameOver(player1, player2)
    {
        return AreAllShipsSunk(player1) || AreAllShipsSunk(player2)
    }

    AreAllShipsSunk(player)
    {
        for(all the player's ships)
        {
            if(!IsSunk(player, currentShip))
            {
                return false
            }
        } return true
    }

    IsSunk(player, ship)
    {
        if(ship.orientation == HORIZONTAL)
        {
            for(columns that ship takes up)
            {
                if(currentPosition on the shipBoard is not hit)
                {
                    return false
                }
            }
        }
        else
        {
            for(rows that the ship takes up)
            {
                if(currentPosition on the shipBoard is not hit)
                {
                    return false
                }
            }
        }
    }

*/

Utils.h:

#ifndef __ UTILS_H__
#define __UTILS_H__

enum CharacterCaseType
{
    CC_UPPER_CASE=0,
    CC_LOWER_CASE,
    CC_EITHER
};

char GetCharacter(const char* prompt, const char*error);
char GetCharacter(const char* prompt, const char* error, const char validInput[], int validInputLength, CharacterCaseType charCase);

#endif

Utils.cpp

#include <iostream>
#include <cctype>
#include "Utils.h"

using namespace std;

const int IGNORE_CHARS = 256; //to do main
const char * INPUT_ERROR_STRING = "input error! Please, try again.";

char GetCharacter(const char* prompt, const char*error)
{
    char input;
    bool failure;

    do
    {
        failure=false;
        cout<<prompt;
        cin>>input;

        if(cin.fail())
        {
            cin.clear();
            cin.ignore(IGNORE_CHARS, '\n');
            cout << error << endl;
            failure=true;
        }
        else
        {
            cin.ignore(IGNORE_CHARS, '\n');

            if(isalpha(input))
            {
                input = tolower(input);
            }
            else
            {
                cout<<error<<endl;
                failure = true;
            }
        }
    }while(failure); return input;
}

char GetCharacter(const char* prompt, const char* error, const char validInput[], int validInputLength, CharacterCaseType charCase)
{
    char input;
    bool failure;

    do
    {
        failure=false;
        cout<<prompt;
        cin>>input;

        if(cin.fail())
        {
            cin.clear();
            cin.ignore(IGNORE_CHARS, '\n');
            cout << error << endl;
            failure=true;
        }
        else
        {
            cin.ignore(IGNORE_CHARS, '\n');

            if(isalpha(input))
            {
                if(charCase == CC_UPPER_CASE)
                {
                    input = toupper(input);
                }
                else if(charCase == CC_LOWER_CASE)
                {
                    input = tolower(input);
                }

                for (int i=0;i<validInputLength;i++)
                {
                    if(input==validInput[i])
                    {
                        return input;
                    }
                }
            }
            cout<<error<<endl;
            failure=true;
        }
    }while(failure); return input;
}

Proszę o wyrozumiałość w związku z tym, że tu jest aż tak dużo błędów.
Wiem, że tego dużo, ale może jednak komuś będzie się chciało to chociaż pobieżnie przejrzeć i podpowiedzieć mi co i jak poprawić ;-)
Z góry dziękuję za odpowiedź :-)

2

Każda dyrektywa preprocesora musi być w osobnej linii, czyli:

#ifndef __ BATTLESHIP_H__ 
#define __BATTLESHIP_H__


strcpy(player, playerName);

strcpy() przyjmuje wskaźniki do ciągów znaków: https://en.cppreference.com/w/cpp/string/byte/strcpy, a Ty przekazujesz obiekt Player.

if(player.guessBoard[row][col].isHit)

guessBoard jest tablicą enumów GuessType, więc nie ma żadnego pola o nazwie isHit.


Błędy kopiuj i wklej jako tekst, a nie obrazek. Ten obrazek w dodatku obcina komunikat.

1

Jak się Uczysz, to Staraj się pisać porządnie, czyli modułowo, małe kawałki kodu, do każdego unit testy, jak moduły współpracują ze sobą to testy funkcjonalne. Będziesz eliminować dużo błędów na bieżąco.

0

Z uwag ogólnych Siostro @Dominika Łęczycka

  • dla nazw zmiennych/funkcji stosuj camelCase
  • w programie masz elementy takie jak Player, Ship, Board i Game. Warto stworzyć osobne pliki .h i .cpp dla każdego.
  • rzeczy wspólne, wykorzystywane przez różne elementy, na przykład enumy, wskazane jest dodać do wspólnego pliku definitions.h
  • zastanów się i zdefiniuj odpowiedzialności poszczególnych elementów. Za co ma być odpowiedzialny Ship, za co Board itd.
0

Kilka moich uwag odnośnie kodu.

  1. Generalnie każda klasa/struktura powinna być umieszczona w osobnych plikach ( definicja w nagłówku *.h i implementacja w *.cpp ) .
    To poprawi czytelność projektu i rozdzieli kod na podstawowe jednostki/moduły.
  2. Zamień wszystkie definicje wyliczeń enum na enum class, gdyż zmniejszają ryzyko wystąpienia błędów związanych z niejawną konwersją typów.
  3. Spróbuj pomyśleć o prawdziwie obiektowym kodzie ( wiem że to jest trudne dla początkujących ) w którym każda funkcja jest składową jakieś klasy.
  4. Używaj komponentów STL (np. vector,string) tam gdzie to jest możliwe.
    Na przykład strukturę Player można zaimplementować w następujący sposób:

    struct Player
    {
    Player( const string& _playerName, int numShips, int boardSize )
    : playerName{_playerName}
    {
       ships.resize(numShips);
       guessBoard.resize(boardSize);
       for( auto& row : guessBoard ) row.resize(boardSize);
       shipBoard.resize(boardSize);
       for( auto& row : shipBoard ) row.resize(boardSize);
    }
    
    string playerName;
    vector<Ship> ships;
    vector<vector<GuessType>> guessBoard;
    vector<vector<ShipPartType>> shipBoard;
    };
    ............
    Player player("Pirate",5,20);
0
MasterBLB napisał(a):

Z uwag ogólnych Siostro @Dominika Łęczycka

  • dla nazw zmiennych/funkcji stosuj camelCase
  • w programie masz elementy takie jak Player, Ship, Board i Game. Warto stworzyć osobne pliki .h i .cpp dla każdego.
  • rzeczy wspólne, wykorzystywane przez różne elementy, na przykład enumy, wskazane jest dodać do wspólnego pliku definitions.h
  • zastanów się i zdefiniuj odpowiedzialności poszczególnych elementów. Za co ma być odpowiedzialny Ship, za co Board itd.

Code::Blockds 17.12

Oczywiście dodaję zawsze w ten sposób, w który napisałeś. Jak nie działa od razu, to próbuję dopisać dyrektywy, ale tym razem pojawia mi się błąd:
unterminated ifndef

0
Dominika Łęczycka napisał(a):

Oczywiście dodaję zawsze w ten sposób, w który napisałeś. Jak nie działa od razu, to próbuję dopisać dyrektywy, ale tym razem pojawia mi się błąd:
unterminated ifndef

Jak obecnie wyglądają u Ciebie wszystkie dyrektywy (ze wszystkich plików)? (#include, #define itd.)

0
Dominika Łęczycka napisał(a):

Witam :-)
W ostatnim czasie zaczęłam pisać w konsoli grę w statki. Jest to jak na razie jeden z moich większych projektów (uczę się programowania raczej od niedawna).
Pisząc grę miałam głównie przećwiczyć używanie wskaźników oraz posługiwanie się strukturami danych, w tym typem wyliczeniowym enum.
Kiedy doszłam do momentu, gdzie zaczęło mieć sens odpalenie gry i obejrzenie efektów swojej pracy- kompilator pokazał mi pierdyliard błędów... :-(
No nic- mimo tego, że jest ich aż tak dużo, wciąż żywię nadzieję, że będę to w stanie jakoś naprawić.
Zanim napisałam ten wątek, spędziłam kilka godzin naprawiając te błędy, które póki co naprawić potrafiłam- i komunikatów jest znacząco mniej niż na początku (musicie mi uwierzyć na słowo :-b).
Ale niestety doszłam do wniosku, że z moim dotychczasowym poziomem umiejętności ze wszystkim sobie sama nie poradzę :-( - dlatego uprzejmie proszę o pomoc.

A więc, po pierwsze:
-nigdy wcześniej w większym projekcie nie posługiwałam się enum, więc nie wiem, jak prawidłowo powinnam to rozdzielić na plik z nagłówkami (spis treści) i część zawierającą całe implementacje klas i funkcji.

-po drugie:
próbując załączyć pliki z nagłówkami pisałam na początku pliku z rozszerzeniem .h:
#ifndef __ BATTLESHIP_H__ #define __BATTLESHIP_H__
kompilator pokazuje mi błąd: unterminated ifndef- jest to dla mnie zupełnie coś nowego i nie wiem, co mam z tym zrobić :-(

  • po trzecie: cała reszta- prawie wszystko to skutki błędów w kodzie, jakie popełniłam przy tworzeniu struktur (wcześniej nie miałam wielu okazji, żeby tego używać)
    Zrobiłam zrzut ekranu i umieściłam w załączniku.

Projekt nieskończonej gry składa się z 6 plików: main.cpp, Battleship.cpp, Battleshipi.h, Instruction.cpp (ten plik to akurat jeden wielki komentarz z pseudokodem, planem tworzenia gry), Utils.cpp i Utils.h (dwa ostatnie zawierają funcje korygujące dane wprowadzane z klawiatury przez użytkownika- użyłam tego w nieco zmienionej formie przy tworzeniu gry w wisielca(poprzedni wpis)).

main.cpp:

include <iostream>
#include "Battleship.h"

using namespace std;

int main()
{
    const char * INPUT_ERROR_STRING = "input error! Please, try again.";

    Player player1;
    Player player2;

    InitializePlayer(player1, "Player1");
    InitializePlayer(player2, "Player2");

    do
    {
        PlayGame(player1, player2);
    }while(WantToPlayAgain());

    return 0;
}

Battleship.h:

enum SizeType
{
    AIRCRAFT_CARRIER_SIZE = 5,
    BATTLESHIP_SIZE = 4,
    CRUISER_SIZE = 3,
    DESTROYER_SIZE = 2,
    SUBMARINE_SIZE = 1,

    BOARD_SIZE = 10,
    NUM_SHIPS = 5,
    PLAYER_NAME_SIZE = 8, // Player1, Player2
    MAX_SHIP_SIZE = AIRCRAFT_CARRIER_SIZE
};

enum ShipType
{
    ST_NONE = 0,
    ST_AIRCRAFT_CARRIER,
    ST_BATTLESHIP,
    ST_CRUISER,
    ST_DESTROYER,
    ST_SUBMARINE
};

enum ShipOrientationType
{
    SO_HORIZONTAL = 0,
    SO_VERTICAL
};

struct ShipPositionType
{
    int row;
    int col;
};

struct Ship
{
    ShipType shipType;
    int shipSize;
    ShipOrientationType orientation;  //stworzylam tutaj typ, ale on sam nie definiuje zadnej kokrenej zmiennej =>
    ShipPositionType position;          // miszê ustawiæ wszystkie statki dla kazdego gracza
};

enum GuessType
{
    GT_NONE = 0,
    GT_MISSED,
    GT_HIT
};

struct ShipPartType
{
    ShipType shipType;
    bool isHit;
};

struct Player
{
    char playerName[PLAYER_NAME_SIZE];
    Ship ships[NUM_SHIPS];                  // musze ustawic wszystkie statki poprawnie i przekazac graczowi jeden typ statku do
    GuessType guessBoard[BOARD_SIZE][BOARD_SIZE];   // kazdego z poszczegolnych elementow tablicy
    ShipPartType shipBoard[BOARD_SIZE][BOARD_SIZE];
};

Battleship.cpp

#include <iostream>
#include <cstring>
#include <cctype>
#include "Battleship.h"
#include "Utils.h"

using namespace std;

const char * INPUT_ERROR_STRING = "input error! Please, try again.";

void InitializePlayer(Player & player, const char * playerName)
{
    if(playerName != nullptr && strlen(playerName)>0)
    {
        {
            strcpy(player, playerName);
        }

        InitializeShip(player.ships[0], AIRCRAFT_CARRIER_SIZE, ST_AIRCRAFT_CARRIER);
        InitializeShip(player.ships[1], BATTLESHIP_SIZE, ST_BATTLESHIP);
        InitializeShip(player.ships[2], CRUISER_SIZE, ST_CRUISER);
        InitializeShip(player.ships[3], DESTROYER_SIZE, ST_DESTROYER);
        InitializeShip(player.ships[4], SUBMARINE_SIZE, ST_SUBMARINE);
    }
}

void InitializeShip(Ship & ship, int shipSize, ShipType shipType)
{
        ship.shipType = ST_AIRCRAFT_CARRIER;
        ship.shipSize = AIRCRAFT_CARRIER_SIZE;
        ship.position.row = 0;
        ship.position.col = 0;
        ship.orientation = SO_HORIZONTAL;
}

void PlayGame(Player& player1, Player&player2)
{
    SetUpBoards(player1);
    SetUpBoards(player2);
}

bool WantToPlayAgain()
{
    char input;
    const char validInput[2] = {'y','n'};
    input = GetCharacter("Would you like to play again? (y/n)", INPUT_ERROR_STRING, validInput, 2, CC_LOWER_CASE);
    return input == 'y';
}

void SetUpBoards(Player& player)
{
    ClearBoards(player);
    DrawBoards(player);
}

void ClearBoards(Player&player)
{
    for(int r=0; r<BOARD_SIZE; r++)
    {
        for(int c=0; c<BOARD_SIZE; c++)
        {
            player.guessBoard[r][c] = GT_NONE;
            player.shipBoard[r][c].shipType = ST_NONE;// no ship here
            player.shipBoard[r][c].isHit = false;

        }
    }
}

void DrawBoards(const Player&player)
{
    DrawColumnsRow();
    DrawColumnsRow();
    cout<<endl;

    for(int r=0; r<BOARD_SIZE; r++)
    {
        DrawSeparatorLine();
        cout<<" ";

        DrawSeparatorLine();
        cout<<endl;

        DrawShipBoardRow(player, r);
        cout<<" ";

        DrawGuessBoardRow(player, r);
        cout<<endl;
    }
    DrawSeparatorLine();
    cout<<" ";
    DrawSeparatorLine();
    cout<<endl;

}

void DrawSeparatorLine()
{
    cout<<" ";

    for(int c=0; c<BOARD_SIZE; c++)
    {
        cout<<"+---";
    }
    cout<<"+";
}

void DrawColumnsRow()
{
    cout<<"  ";
    for(int c=0; c<BOARD_SIZE; c++)
    {
        int columnName = c+1;
        cout<<" "<<columnName<<"  ";
    }
    cout<<"+";
}

char GetShipReprezentation(const Player& player, int row, int col)
{
    if(player.guessBoard[row][col].isHit)
    {
        return '*';// represents hit
    }

    if(player.shipBoard[row][col].shipType == ST_AIRCRAFT_CARRIER)
    {
        return 'A';
    }
    else if(player.shipBoard[row][col].shipType == ST_BATTLESHIP)
    {
        return 'B';
    }
    else if(player.shipBoard[row][col].shipType == ST_CRUISER)
    {
        return 'C';
    }
    else if(player.shipBoard[row][col].shipType == ST_DESTROYER)
    {
        return 'D';
    }
    else if(player.shipBoard[row][col].shipType == ST_SUBMARINE)
    {
        return 'S';
    }
    else return ' ';
}

char GetGuessRepresentationAt(const Player& player, int row, int col)
{
    if(player.guessBoard[row][col] == GT_HIT)
    {
        return '*';
    }
    else if(player.guessBoard[row][col == GT_MISSED])
    {
        return 'o';
    }
    else return ' ';
}

void DrawShipBoardRow(const Player& player, int row)
{
    char rowName = row + 'A';
    cout<<rowName<<"|";

    for(int c=0; c<BOARD_SIZE; c++)
    {
        cout<<" "<<GetShipReprezentation(player, row, c)<<" ";
    }
}

void DrawGuessBoardRow(const Player& player, int row)
{
    char rowName = row + 'A';
    cout<<rowName<<"|";

    for(int c=0; c<BOARD_SIZE; c++)
    {
        cout<<" "<<GetGuessRepresentationAt(player, row, c)<<" ";    // tu trzeba uzupelnic reprezentacja kazdego statku
    }
}

Instruction.cpp:

/*
    InitPlayer(player1, "Player1");
    InitPlayer(player2, "Player2");

    do
    {
        PlayGame(player1, player2);
    } while(WantToPlayAgain());

    PlayGame()
    {
        SetupBoard(Player1);
        SetupBoard(Player2);

        do
        {
            DrawBoards(currentPlayer)

            do
            {
                Prompt the current player for a guess
                guess = GetGuess()
            } while(!IsGuessIsValid(guess, currentPlayer));

            UpdateBoards(guess, currentPlayer, otherPlayer);
            DrawBoard(currentPlayer) // to see the result of the guess

            if(a ship was sunk on currentPlayer's turn)
            {
                output that the current player sunk that ship
            }
            WatForKeyPress

            SwitchPlayers()

        } while(!GameIsOver());

        DisplayWinner();
    }

    SetUpBoards(player)
    {
        ClearBoards(player)

        for(all the ships)
        {
            DrawBoards(player)

            currentShip = Get the current ship

            // sprawdzam, czy statek zostal umieszczony poprawnie

            do
            {
                Get Board Position for the head of the ship
                Get the ship orientation

                isValidPlacement = IsValidPlacement(currenShip, position, orientation, player)
                if (!isValidPlacement)
                {
                    output to the player that it was not a valid placement
                }
            } while(!isValidPlacement)

            PlaceShipOnBoard(currenShip, position, orientation, player)
        }
    }

    IsValidPlacement(currentShip, position, orientation, player)
    {
        if(orientatin == HO0RIZONTAL)
        {
            for(all the columns the currentShip would take up)
            {
                if(ship will overlap another ship or the ship will be off the board horizontally)
                {
                    return false
                }
            }
        }
        else
        {
            for(all the rows the currentShip would take up)
            {
                if(ship will overlap another ship or the ship will be off the board vertically)
                {
                    return false
                }
            }
        } return true
    }

    PlaceShipOnBoard(currentShip, position, orientation, player)
    {
        ship.position = position
        ship.orientation = orientation

        if(orientation == HORIZONTAL)
        {
            for(all the columns the ship would take up)
            {
                set the ship part on the board at position.row and current column
            }
        }
        else
        {
            for(all the rows that the ship would take up)
            {
                set the ship part on the board at current row and position.col
            }
        }
    }

    UpdateBoards(guess, currentPlayer, otherPlayer)
    {
        if(otherPlayer's ship board at guess is a ship)
        {
            // hit
               set hit on the currentPlayer's guess board
               apply damage to the otherPlayer's shipBoard
               return shipType
        }
        else
        {
            set miss on the currentPlayer's guess board
            return ST_NONE
        }
    }

    IsGameOver(player1, player2)
    {
        return AreAllShipsSunk(player1) || AreAllShipsSunk(player2)
    }

    AreAllShipsSunk(player)
    {
        for(all the player's ships)
        {
            if(!IsSunk(player, currentShip))
            {
                return false
            }
        } return true
    }

    IsSunk(player, ship)
    {
        if(ship.orientation == HORIZONTAL)
        {
            for(columns that ship takes up)
            {
                if(currentPosition on the shipBoard is not hit)
                {
                    return false
                }
            }
        }
        else
        {
            for(rows that the ship takes up)
            {
                if(currentPosition on the shipBoard is not hit)
                {
                    return false
                }
            }
        }
    }

*/

Utils.h:

#ifndef __ UTILS_H__
#define __UTILS_H__

enum CharacterCaseType
{
    CC_UPPER_CASE=0,
    CC_LOWER_CASE,
    CC_EITHER
};

char GetCharacter(const char* prompt, const char*error);
char GetCharacter(const char* prompt, const char* error, const char validInput[], int validInputLength, CharacterCaseType charCase);

#endif

Utils.cpp

#include <iostream>
#include <cctype>
#include "Utils.h"

using namespace std;

const int IGNORE_CHARS = 256; //to do main
const char * INPUT_ERROR_STRING = "input error! Please, try again.";

char GetCharacter(const char* prompt, const char*error)
{
    char input;
    bool failure;

    do
    {
        failure=false;
        cout<<prompt;
        cin>>input;

        if(cin.fail())
        {
            cin.clear();
            cin.ignore(IGNORE_CHARS, '\n');
            cout << error << endl;
            failure=true;
        }
        else
        {
            cin.ignore(IGNORE_CHARS, '\n');

            if(isalpha(input))
            {
                input = tolower(input);
            }
            else
            {
                cout<<error<<endl;
                failure = true;
            }
        }
    }while(failure); return input;
}

char GetCharacter(const char* prompt, const char* error, const char validInput[], int validInputLength, CharacterCaseType charCase)
{
    char input;
    bool failure;

    do
    {
        failure=false;
        cout<<prompt;
        cin>>input;

        if(cin.fail())
        {
            cin.clear();
            cin.ignore(IGNORE_CHARS, '\n');
            cout << error << endl;
            failure=true;
        }
        else
        {
            cin.ignore(IGNORE_CHARS, '\n');

            if(isalpha(input))
            {
                if(charCase == CC_UPPER_CASE)
                {
                    input = toupper(input);
                }
                else if(charCase == CC_LOWER_CASE)
                {
                    input = tolower(input);
                }

                for (int i=0;i<validInputLength;i++)
                {
                    if(input==validInput[i])
                    {
                        return input;
                    }
                }
            }
            cout<<error<<endl;
            failure=true;
        }
    }while(failure); return input;
}

Proszę o wyrozumiałość w związku z tym, że tu jest aż tak dużo błędów.
Wiem, że tego dużo, ale może jednak komuś będzie się chciało to chociaż pobieżnie przejrzeć i podpowiedzieć mi co i jak poprawić ;-)
Z góry dziękuję za odpowiedź :-)

Poprzednie błędy już udało mi się poprawić.
Kiedy zmieniłam warunek w funkcji GetShipReprezentation z if(player.guessBoard[row][col].isHit na if(player.guessBoard[row][col]==GT_HIT), kompilator zamiast poprzedniego błędu pokazał mi komunikat 1d returned exit status. Kiedyś miałam już taką sytuację i po prostu tamtego programu nie naprawiłam, bo nie wiedziałam, co z tym zrobić. Ale tej gry nie chciałabym tak po prostu porzucić nieskończonej, bo już dużo czasu nad tym spędziłam :-(

Czy ktoś może kiedyś rozwiązał już podobny problem?
Resetowałam już komputer.
spróbowałam też otworzyć wcześniej działający projekt, dodać odpowiednią ilość plików i po prostu przekleić treść, ale też nie działa :-(
Bardzo proszę o odpowiedź, co mogę jeszcze zrobić w tej sytuacji.

1
  1. Podaj wszystko, co Code::Blocks wypisuje na wyjściu (rozumiem, że budujesz projekt w Code::Blocks).
  2. Czy tam nie powinno być ld ("el-de") zamiast 1d?
  3. Czy w komunikacie nie ma przypadkiem nazwy collect2? (w internecie można spotkać ten błąd z taką nazwą)
  4. Zobacz to: http://users.csc.calpoly.edu/[...]/Resources/errormessages.html Nie sądzę, by trzeba było załączyć wspomnianą na tej stronie bibliotekę math, ale być może zapomniałaś dołączyć, lub źle dołączasz, w jakimś pliku jakąś inną bibliotekę lub plik.
  5. Jak czytam w internecie, część ld być może oznacza, że to linker (a nie kompilator) wyrzuca błąd (zwrócenie statusu 1 oznacza w rozumieniu Linuksa błąd). Możesz zobaczyć dla ciekawości to: https://linux.die.net/man/1/ld

UPDATE: 6. Również na tej stronie wspominany jest podobny błąd: http://web.mst.edu/~cpp/common/common_errors.html

0

Jeżeli "statki w konsoli" nazywasz większym projektem, w dodatku tak napisanym to lepiej daj sobie z tym spokój. Piszesz niby w c++ a to wygląda jak c. Nie korzystasz z dobrodziejstw jakie daje biblioteka STL. Jedyny plus to chyba taki że korzystasz z cin cout zamiast z printf scanf tak jak większość :-D

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0