Brak błędu, mimo to złe działanie gry.

0

Witam, od kilku dni męczę się ze znalezieniem błędu w moim kodzie, jednak nadal mi się to nie udaje (prawdopodobnie jest to związane z ustawianiem wygranego).
Po wpisaniu nr pola, na którym ma zostać postawiony/e kółko/krzyrzyk zamiast zmiany tabeli następuje przerwanie nieskonczonej funkcji for.
Jeżeli ktoś miałby dłuższą chwilę i chciał pomóc będę niezwykle wdzięczny :).
MAIN.CPP:

#include <iostream>
#include <conio.h>
#include "game.h"
using namespace std;

int main()
{
StartGry();
for(;;)
{
   RysujPlansze();
   if(g_Stan == SG_RUCH)
   {
    unsigned NrPola;
    cin >> NrPola;
    Ruch(NrPola);
   }
   if(g_Stan == SG_WYGRANA || g_Stan == SG_REMIS) break;
}
getch();
}

GAME.CPP:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <ctime>
#include "game.h"

using namespace std;

POLE g_aPlansza[3][3] = { { PL_PUSTE, PL_PUSTE, PL_PUSTE, },
	                       { PL_PUSTE, PL_PUSTE, PL_PUSTE, },
	                       { PL_PUSTE, PL_PUSTE, PL_PUSTE, } };
STANGRY g_Stan = SG_STOI;
RODZAJ g_AktualnyGracz;

bool StartGry()
{
	if (g_Stan != SG_STOI) return false;
	srand( time( NULL ) );
	//losowanie gracza
	g_AktualnyGracz = (rand() % 2 == 0 ? RDZ_KOLO : RDZ_KRZYZ);
	//stan gry ustawiany na ruch gracza
	g_Stan = SG_RUCH;
	return true;
}

bool Ruch(unsigned NrPola)
{
	if(g_Stan != SG_RUCH) return false;
	// zly numer
	if(NrPola < 1 && NrPola > 9) return false;
	unsigned iX = (NrPola - 1) % 3;
	unsigned iY = (NrPola - 1) / 3;
	if(g_aPlansza[iX][iY] == PL_PUSTE)
	{
		//Wstawianie znaku na pole
		g_aPlansza[iX][iY] = static_cast<POLE>(g_AktualnyGracz);
	} else return false;
	const int WYGRANE[][3][2] = { { { 0,0 }, { 0,1 }, { 0,2 } },// górna pozioma  
                        { { 1,0 }, { 1,1 }, { 1,2 } },// środ. pozioma  
                        { { 2,0 }, { 2,1 }, { 2,2 } },// dolna pozioma  
                        { { 0,0 }, { 1,0 }, { 2,0 } },// lewa pionowa  
                        { { 0,1 }, { 1,1 }, { 2,1 } },// środ. pionowa  // 8 LINI WYGRYWAJACYCH!
                        { { 0,2 }, { 1,2 }, { 2,2 } },// prawa pionowa 
                        { { 0,0 }, { 1,1 }, { 2,2 } },// p. backslashowa  
                        { { 2,0 }, { 1,1 }, { 0,2 } } };// p. slashowa 
                
    POLE cel, zgodnycel;
    unsigned uLiczbaZgodnychCel;
    for(int i=0;i<8;++i)
    {
    	//Sprawdza kazda wygrana linie z 8 mozliwych
    	
    	//zerowanie zmiennych
    	cel=zgodnycel=PL_PUSTE;
    	uLiczbaZgodnychCel=0;
    	for(int j=0;j<3;++j)
    	{
    		//Sprawdza kazde pole w linii
    		cel = g_aPlansza[WYGRANE[i][j][0]][WYGRANE[i][j][1]];
    		if( cel != zgodnycel)
    		{
    			zgodnycel=cel;
    			uLiczbaZgodnychCel=1;
    		}else ++uLiczbaZgodnychCel;
    		if(uLiczbaZgodnychCel=3 && zgodnycel != PL_PUSTE)
    		{
    			g_Stan = SG_WYGRANA;
    			return true;
    		}
    	}	
    }
    unsigned uLiczbUzytPol=0;
    for (int i=0;i<3;++i)
    {
    	for(int j=0;j<3;++j)
    	{
    			if(g_aPlansza[i][j] != PL_PUSTE) ++uLiczbUzytPol;
    	}
    }
    if(uLiczbUzytPol=9) 
	{
	g_Stan = SG_REMIS;
	return true;
    }
    g_AktualnyGracz = (g_AktualnyGracz == RDZ_KOLO ? RDZ_KRZYZ : RDZ_KOLO);
    return true;
}

