2015-12-20 32 views
-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"); 
} 

如果没有c & = 0x5F它只会继续绘制板而不做任何更改。这条线是做什么的?这是2048年的比赛。我认为这部分代码试图和这个Bitwise,但我真的不明白这个机制。究竟发生了什么使简单的线条变得如此重要,没有它,一切都是错误的?这个操作在C++中做了什么:char c&= 0x5F?

+0

'x&= y' - >'x = x&y'那么问题是“二元&运算符(整数)是做什么的?” - 这很容易在参考资料中找到。注意大多数二元运算符可以用这种形式写成,例如'z + = 1'。 – user2864740

+0

这种缩短称为“复合赋值”。请参阅http://stackoverflow.com/questions/4217762(同样的想法,但对于不同的按位运算符:'|'/按位或 - 而不是'&'/按位AND)。 – user2864740

+0

请在回答问题后不要编辑您的问题。 – MikeMB

回答

1

在你的代码中,通过删除上下字符之间不同的位,这只是做错了c=toupper(c)的方法。

没有c&=0x5f尝试caplock你的代码上

+0

OMG谢谢你!你是一个拯救生命的人! – user3132078

0

c &= 0x5F;计算按位与c & 0x5F和结果分配给c

如果您使用ASCII码,我想它是用于将小写字母转换为大写字母。