# Mit Esc Programm beenden || Tipps für Ki?



## CodeCrafterCpp (30. Dezember 2011)

Hallo,
Ich möchte gerne das man mein Spiel(TicTacToe) und ich möchte gerne das es jeder Zeit mit der Taste ESC beendet werden kann.
Diesen Code habe ich zum großen Teil so aus einen andern Thema bekommen.



```
SHORT state = GetAsyncKeyState(VK_ESCAPE);
	
        if(GetForegroundWindow() == GetConsoleWindow()) {

				if((state & 0x8000) != 0)
				{
					system("cls");
					cout << "Spiel Beenden? Y oder N" << endl;
					escfrage = getch();
					if(escfrage == 'Y' || escfrage == 'y')
					{
						break;
					}
					else if(escfrage == 'N' || escfrage == 'n')
					{
						system("cls");
						Render(f);
					}
					else
					{
						while(true)
						{
							system("cls");
							cout << "Spiel Beenden? Y oder N" << endl;
							escfrage = getch();
							if(escfrage == 'Y' || escfrage == 'y')
							{

								exit(0);
							}
							else if(escfrage == 'N' || escfrage == 'n')
							{
								system("cls");
								Render(f);
								break;
							}

						}
					}
				}
			}
        state = GetAsyncKeyState(VK_ESCAPE);
```

Wie mache ich das aber jetzt das er überall in Spiel beendet wenn ich esc drücke ich möchte das auch gerne in einer Funktion das hat aber auch nicht so geklappt.


Wenn ich damit fertig bin möchte ich gerne eine ki mit 5 Stufen schreiben. Habt ihr da Tipp oder so wie ich da vorgehen soll. Sieht ja ein bisschen doof aus wenn ich jede Möglichkeit mit einer if abfrage mache.


mfG


----------



## FSA (30. Dezember 2011)

Ich nehme mal an unter Windows. Nächstes mal einfach suche verwenden  Ich habe das auch schon gefragt aber hier: exit(int Code); oder PostQuitMessage(0);


----------



## sheel (30. Dezember 2011)

Hi

Wenn du schon mit getch arbeitest, warum dann nicht auf kbhit dazunehmen?
GetAsyncKeyState dazu ist etwas seltsam.

Zur KI: Zuerst mal überlegen, wie der Computerzug abläuft.

zB.:
Eine bestimmte Zuganzahl vorberechnen, jede Möglichkeit.
Ergebnis ist eine Menge Möglichkeiten, die
a) Zum Sieg, b) Zur Niederlage führen,
c) in der berrechneten Zuganzahl das Spiel noch nicht beenden.

Dann zufällig eine der Möglichkeiten hernehmen, wobei die Gewinne viermal so wahrscheinlich wie Verluste gezogen werden, und Noch-Unbekannt zweimal so wahrscheinlich wie Verluste.

Bei jeder Schwierigkeitsstufe hast du eigene Werte
für Zugberechnungsweite und die Gewichtugen (hier 4-2-1).

In ein Array, Schwierigkeit=Index.

Gruß


----------



## CodeCrafterCpp (31. Dezember 2011)

Ok wie das Programm beende ist mir auch klar aber wo schreib ich das denn mach ich eine Funktion und rufe die immer wieder auf oder reicht das wenn ich das an einer bestimmten stelle schreibe?
Ich hab probleme damit das Programm zu beenden wenn ich das in einer Funktion schreibe.


----------



## sheel (31. Dezember 2011)

Entweder überall oder, unschöne Lösung, in einem Thread (dann aber wieder mit AsyncKeyState).


----------



## FSA (31. Dezember 2011)

Hä? Wieso wenn man exit aufruft, dann beendet das Programm sofort. Einfach nach GetAsyncKeyState( VK_ESC ); exit aufrufen. Oder?, verstehe ich das falsch.


----------



## sheel (31. Dezember 2011)

Gemeint war (denk ich), wo man die Abfrage überall einbauen muss,
damit das Programm jederzeit (+- paar Millisekunden) per Esc beendet werden kann.


