سلام!

در ادامه می توانید کد بازی پنتاگو را مشاهده کنید. در صورتی که در باره ی این کد سوال یا پیشنهادی دارید، در قسمت نظرات مطرح کنید.

توضیحات:

کلاس Block مربوط به خانه های بازی است (که شامل ۳۶ تا خانه می باشد).

کلاس Set مربوط به ۴ قسمت بازی است (که شامل ۹ تا Block می باشد).

کلاس Board هم زمین بازی است و دارای ۴ تا set است.

File: color.h

#ifndef COLOR_H
#define COLOR_H

class Color{
    
    private:
        unsigned char *_red, *_green, *_blue, *_alpha;
    
    public:
        Color( unsigned char = 0, unsigned char = 0, unsigned char = 0, unsigned char = 255 );
        Color(const Color&);
        
        ~Color();
        
        unsigned char red() const;
        unsigned char green() const;
        unsigned char blue() const;
        unsigned char alpha() const;

        void setRed( unsigned char );
        void setGreen( unsigned char );
        void setBlue( unsigned char );
        void setAlpha( unsigned char );
        void setColor( unsigned char = 0, unsigned char = 0, unsigned char = 0, unsigned char = 255 );

};

#endif

File: color.cpp

#include "color.h"

Color::Color( unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha ) {
    this->_red = new unsigned char;
    this->_green = new unsigned char;
    this->_blue = new unsigned char;
    this->_alpha = new unsigned char;
    this->setColor( red, green, blue, alpha );
}

Color::Color(const Color& rhs)
{
    this->_red = new unsigned char;
    this->_green = new unsigned char;
    this->_blue = new unsigned char;
    this->_alpha = new unsigned char;
    this->setColor( rhs.red(), rhs.green(), rhs.blue(), rhs.alpha() );
}

unsigned char Color::red () const{
    return *(this->_red);
}

unsigned char Color::green () const{
    return *(this->_green);
}

unsigned char Color::blue () const{
    return *(this->_blue);
}

unsigned char Color::alpha () const{
    return *(this->_alpha);
}

void Color::setRed( unsigned char red ) {
    *(this->_red) = red;
}

void Color::setGreen( unsigned char green ) {
    *(this->_green) = green;
}

void Color::setBlue( unsigned char blue ) {
    *(this->_blue) = blue;
}

void Color::setAlpha( unsigned char alpha ) {
    *(this->_alpha) = alpha;
}

void Color::setColor( unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha ) {
    this->setRed( red );
    this->setGreen( green );
    this->setBlue( blue );
    this->setAlpha( alpha );
}

Color::~Color()
{
    delete _red;
    delete _green;
    delete _blue;
    delete _alpha;
}

File: block.h

#ifndef BLOCK_H
#define BLOCK_H

class Block{
    
    private:
        
        int _color;
    
    public:
        
        Block( int = 0 );

        int color();

        void setColor( int );

        bool operator==( Block );

};

#endif

File: block.cpp

#include "block.h"

Block::Block( int color ) {
    this->setColor( color );    
}

int Block::color() {
    return this->_color;
}

void Block::setColor( int color ) {
    this->_color = color;
}

bool Block::operator==( Block block ) {
    if ( this->color() == block.color() )
        return true;
    return false;
}

File: set.h

#ifndef SET_H
#define SET_H

#include "SDL/SDL.h"
#include "SDL/SDL_gfxPrimitives.h"

#include "block.h"
#include "color.h"

class Set{

    private:
        
//        Blocks
        Block **set;

//        Graphical Cordinates of the set
        int _x, _y;
        int _width, _height;

//        Number of Blocks in a column and in a row
        int _size;

//        Draws a block
        void drawCircle( SDL_Surface*, int, int );

    public:

        Set( int = 0 );
        Set(const Set&);
        
        ~Set();
        
        void draw( SDL_Surface*, const Color&);
        bool putPiece( SDL_Event event, int );
        void rotate( SDL_Event event );

        void setX( int );
        void setY( int );
        void setCor( int, int );
        void setWidth( int );
        void setHeight( int );
        void setSize( int );

