console — Советы по игре Snake в Stack Overflow

Я просто хочу тебя кое о чем спросить. Я не жду от вас никакого кода. Я хочу сделать игру со змеями. Моя идея состоит в том, чтобы создать массив и управлять змеей с помощью GetAsyncKeyState () функция. Я еще не решил, как перемещать змею, но я рассматриваю идею использовать связанный список, чтобы хранить координаты тела змеи в массиве.

У меня есть два вопроса:
1. Вам нравится моя идея использовать связанный список?
2. Мне нужно как-то очистить консоль и снова вывести таблицу. Но если я использую Система ( «ЦБС»), экран мигает. Есть ли лучший способ очистить консоль, не мигая?

Любые другие идеи будут оценены. 🙂

Вот мой код сейчас.

    #include<iostream>
#include<windows.h>
using namespace std;
int matrix[20][40];
void FillMatrix()
{
for(int i = 0; i < 20; i++)
for(int j = 0; j < 40; j++)
matrix[i][j] = 0;
}
void Show()
{
COORD pos = {0, 0};
SetConsoleCursorPosition(cout, pos);
for(int i = 0; i < 20; i++)
{
for(int j = 0; j < 40; j++)
{
if(i == 0 || j == 0 || i == 19 || j == 39) cout << "#";
else if(matrix[i][j] == 0) cout << " ";
else cout << ".";
}
cout << endl;
}
}
void Change(int i, int j)
{
matrix[i][j] = 1;
}
int main()
{
FillMatrix();
int x, y;
x = 4;
y = 4;
while(!GetAsyncKeyState(VK_ESCAPE))
{
Sleep(100);
//system("cls");
if(GetAsyncKeyState(VK_LEFT))
{
y = y-1;
Change(x, y);
}
else
if(GetAsyncKeyState(VK_UP))
{
x = x-1;
Change(x, y);
}
else
if(GetAsyncKeyState(VK_RIGHT))
{
y = y+1;
Change(x, y);
}
else
if(GetAsyncKeyState(VK_DOWN))
{
x = x+1;
Change(x, y);
}
Show();
}
system("pause");
return 0;
}

-4

Решение

Использование связанного списка — почти всегда плохая идея. В этом случае, кажется, есть нет причина даже рассмотреть возможность использования одного. Основной момент в пользу использования связанного списка — это когда вам нужно вставить или удалить элементы в середине списка (и, чтобы выиграть, уже есть что-то, указывающее на конкретное место в списке, где вставка / удаление должны происходить).

Поскольку вы, очевидно, используете Win32, я не буду очищать экран вообще. Вместо этого я бы использовал WriteConsoleOutput записать новый вывод на экран, перезаписав все, что было ранее.

Хотя это не игра змея как таковой, Вот код для реализации Game of Life Джона Конвея с использованием WriteConsoleOutput производить вывод на экран. Он также включает в себя ClrScr функция очистки экрана, если вы действительно должен сделать это (но вы, вероятно, нет).

/*
** A quick "life" (2-d cellular automaton) implementation done in Turbo C 2.0
** on the spur-of-the-moment by Jonathan Guthrie 9/20/1992 and donated to the
** public domain.
**
** In keeping with the guidelines of the C_ECHO, this program has been tested,
** and does seem to operate properly.
*/

/* Modified into a native Win32 program, July 2001 by Jerry Coffin.
*/

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <conio.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>

#ifndef random
#define random(num) (int)(((long)rand()*(num))/RAND_MAX)
#endif

#ifndef randomize
#define randomize() srand(((unsigned int)time(NULL))|1)
#endif

#define     ROWS        50
#define     COLS        80
#define     GENERATIONS 500

int civ1[ROWS+2][COLS+2], civ2[ROWS+2][COLS+2];
CHAR_INFO disp[ROWS][COLS];
HANDLE console;
COORD size = { COLS, ROWS };
COORD src = { 0, 0};
SMALL_RECT  dest = { 0, 0, COLS, ROWS };

void fill_edges(int civ1[ROWS+2][COLS+2]);

void ClrScrn(int attrib) {

HANDLE screen = GetStdHandle(STD_OUTPUT_HANDLE);
COORD pos = { 0, 0};
DWORD written;
CONSOLE_SCREEN_BUFFER_INFO screen_attr;
unsigned size;

GetConsoleScreenBufferInfo(screen, &screen_attr);

size = screen_attr.dwSize.X * screen_attr.dwSize.Y;

FillConsoleOutputCharacter( screen,attrib, size, pos, &written);
SetConsoleCursorPosition(console, pos);
}

void update_generation(int old[ROWS][COLS], int new[ROWS][COLS])
{
int i, j, count;

for (i = 1; i <= ROWS; ++i)
{
for (j = 1; j <= COLS; ++j)
{
count = old[(i + ROWS - 1) % ROWS][(j + COLS - 1) % COLS] +
old[(i + ROWS - 1) % ROWS][j] +
old[(i + ROWS - 1) % ROWS][(j + 1) % COLS] +
old[i][(j + COLS - 1) % COLS] +
old[i][(j + 1) % COLS] +
old[(i + 1) % ROWS][(j + COLS - 1) % COLS] +
old[(i + 1) % ROWS][j] +
old[(i + 1) % ROWS][(j + 1) % COLS];

switch(count)
{
default:
new[i][j] = 0;
disp[i][j].Char.AsciiChar = ' ';
break;

case 2:
new[i][j] = old[i][j];
break;

case 3:
new[i][j] = 1;
disp[i][j].Char.AsciiChar = '*';
break;
}
}
}
WriteConsoleOutput(console,disp, size, src, &dest);
}void initialize(void)
{
int i, j;

ClrScrn(0x71);
randomize();

for (i = 1; i <= ROWS; ++i)
{
for (j = 1; j <= COLS; ++j)
{
civ1[i][j] = random(2);
disp[i][j].Char.AsciiChar = civ1[i][j] ? '*' : ' ';
disp[i][j].Attributes = 0x71;
}
}
WriteConsoleOutput(console,disp, size, src, &dest);
fill_edges(civ1);
}

void fill_edges(int civ1[ROWS+2][COLS+2]) {
int i;

for (i=1; i<ROWS; ++i) {
civ1[i][0] = civ1[i][ROWS+1];
civ1[i][ROWS+2] = civ[i][1];
}
for (j=1; j<COLS; ++j) {
civ1[0][j] = civ1[COLS+1][j];
civ1[COLS+2][j] = civ1[1][j];
}
civ1[0][0] = civ1[COLS+1][ROWS+1];
civ1[COLS+2][ROWS+2] = civ1[1][1];
civ1[COLS+2][0] = civ1[

}int main(void)
{
int i;

console = (HANDLE)_get_osfhandle(_fileno(stdout));
initialize();
for (i = 0; i < GENERATIONS; ++i)
{
update_generation(civ1, civ2);
update_generation(civ2, civ1);
}
//  getch();
return EXIT_SUCCESS;
}
1

Другие решения

Пока вы не можете доказать обратное с некоторой рационализацией, это звучит так, как будто вы выбрали связанный список, потому что вы слышали название раньше.

Что касается мерцания экрана, терминалы не удваивают буфер, так что это так, пока вы не используете библиотеку, как ncurses переместить курсор вокруг переписывание позиций вместо того, чтобы повторно чистить экран и начинать с нуля.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector