我正在制作蛇游戏并制作原型。我附上了代码。它可能不是那么好但仍然是凌乱的。我可以让它移动,但我不知道为什么下界区域闪烁。如何减少这种整体闪烁,这几乎让我头晕目眩?还有,还有一个问题:如何使角色移动(就像在原始的蛇游戏中一样),而不是等到我的命令?请帮我!对不起该语言。
#include<iostream.h>
#include<stdlib.h>
#include<windows.h>
int main() {
char a[25][80]={0};
system("Color 0");
int x=40,y=15;
int m=0,n;
a[16][2]='X';
a[y][x]='O';
for(int i=0;i<25;++i) {
for(int j=0;j<80;++j) cout<<a[i][j];
}
while(m!=1000) {
Sleep(70);
if(GetAsyncKeyState(VK_LEFT)) {
a[y][x]=0;
x--;++m;a[y][x]='O';
}
if(GetAsyncKeyState(VK_RIGHT)) {
a[y][x]=0;
x++;
++m;
a[y][x]='O';
}
if(GetAsyncKeyState(VK_UP)) {
a[y][x]=0;
y--;
++m;
a[y][x]='O';
}
if(GetAsyncKeyState(VK_DOWN)) {
a[y][x]=0;
y++;
++m;
a[y][x]='O';
}
system("cls");
for(int i=0;i<25;++i) {
for(int j=0;j<80;++j) cout<<a[i][j];
}
}
}
return 0;
}
答案 0 :(得分:0)
你选择了一种图形渲染方法,没有人计划过无闪烁。您需要将图形绘制到窗口,或学习如何使用Windows控制台功能。考虑到你的时间紧迫,我建议你忽略闪烁。
为了让蛇继续移动,记住玩家移动蛇的最后方向;如果没有按下按键,则移动该方向。
您的代码不按原样编译。练习复制和粘贴更难(将其从stackoverflow复制回编译器以确保其有效)
答案 1 :(得分:0)
要克服闪烁,你必须减少你的系统(“cls”)时间。一转后,你的代码没有为蛇提供其他饲料。让它循环。 并且还可以制作地图的边界墙,以便人们可以理解地图的范围。当你按任何一个移动键时,你必须为它的运动运行循环,以便它连续移动。希望这会有所帮助。
答案 2 :(得分:0)
考虑到您可以在不清除之前绘制“屏幕”,可以部分避免闪烁。例如,在Windows控制台环境中(显然您正在使用),此功能可用于清除屏幕而不是system("cls")
:
void clear_screen ( void ) {
DWORD n; /* Number of characters written */
DWORD size; /* number of visible characters */
COORD coord = {0,0}; /* Top left screen position */
CONSOLE_SCREEN_BUFFER_INFO csbi;
/* Get a handle to the console */
HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
GetConsoleScreenBufferInfo ( h, &csbi );
/* Find the number of characters to overwrite */
size = csbi.dwSize.X * csbi.dwSize.Y;
/* Overwrite the screen buffer with whitespace */
FillConsoleOutputCharacter ( h, TEXT ( ' ' ), size, coord, &n );
GetConsoleScreenBufferInfo ( h, &csbi );
FillConsoleOutputAttribute ( h, csbi.wAttributes, size, coord, &n );
/* Reset the cursor to the top left position */
SetConsoleCursorPosition ( h, coord );
}
读取代码时,您会注意到它用足够的空格覆盖屏幕,然后将光标位置重置为左上角位置。因此,我们可以将光标设置在原点,然后编写已经包含空格的字符串,而不是消隐屏幕然后绘制字符串。
此外,我们可以使用单维空终止的char数组,大到足以代表整个屏幕。你使用80x25的大小,但在Windows中控制台更大(至少我的宽度约为100焦),所以我会考虑将81x25的大小放在每行的额外字符中\n
。所以我最终得到了这个:
void update_screen ( char *buffer )
{
COORD coord = {0,0}; /* Top left screen position */
/* Get a handle to the console */
HANDLE h = GetStdHandle ( STD_OUTPUT_HANDLE );
/* Reset the cursor to the top left position */
SetConsoleCursorPosition ( h, coord );
/* Draw the screen buffer */
cout << buffer;
}
要使角色移动,您必须在每次绘制时更新其位置,并仅在按下某个键时更改移动方向。最好还是检查边界碰撞,至少停止游戏:
#include<iostream>
#include<stdlib.h>
#include<windows.h>
#include<string>
using std::cout;
using std::string;
const int scr_rows = 25;
const int scr_cols = 80;
constexpr int buf_rows = scr_rows;
constexpr int buf_cols = scr_cols + 1;
constexpr int buf_size = scr_rows * buf_cols;
void draw( char *buf, int x, int y, char c) {
// warning, unchecked out of bounds;
buf[y * buf_cols + x] = c;
}
char value_at( char *buf, int x, int y ) {
// warning, unchecked out of bounds;
return buf[y * buf_cols + x];
}
int main() {
// initialize buffer
char screen[buf_size + 1];
for ( int i = 0, pos = 0; i < scr_rows; ++i ) {
for ( int j = 0; j < scr_cols; ++j ) {
screen[pos] = ' ';
++pos;
}
screen[pos] = '\n';
++pos;
}
screen[buf_size] = '\0';
clear_screen();
int x = 40, y = 15;
draw(screen, 2, 16,'X');
draw(screen, x, y, 'O');
int vx = -1;
int vy = 0;
bool victory = false;
while( !GetAsyncKeyState(VK_ESCAPE) ) {
Sleep(100);
if (GetAsyncKeyState(VK_LEFT)) {
vx = -1;
vy = 0;
}
if (GetAsyncKeyState(VK_RIGHT)) {
vx = 1;
vy = 0;
}
if (GetAsyncKeyState(VK_UP)) {
vx = 0;
vy = -1;
}
if (GetAsyncKeyState(VK_DOWN)) {
vx = 0;
vy = 1;
}
draw(screen, x, y, ' ');
x += vx;
y += vy;
// check bounds
if ( x < 0 || x >= scr_cols || y < 0 || y >= scr_rows )
break;
if ( 'X' == value_at(screen, x, y) ) {
victory = true;
break;
}
draw(screen, x, y, 'O');
update_screen(screen);
}
if ( victory )
cout << "\n **** You win! ****\n";
else
cout << "\n **** You loose! ****\n";
return 0;
}