        int x() const;
        int y() const;
        int width() const;
        int height() const;
        int size() const;

        Block *operator[]( int ) const;
        Set& operator=(const Set&);
        bool operator!=(const Set&);
};

#endif

File: set.cpp

#include "set.h"

Set::Set( int size ) {
    this->setSize( size );
    set = new Block*[ size ];
    for ( int i = 0; i < size; i++ ){
        set[i] = new Block[ size ];
        for ( int j = 0; j < size; j++ )
            set[i][j].setColor( 0 );
    }
}

Set::Set(const Set& rhs) {
    this->setCor(rhs.x() , rhs.y());
    this->setWidth(rhs.width());
    this->setHeight(rhs.height());
    this->setSize( rhs.size() );
    set = new Block*[ this->size() ];
    for ( int i = 0; i < this->size(); i++ ){
        set[i] = new Block[ this->size() ];
        for ( int j = 0; j < this->size(); j++ )
            set[i][j].setColor( rhs[i][j].color() );
    }
}

void Set::drawCircle( SDL_Surface* screen, int x, int y ) {

//    If intended block was red
    if ( set[y][x].color() == 1 )
        filledEllipseRGBA( screen, x * this->width() / 3 + this->width() / 6 + this->x(), y * this->height() / 3 + this->height() / 6 + this->y(), this->width() / 6 - 5, this->height() / 6 - 5, 255, 0, 0, 255 );

//    If intended block was black
    else if ( set[y][x].color() == -1 )
        filledEllipseRGBA( screen, x * this->width() / 3 + this->width() / 6 + this->x(), y * this->height() / 3 + this->height() / 6 + this->y(), this->width() / 6 - 5, this->height() / 6 - 5, 0, 0, 0, 255 );

}

void Set::draw( SDL_Surface *screen, const Color& color ) {

//    Drawing the set
    boxRGBA( screen, this->x(), this->y(), this->x() + this->width(), this->y() + this->height(), color.red(), color.green(), color.blue(), color.alpha() );

//    Drawing the lines
    for ( int i = 1; i < 3; i++ ) {
            lineRGBA( screen, this->x(), this->height() / 3 * i + this->y(), this->x() + this->width(), this->height() / 3 * i + this->y(), 255 - color.red(), 255 - color.green(), 255 - color.blue(), color.alpha() );
            lineRGBA( screen, this->width() / 3 * i + this->x(), this->y(), this->width() / 3 * i + this->x(), this->y() + this->height(), 255 - color.red(), 255 - color.green(), 255 - color.blue(), color.alpha() );
    }

//    Drawing all of the blocks
    for ( int i = 0; i < 3; i++ ){
        for ( int j = 0; j < 3; j++ ){
            drawCircle( screen, j, i );
        }
    }

}

bool Set::putPiece( SDL_Event event, int turn ) {
    int x = ( event.button.x - this->x() ) / ( this->width() / 3 );
    int y = ( event.button.y - this->y() ) / ( this->height() / 3 );
    if ( set[y][x].color() != 0 )
        return false;
    set[y][x].setColor( turn );
    return true;
}

void Set::rotate( SDL_Event event ) {

    Block **temp;
    temp = new Block*[ this->size() ];
    for ( int i = 0; i < this->size(); i++ ){
        temp[i] = new Block[ this->size() ];
    }

//    If user wants to rotate the set clockwise
    if ( event.button.button == SDL_BUTTON_RIGHT )
        for ( int i = 0; i < this->size(); i++ )
            for ( int j = 0; j < this->size(); j++ )
                temp[ i ][ j ].setColor( set[ this->size() - j - 1 ][ i ].color() );

//    If user wants to rotate the set counter-clockwise
    if ( event.button.button == SDL_BUTTON_LEFT )
        for ( int i = 0; i < this->size(); i++ )
            for ( int j = 0; j < this->size(); j++ )
                temp[i][j].setColor( set[ j ][ this->size() - i - 1 ].color() );
    
    for ( int i = 0; i < this->size(); i++ )
        for ( int j = 0; j < this->size(); j++ )
            set[i][j].setColor( temp[i][j].color() );
    
    for ( int i = 0; i < this->size(); i++ )
        delete[] temp[i];
    delete[] temp;
}

