c++ Switch Anweisung möglichkeiten?

2 Antworten

Wenn du mit reinen Integern arbeitest, die deine Felder repräsentieren, wirst du dich vermutlich schnell verzetteln. An deiner Stelle würde ich eine kompakte constexpr-Ministruktur (bzw. Klasse) dafür bauen, die einige Operatoren überlädt, um dir das Leben zu erleichtern.

Die andere Antwort mit der Enum ist auch OK, allerdings mag ich Enums nicht, die unangemessen viele Konstanten enthalten, denn das ist normalerweise ein Designfehler. (Und 8 * 8 = 64 Konstanten sind m. M. n. eindeutig unangemessen.)

Da du aber von C++ in Kombination mit Switch schreibst, könntest du zur Not auch eigene Literale implementieren! Wenn du also z. B. ...

"C4"_chess

... schreibst, ist das in Wirklichkeit eine Integer-Konstante mit dem Hex-Wert 0x0304. (Die 3 steht für den dritten Buchstaben, also das "C"!) Dabei wird nichts zur Laufzeit berechnet und der Compiler wandelt diese Werte zur Kompilierzeit in Konstanten um!

Siehe dazu folgendes kleines Beispiel, was regen Gebrauch von C++11-Features macht:

#include <ios> // hex
#include <iostream> // cout, endl

#include <cstdlib> // EXIT_SUCCESS, size_t

static_assert(
'0' == 48 && '9' == 57 &&
'a' == 97 && 'z' == 122 &&
'A' == 65 && 'Z' == 90,
"only ASCII supported");

constexpr bool in_range(
const char x, const char lo, const char hi
) noexcept {
return x >= lo && x <= hi;
}

constexpr bool is_chess_char(const char c) noexcept {
return in_range(c, 'a', 'h') || in_range(c, 'A', 'H');
}

constexpr bool is_chess_num(const char c) noexcept {
return in_range(c, '0', '9');
}

constexpr unsigned operator "" _chess(
const char * cstr, const size_t len
) noexcept {
return
(2 == len) && is_chess_char(cstr[0]) && is_chess_num(cstr[1])
? (((1 + (cstr[0] | 0x20) - 'a') << 8) | (cstr[1] - '0'))
: 0;
}

int main(void) {
using namespace std;

auto fields = {"a1"_chess, "c4"_chess, "h8"_chess, "z9"_chess};

for (const auto field : fields) {
cout << "0x" << hex;

cout.width(4);
cout.fill('0');

cout << field << ": ";

switch (field) {
case 0:
cout << "-invalid-";
break;
case "a1"_chess:
cout << "bottom left";
break;
case "H8"_chess:
cout << "top right";
break;
default:
cout << static_cast<char>('A' + (field >> 8) - 1);
cout << static_cast<char>('0' + (field & 0xFF));
break;
}

cout << endl;
}

return EXIT_SUCCESS;
}

Disclaimer A: Ich sage ausdrücklich NICHT, dass du es so machen sollst, sondern wollte nur mal demonstrieren, wie du eigene Literale implementieren kannst. (Es gibt noch mehr Möglichkeiten, auch für numerische Literale!)

Disclaimer B: Der teilweise merkwürdige Einrückungsstil rührt daher, dass ich dem Leser möglichst horizontales Scrollen in dem merkwürdigen Codefenster hier auf GF ersparen möchte. Ich hoffe, man kann das so halbwegs alles untereinander entziffern.

Disclaimer C: Ich weiß, dass die Koordinaten der Feldwerte auch in ein einziges Nibble gepasst hätten, aber als Wort ist es für Einsteiger vielleicht besser fassbar.

Falls dich der Code überfordern sollte, konzentriere dich auf die Schleife in main() am Ende. Hier siehst du wie die Variable "field" vorher indirekt mit einem Fantasie-_chess-Literal initialisiert wurde, und innerhalb der Switch-Cases ebenfalls mit diesen (konstanten!) Literalen verglichen wird.

Wie gesagt, es gibt einen Haufen Möglichkeiten dein Vorhaben zu realisieren. Kommt eben auch immer drauf an, wie groß dein Schachprojekt ist / wird und auf welcher Plattform es hauptsächlich laufen soll. Bei einem Mikrocontroller würde ich Integermagie oder Enums bevorzugen, bei einem Desktop-Programm eine ordentliche Klasse.

Naja, viel Spaß! :)

