#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?
'x&= y' - >'x = x&y'那么问题是“二元&运算符(整数)是做什么的?” - 这很容易在参考资料中找到。注意大多数二元运算符可以用这种形式写成,例如'z + = 1'。 – user2864740
这种缩短称为“复合赋值”。请参阅http://stackoverflow.com/questions/4217762(同样的想法,但对于不同的按位运算符:'|'/按位或 - 而不是'&'/按位AND)。 – user2864740
请在回答问题后不要编辑您的问题。 – MikeMB