-7
#include <time.h>
#include <iostream>
#include <string>
#include <iomanip>
#include <cstdlib>

//using this to avoid repeating
typedef unsigned int uint;
using namespace std;

//directions enumerations
enum movDir { UP, DOWN, LEFT, RIGHT };

class tile
{
public:
    tile() : val( 0 ), blocked( false ) {}
    //unsigned integer
    uint val;
    bool blocked;
};

// Board, winning and losing, control keys,
class g2048
{
public:
    //we're not done, no one's won, score's 0 and we are gonna move
    g2048() : done( false ), win( false ), moved( true ), score( 0 ) {}

    //function loop
    void loop()
    {
        addTile();
        while( true )
        {
            if( moved )
                addTile();
            drawBoard();
            if( done )
                break;

            ControlKey();
        }

        string s = "Game Over!";
        if( win ) s = "You made it!";
        cout << s << endl << endl;

    } //end of func loop

private:

    //This is how the board looks like
    void drawBoard()
    {string
        system( "cls" );
        cout << "SCORE: " << score << endl << endl;

        for( int y = 0 ; y < 4 ; y++ )
        {
            cout << "+------+------+------+------+" << endl << "| ";
            for( int x = 0; x < 4; x++ )
            {
                if( !board[x][y].val )
                    //setw is to add in spaces in each box
                    cout << setw( 4 ) << " ";
                else
                    cout << setw( 4 ) << board[x][y].val;
                cout << " | ";
            }
            cout << endl;
        }
        cout << "+------+------+------+------+" << endl << endl;

    }


    void ControlKey()
    {
        moved = false;
        char c;
        //Control Keys
        cout << "(W)Up (S)Down (A)Left (D)Right ";
        cin >> c;
        /* Bitwise AND, the individual bits of c will be ANDed with
        the corresponding bits of the hex number 0x5F.
        This is a bitmasking, so the bit 5 of c gets cleared, while bits
         0 to 4 and 6 remain untouched. (all higher order bits will be cleared)
         */
        c &= 0x5F;
        switch ( c )
        {
            case 'W': move( UP );
                break;
            case 'A': move( LEFT );
                break;
            case 'S': move( DOWN );
                break;
            case 'D': move( RIGHT );
        }

        // can you still move?
        for( int y = 0; y < 4; y++ )
            for( int x = 0; x < 4; x++ )
                board[x][y].blocked = false;
    }


    void addTile()
    {
        for( int y = 0; y < 4; y++ )
            for( int x = 0; x < 4; x++ )
                //if board is not empty
                if( !board[x][y].val )
                {
                    uint a, b;
                    do
                    {
                        //rand() standard lib func that generates rand #
                        a = rand() % 4;
                        b = rand() % 4;
                    }
                    while( board[a][b].val );

                    int s = rand() % 100;
                    if( s > 89 ) board[a][b].val = 4;
                    else board[a][b].val = 2;
                    if( canMove() )
                        return;
                }

        done = true;
    }


    bool canMove()
    {
        for( int y = 0; y < 4; y++ )
            for( int x = 0; x < 4; x++ )
                //if the board's empty, you can move
                if( !board[x][y].val )
                    return true;

        for( int y = 0; y < 4; y++ )
            for( int x = 0; x < 4; x++ )
            {
                if( testAdd( x + 1, y, board[x][y].val ) )
                    return true;
                if( testAdd( x - 1, y, board[x][y].val ) )
                    return true;
                if( testAdd( x, y + 1, board[x][y].val ) )
                    return true;
                if( testAdd( x, y - 1, board[x][y].val ) )
                    return true;
            }

        return false;
    }
    //v is the board[x][y].val
    bool testAdd( int x, int y, uint v )
    {
        //out of range
        if( x < 0 || x > 3 || y < 0 || y > 3 )
            return false;
        return board[x][y].val == v;
    }

