Du bist nicht angemeldet.

Stilllegung des Forums
Das Forum wurde am 05.06.2023 nach über 20 Jahren stillgelegt (weitere Informationen und ein kleiner Rückblick).
Registrierungen, Anmeldungen und Postings sind nicht mehr möglich. Öffentliche Inhalte sind weiterhin zugänglich.
Das Team von spieleprogrammierer.de bedankt sich bei der Community für die vielen schönen Jahre.
Wenn du eine deutschsprachige Spieleentwickler-Community suchst, schau doch mal im Discord und auf ZFX vorbei!

Werbeanzeige

1

19.03.2015, 20:36

Anfängerfrage zu Arrays (2-Dimensional)

Hallo liebe Community. Ich arbeite jetzt seit ca. 2 Wochen mit dem Buch "c++ für Spieleprogrammierer" von Heiko Kalista und bin jetzt mit dem Kapitel "Arrays und Strukturen" fertig.
Da ich alles bisherige FESTIGEN möchte, bevor ich zu den Zeigern & Referenzen komme, hab ich ein kleines Programm geschrieben, was an eine ultra-primitive Version von "Schiffe versenken" angelehnt ist.
Ich poste den Code und erkläre danach, was er tut und wo genau mein Problem liegt.

Zuerst der Code:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
#include <iostream>
#include <Windows.h>

#pragma comment (lib, "winmm.lib")
using namespace std;




struct s_Spielfeld
{
 bool bBesetzt;
 bool bBeschossen;
};

const int Breite = 12;
const int Hoehe = 12;
s_Spielfeld Feld[Breite][Hoehe];


void Erstellen();
void Besetzen();
void Anzeigen();



int main()
{
 srand (timeGetTime() );
 int Auswahl = 0;

 do
 {
  cout << "Menue:" << endl;
  cout << "-----------------------" << endl;
  cout << "1. Erstellen" << endl;
  cout << "2. Besetzen" << endl;
  cout << "3. Anzeigen" << endl;
  cout << "4. Beenden" << endl;
  cout << "-----------------------" << endl << endl;

  
 cin >> Auswahl;

 switch(Auswahl)
 {
 case(1):
 {
  Erstellen();
 }break;
 case(2):
 {
  Besetzen();
 }break;
 case(3):
 {
  Anzeigen();
 }break;
 case(4):
 {
 }break;
 }


 }while(Auswahl!=4);

 return 0;

}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////


void Erstellen()
{
 int Random;
 int Random1;
 int VertHori;
 //Zufallsgenerator 
 

 VertHori = (rand()%2); //Schiff horizontal oder vertikal?


 if(VertHori==0) //Schiff wird VERTIKAL gestellt
 {
     do
     {
        Random = (rand()%12); 
        Random1 = (rand()%12);

     }while (Random1 < 3);
     
    Feld[Random][Random1].bBesetzt=1;
    ////////////////
    for(int i=Random1-3; i<Random1; i++)
    {
        Feld[Random][i].bBesetzt=1;
    }
    ////////////////

 }
    else            //Schiff wird HORIZONTAL gestellt
     {
         do
         {
        Random = (rand()%12); 
        Random1 = (rand()%12);
    
         }while (Random < 3);
            
 Feld[Random][Random1].bBesetzt=1;
        
for(int j=Random-3; j<Random;j++)
{
    Feld[j][Random1].bBesetzt=1;
        
}
 
 
}
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

void Besetzen()
{
 int x, y;

 do
 {
 cout << "X-Koordinate:";
 cin >> x;

 cout << "Y-Koordinate";
 cin >> y;

 if (Feld[x-1][y-1].bBesetzt==1)
  cout << "Getroffen!!!!!" << endl << endl;
 else
  cout << "Daneben!!!!!" << endl << endl;

 Feld[x-1][y-1].bBeschossen=1;

 }while(x<1 || x>13);


}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////



void Anzeigen()                         //DEBUG-ANZEIGE
{
 for(int i=0; i<Hoehe; i++)
 {
  for (int j=0; j<Breite; j++)
  {
  
    if(Feld[j][i].bBesetzt==1)
    cout << "X";
    else
    cout << ".";
   }
    cout << endl;
  }
 
 }



Ich erstelle mir quasi ein 12x12 großes leeres Spielfeld, ähnlich wie bei "Schiffe versenken". Wenn ich Menüpunkt 1 auswähle, stellt der Computer per Zufall ein 4-Felder großes Schiff horizontal oder vertikal auf das Feld.
Bei Menüpunkt zwei kann ich quasi die Felder "beschießen" und erfahre, ob ich mit meinem Schuss ein Schiff getroffen habe.
Menüpunkt 3 zeigt mir einfach das Feld an und wo die Schiffe stehen. Ich sende vorsichtshalber auch ein Bild mit.
Auf dem Bild sieht man quasi das Spielfeld, auf dem bereits das Schiff steht.

Mein Problem ist jetzt folgendes. Ich möchte, dass der Computer MEHRERE Schiffe auf dem Feld auslegt. Aber die Schiffe sollen sich NICHT überschneiden.
Ich weiß nicht, wie ich dem Programm sagen soll, es soll abfragen, ob sich an einer der Positionen schon ein belegtes Feld befindet.
Ich könnte die Funktion "ERSTELLEN" ja mehrmals aufrufen und er erstellt mir jedes mal ein 4er-Schiff. Jedoch möchte ich verhindern dass diese sich überschneiden!

Ich hoffe, jemand versteht mein Problem und kann mir helfen. Vielen lieben Dank im voraus!!
»Sacume« hat folgendes Bild angehängt:
  • Spielfeld.png

2

19.03.2015, 20:57

Ähm ich versteh die Frage glaube nicht ganz: Du hast ein Feld mxn wo du speicherst, ob auf dem jeweiligen Feld ein Schiff is oder nicht. Und du willst, dass sobald du ein zweites Schiff positionierst, sich die nicht überschneiden?

Dann musst du einfach nur beim neuen Erstellen eines Schiffes überprüfen, ob die jeweiligen Felder schon besetzt sind oder nicht. Falls ja => neue Position suchen. Oder meintest du was anderes?

3

19.03.2015, 21:06

Die Frage hast du schon richtig verstanden! Ich weiß natürlich, dass ich prüfen muss, ob sich an der jeweiligen Stelle schon ein Schiff befindet! Jedoch zerbrech ich mir den Kopf, WIE ich das mache.
Hier ist der Code-Fetzen der ein Schiff auf Feld[x][y] legt.

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
void Erstellen(){
 int Random;
 int Random1;
 int VertHori;
 //Zufallsgenerator 
 

 VertHori = (rand()%2); //Schiff horizontal oder vertikal?


 if(VertHori==0) //Schiff wird VERTIKAL gestellt
 {
     do
     {
        Random = (rand()%12); 
        Random1 = (rand()%12);

     }while (Random1 < 3);
     
    Feld[Random][Random1].bBesetzt=1;
    ////////////////
    for(int i=Random1-3; i<Random1; i++)
    {
        Feld[Random][i].bBesetzt=1;
    }
    ////////////////

 }
    else            //Schiff wird HORIZONTAL gestellt
     {
         do
         {
        Random = (rand()%12); 
        Random1 = (rand()%12);
    
         }while (Random < 3);
            
 Feld[Random][Random1].bBesetzt=1;
        
for(int j=Random-3; j<Random;j++)
{
    Feld[j][Random1].bBesetzt=1;
         }




Ich weiß eben nicht, wie genau ich die Bedingung schreiben muss, dass es funktioniert :D

4

19.03.2015, 21:12

C-/C++-Quelltext

1
2
3
4
5
6
7
8
for (int i = Random1 - 3; i<Random1; i++)
{
    if (Feld[Random][i].bBesetzt == 1) {
        //feld ist besetzt => setze das schiff woanders
        break;
    }
    Feld[Random][i].bBesetzt = 1;
}

So nach dem Motto würde ich das machen ^^

BlueCobold

Community-Fossil

Beiträge: 10 738

Beruf: Teamleiter Mobile Applikationen & Senior Software Engineer

  • Private Nachricht senden

5

20.03.2015, 06:29

Das ist aber sehr unschön und kann noch immer Überschneidungen liefern. Was man wohl will, ist das:

- tue
-- erzeuge zufällige Position
- solange Position schon besetzt
Teamleiter von Rickety Racquet (ehemals das "Foren-Projekt") und von Marble Theory

Willkommen auf SPPRO, auch dir wird man zu Unity oder zur Unreal-Engine raten, ganz bestimmt.[/Sarkasmus]

6

20.03.2015, 08:52

An sich könnte man ja alle möglichen Varianten in einen vector schieben und dann daraus einen per Zufall aussuchen.
Dann könnte man auch relativ straight vorgehen, indem man von oben nach unten und rechts nach links alle Felder durchsucht und dann einfach ein beliebiges Element ausgibt.

So würde ich pseudo mäßig vorgehen:

C-/C++-Quelltext

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
struct ShipPosition
{
    int x = 0;
    int y = 0;
    bool vertical = true;
};

ShipPosition getRandomValidPosition(int shipSize)
{
    // befülle zuerst den vector mit valid Positions
    std::vector<ShipPosition> posVec;
    for (int x = 0;  x < width; ++x)
    {
        for (int y = 0; y < height; ++y)
        {
            ShipPosition pos(x, y, true);
            if (validPosition(pos))
                posVec.push_back(pos);
            else
            {
                pos.vertical = false;
                if (validPosition(pos))
                    posVec.push_back(pos);
            }
        }
    }
    
    // wenn keine valide Position vorhanden ist, schmeiße eine exception
    if (posVec.empty())
        throw std::runtime_error("leerer vector");
    
    return posVec.at(randomPosition);
}

bool validPosition(ShipPosition pos, int shipSize)
{
    if (pos.vertical)
    {
        for (int x = 0; pos.x + x < width && x < shipSize; ++x)
        {
            if (Feld[pos.y][pos.x  + x].bBesetzt==1)
                return false;
        }
    }
    else
    {
        for (int y = 0; pos.y + y < height && y < shipSize; ++y)
        {
            if (Feld[pos.y + y][pos.x].bBesetzt==1)
                return false;
        }
    }
    return true;
}

7

20.03.2015, 14:41

Vielen Dank für die Antworten. Da ich momentan noch ein blutiger Anfänger bin und keine Ahnung von Vektoren habe, weiß ich jetzt, dass es mit meinem jetzigen Wissensstand einfach nur schwer möglich ist.
Ist auch kein wichtiges Projekt oder sowas. Ich wollte nur wissen, ob es mit den mir zur Verfügung stehenden mitteln (Schleifen, Arrays, Strukturen, Funktionen) schon möglich ist, sowas zu programmieren.

Ich bedanke mich herzlich für Eure Hilfe, war aber wohl leider nicht das letzte Mal, dass ich irgendwelchen Fragen stellen muss!! :(
Nochmals vielen Dank!

Sacaldur

Community-Fossil

Beiträge: 2 301

Wohnort: Berlin

Beruf: FIAE

  • Private Nachricht senden

8

20.03.2015, 14:56

[Nachtrag: falsches Thema... *hust*]
Vektoren sind keine schwarze Magie und sie zu verstehen sollte nicht zu schwierig sein. Such einfach nach entsprechenden Erklärungen im Internet und versuche diese beim Programmieren zu verwenden.
Wenn man keine Vektoren verwendet (zugegebenermaßen gab es auch bei mir eine solche Zeit), führt man letztendlich die gleichen Berechnungen durch, nur statt position += delta; zu rechnen, macht man positionX += deltyX; positionY += deltaY;. (Letztendlich ist das einfach nur eine Sache aus der Mathematik, nicht aus der Programmierung.)
Spieleentwickler in Berlin? (Thema in diesem Forum)
---
Es ist ja keine Schande etwas falsch zu machen, als Programmierer tu ich das täglich, [...].

Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von »Sacaldur« (20.03.2015, 17:47)


Schorsch

Supermoderator

Beiträge: 5 145

Wohnort: Wickede

Beruf: Softwareentwickler

  • Private Nachricht senden

9

20.03.2015, 16:21

Sacaldur hier ging es um std::vector und nicht um Vektoren. Ein std::vector ist eine Art Array. Ist ein bisschen cooler und kann ein bisschen mehr. Guck vielleicht einfach mal bei Google was das ganze soll. Ansonsten ist anti-freaks Idee zu bevorzugen. Wenn du eine zufällige Position suchst, dann prüfst ob sie schon besetzt ist und gegebenenfalls dann eine neue Position suchst und wieder von vorne beginnst kann es dir theoretisch passieren dass dein Programm nie endet. Was wäre denn wenn die zufällige Position zufälligerweise immer eine Position ist die besetzt ist? Also ist es besser so wie schon vorgeschlagen, alle möglichen passenden Positionen zu suchen/bestimmen und dann davon eine zufällige auszuwählen.
„Es ist doch so. Zwei und zwei macht irgendwas, und vier und vier macht irgendwas. Leider nicht dasselbe, dann wär's leicht.
Das ist aber auch schon höhere Mathematik.“

Werbeanzeige