----------



## CodeCrafterCpp (31. Dezember 2011)

Genau und genau 
Ich hatte mit exit(0); auch einige Probleme.
Das mit über all ist eine unschöne Lösung oder verstehe ich das falsch?
Habt ihr ein gutes Tutorial zu Thread oder könnt ihr mir sagen wie man msdn verstehen soll. Wenn ich mir das so anschaue verstehe ich nicht mal wie ich std::cout benutze.



Hoffe es ist nicht zu viel verlangt. 


mfG


----------



## sheel (1. Januar 2012)

Überall wäre die saubere Lösung.
Bei jeder Tastatureingabe auch auf Esc prüfen, auch wo keine Eingaben sind ein paar Prüfstellen in den Code, ob Esc gedrückt wurde...
Nachteil: Viel Aufwand

Thread: Einfach, aber meistens ungeeignet.
Also am main-Anfang einen Thread starten, der gleichzeitig mit main läuft.
Im Thread nur darauf warten, dass Esc gedrückt wird.
Wenn das passiert, mit exit alles (Thread und main) beenden.
Falls main ohne Esc sein Ende ereicht, beendet sich der Thread automatisch mit.

Problem an der Sache: man hat keine Vorwarnung, wird einfach gekillt.
Offene Dateien werden nicht automatisch geschlossen, etc...

Frohes neues Jahr!


----------



## cwriter (1. Januar 2012)

Wunderschönes 2012 alle zusammen!
Also ich fände die Lösung mit dem Thread nicht schlecht, heutzutage haben die meisten Comuter mindestens Dual-Core und das sollte man auch nutzen, zumal die Belastung solcher Funktionen vernachlässigbar ist.
Die Frage ist, WIE man das machen soll.
Ich fände eine Prüfung der Variablen im Thread nicht schlecht, da weiss man immer, ob auch alles gut läuft. Zeige bitte mal deinen Code von bisher.

@CodeCrafterCpp
Anstatt GetAsyncKeyState() aufzurufen und zu prüfen, ob das Fenster vorne ist, weshalb nicht kbhit() und getch() bzw. _kbhit() und _getch() verwenden und dann die Richtigkeit kontrollieren?
Weshalb willst du unbedingt die std::cout verwenden?
Immer gute Tutorials: 
http://www.youtube.com/user/SterminioProductions/videos?view=pl
Alles ist gut geordnet, ob es jetzt Standard oder WinApi oder STL, alles ist da und erst noch in Deutsch.

Gruss
cwriter


----------



## CodeCrafterCpp (2. Januar 2012)

Also für mich hört sich das mit den Thread auch besser an weil das übersichtlicher ist.