Block *Set::operator[]( int pos ) const{
    return set[ pos ];
}

Set& Set::operator=(const Set& rhs) {
    this->setCor(rhs.x() , rhs.y());
    this->setWidth(rhs.width());
    this->setHeight(rhs.height());
    if (rhs.size() !=  this->size())
    {
        for ( int i = 0; i < this->size(); i++ )
            delete[] set[i];
        delete[] set;    
        this->setSize(rhs.size());
        set = new Block*[ this->size() ];
        for ( int i = 0; i < this->size(); i++ ){
            set[i] = new Block[ this->size() ];
            for ( int j = 0; j < this->size(); j++ )
                set[i][j].setColor( rhs[i][j].color() );
        }
    }
    else
    {
        for ( int i = 0; i < this->size(); i++ )
            for ( int j = 0; j < this->size(); j++ )
                set[i][j].setColor( rhs[i][j].color() );
    }
    return *this;
}

void Set::setX( int x ) {
    this->_x = x;
}

void Set::setY( int y ) {
    this->_y = y;
}

void Set::setCor( int x, int y ) {
    this->setX( x );
    this->setY( y );
}

void Set::setWidth( int width ) {
    this->_width = width;
}

void Set::setHeight( int height ) {
    this->_height = height;
}

void Set::setSize( int size ) {
    this->_size = size;
}

int Set::x() const{
    return this->_x;
}

int Set::y() const{
    return this->_y;
}

int Set::width() const{
    return this->_width;
}

int Set::height() const{
    return this->_height;
}

int Set::size() const{
    return this->_size;
}

Set::~Set()
{
    for ( int i = 0; i < this->size(); i++ )
            delete[] set[i];
    delete[] set;
}

File: board.h

#ifndef BOARD_H
#define BOARD_H

#include <string>

#include "SDL/SDL.h"
#include "SDL/SDL_gfxPrimitives.h"
#include "SDL/SDL_ttf.h"

#include "color.h"
#include "set.h"

using namespace std;

class Board{
    
    friend bool clickOn( Set );

    private:
        const Color _c = Color( 0, 255, 255, 255);
        
//        Four sets
        Set **sets;

        void drawTable( SDL_Surface* );
        int startGame( SDL_Surface* );

//        for player state
        bool _mustPut, _mustRot;
    
//        Represents turn
        int _turn;

//        Represents winner
        int _winner;

        void setMustPut( bool );
        void setMustRot( bool );
        void setTurn( int );
        void setWinner( int );

        int checkWinning();

//        These functions change the board state
        void addedPiece();
        void rotated();

    public:

//        Constructor and destructor
        Board( SDL_Surface*, int );
        ~Board();

//        Runs the game
        int run( SDL_Surface* );

//        Show the winner on screen
        void showWinner( SDL_Surface* );

        Set *operator[]( int );

        bool mustPut();
        bool mustRot();
        int turn();
        string winner();

};


/*
This Function checks if the click was inside the set
*/

inline bool clickOn( SDL_Event event, const Set &set ) {

    if ( event.button.x >= set.x() && event.button.x <= set.x() + set.width() && event.button.y >= set.y() && event.button.y <= set.y() + set.height() ){
        return true;
    }

    return false;

}

#endif

File: board.cpp

#include "board.h"

Board::Board( SDL_Surface *screen, int size ) {

    this->setMustPut( true );
    this->setMustRot( false );
    this->setTurn( 1 );
    
    sets = new Set*[ 2 ];
    for ( int i = 0; i < 2; i++ ){
        sets[ i ] = new Set[ 2 ];
        for ( int j = 0; j < 2; j++ ){
            sets[i][j] = Set( size );
            sets[i][j].setWidth( screen->w / 2 - 10 );
            sets[i][j].setHeight( screen->h / 2 - 10);
        }
    }
    sets[0][0].setCor( 5, 5 );
    sets[0][1].setCor( screen->w / 2 + 5, 5 );
    sets[1][0].setCor( 5, screen->h / 2 + 5 );
    sets[1][1].setCor( screen->w / 2 + 5, screen->h / 2 + 5 );
}