PS: Wenn du schon Enums nimmst, dann nimm eine Enum Class! Damit landen deine Konstanten nicht im umgebenden Gültigkeitsbereich, sondern derselbe ist klar abgegrenzt, und du kannst sogar den zu Grunde liegenden Typen genau spezifizieren (wichtig wenn du auf eingebetteten Systemen Platz sparen willst!):

enum class Field : unsigned char {
A1, A2, A3, A4, A5, A6, A7, A8,
B1, B2, B3, ...
};

Das ist dann ordentlicher, mit "Field::A1" anstelle von einem nackten "A1" auf die Konstanten zuzugreifen. Außerdem sind die Regeln zur automatischen Konvertierung wesentlich strenger ggü. normalen Enums, aber das wirst du dann schon noch lernen, wenn es dich betrifft.

Also dann ... viel Erfolg mit deinem Schachprogramm! :)

Danke für die ausführliche Antwort, sehe öfters solche Brecher von dir, und jedes mal Klasse geschrieben!

1

Kannst du nicht einfach ein enum verwenden welches alle spielfelder beinhaltet.

Ups, das macht ja alles einfacher, danke...

0

Problem bei Programmierung eines Multiplayerspiels (allgemein)?

Wenn ich ein Spiel für 2 Spieler programmiere, es aber an nur einem PC gespielt wird, muss ich dann für jeden Spieler eigene Methoden schreiben?

Wenn es beispielsweise ein Spiel auf einer 2D-Karte ist, muss ich dann 2 Methoden schreiben, dass sich die Spieler bewegen können? Denn ansonsten nutzen sie ja die gleichen Variablen, oder?

Pseudo-Code:

//Bewegung mit W (Spieler 1) und mit UP-Pfeil
//Beispiel: Eindimensionale Position
int pos1 = 0, pos2 = 0; int speed = 5; 
if (keyPressed) {
  if(spieler1_key) { move(1, speed); }
  if(spieler2_key) { move(2, speed); } 
}
  
void move(int spieler, int speed) {
  switch(spieler) {
    case 1: if(pos1+speed != hindernis) {pos1 += speed;}
    case 2: if(pos2+speed != hindernis) {pos2 += speed;}
  }
}

Könnte sixh im Beispiel immer nur ein Spieler bewegen?

Und wenn ja, wie löse ich dann das Problem, dass sich am Ende beide spieler gleichzeitig bewegen können?

...zur Frage

c, c++ | LNK2019, Verweiß auf nicht aufgelöstes externes Symbol?

Natürlich habe ich, bevor ich hier frage, auch schon im Internet nach vorherigen ähnlichen Problemen gesucht und die gab es natürlich auch, aber keine der bereits vorhandenen Lösungen hat mir in meinem speziellen Fall wirklich geholfen.

Soweit wie ich es verstanden habe, meint dieser Error, dass man zB innerhalb einer Funktion einen Funktionsaufruf hat, von einer Funktion aus einer anderen Datei, diese findet der Linker aber nicht.

Es ist auch tatsächlich so, dass ich neben der Datei meiner main auchnoch andere Dateien verwende, nämlich genau zwei: header.h und header.cpp.

In der Headerdatei habe ich nur Deklarationen, in der cpp die entsprechenden Definitionen, beide Dateien habe ich im richtigen Verzeichnis und auch im Projekt-Explorer hinzugefügt, compilieren kann ich auch alles.

Bisher hatte es eigentlich immer funktioniert (unter der Voraussetzung dass ich die Dateien im Proj-Expl hinzugefügt habe)

Jetzt habe ich im selbigen namespace 4000 weitere Zeilen hinzugefügt, welche extern auch problemlos funktioniert haben und auch hier wird intellisense keine Fehler, aber sobald ich irgend eine der neuen Funktionen verwende (die alten gehen nach wie vor), wirft mir der Linker den Fehler LNK2019

(ConsoleApplication47.obj : error LNK2019: Verweis auf nicht aufgelöstes externes Symbol ""bool __cdecl MS::Experimental::save<int>(char const * const,int &)" (??$save@H@Experimental@MS@@YA_NQBDAAH@Z)" in Funktion "_main")

Zugegeben, es ist nicht ganz der gleiche namespace, aber der namespace befindet sich im gleichen namespace.

In der Headerdatei liegen die gleichen namespaces mit den Deklarationen und Visual Studio findet auch die dazugehörigen Definitionen.

Woran könnte es liegen? Muss ich vielleicht irgendwo in den Projekteinstellungen unter Linker eigentlich noch angeben, dass ich Funktionen aus der cpp nutze? Oder muss ich die Deklarationen mit dem Schlüsselwort extern machen?

Danke im Voraus schonmal für alle Antworten.