bool RysujPlansze()
{
	if(g_Stan == SG_STOI) return false;
	system ("cls");
	cout << "          ------------------------- " << endl;
	cout << "         |   GRA KOLKO I KRZYZYK   |" << endl;
	cout << "          ------------------------- " << endl;
	cout << endl;
	cout << "                    =====           " << endl;
	for(int i=0;i<3;++i)
	   {
	   cout << "                    |";
	      for(int j=0;j<3;++j)
	      {
	      if(g_aPlansza [i][j] == PL_PUSTE) cout << (i*3)+(j+1);		//Wyswietlanie pustego pola
	      else cout << static_cast<char>(g_aPlansza[i][j]);           //Wyswietlanie pola z kolem albo krzyzem
          }
       cout << "|" << endl;
	   }
    cout << "                    =====           " << endl;
    cout << endl;
    switch(g_Stan)
    {
    	case SG_RUCH:
    		//Prosba o ruch
    		cout << "Podaj numer pola, w ktorym\nchcesz postawic " << (g_AktualnyGracz == RDZ_KOLO ? "kolko" : "krzyzyk") << ": ";
    	   break;
    	case SG_WYGRANA:
    		//Jezeli wygrana
    		cout << (g_AktualnyGracz == RDZ_KOLO ? "Wygralo kolko!" : "Wygral krzyzyk!");
    	   break;
    	case SG_REMIS:
    		//Jezeli remis
    		cout << "Gra zakonczyla sie remisem!";
    	   break;   		
    }
return true;
}

GAME.H:

enum STANGRY { SG_STOI, SG_RUCH, SG_WYGRANA, SG_REMIS };
enum RODZAJ { RDZ_KOLO = 'O', RDZ_KRZYZ = 'X' };
enum POLE { PL_PUSTE, PL_KOLO = RDZ_KOLO, PL_KRZYZ = RDZ_KRZYZ };
extern STANGRY g_Stan;

// deklaracja funkcji
//------------------ 
// rozpoczęcie gry 
bool StartGry();
// wykonanie ruchu 
bool Ruch(unsigned);  
// rysowanie planszy 
bool RysujPlansze();
0
if(uLiczbUzytPol=9) 

Przypisujesz zamiast porównać.

Powinieneś kompilować z warningami - kompilator by Ci o tym powiedział.

Przy okazji: staraj się jednolicie formatować kod

0

Dzięki!
Znalazłem jeszcze jeden błąd identyczny jak twój. Oba poprawiłem. Dodatkowo zauważyłem, że trzeba zamienić:

	unsigned iX = (NrPola - 1) % 3;
	unsigned iY = (NrPola - 1) / 3;

na

	unsigned iY = (NrPola - 1) % 3;
	unsigned iX = (NrPola - 1) / 3;

Jednak teraz podczas wpisania ostatniego kółka lub krzyżyku przed wygraną/remisem program zamiast wpisać je na tamto miejsce oraz wyświetlić komunikat przerywa działanie programu :c.

1

Ten program to dobry przykład na to gdzie przydaje się "programowanie defensywne".

  • switch zawsze powinien zawierać sekcję "default"
  • jeśli funkcja zwraca boolean to obsłuż jej wynik
  • używaj nazw dla podwyrażeń, trudno czyta się takie tasiemce:
cel = g_aPlansza[WYGRANE[i][j][0]][WYGRANE[i][j][1]];
  • funkcja powinna mieć jedno return, ew. sekcję kontroli wejścia i jeden końcowy return. Nie daje się? dziel (na funkcje) i rządź
  • na końcu bool Ruch() masz niepotrzebnie dwa razy return true
  • podziel bool RysujPlansze() na bool RysujPlansze(), bool PokazWynik() i bool PobierzKomende() / bool PobierzRuch()
  • wynik gry wyświetlaj za pętlą a nie w środku

Jak to poprawisz to pewnie sam znajdziesz gdzie jest błąd (ew. inne które tu mogą występować).

1 użytkowników online, w tym zalogowanych: 0, gości: 1