Board::~Board() {
    for ( int i = 0; i < 2; i++ )
        delete[] sets[i];
    delete[] sets;
}

void Board::drawTable( SDL_Surface *screen ) {

//    Drawing each set
    for ( int i = 0; i < 2; i++ )
        for ( int j = 0; j < 2; j++ )
            sets[i][j].draw( screen, _c);
    SDL_Flip( screen );
}

int Board::run( SDL_Surface *screen ) {
    this->drawTable( screen );
    return this->startGame( screen );
}

void Board::addedPiece () {
    this->setMustPut( false );
    this->setMustRot( true );
}

void Board::rotated() {
    this->setMustPut( true );
    this->setMustRot( false );
    this->setTurn( this->turn() * -1 ) ;
}

int Board::startGame( SDL_Surface *screen ) {
    
    SDL_Event event;

    while ( 1 ) {
        while ( SDL_PollEvent( &event ) ){
            
            if ( event.type == SDL_QUIT )
                return 0;

            if ( event.type == SDL_KEYDOWN )
                if ( event.key.keysym.sym == SDLK_F4 && ( event.key.keysym.mod != 0 && ( event.key.keysym.mod & KMOD_ALT ) ) )
                    return 0;

            if ( event.type == SDL_MOUSEBUTTONDOWN ) {
                for ( int i = 0; i < 2; i++ ){
                    for ( int j = 0; j < 2; j++ ){

//                        If clicked on a set
                        if ( clickOn( event, sets[i][j] ) ){

//                            If player must put a piece
                            if ( this->mustPut() ){
//                                If is was possible to add a piece and the piece added
                                if ( sets[i][j].putPiece( event, this->turn() ) ){
//                                    Tell the program that a piece added
                                    this->addedPiece();

                                }
                                
                            }
                            
//                            If the player must rotate a set
                            else if ( this->mustRot() ){
//                                Rotate the selected set
                                sets[i][j].rotate( event );
//                                Tell the program that a set is rotated
                                this->rotated();
                                
//                                Drawing the surface, the updating it
                                this->drawTable( screen );
                                SDL_Flip( screen );
                                
//                                If a player won the game
                                if ( this->checkWinning() ){
//                                    Set the winner
                                    this->setWinner( this->checkWinning() );
//                                    Telling that we have a winner here!
                                    return 1;
                                }
                            }

//                            Drawing all of the sets
                            sets[i][j].draw( screen, _c );
                            
//                            Updating the surface
                            SDL_Flip( screen );

                        }
                    }
                }
            }

        }
    }
}

void Board::showWinner ( SDL_Surface* screen ) {

//    Initializing ttf library
    TTF_Init();

//    Opening the font
    TTF_Font *font = TTF_OpenFont( "fonts/Arial.ttf", 32 );

//    Color of the text
    SDL_Color color{ 255, 255, 255 };

//    message
    string text;
    text.append( this->winner() ).append( " Won the game!" );

//    Message surface
    SDL_Surface *message = TTF_RenderText_Solid( font, text.c_str(), color );

//    Position of the message
    SDL_Rect pos;
    pos.x = ( screen->w - message->w ) / 2;
    pos.y = ( screen->h - message->h ) / 2;

//    Applying the message to the screen
    SDL_BlitSurface( message, NULL, screen, &pos );

//    Updating the surface
    SDL_Flip( screen );

}