```
#include <iostream>
#include <conio.h>
#include <Windows.h>
 
using namespace std;
 
void Render(char *f);
char Setzen(char eingabe, char *f, bool player_turn, char zeichen);
char kiSetzen(char eingabe, char *f, bool player_turn, char zeichen, int kiEingabe, int ki);
int gewinnPruf(char *f, int gewinn, bool player_turn);
int neuesSpiel(int gewinn, char eingabe, char *f);
char meneu(char ki);
void gameloop(bool player_turn, int gewinn, char ki, char zeichen, char eingabe, bool exit, char *f);
int kiEingabe(char *f, int ki, char eingabe);


int main()
{
    //********************************************//
    //Variablen
    //********************************************//
    bool player_turn = 0;
    int gewinn = 0;
    char ki = ' ';
	char zeichen = ' ';
    char eingabe = ' ';

    bool exit = false;
    char f[9];
    for(int i = 0; i < 9; i++)
    {
        f[i] = i+'1';
    }
	ki = meneu(ki);
	gameloop(player_turn, gewinn, ki, zeichen, eingabe, exit, f);

	return 0;
}
 
void Render(char *f)
{
	for(int i = 1; i <=9; i++)
	{
		cout << f[i - 1];
		if(!(i % 3)) cout << endl << "-+-+-" << endl;
		else cout << "|";
	}
}
char Setzen(char eingabe, char *f, bool player_turn, char zeichen)
{

	if(player_turn)
	{
		cout << "Spieler 1 ist dran. Bitte waehle ein Feld: ";
		zeichen = 'x';
	}
	if(!player_turn)
	{
		cout << "Spieler 2 ist dran. Bitte waehle ein Feld: ";
		zeichen = 'o';
    }
    eingabe = getch();


	while(true)
	{
		int zahl = eingabe - 49;
		if(eingabe >= 49 && eingabe <= 57)
		{
			if(f[zahl] == eingabe)
			{
				f[zahl] = zeichen;
				system("cls");
				Render(f);
				break;
			}
			else
			{
				system("cls");
				Render(f);
				cout << "Dieses Feld ist besetzt. Waehle ein neues: ";
				eingabe = getch();
			}
		}
		else
		{
			system("cls");
			Render(f);
			cout << "Flasche Eingabe" << endl
				 << "Waehle ein neues Feld: ";
			eingabe = getch();
		}
	}
    return eingabe, *f, zeichen;
}
char kiSetzen(char eingabe, char *f, bool player_turn, char zeichen, int kiEingabe, int ki)
{

	if(player_turn)
	{
		zeichen = 'x';
		cout << "Spieler 1 ist dran. Bitte waehle ein Feld: ";
		eingabe = getch();
	}
	while(true)
	{
		int zahl = eingabe - 49;
		if(eingabe >= 49 && eingabe <= 57)
		{
			if(f[zahl] == eingabe)
			{
				f[zahl] = zeichen;
				system("cls");
				Render(f);
				break;
			}
			else
			{
				system("cls");
				Render(f);
				cout << "Dieses Feld ist besetzt. Waehle ein neues: ";
				eingabe = getch();
			}
		}
		else
		{
			system("cls");
			Render(f);
			cout << "Flasche Eingabe" << endl
				 << "Waehle ein neues Feld: ";
			eingabe = getch();
		}
	}

	if(!player_turn)
	{
		zeichen = 'o';
		int zahl = kiEingabe(f, ki, eingabe);
		f[zahl] = zeichen;
	}
    return *f;
}
int gewinnPruf(char *f, int gewinn, bool player_turn)
{
	
	int c;
	for(c = 0;c<=8;c++)
	{
		if(f[ c]==f[c+1]&&f[c+1]==f[c+2])
		{
			if( player_turn)gewinn=1;
			if(!player_turn)gewinn=2;
		}
		else if(f[ c]==f[c+3]&&f[c+3]==f[c+6])
		{
			if( player_turn)gewinn=1;
			if(!player_turn)gewinn=2;
		}
		else if(f[0]==f[4]&&f[4]==f[8])
		{
			if( player_turn)gewinn=1;
			if(!player_turn)gewinn=2;
		}
		else if(f[2]==f[4]&&f[4]==f[6])
		{
			if( player_turn)gewinn=1;
			if(!player_turn)gewinn=2;
		}
		else if( f[0] != '1' && f[1] != '2' && f[2] != '3' &&
				 f[3] != '4' && f[4] != '5' && f[5] != '6' &&
				 f[6] != '7' && f[7] != '8' && f[8] != '9' )
		{
			gewinn = 3;
		}
	}
	return gewinn;
}
int neuesSpiel(int gewinn,char eingabe, char *f)
{
	while(true)
	{
	if(gewinn == 1 || gewinn == 2)
	{
		system("cls");
		cout << "Spieler "<< gewinn << " hat gewonnen!" << endl << "Neues Spiel?(Y fuer Ja und N fuer Nein)";
		eingabe = getch();
		if(eingabe == 'Y'|| eingabe == 'y')
		{
			gewinn = 0;
			for(int i = 0; i < 9; i++)
			{
				f[i] = i+'1';
			}


			break;
		}
		else if( eingabe == 'N' || eingabe == 'n')
		{
			exit(0);
		}
	}
	else if(gewinn == 3)
	{

	}
	else
	{
		break;
	}
	}
	return gewinn;
}
char meneu(char ki)
{
	cout << "TicTacToe" << endl;
    cout << "Waehle eine Spiel Modus aus:" << endl
         << "0: mehr Spieler Modus" << endl
         << "1: gegen Computer einfach" << endl
         << "2: gegen Computer schwerer als einfach" << endl
         << "3: gegen Computer mittel" << endl
         << "4: gegen Computer leichter als schwer" << endl
         << "5: gegen Computer schwer" << endl;
    ki = getch();
 
	return ki;
}
void gameloop(bool player_turn, int gewinn, char ki, char zeichen, char eingabe, bool exit, char *f)
{

	    if(ki == '0')
        {
        while(!exit)
        {
                system("cls");
                Render(f);
                Setzen(eingabe, f, player_turn, zeichen);
				gewinn = gewinnPruf(f, gewinn, player_turn);
				gewinn = neuesSpiel(gewinn, eingabe, f);
				player_turn = !player_turn;
            }
        }
        else if(ki == '1')
        {
            while(!exit)
            {
				system("cls");
				Render(f);

            }
        }
        else if(ki == '2')
        {
            while(!exit)
            {
 
            }
        }
        else if(ki == '3')
        {
            while(!exit)
            {
 
            }
        }
        else if(ki == '4')
        {
            while(!exit)
            {
 
            }
        }
        else if(ki == '5')
        {
            while(!exit)
            {
 
            }
        }
 
 
 

}
int kiEingabe(char *f, int ki, char eingabe)
{

	return eingabe;
}
```



