Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Dziwny problem w Kółko krzyżyk

Ostatnio zmodyfikowano 2013-07-13 16:23
Autor Wiadomość
Bimbol
Temat założony przez niniejszego użytkownika
[C++] Dziwny problem w Kółko krzyżyk
» 2013-07-13 13:02:04
Witam,
napisałem OX używając klas, oraz porad z poprzednich tematów.

Wszystko działa, a przynajmniej powinno działać, ale nie wiem skąd na planszy zamiast numerków mam znaki ASCII.
Z kolei gdy w konstruktorze zamienie kolejność
CreateBoard();
 z
CreateSolutions();
 to
plansza się wyświetla dobrze, jednak tablica z rozwiązaniami zaś z kolei wskazuje ciągle na pole 0.

Gdy sprawdzam co się dzieje w obu funkcjach to rozwiązania są tworzone dobrze, a plansza jest wypełniana również dobrze.
Jednak gdy przychodzi do wypisania na ekran, to nie wiem dlaczego wartości tych liczb się zmieniają.
A w rozwiązaniach wszystko wskazuje na pole 0, ten kto tam postawi X albo O ten wygrywa.

main.cpp:
C/C++
#include "ox.h"

int main()
{
    BeginGame(); // Pocz¹tek
    while( true )
    {
        Board.ShowBoard();
        unsigned field;
        cin >> field;
        cin.clear();
        cin.sync();
        Board.Move( field );
        if( g_Game == G_DRAW || g_Game == G_WIN ) break;
       
    }
   
    return 0;
}

ox.h:
C/C++
#ifndef OX_H_INCLUDED
#define OX_H_INCLUDED

#include <iostream>
#include <conio.h>
#include <cstdlib>
#include <ctime>
using namespace std;

enum FIELD { FIELD_EMPYTY, FIELD_X = 'X', FIELD_O = 'O' };
enum GAMESTATE { G_NONSTARTED, G_MOVE, G_DRAW, G_WIN };
const unsigned BOARD_SIZE = 3;

class CPlayer
{
private:
    string m_Nick;
    FIELD m_Sign;
public:
    CPlayer( string Nick )
        : m_Nick( Nick )
    { }
   
    void SetSign( FIELD field ) { m_Sign = field; }
    string GetNick() { return m_Nick; }
    FIELD GetSign() { return m_Sign; }
};

class CBoard
{
private:
    unsigned m_Size;
    FIELD m_Board[];
    unsigned m_Solutions[][ BOARD_SIZE ];
    unsigned m_AmountSolutions;
public:
    CBoard( unsigned Size )
        : m_Size( Size )
        , m_AmountSolutions( 0 )
    {
        CreateBoard(); // Zamien miejscami
        CreateSolutions(); // Zamien miejscami
    }
    unsigned GetBoardSize() { return m_Size; }
    void CreateBoard();
    void CreateSolutions();
    void ShowBoard();
    bool Move( unsigned field );
    bool Check();
};

bool BeginGame();

extern CBoard Board;
extern GAMESTATE g_Game;

#endif // OX_H_INCLUDED

ox.cpp:
C/C++
#include "ox.h"

CPlayer * Player[ 2 ];
GAMESTATE g_Game = G_NONSTARTED;
unsigned g_ActivePlayer;
CBoard Board( BOARD_SIZE ); // Wielkosc planszy

bool BeginGame()
{
    if( g_Game != G_NONSTARTED ) return false;
   
    for( unsigned i = 0; i < 2; ++i )
    {
        cout << "Gracz " << i + 1 << ": ";
        string Nick;
        cin >> Nick;
        Player[ i ] = new CPlayer( Nick );
    }
   
    srand( static_cast < unsigned >( time( NULL ) ) );
   
    // Dobór O i X
    if( rand() % 2 == 0 )
    {
        Player[ 0 ]->SetSign( FIELD_O );
        Player[ 1 ]->SetSign( FIELD_X );
    }
    else
    {
        Player[ 0 ]->SetSign( FIELD_X );
        Player[ 1 ]->SetSign( FIELD_O );
    }
   
    // Losujemy kto ma zaczyna
    rand() % 2 == 0 ? g_ActivePlayer = 0
        : g_ActivePlayer = 1;
   
    g_Game = G_MOVE;
   
    return true;
}

// Klasy

void CBoard::CreateBoard()
{
    for( unsigned i = 0; i < GetBoardSize() * GetBoardSize(); ++i )
    {
        m_Board[ i ] = FIELD_EMPYTY;
    }
}

void CBoard::CreateSolutions()
{
    //Poziome
    for( unsigned i = 0; i < GetBoardSize() * GetBoardSize(); i += GetBoardSize() )
    {
        for( unsigned j = 0; j < GetBoardSize(); ++j )
        {
            m_Solutions[ m_AmountSolutions ][ j ] = i + j;
        }
        m_AmountSolutions++;
    }
}

void CBoard::ShowBoard()
{
    system( "cls" );
   
    cout << "      KOLKO i KRZYZYK      " << endl;
    cout << "---------------------------" << endl;
   
    for( unsigned i = 0; i < GetBoardSize() * GetBoardSize(); ++i )
    {
        m_Board[ i ] != FIELD_EMPYTY ? cout << static_cast < char >( m_Board[ i ] ) << " "
            : cout << i + 1 << " ";
        if(( i + 1 ) % GetBoardSize() == 0 ) cout << endl;
       
    }
   
    if( g_Game != G_DRAW && g_Game != G_WIN )
         cout << "Ruch gracza " << Player[ g_ActivePlayer ]->GetNick() << " (" << static_cast < char >( Player[ g_ActivePlayer ]->GetSign() ) << "): ";
    else
    if( g_Game == G_DRAW )
         cout << "Remis!" << endl;
    else
         cout << "Wygral " << Player[ g_ActivePlayer ]->GetNick() << " (" << static_cast < char >( Player[ g_ActivePlayer ]->GetSign() ) << ")!" << endl;
   
}

