//Der Controller für die Console-Variante //Für die GUI-Variante ist dieser abzuändern #include "TTTController.h" TTTController::TTTController(void) { string partner=""; #ifdef SERIAL_LINK cout << "Tic Tac Toe per Serial" << endl; cout << "Com-Port [COM1]: "; getline(cin, partner); if ( partner == "" ) partner = "COM1"; #elif defined SOCKET_LINK cout << "Tic Tac Toe per Socket" << endl; cout << "IP-Adresse [127.0.0.1]: "; getline(cin, partner); if ( partner == "" ) partner = "192.168.26"; //if ( partner == "" ) partner = "127.0.0.1"; #endif //Kennzeichen, welche Instanz der "Master" ist. master = false; //Noch kein beginnender Spieler fest gelegt beginningplayer = -1; //Erst ein TTTModel-Objekt erzeugen model = new TTTModel(); //Nun das View-Objekt erzeugen view = new TTTViewConsole(); //Objekt zu Kommunikation #ifdef SERIAL_LINK comm = new TTTSerialCommunication(partner); master = comm->getMaster(); #elif defined SOCKET_LINK comm = new TTTSocketCommunication(partner); master = comm->getMaster(); #endif //das Modell setzten view->setModel(model); //Spielfeld zeichnen view->drawGameField(); } TTTController::~TTTController(void) { //Dynamisch erzeugte Objekte zerstören delete comm; delete view; delete model; } void TTTController::clrscr(void) { cout.flush(); static HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); COORD coord = {0, 0}; DWORD dw; CONSOLE_SCREEN_BUFFER_INFO csbi; DWORD dwSize; GetConsoleScreenBufferInfo(hConsole,&csbi); dwSize = csbi.dwSize.X * csbi.dwSize.Y; FillConsoleOutputCharacter(hConsole, ' ', dwSize, coord, &dw); FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwSize, coord, &dw); SetConsoleCursorPosition(hConsole, coord); } void TTTController::gotoXY(int x, int y) { HANDLE screen_buffer_handle = GetStdHandle(STD_OUTPUT_HANDLE); COORD coord; coord.X = x; coord.Y = y; SetConsoleCursorPosition(screen_buffer_handle, coord); } int TTTController::setPlayerData(string n1, string n2) { players[0].setPlayerName(n1); players[1].setPlayerName(n2); return 0; } int TTTController::place(int x, int y, Fieldvalue f) { //Rückgabewert 0: Setzen erfolgreich //Rückgabewert 1: Feld bereits gesetzt //Rückgabewert 2: Ungültige Feldkoordinaten //Rückgabewert 3: Ungültiger Feldwert int rc = model->setValue(x,y,f); switch (rc) { case 0: //Erfolgreicher Zug aktualisiert die View view->actualizeGameField(); break; case 1: gotoXY(0,22); cout << " "; gotoXY(0,22); cout << "Feld bereits belegt"; break; case 2: gotoXY(0,22); cout << " "; gotoXY(0,22); cout << "Ungueltige Feldkoordinaten"; break; case 3: gotoXY(0,22); cout << " "; gotoXY(0,22); cout << "Ungueltiger Feldwert"; break; } return rc; } bool TTTController::detectMaster(void) { return master; } int TTTController::getBeginningPlayer(void) { return beginningplayer; } int TTTController::getMoveNumber(void) { return movenumber; } string TTTController::startGame(void) { //Eingabe für Spieler int column=0, row=0; //Rückgabewert für place-Methode int placevalue=0; //Rückgabewert für Gewinntest bool win=false; //Enthält Gewinnstatus nach Zug zur Übermittlung //an die Gegenstation //winstate = 0 -> Player 1 hat gewonnen //winstate = 1 -> Player 2 hat gewonnen //winstate = 2 -> noch kein Gewinner //winstate = 4 -> Patt int winstate = 2; //Player 1 spielt immer am eigenen System //Player 2 spielt immer am entfernten System string n1="Heim", n2="Gegner"; //Zugkoordinaten COORD move; //Port öffnen if ( !comm->open() ) { //Fehler beim Öffnen --> Programmende return "Error by port->open()"; } //Eigene Station aktiv schalten comm->setStationActive(); if ( !comm->isOtherStationActive() ) { //Warten auf Gegenstation gotoXY(0,13); cout << "Warte auf zweiten Spieler..." << endl; //Hier könnte ein Timeout programmiert werden while ( !comm->isOtherStationActive() ); gotoXY(0,14); cout << "...Gegenstation verbunden!" << endl; //Spielernamen 2 von Gegenstation lesen n2 = comm->readPlayerName2(); //Spielernamen 1 einlesen gotoXY(0,15); cout << "Spielername: "; cin >> n1; //Spielername 2 übertragen comm->sendPlayerName1(n1); } else { //Andere Station ist schon aktiv gewesen gotoXY(0,16); cout << "Gegenstation verbunden!" << endl; //Spielernamen 1 einlesen und übertragen gotoXY(0,17); cout << "Spielername: "; cin >> n1; comm->sendPlayerName1(n1); //Spielernamen 2 von Gegenstation lesen n2 = comm->readPlayerName2(); gotoXY(0,18); cout << "Gegenspieler: " << n2 << endl; } gotoXY(0,19); cerr << "Master: " << master << endl; //Master bestimmt beginnenden Spieler if ( master ) { //Beginnenden Spieler bestimmen srand ( (unsigned)time (NULL)); beginningplayer = rand() % 2; comm->sendBeginningPlayer( beginningplayer); cerr << "BeginningPlayer(Master): " << beginningplayer << endl; } else { //Beginnenden Spieler von Gegenstation lesen //und auf den zweiten Player setzen beginningplayer = (comm->readBeginningPlayer() + 1) % 2; cerr << "BeginningPlayer(Slave): " << beginningplayer << endl; } //Name der Spieler setzen setPlayerData(n1, n2); cerr << "Spieler initialisiert" << endl; movenumber = 0; if ( beginningplayer == 0 ) { //Eigene Station beginnt while ( movenumber <= MAXMOVES ) { //***************************************************************************** //Zug eigene Station do { #ifdef DEBUG gotoXY(0,21); cerr << "In Zug eigene Station (0)"; #endif view->drawStatusField( players[0].getPlayerName(), movenumber+1 ); //gewünschten Platz einlesen gotoXY(15,23); cin >> column; gotoXY(15,24); cin >> row; //Symbol platzieren placevalue = place(column, row, CROSS); } while ( placevalue != 0); movenumber++; //Zug an Gegenstation übermitteln move.X = column; move.Y = row; comm->sendMove(move); //Gewinnsituation überprüfen if ( movenumber >= 5 ) { win = model->checkColWin(CROSS) || model->checkRowWin(CROSS) || model->checkDiaWin(CROSS); if ( win ) comm->sendWinState(0); else if (movenumber == 9 ) comm->sendWinState(4); comm->sendWinState(2); } else comm->sendWinState(2); if ( win ) { gotoXY(0,25); return players[0].getPlayerName(); } view->deleteStatusField(players[1].getPlayerName()); //***************************************************************************** //Zug Gegenstation lesen #ifdef DEBUG gotoXY(0,21); cerr << "In Zug Gegenstation (0)"; #endif move = comm->readMove(); //Ins Spiel eintragen; Zugüberprüfung bereits auf Gegenseite erfolgt placevalue = place(move.X, move.Y, CIRCLE); movenumber++; winstate = comm->readWinState(); switch ( winstate ) { case 0: gotoXY(0,23); return players[0].getPlayerName(); break; case 1: gotoXY(0,23); return players[1].getPlayerName(); break; case 4: gotoXY(0,23); return "Patt!"; break; } }; //Ende while } //Ende if else if (beginningplayer == 1 ) { //Gegenstation beginnt while ( movenumber <= MAXMOVES ) { #ifdef DEBUG gotoXY(0,21); cerr << "In Zug GegenStation (1)"; #endif view->deleteStatusField(players[1].getPlayerName()); //***************************************************************************** //Zug Gegenstation lesen move = comm->readMove(); //Ins Spiel eintragen; Zugüberprüfung bereits auf Gegenseite erfolgt placevalue = place(move.X, move.Y, CROSS); movenumber++; winstate = comm->readWinState(); switch ( winstate ) { case 0: gotoXY(0,23); return players[1].getPlayerName(); break; case 1: gotoXY(0,23); return players[0].getPlayerName(); break; case 4: gotoXY(0,23); return "Patt!"; break; } //***************************************************************************** //Zug eigene Station do { #ifdef DEBUG gotoXY(0,21); cerr << "In Zug eigene Station (1)"; #endif view->drawStatusField( players[0].getPlayerName(), movenumber+1 ); //gewünschten Platz einlesen gotoXY(15,23); cin >> column; gotoXY(15,24); cin >> row; //Symbol platzieren placevalue = place(column, row, CIRCLE); } while ( placevalue != 0); movenumber++; //Zug an Gegenstation übermitteln COORD move; move.X = column; move.Y = row; comm->sendMove(move); if ( movenumber >= 5 ) { win = model->checkColWin(CIRCLE) || model->checkRowWin(CIRCLE) || model->checkDiaWin(CIRCLE); if ( win ) comm->sendWinState(1); else if (movenumber == 9 ) comm->sendWinState(4); comm->sendWinState(2); } else comm->sendWinState(2); if ( win ) { gotoXY(0,25); return players[0].getPlayerName(); } }; //Ende while } //Ende else //MAXMOVES erreicht return "Patt"; }