int Board::checkWinning () {
    
//    Combining all sets
    Set temp( 6 );
    for ( int i = 0; i < 2; i++ )
        for ( int j = 0; j < 2; j++ )
            for ( int k = 0; k < 3; k++ )
                for ( int l = 0; l < 3; l++ )
                    temp[ i * 3 + k ][ j * 3 + l ] = sets[i][j][k][l];
    
    for ( int i = 0; i < 6; i++ ){

//        Checking for a winner in vertical form
        if ( temp[1][i] == temp[2][i] && temp[2][i] == temp[3][i] && temp[3][i] == temp[4][i] && temp[1][i].color() != 0 )
            if ( temp[0][i] == temp[1][i] || temp[5][i] == temp[1][i] )
                return temp[1][i].color();

//        Checking for a winner in horizontal form
        if ( temp[i][1] == temp[i][2] && temp[i][2] == temp[i][3] && temp[i][3] == temp[i][4] && temp[i][1].color() != 0 )
            if ( temp[i][0] == temp[i][1] || temp[i][5] == temp[i][1] )
                return temp[i][1].color();
    }

//    Checking for a winner in diagonal form
    if ( temp[1][1] == temp[2][2] && temp[2][2] == temp[3][3] && temp[3][3] == temp[4][4] && temp[1][1].color() != 0 )
        if ( temp[0][0] == temp[1][1] || temp[5][5] == temp[1][1] )
            return temp[1][1].color();
    if ( temp[1][4] == temp[2][3] && temp[2][3] == temp[3][2] && temp[3][2] == temp[4][1] && temp[1][4].color() != 0 )
        if ( temp[0][5] == temp[1][4] || temp[5][0] == temp[1][4] )
            return temp[1][4].color();

    return 0;

}

Set *Board::operator []( int pos ) {
    return sets[ pos ];
}

void Board::setMustPut( bool mustPut ) {
    this->_mustPut = mustPut;
}

void Board::setMustRot( bool mustRot ) {
    this->_mustRot = mustRot;
}

void Board::setTurn( int turn ) {
    this->_turn = turn;
}

void Board::setWinner( int winner ) {
    this->_winner = winner;
}

bool Board::mustPut () {
    return this->_mustPut;
}

bool Board::mustRot () {
    return this->_mustRot;
}

int Board::turn () {
    return this->_turn;
}

string Board::winner () {
    if ( this->_winner == 0 )
        return "";
    return ( this->_winner == 1 ? "Red" : "Black" );
}


File: main.cpp

#include <algorithm>
#include <iostream>

#include "SDL/SDL.h"

#include "board.h"

using namespace std;

int main () {
    
    SDL_Init( SDL_INIT_EVERYTHING );

    const SDL_VideoInfo *videoInfo = SDL_GetVideoInfo();
    SDL_Surface *screen = SDL_SetVideoMode( min( videoInfo->current_w / 2, videoInfo->current_h / 2 ), min( videoInfo->current_w / 2, videoInfo->current_h / 2 ), 32, SDL_HWSURFACE );
    Board *board = new Board( screen, 3 );

    if ( !board->run( screen ) ){
        delete board;
        return 0;
    }

    board->showWinner( screen );

    SDL_Event event;

    while ( 1 )
        while ( SDL_PollEvent( &event ) ){
            if ( event.type == SDL_QUIT ){
SDL_Quit();
                delete board;
                return 0;
            }
            if ( event.type == SDL_KEYDOWN )
                if ( event.key.keysym.sym == SDLK_F4 )
                    if ( event.key.keysym.mod != 0 && ( event.key.keysym.mod & KMOD_ALT ) ){
SDL_Quit();
                        delete board;
                        return 0;
                    }
        }

}

File: makefile

run: all
./Pentago
all: color.o block.o set.o board.o main.o
    g++ main.o board.o set.o block.o color.o -o Pentago -g -Wall -lSDL -lSDL_gfx -lSDL_ttf
color.o: color.h color.cpp
    g++ -c color.cpp
block.o: block.h block.cpp
    g++ -c block.cpp
set.o: color.o block.o set.h set.cpp
    g++ -c set.cpp
board.o: set.o color.o board.h board.cpp
    g++ -c board.cpp
main.o: board.o main.cpp
    g++ -c main.cpp
clean:
    rm -rf *.o Pentago

فولدر مربوط به این پروژه را می توانید از این جا دریافت کنید.

موفق باشید!