问题描述
我当时正在用代码块编码c,并且由于它倾向于更好地编译程序,所以想转到Visual Studio,但是由于某种原因,在代码块中显示数字很好的ascii值似乎给了我奇怪的结果在vs中,这是他们的样子的片段:
由于每个平台上的代码完全相同,这使我相信我忽略了int相对于已经在代码块中设置的ascii的某些设置。要检查,这是我的代码:
#include <windows.h>
#define WIDTH 18
#define HEIGHT 18
#define BOMBS 50
struct xorshift_state {
int a;
};
int xorshift(struct xorshift_state *state)
{
int x = state->a;
x ^= x << 13;
x ^= x >> 17;
x ^= x << 5;
return state->a = x;
}
void ExpandGrid(int fullGrid[WIDTH][HEIGHT],int kNownGrid[WIDTH][HEIGHT],int blankPos[2])
{
int neighbors[8][2] = { { 0,1 },{ 1,0 },{ 0,-1 },{ -1,-1 } };
int curTile[2];
kNownGrid[blankPos[0]][blankPos[1]] = 1;
if (fullGrid[blankPos[0]][blankPos[1]] != 0) return;
for (int blck = 0; blck < 8; ++blck)
{
curTile[0] = blankPos[0] + neighbors[blck][0];
curTile[1] = blankPos[1] + neighbors[blck][1];
if (curTile[0] > WIDTH - 1 || curTile[1] > HEIGHT - 1 || curTile[0] < 0 || curTile[1] < 0) continue;
if (fullGrid[curTile[0]][curTile[1]] == 0 && kNownGrid[curTile[0]][curTile[1]] == 0)
{
kNownGrid[curTile[0]][curTile[1]] = 1;
ExpandGrid(fullGrid,kNownGrid,curTile);
}
else if (fullGrid[curTile[0]][curTile[1]] > 0) kNownGrid[curTile[0]][curTile[1]] = 1;
}
}
int main(int argc,char *argv[])
{
COORD characterBufferSize = { WIDTH,HEIGHT };
COORD characterPosition = { 0,0 };
SMALL_RECT consoleWriteArea = { 0,WIDTH - 1,HEIGHT - 1 };
CHAR_INFO consoleBuffer[WIDTH][HEIGHT];
HANDLE wHnd = GetStdHandle(-11);
HANDLE rHnd = GetStdHandle(-10);
DWORD numEventsRead = 0;
DWORD numEvents = 0;
INPUT_RECORD *eventBuffer = { 0 };
int wait = 1000;
int startGrid[WIDTH][HEIGHT] = { 0 };
int kNownGrid[WIDTH][HEIGHT] = { 0 };
int arrowPos[2] = { 0,0 };
int bomb[2] = { 0 };
struct xorshift_state seed = { argc == 2 ? (int)argv[1] : 1 };
for (int i = 0; i < BOMBS; i++)
{
while (startGrid[bomb[0]][bomb[1]] < -1 || bomb[0] <= 0 || bomb[1] <= 0 || bomb[0] >= WIDTH - 1 || bomb[1] >= HEIGHT - 1)
{
bomb[0] = (xorshift(&seed) % WIDTH - 1) + 1;
bomb[1] = (xorshift(&seed) % HEIGHT - 1) + 1;
}
startGrid[bomb[0]][bomb[1]] = -9;
startGrid[bomb[0] + 1][bomb[1] + 1]++;
startGrid[bomb[0] + 1][bomb[1]]++;
startGrid[bomb[0]][bomb[1] + 1]++;
startGrid[bomb[0] - 1][bomb[1] + 1]++;
startGrid[bomb[0]][bomb[1] - 1]++;
startGrid[bomb[0] + 1][bomb[1] - 1]++;
startGrid[bomb[0] - 1][bomb[1] - 1]++;
startGrid[bomb[0] - 1][bomb[1]]++;
}
while (1)
{
if (arrowPos[0] > WIDTH - 1) arrowPos[0] = WIDTH - 1;
if (arrowPos[0] < 0) arrowPos[0] = 0;
if (arrowPos[1] > HEIGHT - 1) arrowPos[1] = HEIGHT - 1;
if (arrowPos[1] < 0) arrowPos[1] = 0;
for (int x = 0; x < WIDTH; ++x)
{
for (int y = 0; y < HEIGHT; ++y)
{
if (kNownGrid[x][y] == 1)
{
if (startGrid[x][y] > 0)
{
consoleBuffer[x][y].Char.AsciiChar = '0' + startGrid[x][y];
consoleBuffer[x][y].Attributes = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
}
else
{
consoleBuffer[x][y].Char.AsciiChar = 'o';
consoleBuffer[x][y].Attributes = (startGrid[x][y] < 0 ? FOREGROUND_RED : FOREGROUND_BLUE) | FOREGROUND_INTENSITY;
}
}
else
{
consoleBuffer[x][y].Char.AsciiChar = '00';
consoleBuffer[x][y].Attributes = 0;
}
if (arrowPos[0] == x && arrowPos[1] == y)
{
consoleBuffer[x][y].Attributes = BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_GREEN;
}
}
}
WriteConsoleOutput(wHnd,*consoleBuffer,characterBufferSize,characterPosition,&consoleWriteArea);
numEvents = 0;
numEventsRead = 0;
GetNumberOfConsoleInputEvents(rHnd,&numEvents);
if (numEvents)
{
eventBuffer = malloc(sizeof(INPUT_RECORD) * numEvents);
ReadConsoleInput(rHnd,eventBuffer,numEvents,&numEventsRead);
}
if (numEventsRead && wait <= 0)
{
wait = 1000;
switch (eventBuffer[0].Event.KeyEvent.wVirtualKeyCode)
{
case 38:
arrowPos[0]--;
break;
case 40:
arrowPos[0]++;
break;
case 37:
arrowPos[1]--;
break;
case 39:
arrowPos[1]++;
break;
case 13:
ExpandGrid(startGrid,arrowPos);
break;
}
}
wait--;
}
}
解决方法
这不符合您的预期:
bomb[0] = (xorshift(&seed) % WIDTH - 1) + 1;
从此之后开始使用此计算值,您似乎希望它返回[1,WIDTH-2]范围内的值。
但是:
- operator precedence表示
(foo % WIDTH - 1) + 1
与((foo % WIDTH) - 1) + 1
相同。就是通过再次添加1
来抵消减去的1
。 - left-shifting negative values(就像您在种子为负值时变成
xorshift
时可能要做的那样)具有undefined behavior:即。任何事情都可能发生。 - right-shifting negative values(就像您在种子为负值时变成
xorshift
时可能要做的那样)具有implementation defined behavior:即。它的行为可能有所不同,具体取决于编译器等。 - modulo operations on negative values定义明确,将导致另一个负值。
考虑到所有这些问题,我不奇怪您看到奇怪的事情发生了。您不仅没有适当地限制计算值的范围,而且还是实现定义和未定义行为的受害者。
代码中可能还存在其他问题,但我将从这些问题开始。