سلام!
در ادامه می توانید کد بازی پنتاگو را مشاهده کنید. در صورتی که در باره ی این کد سوال یا پیشنهادی دارید، در قسمت نظرات مطرح کنید.
توضیحات:
کلاس 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
فولدر مربوط به این پروژه را می توانید از این جا دریافت کنید.
موفق باشید!
set هم باید destructor داشته باشه
دقیق کد رو نخوندم ولی از اون xo خیلی بهتره.