PS: Was ist hier schon wieder für ein Fehler?


```
if(!player_turn)
	{
		zeichen = 'o';
		int zahl = kiEingabe(f, ki, eingabe);
		f[zahl] = zeichen;
	}
```


----------



## FSA (2. Januar 2012)

> PS: Was ist hier schon wieder für ein Fehler?


Was kommt denn für ein Fehler? Bitte sag doch auch mal was nicht geht!


----------



## ibafluss (2. Januar 2012)

Wenn ich mir die Funktion kiEingabe() ansehe, tut die ja nichts, außer eingabe zurückzugeben. Und eingabe ist ein char und bekommt den Rückgabewert von getch(), bevor kiEingabe() aufgerufen wird. Das heißt in eingabe steht eine Zahl als Zeichen (z.B.: '2'). Wenn du das in ein int konvertierst, wird in dem int der ASCII-Code des Zeichens abgespeichert, der bei einer Zahl glaube ich so um 50 herum liegt. Das Array f hat nur 9 Element und in zahl steht ein Wert um 50, das ist das Problem.

Lg


----------



## CodeCrafterCpp (2. Januar 2012)

@ ibafluss: Das wollte ich auch noch machen. Aber das ist nicht mein Fehler!

Ich bekomme den Error: 	1	IntelliSense: Der Ausdruck muss einen (pointer-to-)Funktionstyp aufweisen.	c:\users\zensur\desktop\alles\ent\tictactoemitki\tictactoemitki\main.cpp	138

mfG


----------



## ibafluss (2. Januar 2012)

Das Problem ist, dass du eine Variable namens kiEingabe ebenfalls der Funktion kiSetzen() übergibst. Die Variable benötigst du aber nicht, streich das einfach und das Problem ist erledigt.

Lg


----------



## CodeCrafterCpp (2. Januar 2012)

Achso Danke wie doof von mir 
Jetzt möchte ich eben nochmal das Thema Thread aufnehmen. Und zwar hab ich überhaupt keine Ahnung wie ich die erstelle und wollte mal fragen ob ich gutes Tut habt bzw. wie man msdn verstehen soll da ich dort garnichts verstehe.


----------



## ibafluss (2. Januar 2012)

Hier habe ich einen kleinen Link auf Deutsch für die Grundlagen: http://www.c-programmieren.com/C-Lernen.html#Der Thread


----------