    // Verticall movement (Up, Down)
    void moveVert( int x, int y, int d )
    {
        if( board[x][y + d].val && board[x][y + d].val == board[x][y].val && !board[x][y].blocked && !board[x][y + d].blocked  )
        {
            board[x][y].val = 0;
            board[x][y + d].val *= 2;
            //update score
            score += board[x][y + d].val;
            board[x][y + d].blocked = true;
            moved = true;
        }
        else if( !board[x][y + d].val && board[x][y].val )
        {
            board[x][y + d].val = board[x][y].val;
            board[x][y].val = 0;
            moved = true;
        }
        if( d > 0 ) {
            if( y + d < 3 )
                moveVert( x, y + d,  1 );
        }

        else {
            if( y + d > 0 )
                moveVert( x, y + d, -1 );
        }

    }
    //Horizontal movement (Right, Left)
    void moveHori( int x, int y, int d )
    {
        if( board[x + d][y].val && board[x + d][y].val == board[x][y].val
           && !board[x][y].blocked && !board[x + d][y].blocked  )
        {
            board[x][y].val = 0;
            board[x + d][y].val *= 2;
            //update score
            score += board[x + d][y].val;
            board[x + d][y].blocked = true;
            moved = true;
        }
        else if( !board[x + d][y].val && board[x][y].val )
        {
            board[x + d][y].val = board[x][y].val;
            board[x][y].val = 0;
            moved = true;
        }
        if( d > 0 ) { 
            if( x + d < 3 ) 
                moveHori( x + d, y,  1 ); 
        }
        else        { 
            if( x + d > 0 )
                moveHori( x + d, y, -1 ); 
        }
    }

    void move( movDir d )
    {
        switch( d )
        {
            case UP:
                for( int x = 0; x < 4; x++ )
                {
                    int y = 1;
                    while( y < 4 )
                    { 
                        if( board[x][y].val )
                            moveVert( x, y, -1 ); 
                        y++;
                    }
                }
                break;
            case DOWN:
                for( int x = 0; x < 4; x++ )
                {
                    int y = 2;
                    while( y >= 0 )
                    { 
                        if( board[x][y].val )
                            moveVert( x, y, 1 ); 
                        y--;
                    }
                }
                break;
            case LEFT:
                for( int y = 0; y < 4; y++ )
                {
                    int x = 1;
                    while( x < 4 )
                    { 
                        if( board[x][y].val ) 
                            moveHori( x, y, -1 );
                        x++;
                    }
                }
                break;
            case RIGHT:
                for( int y = 0; y < 4; y++ )
                {
                    int x = 2;
                    while( x >= 0 )
                    { 
                        if( board[x][y].val ) 
                            moveHori( x, y, 1 ); 
                        x--;
                    }
                }
        }
    }

    tile board[4][4];
    bool win, done, moved;
    uint score;
};


int main()
{
    //srand() std lib func, seeding a rand num generator
    //return val of unsigned int time() ---> random value
    srand( static_cast <uint>( time( NULL ) ) );
    g2048 g; 
    g.loop();
    return system( "pause" );
}

Without the c &= 0x5F it would just keep drawing the board without any changes made to it. What does this line do? This is the 2048 game. I think this part of the code is trying to AND this Bitwise, but I don't really understand the mechanism. What exactly happens that makes the simple line so important that without it, everything's wrong?

Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
  • `x &= y` -> `x = x & y` Then the question is "what does the binary & operator (on integers) do?" - and that is readily found in reference material. Note that most binary operators can be written in this form, e.g. `z += 1`. – user2864740 Dec 20 '15 at 07:33
  • This shortening is called "compound assignment". See http://stackoverflow.com/questions/4217762 (same idea, but for a differnet bitwise operator: `|`/bitwise-OR instead of `&`/bitwise-AND). – user2864740 Dec 20 '15 at 07:42
  • Please don't edit your questions after they have been answered. – MikeMB Dec 20 '15 at 08:51
  • I have rolled back your edit, please don't obfuscate, fundamentally alter, or "destroy" your question after answers have been given. That isn't helpful for future visitors to your question, and may lead to downvotes to yourself and to the people who took their time to answer your question. – Mark Rotteveel Dec 20 '15 at 09:11

2 Answers2

1

In your code it's just the wrong way of doing c=toupper(c) by removing the bit who differ between upper and lower char.

Without c&=0x5ftry your code with caplock on

Jerome
  • 529
  • 4
  • 14
0

c &= 0x5F; calculates bitwise AND c & 0x5F and assign the result to c.

If you use ASCII code, I guess it is used for converting lower-case alphabets to upper-case ones.

MikeCAT
  • 73,922
  • 11
  • 45
  • 70