C++ :: Aufgabe #48 :: Lösung #1
1 Lösung

#48
Spiel: Schiffe versenken
Fortgeschrittener - C++
von david_k
- 06.01.2013 um 17:24 Uhr
Es soll ein Schiffe-Versenken Spiel (Konsole oder Gui) erstellt werden. Man solll gegen den Computer oder gegen einen Menschen spielen können.
#1

von mraimbot (590 Punkte)
- 19.08.2019 um 17:41 Uhr
Umsetzung ist für Konsole. Spiel ist gegen Computer und Mensch möglich. Der Computer ist sehr einfach gestaltet und wählt eine zufällige noch nicht besuchte Position aus.
Im Anhang liegen drei Screenshots vom Spiel vor.
C-Code
Im Anhang liegen drei Screenshots vom Spiel vor.

/////////////////////////////////////////////////////////////// /// Aufgabe: https://trainyourprogrammer.de - C++ - #48 /// - Spiel: Schiffe versenken /// Programmierer: Sebastian Schröder /// Datum: 19.08.2019 /// Software: Visual Studio 2019, Windows 10 /////////////////////////////////////////////////////////////// #include <conio.h> #include <iostream> #include <windows.h> #define MAP_SIZE_X 10 #define MAP_SIZE_Y 10 #define MAP_OFFSET_X_PLAYER1 1 #define MAP_OFFSET_X_PLAYER2 12 #define MAP_OFFSET_Y 1 #define icnSHIP 'O' #define icnXSHIP '0' #define icnNOSHIP '#' enum Colors { BORDER = 0, EMPTY = 51, HIT = 52, SHIPGHOSTFALSE = 52, SHIPPLACED = 54, SHIPGHOST = 62, FAIL = 55, TITLE = 112, TEXT = 129, KEY = 133 }; enum Keys { ONE = 49, TWO = 50, ZERO = 48, A = 97, D = 100, F = 102, R = 114, S = 115, W = 119 }; enum GameModes { PvP = 0, PvC = 1 }; enum Players { Player1 = 0, Player2 = 1 }; enum Ships { NONE = 0, SHIP, NOSHIP, XSHIP }; static HANDLE hConsole; static Ships maps[2][MAP_SIZE_Y][MAP_SIZE_X] = {Ships::NONE}; void Draw_Menu(void); void Draw_Game_Brackground(void); void Draw_Ships(Players player); void Draw_shots(void); void Game_Setup(GameModes gamemode); void Game_Play(GameModes gamemode); void Game_Reset(void); void Place_Ship(Players player, short length, bool random); COORD select_target(Players player); void CClear(void); // clears the whole console void CColor(short color); // set fore- and backgroundcolor of console void CCursorPos(short x, short y); // set cursor position of console int main() { hConsole = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO csbi; GetConsoleScreenBufferInfo(hConsole, &csbi); WORD colors_standard = csbi.wAttributes; CClear(); Draw_Menu(); do { short choice = _getch(); switch (choice) { case Keys::ONE: Game_Setup(GameModes::PvP); Game_Play(GameModes::PvP); Game_Reset(); break; case Keys::TWO: Game_Setup(GameModes::PvC); Game_Play(GameModes::PvC); Game_Reset(); break; case Keys::ZERO: CColor(colors_standard); return 0; default: continue; } Draw_Menu(); } while (true); } void Draw_Menu(void) { CClear(); CColor(Colors::TITLE); std::cout << " Schiffe versenken \n"; CColor(Colors::KEY); std::cout << "[1] "; CColor(Colors::TEXT); std::cout << "Spieler gegen Spieler \n"; CColor(Colors::KEY); std::cout << "[2] "; CColor(Colors::TEXT); std::cout << "Spieler gegen Computer\n"; CColor(Colors::KEY); std::cout << "[0] "; CColor(Colors::TEXT); std::cout << "Spiel beenden \n\n"; CColor(Colors::TITLE); std::cout << "Credits\n"; CColor(Colors::TEXT); std::cout << "Code & Design: Sebastian Schroeder\n\n"; CColor(Colors::TITLE); std::cout << "Spielregeln: \n"; CColor(Colors::TEXT); std::cout << "Jeder Spieler versteckt eine kleine Flotte \n"; std::cout << "von Schiffen vor seinem Gegner. Derjenige, \n"; std::cout << "der alle Schiffe des Gegners komplett ge- \n"; std::cout << "troffen und versenkt hat, gewinnt. \n\n"; std::cout << "Eine Flotte besteht aus: \n"; std::cout << "- 1x Schlachtschiff (5 Treffer zum Versenken)\n"; std::cout << "- 1x Kreuzer (4 Treffer zum Versenken) \n"; std::cout << "- 2x Fregatten (3 Treffer zum Versenken) \n"; std::cout << "- 1x Minensucher (2 Treffer zum Versenken) \n"; } void Game_Setup(GameModes gamemode) { CClear(); Draw_Game_Brackground(); CColor(Colors::TEXT); std::cout << "Spieler 1 setzt seine Schiffe. Spieler 2 sollte solange den Bildschirm nicht beachten.\n"; std::cout << "Schiffe: ein 5er, ein 4er, zwei 3er und ein 2er. \n"; CColor(Colors::KEY); std::cout << "[WASD] "; CColor(Colors::TEXT); std::cout << "Schiff bewegen \n"; CColor(Colors::KEY); std::cout << "[R] "; CColor(Colors::TEXT); std::cout << "Schiff rotieren \n"; CColor(Colors::KEY); std::cout << "[F] "; CColor(Colors::TEXT); std::cout << "Schiff platzieren" << std::endl; Place_Ship(Players::Player1, 5, false); Place_Ship(Players::Player1, 4, false); Place_Ship(Players::Player1, 3, false); Place_Ship(Players::Player1, 3, false); Place_Ship(Players::Player1, 2, false); CClear(); Draw_Game_Brackground(); CColor(Colors::TEXT); std::cout << "Spieler 2 setzt seine Schiffe. Spieler 1 sollte solange den Bildschirm nicht beachten.\n"; std::cout << "Schiffe: ein 5er, ein 4er, zwei 3er und ein 2er. \n"; CColor(Colors::KEY); std::cout << "[WASD] "; CColor(Colors::TEXT); std::cout << "Schiff bewegen \n"; CColor(Colors::KEY); std::cout << "[R] "; CColor(Colors::TEXT); std::cout << "Schiff rotieren \n"; CColor(Colors::KEY); std::cout << "[F] "; CColor(Colors::TEXT); std::cout << "Schiff platzieren" << std::endl; Place_Ship(Players::Player2, 5, gamemode); Place_Ship(Players::Player2, 4, gamemode); Place_Ship(Players::Player2, 3, gamemode); Place_Ship(Players::Player2, 3, gamemode); Place_Ship(Players::Player2, 2, gamemode); } void Draw_Game_Brackground(void) { CColor(Colors::BORDER); std::cout << " \n"; for (short y = 0; y < MAP_SIZE_Y; y++) { CColor(Colors::BORDER); std::cout << " "; CColor(Colors::EMPTY); std::cout << " "; CColor(Colors::BORDER); std::cout << " "; CColor(Colors::EMPTY); std::cout << " "; CColor(Colors::BORDER); std::cout << " \n"; } CColor(Colors::BORDER); std::cout << " \n"; } void Draw_Ships(Players player) { short Cpos_x = (player == Players::Player1) ? MAP_OFFSET_X_PLAYER1 : MAP_OFFSET_X_PLAYER2; short Cpos_y = MAP_OFFSET_Y; CCursorPos(Cpos_x, Cpos_y); for (short y = 0; y < MAP_SIZE_Y; y++) { for (short x = 0; x < MAP_SIZE_X; x++) { if (maps[player][y][x] == Ships::NONE) { CColor(Colors::EMPTY); std::cout << " "; } else { CColor(Colors::SHIPPLACED); std::cout << icnSHIP; } } std::cout << "\n"; Cpos_y++; CCursorPos(Cpos_x, Cpos_y); } } void Draw_shots(void) { // Player 1 short Cpos_x = MAP_OFFSET_X_PLAYER1; short Cpos_y = MAP_OFFSET_Y; CCursorPos(Cpos_x, Cpos_y); for (short y = 0; y < MAP_SIZE_Y; y++) { for (short x = 0; x < MAP_SIZE_X; x++) { if (maps[0][y][x] == Ships::NONE || maps[0][y][x] == Ships::SHIP) { CColor(Colors::EMPTY); std::cout << " "; } else if (maps[0][y][x] == Ships::XSHIP) { CColor(Colors::HIT); std::cout << icnXSHIP; } else { CColor(Colors::FAIL); std::cout << icnNOSHIP; } } std::cout << "\n"; Cpos_y++; CCursorPos(Cpos_x, Cpos_y); } // Player 2 Cpos_x = MAP_OFFSET_X_PLAYER2; Cpos_y = MAP_OFFSET_Y; CCursorPos(Cpos_x, Cpos_y); for (short y = 0; y < MAP_SIZE_Y; y++) { for (short x = 0; x < MAP_SIZE_X; x++) { if (maps[1][y][x] == Ships::NONE || maps[1][y][x] == Ships::SHIP) { CColor(Colors::EMPTY); std::cout << " "; } else if (maps[1][y][x] == Ships::XSHIP) { CColor(Colors::HIT); std::cout << icnXSHIP; } else { CColor(Colors::FAIL); std::cout << icnNOSHIP; } } std::cout << "\n"; Cpos_y++; CCursorPos(Cpos_x, Cpos_y); } } void Place_Ship(Players player, short length, bool random) { short Cpos_x = (player == Players::Player1) ? MAP_OFFSET_X_PLAYER1 : MAP_OFFSET_X_PLAYER2; short Cpos_y = MAP_OFFSET_Y; short pos_x = 0; short pos_y = 0; bool rotated = false; bool ship_placed = false; bool pos_OK; do { if (random) { rotated = rand() % 2; pos_x = rand() % (MAP_SIZE_X - (rotated ? 0 : length)); pos_y = rand() % (MAP_SIZE_Y - (rotated ? length : 0)); } else { Draw_Ships(player); } pos_OK = true; for (short tile = 0; tile < length; tile++) { if (rotated) { if (maps[player][pos_y + tile][pos_x] != Ships::NONE || (pos_y + tile > 0 && maps[player][pos_y + tile - 1][pos_x] != Ships::NONE) || (pos_y + tile < MAP_SIZE_Y - 1 && maps[player][pos_y + tile + 1][pos_x] != Ships::NONE) || (pos_x > 0 && maps[player][pos_y + tile][pos_x - 1] != Ships::NONE) || (pos_x < MAP_SIZE_X - 1 && maps[player][pos_y + tile][pos_x + 1] != Ships::NONE)) { pos_OK = false; break; } } else if (maps[player][pos_y][pos_x + tile] != Ships::NONE || (pos_y > 0 && maps[player][pos_y - 1][pos_x + tile] != Ships::NONE) || (pos_y < MAP_SIZE_Y - 1 && maps[player][pos_y + 1][pos_x + tile] != Ships::NONE) || (pos_x + tile > 0 && maps[player][pos_y][pos_x + tile - 1] != Ships::NONE) || (pos_x + tile < MAP_SIZE_X - 1 && maps[player][pos_y][pos_x + tile + 1] != Ships::NONE)) { pos_OK = false; break; } } if (random) { if (pos_OK) { maps[player][pos_y][pos_x] = Ships::SHIP; if (rotated) { for (int tile = 1; tile < length; tile++) { maps[player][pos_y + tile][pos_x] = Ships::SHIP; } } else { for (int tile = 1; tile < length; tile++) { maps[player][pos_y][pos_x + tile] = Ships::SHIP; } } ship_placed = true; } } else { pos_OK ? CColor(Colors::SHIPGHOST) : CColor(Colors::SHIPGHOSTFALSE); CCursorPos(Cpos_x, Cpos_y); std::cout << icnSHIP; if (rotated) { for (int tile = 1; tile < length; tile++) { CCursorPos(Cpos_x, Cpos_y + tile); std::cout << icnSHIP; } } else { for (int tile = 1; tile < length; tile++) { std::cout << icnSHIP; } } CCursorPos(Cpos_x, Cpos_y); short choice = _getch(); switch (choice) { case Keys::W: if (pos_y > 0) { pos_y--; Cpos_y--; } break; case Keys::S: if (pos_y < MAP_SIZE_Y - (rotated ? length : 1)) { pos_y++; Cpos_y++; } break; case Keys::A: if (pos_x > 0) { pos_x--; Cpos_x--; } break; case Keys::D: if (pos_x < MAP_SIZE_X - (rotated ? 1 : length)) { pos_x++; Cpos_x++; } break; case Keys::R: rotated = !rotated; if (rotated && pos_y + length - 1 >= MAP_SIZE_Y) { pos_y = MAP_SIZE_Y - length; Cpos_y = pos_y + MAP_OFFSET_Y; } if (!rotated && pos_x + length - 1 >= MAP_SIZE_X) { pos_x = MAP_SIZE_X - length; Cpos_x = pos_x + (player == Players::Player1 ? MAP_OFFSET_X_PLAYER1 : MAP_OFFSET_X_PLAYER2); } break; case Keys::F: if (pos_OK) { maps[player][pos_y][pos_x] = Ships::SHIP; if (rotated) { for (int tile = 1; tile < length; tile++) { maps[player][pos_y + tile][pos_x] = Ships::SHIP; } } else { for (int tile = 1; tile < length; tile++) { maps[player][pos_y][pos_x + tile] = Ships::SHIP; } } ship_placed = true; } break; } } } while (!ship_placed); } void Game_Reset() { for (short p = 0; p < 2; p++) { for (short y = 0; y < MAP_SIZE_Y; y++) { for (short x = 0; x < MAP_SIZE_X; x++) { maps[p][y][x] = Ships::NONE; } } } } void Game_Play(GameModes gamemode) { short points_player1 = 17; // 5 + 4 + 3 + 3 + 2; short points_player2 = 17; CClear(); Draw_Game_Brackground(); CColor(Colors::KEY); std::cout << "[WASD] "; CColor(Colors::TEXT); std::cout << "Ziel suchen \n"; CColor(Colors::KEY); std::cout << "[F] "; CColor(Colors::TEXT); std::cout << "Ziel befeuern" << std::endl; do { CCursorPos(0, 0); Draw_Game_Brackground(); Draw_shots(); // Player 1 COORD target = select_target(Players::Player1); if (maps[Players::Player2][target.Y][target.X] == Ships::SHIP) { maps[Players::Player2][target.Y][target.X] = Ships::XSHIP; points_player2--; if (points_player2 == 0) { CCursorPos(0, 0); CColor(Colors::TEXT); std::cout << "Spieler 1 hat alle Schiffe versenkt und das Spiel gewonnen! Weiter mit beliebiger Taste ...\n"; Draw_shots(); points_player2 = _getch(); return; } } else if (maps[Players::Player2][target.Y][target.X] != Ships::XSHIP) { maps[Players::Player2][target.Y][target.X] = Ships::NOSHIP; } Draw_shots(); // Player 2 if (gamemode == GameModes::PvP) { target = select_target(Players::Player2); } else { do { target.X = rand() % MAP_SIZE_X; target.Y = rand() % MAP_SIZE_Y; } while (maps[Players::Player1][target.Y][target.X] == Ships::NOSHIP || maps[Players::Player1][target.Y][target.X] == Ships::XSHIP); } if (maps[Players::Player1][target.Y][target.X] == Ships::SHIP) { maps[Players::Player1][target.Y][target.X] = Ships::XSHIP; points_player1--; if (points_player1 == 0) { CCursorPos(0, 0); CColor(Colors::TEXT); std::cout << "Spieler 2 hat alle Schiffe versenkt und das Spiel gewonnen! Weiter mit beliebiger Taste ...\n"; Draw_shots(); points_player1 = _getch(); return; } } else if (maps[Players::Player1][target.Y][target.X] != Ships::XSHIP) { maps[Players::Player1][target.Y][target.X] = Ships::NOSHIP; } } while (true); } COORD select_target(Players player) { short Cpos_x = (player == Players::Player1) ? MAP_OFFSET_X_PLAYER2 : MAP_OFFSET_X_PLAYER1; short Cpos_y = MAP_OFFSET_Y; COORD target = {0}; do { CCursorPos(Cpos_x, Cpos_y); short choice = _getch(); switch (choice) { case Keys::W: if (target.Y > 0) { target.Y--; Cpos_y--; } break; case Keys::S: if (target.Y < MAP_SIZE_Y - 1) { target.Y++; Cpos_y++; } break; case Keys::A: if (target.X > 0) { target.X--; Cpos_x--; } break; case Keys::D: if (target.X < MAP_SIZE_X - 1) { target.X++; Cpos_x++; } break; case Keys::F: return target; } } while (true); } void CClear(void) { CColor(0); system("cls"); } void CColor(short color) { SetConsoleTextAttribute(hConsole, color); } void CCursorPos(short x, short y) { COORD c = {x, y}; SetConsoleCursorPosition(hConsole, c); }
Kommentare:
Für diese Lösung gibt es noch keinen Kommentar
Seite 1 von 0
1