Hier noch für die die sich den Code durchlesen wollen (zumindest Teile)

Header:

namespace MS
{
  namespace Experimental
  {
    template <>  //Spezialisierung von vorheriger Funktion
    bool save(const char varName[], char &var);
  }
}

Cpp:

http://codepad.org/I6zkckyk       (ist zu lang)

Ich weiß, das ist alles im Moment noch nicht so schön gelöst, aber das ist ja auch noch nicht fertig :)

Alle Konstanten mit F_ sind im header definiert und werden erkannt.

Alle Funktionen mit F_ sind für den namespace von mir erstellte Funktionen, sie befinden sich über dieser Funktion.

...zur Frage

Csgo cheaten 123?

Wieso wird in csgo soviel gecheatet? Vorallem die deutschen wie ich nach 2 Jahren spiel erfahrung gemerkt habe sind die deutschen an der ersten Stelle wenn es um cheaten geht. Wendern es sind kleine rage "kiddys" die einfach cheats kaufen, oder auch ältere personen "u18" die cheats selber programmieren. Was ist so "geil" am cheaten, einfach nur aus spaß, andere leute zu ärgern oder einfach um zu zeigen wie gut man ist ? Noch etwas, was ich nicht verstehe ist dass Valve manchmal hier manchmal da eine vac welle rausbringt aber erst dann wenn ein steam sale war, zufall? Das schön alle cheater erst ein account kaufen damit valve geld verdient und die dann gebannt werden. Und denkt ihr dass csgo austerben wird oder valve doch noch die kurwe bekommt und dass cheaten unmöglich wird in der zukunft?

...zur Frage

C++ (Anfänger) Visual Studio Fehler?

Hi ich versuche ein sehr simples Programm was keine syntaktischen Fehler hat in VS auszuführen, auf meinem Laptop klappt alles super jedoch kommt hier bei ausführen (ja mit Debugger) Folgende Fehlermeldungen:

"Project.exe" (Win32): "C:\Users\kaipo\source\repos\Project2\Debug\Project.exe" geladen. Symbole wurden geladen.

"Project.exe" (Win32): "C:\Windows\SysWOW64\ntdll.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\kernel32.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\KernelBase.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\msvcp140d.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\vcruntime140d.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\ucrtbased.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\vcruntime140d.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\ucrtbased.dll" wurde entladen.

"Project.exe" (Win32): "C:\Windows\SysWOW64\vcruntime140d.dll" wurde entladen.

"Project.exe" (Win32): "C:\Windows\SysWOW64\ucrtbased.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\ucrtbased.dll" wurde entladen

"Project.exe" (Win32): "C:\Windows\SysWOW64\cryptbase.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\bcryptprimitives.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

"Project.exe" (Win32): "C:\Windows\SysWOW64\sechost.dll" geladen. PDB-Datei wurde nicht gefunden oder konnte nicht geöffnet werden.

Der Thread 0x2694 hat mit Code 0 (0x0) geendet.

Der Thread 0x2af8 hat mit Code 0 (0x0) geendet.

Der Thread 0x47d0 hat mit Code 0 (0x0) geendet.

Das Programm "[17444] Project.exe" wurde mit Code 0 (0x0) beendet.

Habe schon etwas gegoogelt aber bisher nicht so weit gekommen, wenn jemand nen schnellen fix hätte wäre ich sehr dankbar

...zur Frage

[c++] const char und char* probleme?

Hallo. Ich habe seit kurzem das problem dass ich eine fehlermeldung bei folgendem code bekomme:

char s = "Hello world"; 

Bekomme dann folgendes angezeigt:

"Ein wert vom Typ ""const char*"" kann nicht zum Initialisieren einer Entität vom Typ ""char"" verwendet werden"

soweit ich denke ist damit gemeint dass die art wie ich versuche den char zu Initialisieren, nicht für den typen geeignet ist.

Habe das bemerkt als ich bei diesem code eine fehlermeldung bekam:

vam.Process("csgo.exe");

(Damit kann aber denke ich niemand was anfangen).

Da bekomme ich folgende meldung:

"Das Argument vom Typ ""const char*"" ist mit dem Parameter vom Typ ""char"" inkompatibel". Soweit ich das hier verstehe ist der Typ den ich übergeben will (char) nicht kompatibel da vam.Process(); einen const char haben will.

Sind nur meine vermutungen.

So, nun zu der frage: Kann mit vllt irgendjemand das alles erklären? verstehe auch nicht den unterschied zwischen const char* und char...(Bin neu in c++)

Danke im voraus

...zur Frage

Was möchtest Du wissen?