bool CBoard::Move( unsigned field )
{
    if( g_Game != G_MOVE ) return false;
   
    if( !( field >= 1 && field <= GetBoardSize() * GetBoardSize() ) )
    {
        cout << "Zakres <1;" << GetBoardSize() * GetBoardSize() << ">" << endl;
        getch();
        return false;
    }
    else
    if( m_Board[ field - 1 ] != FIELD_EMPYTY )
    {
        cout << "Pole zajete!" << endl;
        getch();
        return false;
    }
   
    m_Board[ field - 1 ] = Player[ g_ActivePlayer ]->GetSign();
   
    if( Board.Check() )
    {
        g_Game = G_WIN;
        CBoard::ShowBoard();
        return true;
    }
   
    unsigned counter = 0;
   
    for( unsigned i = 0; i < GetBoardSize() * GetBoardSize(); ++i )
    if( m_Board[ i ] != FIELD_EMPYTY )
         counter++;
   
    if( counter == GetBoardSize() * GetBoardSize() )
    {
        g_Game = G_DRAW;
        CBoard::ShowBoard();
        return true;
    }
   
    g_ActivePlayer == 0 ? g_ActivePlayer = 1: g_ActivePlayer = 0;
   
    return true;
}

bool CBoard::Check()
{
    unsigned AmountMatchingField = 0;
   
    for( unsigned i = 0; i < m_AmountSolutions; ++i )
    {
        for( unsigned j = 0; j < GetBoardSize(); ++j )
        {
            if( m_Board[ m_Solutions[ i ][ j ] ] == Player[ g_ActivePlayer ]->GetSign() )
            {
                cout << i << " " << j << " " << m_Solutions[ i ][ j ] << " " << m_Board[ m_Solutions[ i ][ j ] ] << " " << Player[ g_ActivePlayer ]->GetSign() << endl; // Sprawdza rozwiązania jednak nie działa tak jak powinno.
                getch();
                //AmountMatchingField++;
            }
            else
                 break;
           
        }
        if( AmountMatchingField == GetBoardSize() )
        {
            return true;
        }
       
        AmountMatchingField = 0;
    }
    return false;
}

Dziękuję za pomoc.
Liczę się również z krytyką tej prymitywnej gry.
P-87729
Monika90
» 2013-07-13 13:16:31
Jak drukujesz znaki, to się wyświetlają znaki
C/C++
m_Board[ i ] != FIELD_EMPYTY ? cout << static_cast < char >( m_Board[ i ] ) << " "
Poza tym twój program jest błędny i nie da się nawet skompilować.
Używasz typu std::string a nie masz #include <string>
Nie można też deklarować niestatycznych składowych klas typu tablicowaego bez podania rozmiaru
C/C++
FIELD m_Board[];
unsigned m_Solutions[][ BOARD_SIZE ];
P-87732
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-07-13 14:19:29
Nie rozumiem dlaczego kompiluje się się u mnie na IDE Code::Blocks.
Myślałem, że skoro Kompilator przyjął taką formę tablicy to pomyślałem, że jest to dozwolone.
Wyrzuca błędy tylko gry próbuje tak zrobić, więcej niż 1 wymiar.

Jak drukujesz znaki, to się wyświetlają znaki
Tyle, że
CBoard::CreateBoard()
 tutaj dochodzi przypisania planszy pustych pól, a mimo to pokazuje inne znaki.
P-87743
pekfos
» 2013-07-13 14:24:04
Nie rozumiem dlaczego kompiluje się się u mnie na IDE Code::Blocks.
Bez dołączania <string> program może się skompilować, ale nie musi. Poza tym, Code::Blocks to, jak sam napisałeś, IDE, a nie kompilator ;)

Myślałem, że skoro Kompilator przyjął taką formę tablicy to pomyślałem, że jest to dozwolone.
Nie wszystko, co kompilator przyjmuje, jest dozwolone.

[cytuj]
[cytat]
P-87744
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-07-13 14:29:04
Ale pobrałem wersje z kompilatorem minigw. (Wybaczcie jeśli źle mówię)
Dodałem
#include <string>
 mimo to nie ma żadnych błędów.

Zaś inne błędy wykrywa normalnie.
P-87747
Monika90
» 2013-07-13 14:31:59
Tyle, że
CBoard::CreateBoard()
 tutaj dochodzi przypisania planszy pustych pól, a mimo to pokazuje inne znaki.
Ale nie podałeś rozmiaru tablicy, nie wiem co g++ robi w takiej sytuacji. Załóżmy że przyjmuje rozmiar zero. Wtedy zapisywanie danych do tej tablicy spowoduje zmiany jakiś innch składowych klasy. Np. modyfikujesz m_board, a zmienia się m_Solutions i m_AmountSolutions i odwrotnie.

Możesz kompilować z flagą -pedantic, to przynajmniej dostaniesz warning, w sytuacji kiedy, źle zadeklarujesz tablicę.
P-87749
Bimbol
Temat założony przez niniejszego użytkownika
» 2013-07-13 14:34:05
No to już wiem skąd się wzięły te "dziwne błędy".

A więc inne pytanie, czy jest jakiś sposób by nie trzeba było określać wielkości tablicy od razu w klasie?
Czy można z tym w jakiś sposób poczekać?
P-87750
Berux
» 2013-07-13 14:41:28
Zawsze możesz użyć vectora ;)
P-87751
« 1 » 2
  Strona 1 z 2 Następna strona