Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > разработка игр, графический дизайн и моделирование > Gamedev - cоздание игр: Unity, OpenGL, DirectX
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.11.2023, 19:35   #1
Timurkh77
Форумчанин
 
Регистрация: 16.02.2013
Сообщений: 151
По умолчанию фигура не падает в тетрисе

Фигура появляется и смещается на один пиксел.На следующей итерации фигура снова оказывается наверху.Не понятно почему фигура не падает.Также почему-то,смещается вбок экран.Об этом в предыдущей теме.
Вложения
Тип файла: rar tetris2.rar (251.0 Кб, 5 просмотров)
Timurkh77 на форуме Ответить с цитированием
Старый 17.11.2023, 09:58   #2
NetSpace
Участник клуба
 
Аватар для NetSpace
 
Регистрация: 03.06.2009
Сообщений: 1,814
По умолчанию

так, на следующей итерации вы позицию фигуры должны менять и прорисовывать её заново.
а если экран смещается, то вы, выходит, ему новые координаты предаёте, а не фигуре...
Программирование - это единственный способ заставить компьютер делать то, что тебе хочется, а не то, что приходится.
NetSpace вне форума Ответить с цитированием
Старый 17.11.2023, 17:43   #3
Timurkh77
Форумчанин
 
Регистрация: 16.02.2013
Сообщений: 151
По умолчанию

У меня фигура падала , до того как внес кое какие-то изменения,а экран все равно сдвигался.То есть это не связанные вещи.Опубликовал код,где может быть ошибка?
Код:
#include <iostream>
#include<windows.h>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <cstring>

using namespace std;

const int fld_width = 20;
const int fld_height = 30;
const int scr_width = fld_width * 2;
const int scr_height = fld_height;

const char c_fig = 219;
const char c_field = 176;
const char c_figDwn = 178;

typedef char TScreenMap[scr_height][scr_width];
typedef char TFieldMap[fld_height][fld_width];

const int shp_width = 4;
const int shp_height = 4;

typedef char TShape[shp_height][shp_width];

char* shpArr[] = {
    (char*)".....**..**.....",
    (char*)"....****........",
    (char*)"....***..*......",
    (char*)"....***.*.......",
    (char*)".....**.**......" };

const int shpArrCnt = sizeof(shpArr) / sizeof(shpArr[0]);

TFieldMap fld;

void SetCurPos(int x, int y)
{
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

class TScreen
{
    void SetEnd() { scr[scr_height - 1][scr_width - 1] = '\0'; }
public:
    TScreenMap scr;
    TScreen() { Clear(); }
    void Clear() { memset(scr, '.', sizeof(scr)); }
    void Show() { SetCursorPos(0, 0); SetEnd(); cout << scr[0]; }
};

class TField
{
public:
    TFieldMap fld;
    TField() { Clear(); }
    void Clear() { memset(fld, c_field, sizeof(fld)); }
    void Put(TScreenMap& src);
    void Burning();
};

class TFigure
{
    int x, y;
    TShape vid;
    TField* field;
    COORD coord[shp_width * shp_height];
    int coordCnt;
    char turn;
public:
    //TFieldMap fld;
    TFigure() { memset(this, 0, sizeof(*this)); }
    void Shape(char* _vid) { memcpy(vid, _vid, sizeof(vid)); }
    void Pos(int _x, int _y) { x = _x; y = _y; Calccoord(); }
    void Put(TScreenMap& scr);
    void Move(int dx, int dy);
    char TurnGet() { return turn; }
    void TurnSet(char _turn);
    void FieldSet(TField* _field) { field = _field; }
    void Calccoord();
};

class TGame
{
    TScreen screen;
    TFigure figure;
    TField field;
    int x, y;
    COORD coord[shp_width * shp_height];
    int coordCnt;
public:
    TGame();
    void Pos(int _x, int _y) { x = _x; y = _y; figure.Calccoord(); }
    void PlayerControl();
    void Show();
    void Move(int dx,int dy);
};

TGame::TGame()
{
    figure.FieldSet(&field);
    figure.Shape(shpArr[rand() % shpArrCnt]);
    figure.Pos(fld_width / 2 - shp_width / 2, 0);
}

void TGame::PlayerControl()
{
    static int trn = 0;

    /*if (GetKeyState('W') < 0) trn += 1;
    if (trn == 1) figure.TurnSet(figure.TurnGet() + 1), trn++;
    if (GetKeyState('W') > 0) trn = 0;*/

    if (GetKeyState('S') < 0) Move(0, 1);
    if (GetKeyState('A') < 0) Move(-1, 0);
    if (GetKeyState('D') < 0) Move(1, 0);
}


void TGame::Show()
{
    screen.Clear();
    field.Put(screen.scr);/*Выводим игровое поле*/
    figure.Put(screen.scr);/*Выводим фигуру*/
    screen.Show();
}

void TGame::Move(int dx,int dy)
{
    static int tick = 0;

    tick++;
    if (tick >= 5)
    {
            int oldX = x, oldY = y;
            Pos(x + dx, y + dy);

            
            for (int i = 0; i < coordCnt; i++)
                if (coord[i].X < 0 || coord[i].X >= fld_width)
                    Pos(oldX, oldY);
            for (int i = 0; i < coordCnt; i++)
                if (coord[i].Y >= fld_height || fld[coord[i].Y][coord[i].X] == c_figDwn)
                {
                    Pos(oldX, oldY);
                    fld[coord[i].Y][coord[i].X] = c_figDwn;

                    figure.Shape(shpArr[rand() % shpArrCnt]);
                    figure.Pos(fld_width / 2 - shp_width / 2, 0);
                }
        tick = 0;
    }
}

void TFigure::Put(TScreenMap& scr) /*Выводим фигуру*/
{
    for (int i = 0; i < coordCnt; i++)
        scr[coord[i].Y][coord[i].X * 2] = scr[coord[i].Y][coord[i].X * 2 + 1] = c_fig;
}

/*void TFigure::TurnSet(char _turn)
{
    int oldTurn = turn;
    turn = (_turn > 3 ? 0 : (_turn < 0 ? 3 : _turn));
    int chk = Check();
    if (chk == 0) return;
    if (chk == 1)
    {
        int xx = x;
        int k = (x > (fld_width / 2) ? -1 : +1);
        for (int i = 1; i < 3; i++)
        {
            x += k;
            if (Check() == 0) return;
        }
        x = xx;
    }
    turn = oldTurn;
    Calccoord();
}*/



/*bool TFigure::Move(int dx, int dy)
{
    int oldX = x, oldY = y;
    Pos(x + dx, y + dy);
    int chk = Check();
    if (chk >= 1)
    {
        Pos(oldX, oldY);
        if (chk == 2)
            return false;
    }
    return true;
}*/

void TFigure::Calccoord()
{
    int xx;
    int yy;
    coordCnt = 0;
    for (int i = 0; i < shp_width; i++)
        for (int j = 0; j < shp_height; j++)
            if (vid[j][i] == '*')
            {
                if(turn==0) xx = x + i; yy = y + j;
                if (turn == 1) xx = x + (shp_height - j - 1), yy = y + i;
                if (turn == 2) xx = x + (shp_width - i - 1), yy = y + (shp_height - j - 1);
                if (turn == 3) xx = x + j, yy = y + (shp_height - i - 1) + (shp_width - shp_height);

                coord[coordCnt] = { (short)xx,(short)yy };
                coordCnt++;
            }
}

void TField::Put(TScreenMap& scr)
{
    for (int i = 0; i < fld_width; i++)
        for (int j = 0; j < fld_height; j++)
            scr[j][i * 2] = scr[j][i * 2 + 1] = fld[j][i]; /*Выводим измененное игровое поле*/
}


void TField::Burning()
{
    for (int j = fld_height - 1; j >= 0; j--)
    {
        static bool fillLine;
        fillLine = true;
        for (int i = 0; i < fld_width; i++)
            if (fld[j][i] != c_figDwn)
                fillLine = false;
        if (fillLine)
        {
            for (int y = j; y >= 1; y--)
                memcpy(fld[y], fld[y - 1], sizeof(fld[y]));
            return;
        }
    }
}




int main()
{
    char command[1000];
    sprintf_s(command, "mode con cols=%d lines=%d", scr_width, scr_height);
    system(command);

    srand(time(0));


    TGame game;
    
    while (1)
    {
        game.PlayerControl();
        game.Move(0,1);
        game.Show();
        if (GetKeyState(VK_ESCAPE) < 0) break;
        Sleep(50);
    }
    return 0;

Последний раз редактировалось BDA; 17.11.2023 в 17:47.
Timurkh77 на форуме Ответить с цитированием
Старый 17.11.2023, 18:02   #4
Timurkh77
Форумчанин
 
Регистрация: 16.02.2013
Сообщений: 151
По умолчанию

Фигуру я смещаю в основном цикле

Код:
int main()
{
    char command[1000];
    sprintf_s(command, "mode con cols=%d lines=%d", scr_width, scr_height);
    system(command);

    srand(time(0));


    TGame game;
    
    while (1)
    {
        game.PlayerControl();
        game.Move(0,1);
        game.Show();
        if (GetKeyState(VK_ESCAPE) < 0) break;
        Sleep(50);
    }
    return 0;

}
Оператором game.Move(0,1);

Вот текст функции Move();
Код:
void TGame::Move(int dx,int dy)
{
    static int tick = 0;

    tick++;
    if (tick >= 5)
    {
            int oldX = x, oldY = y;
            Pos(x + dx, y + dy);

            
            for (int i = 0; i < coordCnt; i++)
                if (coord[i].X < 0 || coord[i].X >= fld_width)
                    Pos(oldX, oldY);
            for (int i = 0; i < coordCnt; i++)
                if (coord[i].Y >= fld_height || fld[coord[i].Y][coord[i].X] == c_figDwn)
                {
                    Pos(oldX, oldY);
                    fld[coord[i].Y][coord[i].X] = c_figDwn;

                    figure.Shape(shpArr[rand() % shpArrCnt]);
                    figure.Pos(fld_width / 2 - shp_width / 2, 0);
                }
        tick = 0;
    }
}
Координаты смещаю функцией Pos(x+dx,y+dy);

В этой функции вызываю функцию Calccoord().
Которая добавляет к координатам xx=x+i ; yy=y+j;

Код:
void TFigure::Calccoord()
{
    int xx;
    int yy;
    coordCnt = 0;
    for (int i = 0; i < shp_width; i++)
        for (int j = 0; j < shp_height; j++)
            if (vid[j][i] == '*')
            {
                xx = x + i; yy = y + j;
                
                coord[coordCnt] = { (short)xx,(short)yy };
                coordCnt++;
            }
}

Последний раз редактировалось BDA; 17.11.2023 в 18:41.
Timurkh77 на форуме Ответить с цитированием
Старый 18.11.2023, 21:31   #5
NetSpace
Участник клуба
 
Аватар для NetSpace
 
Регистрация: 03.06.2009
Сообщений: 1,814
По умолчанию

а убери-ка из игры фигуру и всё, что с ней связано (уничтожение-сжигание полной строки). пусть будет чистое поле. и какова будет реакция на клавиши A, S, D? если и тогда экран будет смещаться, копай дальше - смотри процедуру прорисовки поля.
Программирование - это единственный способ заставить компьютер делать то, что тебе хочется, а не то, что приходится.
NetSpace вне форума Ответить с цитированием
Старый 21.11.2023, 00:19   #6
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

SetCursorPos меняет положение курсора мыши, а не курсора в консоли. TScreen.SetEnd "портит" последний символ экрана. Предлагаю такие замены:
Код:
typedef char TScreenMap[scr_height + 1][scr_width];
...
void hidecursor()
{
    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO info;
    info.dwSize = 100;
    info.bVisible = FALSE;
    SetConsoleCursorInfo(consoleHandle, &info);
}

class TScreen
{
    void SetEnd() { scr[scr_height][0] = '\0'; }
public:
    TScreenMap scr;
    TScreen() { Clear(); }
    void Clear() { memset(scr, '.', sizeof(scr)); }
    void Show() { SetEnd(); cout << scr[0]; }
};
...
int main()
{
    hidecursor();
    ...
Курсор в консоли будет не виден, а экран будет печататься полностью. Но движения фигуры нет - нужно еще искать проблемы.

UPD. Чуть причесанный вариант, в который можно поиграть:
Код:
#include <iostream>
#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <cstring>

using namespace std;

const int fld_width = 20;
const int fld_height = 30;
const int scr_width = fld_width * 2;
const int scr_height = fld_height;

const char c_fig = 219;
const char c_field = 176;
const char c_figDwn = 178;

typedef char TScreenMap[scr_height + 1][scr_width];
typedef char TFieldMap[fld_height][fld_width];

const int shp_width = 4;
const int shp_height = 4;

typedef char TShape[shp_height][shp_width];

char* shpArr[] = {
    (char*)".....**..**.....",
    (char*)"....****........",
    (char*)"....***..*......",
    (char*)"....***.*.......",
    (char*)".....**.**......" };

const int shpArrCnt = sizeof(shpArr) / sizeof(shpArr[0]);

void hidecursor()
{
    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO info;
    info.dwSize = 100;
    info.bVisible = FALSE;
    SetConsoleCursorInfo(consoleHandle, &info);
}

class TScreen
{
    void SetEnd() { scr[scr_height][0] = '\0'; }
public:
    TScreenMap scr;
    TScreen() { Clear(); }
    void Clear() { memset(scr, '.', sizeof(scr)); }
    void Show() { SetEnd(); cout << scr[0]; }
};

class TField
{
public:
    TFieldMap fld;
    TField() { Clear(); }
    void Clear() { memset(fld, c_field, sizeof(fld)); }
    void Put(TScreenMap& src);
    void Burning();
};

class TFigure
{
    int x, y;
    TShape vid;
    TField* field;
    COORD coord[shp_width * shp_height];
    int coordCnt;
    char turn;
public:
    TFigure() { memset(this, 0, sizeof(*this)); }
    void Shape(char* _vid) { memcpy(vid, _vid, sizeof(vid)); }
    void Pos(int _x, int _y) { x = _x; y = _y; Calccoord(); }
    void Put(TScreenMap& scr);
    void Move(int dx, int dy);
    char TurnGet() { return turn; }
    void TurnSet(char _turn);
    void FieldSet(TField* _field) { field = _field; }
    void Calccoord();
    void NewFigure();
};

class TGame
{
    TScreen screen;
    TFigure figure;
    TField field;
public:
    TGame();
    void PlayerControl();
    void Show();
    void Loop();
};

TGame::TGame()
{
    figure.FieldSet(&field);
    figure.NewFigure();
}

void TGame::PlayerControl()
{
    static int trn = 0;

    /*if (GetKeyState('W') < 0) trn += 1;
    if (trn == 1) figure.TurnSet(figure.TurnGet() + 1), trn++;
    if (GetKeyState('W') > 0) trn = 0;*/

    if (GetKeyState('S') < 0) figure.Move(0, 1);
    if (GetKeyState('A') < 0) figure.Move(-1, 0);
    if (GetKeyState('D') < 0) figure.Move(1, 0);
}


void TGame::Show()
{
    screen.Clear();
    field.Put(screen.scr);/*Выводим игровое поле*/
    figure.Put(screen.scr);/*Выводим фигуру*/
    screen.Show();
}

void TGame::Loop()
{
    while (1)
    {
        PlayerControl();
        figure.Move(0, 1);
        Show();
        if (GetKeyState(VK_ESCAPE) < 0) break;
        Sleep(50);
    }
}

void TFigure::NewFigure()
{
    Shape(shpArr[rand() % shpArrCnt]);
    Pos(fld_width / 2 - shp_width / 2, 0);
}

void TFigure::Move(int dx, int dy)
{
    static int tick = 0;

    tick++;
    if (tick >= 5)
    {
        int oldX = x, oldY = y;
        Pos(x + dx, y + dy);

        for (int i = 0; i < coordCnt; i++)
            if (coord[i].X < 0 || coord[i].X >= fld_width)
            {
                Pos(oldX, y + dy);
                break;
            }

        for (int i = 0; i < coordCnt; i++)
            if (coord[i].Y >= fld_height || field->fld[coord[i].Y][coord[i].X] == c_figDwn)
            {
                Pos(oldX, oldY);

                for (int j = 0; j < coordCnt; j++)
                    field->fld[coord[j].Y][coord[j].X] = c_figDwn;

                NewFigure();

                break;
            }

        tick = 0;
    }
}

void TFigure::Put(TScreenMap& scr) /*Выводим фигуру*/
{
    for (int i = 0; i < coordCnt; i++)
        scr[coord[i].Y][coord[i].X * 2] = scr[coord[i].Y][coord[i].X * 2 + 1] = c_fig;
}

void TFigure::Calccoord()
{
    int xx;
    int yy;
    coordCnt = 0;
    for (int i = 0; i < shp_width; i++)
        for (int j = 0; j < shp_height; j++)
            if (vid[j][i] == '*')
            {
                if (turn == 0) xx = x + i; yy = y + j;
                if (turn == 1) xx = x + (shp_height - j - 1), yy = y + i;
                if (turn == 2) xx = x + (shp_width - i - 1), yy = y + (shp_height - j - 1);
                if (turn == 3) xx = x + j, yy = y + (shp_height - i - 1) + (shp_width - shp_height);

                coord[coordCnt] = { (short)xx,(short)yy };
                coordCnt++;
            }
}

void TField::Put(TScreenMap& scr)
{
    for (int i = 0; i < fld_width; i++)
        for (int j = 0; j < fld_height; j++)
            scr[j][i * 2] = scr[j][i * 2 + 1] = fld[j][i]; /*Выводим измененное игровое поле*/
}

void TField::Burning()
{
    for (int j = fld_height - 1; j >= 0; j--)
    {
        static bool fillLine;
        fillLine = true;
        for (int i = 0; i < fld_width; i++)
            if (fld[j][i] != c_figDwn)
                fillLine = false;
        if (fillLine)
        {
            for (int y = j; y >= 1; y--)
                memcpy(fld[y], fld[y - 1], sizeof(fld[y]));
            return;
        }
    }
}

int main()
{
    hidecursor();
    char command[1000];
    sprintf_s(command, "mode con cols=%d lines=%d", scr_width, scr_height);
    system(command);

    srand(time(0));

    TGame game;

    game.Loop();

    return 0;
}
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 22.11.2023 в 05:19.
BDA вне форума Ответить с цитированием
Старый 03.01.2024, 17:23   #7
Timurkh77
Форумчанин
 
Регистрация: 16.02.2013
Сообщений: 151
По умолчанию

Все работает.Но если сделать figure.Move(0,5),то фигуры падают не впритык.При увеличении скорости
программа не работает.Как сделать , чтобы фигуры попадали друг на друга.Подозреваю , что дело в том, что при вызове Pos(oldX,oldY) передаются координаты на 4 больше.
Другой вопрос
void Clear() { memset(scr, '.', sizeof(scr)); }
void Show() { SetEnd(); cout << scr[0];
как заполняется весь массив scr точками , ведь memset заполняется не в цикле.И как выводится
scr[0].Ведь выводится вроде бы первый элемент.
Timurkh77 на форуме Ответить с цитированием
Старый 04.01.2024, 20:01   #8
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Цитата:
Сообщение от Timurkh77 Посмотреть сообщение
то фигуры падают не впритык
Потому что текущий TFigure::Move работает только для dy 0 или 1, а при 5 он пытается передвинуть фигуру сразу на 5 клеток, а если это невозможно, то останавливается. Вот измененная версия с Game Over и любым dy.
Код:
#include <iostream>
#include <windows.h>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <cstring>

using namespace std;

const int fld_width = 20;
const int fld_height = 30;
const int scr_width = fld_width * 2;
const int scr_height = fld_height;

const char c_fig = 219;
const char c_field = 176;
const char c_figDwn = 178;

typedef char TScreenMap[scr_height + 1][scr_width];
typedef char TFieldMap[fld_height][fld_width];

const int shp_width = 4;
const int shp_height = 4;

typedef char TShape[shp_height][shp_width];

char* shpArr[] = {
    (char*)".....**..**.....",
    (char*)"....****........",
    (char*)"....***..*......",
    (char*)"....***.*.......",
    (char*)".....**.**......" };

const int shpArrCnt = sizeof(shpArr) / sizeof(shpArr[0]);

void hidecursor()
{
    HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
    CONSOLE_CURSOR_INFO info;
    info.dwSize = 100;
    info.bVisible = FALSE;
    SetConsoleCursorInfo(consoleHandle, &info);
}

class TScreen
{
    void SetEnd() { scr[scr_height][0] = '\0'; }
public:
    TScreenMap scr;
    TScreen() { Clear(); }
    void Clear() { memset(scr, '.', sizeof(scr)); }
    void Show() { SetEnd(); cout << scr[0]; }
    void Put(const char* s, int y, int x) { memcpy(&scr[y][x], s, strlen(s)); }
};

class TField
{
public:
    TFieldMap fld;
    TField() { Clear(); }
    void Clear() { memset(fld, c_field, sizeof(fld)); }
    void Put(TScreenMap& src);
    void Burning();
};

class TFigure
{
    int x, y;
    TShape vid;
    TField* field;
    char turn;
    COORD coord[shp_width * shp_height];
    int coordCnt;
public:
    bool exists = false;
    TFigure() { memset(this, 0, sizeof(*this)); }
    void Shape(char* _vid) { memcpy(vid, _vid, sizeof(vid)); }
    void Pos(int _x, int _y) { x = _x; y = _y; Calccoord(); }
    void Put(TScreenMap& scr);
    void Move(int dx, int dy);
    char TurnGet() { return turn; }
    void TurnSet(char _turn);
    void FieldSet(TField* _field) { field = _field; }
    void Calccoord();
    void NewFigure();
};

class TGame
{
    TScreen screen;
    TFigure figure;
    TField field;
public:
    TGame();
    void PlayerControl();
    void Show();
    void Loop();
};

TGame::TGame()
{
    figure.FieldSet(&field);
    figure.NewFigure();
}

void TGame::PlayerControl()
{
    static int trn = 0;

    /*if (GetKeyState('W') < 0) trn += 1;
    if (trn == 1) figure.TurnSet(figure.TurnGet() + 1), trn++;
    if (GetKeyState('W') > 0) trn = 0;*/

    if (GetKeyState('S') < 0) figure.Move(0, 1);
    if (GetKeyState('A') < 0) figure.Move(-1, 0);
    if (GetKeyState('D') < 0) figure.Move(1, 0);
}


void TGame::Show()
{
    screen.Clear();
    field.Put(screen.scr);/*Выводим игровое поле*/
    figure.Put(screen.scr);/*Выводим фигуру*/
    screen.Show();
}

void TGame::Loop()
{
    while (figure.exists)
    {
        PlayerControl();
        figure.Move(0, 5);
        Show();
        if (GetKeyState(VK_ESCAPE) < 0) break;
        Sleep(50);
    }
    if (!figure.exists)
    {
        screen.Put("GAME  OVER", scr_height / 2, scr_width / 2 - 5);
        screen.Show();
        while (1)
        {
            if (GetKeyState(VK_ESCAPE) < 0) break;
            Sleep(50);
        }
    }
}

void TFigure::NewFigure()
{
    Shape(shpArr[rand() % shpArrCnt]);
    Pos(fld_width / 2 - shp_width / 2, 0);

    bool Possible = true;
    for (int i = 0; i < coordCnt && Possible; i++)
        Possible = field->fld[coord[i].Y][coord[i].X] != c_figDwn;
    exists = Possible;
}

void TFigure::Move(int dx, int dy)
{
    static int tick = 0;

    tick++;
    if (tick >= 5)
    {
        int oldX = x, oldY = y, new_dx = 0, new_dy = 0;

        if (dx > 0)
            for (int j = 1; j <= dx; ++j)
            {
                Pos(oldX + j, oldY);
                bool Possible = true;
                for (int i = 0; i < coordCnt && Possible; i++)
                    Possible = coord[i].X < fld_width && field->fld[coord[i].Y][coord[i].X] != c_figDwn;
                if (Possible)
                    new_dx = j;
                else
                    break;
            }
        else if (dx < 0)
        {
            for (int j = -1; j >= dx; --j)
            {
                Pos(oldX + j, oldY);
                bool Possible = true;
                for (int i = 0; i < coordCnt && Possible; i++)
                    Possible = coord[i].X >= 0 && field->fld[coord[i].Y][coord[i].X] != c_figDwn;
                if (Possible)
                    new_dx = j;
                else
                    break;
            }
        }
        oldX += new_dx;

        for (int j = 1; j <= dy; ++j)
        {
            Pos(oldX, oldY + j);
            bool Possible = true;
            for (int i = 0; i < coordCnt && Possible; i++)
                Possible = coord[i].Y < fld_height && field->fld[coord[i].Y][coord[i].X] != c_figDwn;
            if (Possible)
                new_dy = j;
            else
                break;
        }
        oldY += new_dy;
        Pos(oldX, oldY);

        if (dy != 0 && new_dy == 0)
        {
            for (int i = 0; i < coordCnt; i++)
                field->fld[coord[i].Y][coord[i].X] = c_figDwn;
            NewFigure();
        }

        tick = 0;
    }
}

void TFigure::Put(TScreenMap& scr) /*Выводим фигуру*/
{
    if (exists)
        for (int i = 0; i < coordCnt; i++)
            scr[coord[i].Y][coord[i].X * 2] = scr[coord[i].Y][coord[i].X * 2 + 1] = c_fig;
}

void TFigure::Calccoord()
{
    int xx;
    int yy;
    coordCnt = 0;
    for (int i = 0; i < shp_width; i++)
        for (int j = 0; j < shp_height; j++)
            if (vid[j][i] == '*')
            {
                if (turn == 0) xx = x + i; yy = y + j;
                if (turn == 1) xx = x + (shp_height - j - 1), yy = y + i;
                if (turn == 2) xx = x + (shp_width - i - 1), yy = y + (shp_height - j - 1);
                if (turn == 3) xx = x + j, yy = y + (shp_height - i - 1) + (shp_width - shp_height);

                coord[coordCnt] = { (short)xx,(short)yy };
                coordCnt++;
            }
}

void TField::Put(TScreenMap& scr)
{
    for (int i = 0; i < fld_width; i++)
        for (int j = 0; j < fld_height; j++)
            scr[j][i * 2] = scr[j][i * 2 + 1] = fld[j][i]; /*Выводим измененное игровое поле*/
}

void TField::Burning()
{
    for (int j = fld_height - 1; j >= 0; j--)
    {
        static bool fillLine;
        fillLine = true;
        for (int i = 0; i < fld_width; i++)
            if (fld[j][i] != c_figDwn)
                fillLine = false;
        if (fillLine)
        {
            for (int y = j; y >= 1; y--)
                memcpy(fld[y], fld[y - 1], sizeof(fld[y]));
            return;
        }
    }
}

int main()
{
    hidecursor();
    char command[1000];
    sprintf_s(command, "mode con cols=%d lines=%d", scr_width, scr_height);
    system(command);

    srand(time(0));

    TGame game;

    game.Loop();

    return 0;
}
Цитата:
Сообщение от Timurkh77 Посмотреть сообщение
ведь memset заполняется не в цикле
3й параметр memset задает количество байтов для заполнения.
Цитата:
Сообщение от Timurkh77 Посмотреть сообщение
как выводится scr[0].Ведь выводится вроде бы первый элемент.
Тип src[0] это char[], поэтому при печати считается указателем на нультерминированную строку.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Старый 08.01.2024, 21:08   #9
Timurkh77
Форумчанин
 
Регистрация: 16.02.2013
Сообщений: 151
По умолчанию

Сделал переход на следующий уровень.Выдается ошибка в
screen.Put(buf, scr_height / 2, scr_width / 2 - 9); необъявленный идентификатор в функции NewFigure.Почему не воспринимает screen в этой функции.

Код:
#include <iostream>
#include<windows.h>
#include <cstdlib>
#include <ctime>
#include <cstdio>
#include <cstring>

using namespace std;

const int fld_width = 20;
const int fld_height = 30;
const int scr_width = fld_width * 2;
const int scr_height = fld_height;

const char c_fig = 219;
const char c_field = 176;
const char c_figDwn = 178;

typedef char TScreenMap[scr_height + 1][scr_width];
typedef char TFieldMap[fld_height][fld_width];

const int shp_width = 4;
const int shp_height = 4;

typedef char TShape[shp_height][shp_width];

char* shpArr[] = {
    (char*)".....**..**.....",
    (char*)"....****........",
    (char*)"....***..*......",
    (char*)"....***.*.......",
    (char*)".....**.**......" };

const int shpArrCnt = sizeof(shpArr) / sizeof(shpArr[0]);

int score = 0;
int dx = 0, dy = 1;
int level = 1;


void SetCurPos(int x, int y)
{
    COORD coord;
    coord.X = x;
    coord.Y = y;
    SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), coord);
}

class TScreen
{
    void SetEnd() { scr[scr_height][0] = '\0'; }
public:
    TScreenMap scr;
    TScreen() { Clear(); }
    void Clear() { memset(scr, ' ', sizeof(scr)); }
    void Show() { SetEnd(); cout << scr[0]; }
    void Put(const char* s, int y, int x) { memcpy(&scr[y][x], s, strlen(s)); }
};

class TField
{
public:
    TFieldMap fld;
    TField() { Clear(); }
    void Clear() { memset(fld, c_field, sizeof(fld)); }
    void Put(TScreenMap& src);
    void Burning();
};

class TFigure
{
    int x, y;
    TShape vid;
    TField* field;
    COORD coord[shp_width * shp_height];
    int coordCnt;
    char turn;
public:
    bool exists = false;
    TFigure() { memset(this, 0, sizeof(*this)); }
    void Shape(char* _vid) { memcpy(vid, _vid, sizeof(vid)); }
    void Pos(int _x, int _y) { x = _x; y = _y; Calccoord(); }
    void Put(TScreenMap& scr);
    void Move(int dx, int dy);
    char TurnGet() { return turn; }
    void TurnSet(char _turn);
    void FieldSet(TField* _field) { field = _field; }
    void Calccoord();
    void NewFigure();
};

class TGame
{
    TScreen screen;
    TFigure figure;
    TField field;
public:
    TGame();
    void PlayerControl();
    void Show();
    void Loop();
};

TGame::TGame()
{
    figure.FieldSet(&field);
    figure.NewFigure();
}

void TFigure::NewFigure()
{
    char buf[80];
    Shape(shpArr[rand() % shpArrCnt]);
    Pos(fld_width / 2 - shp_width / 2, 0);

    bool Possible = true;
    for (int i = 0; i < coordCnt && Possible; i++)
        Possible = field->fld[coord[i].Y][coord[i].X] != c_figDwn;
    if (!Possible)
    {
        dy += 1;
        level++;
        field->Clear();
        sprintf_s(buf, "Welcome to level %d", level);
        screen.Put(buf, scr_height / 2, scr_width / 2 - 9);
        screen.Show();
        if (level > 5)
            exists = Possible;
    }
}

void TGame::PlayerControl()
{
    static int trn = 0;

    if (GetKeyState('W') < 0) trn += 1;
    if (trn == 1) figure.TurnSet(figure.TurnGet() + 1), trn++;
    if (GetKeyState('W') > 0) trn = 0;

    if (GetKeyState('S') < 0) figure.Move(0, 1);
    if (GetKeyState('A') < 0) figure.Move(-1, 0);
    if (GetKeyState('D') < 0) figure.Move(1, 0);
}


void TGame::Show()
{
    screen.Clear();
    field.Put(screen.scr);/*Выводим игровое поле*/
    figure.Put(screen.scr);/*Выводим фигуру*/
    screen.Show();
}

void TFigure::Move(int dx, int dy)
{
  /**/  
        field->Burning();
        tick = 0;

    }
}

void TFigure::Put(TScreenMap& scr) /*Выводим фигуру*/
{
    if(exists)
     for (int i = 0; i < coordCnt; i++)
         scr[coord[i].Y][coord[i].X * 2] = scr[coord[i].Y][coord[i].X * 2 + 1] = c_fig;
}

void TFigure::TurnSet(char _turn)
{
    int oldTurn = turn;
    turn = (_turn > 3 ? 0 : (_turn < 0 ? 3 : _turn));

    int error;
    for (int i = 0; i < coordCnt; i++)
    {
        error = 0;
        if (coord[i].X < 0 || coord[i].X >= fld_width)
        {
            error = 1;
            int xx = x;
            int k = (x > (fld_width / 2) ? -1 : +1);
            for (int i = 1; i < 3; i++)
            {
                x += k;
                int t = 0;
                for (int j = 0; j < coordCnt; j++)
                    if (coord[j].X > 0 && coord[j].X <= fld_width)
                        t = 1;
                    else
                    {
                        t = 0;
                        break;
                    }
                if (t == 0) return;
            }
            x = xx;
        }
    }
    if (error == 0) return;
    turn = oldTurn;
    Calccoord();

}

void TFigure::Calccoord()
{
    int xx;
    int yy;
    coordCnt = 0;
    for (int i = 0; i < shp_width; i++)
        for (int j = 0; j < shp_height; j++)
            if (vid[j][i] == '*')
            {
                if (turn == 0) xx = x + i; yy = y + j;
                if (turn == 1) xx = x + (shp_height - j - 1), yy = y + i;
                if (turn == 2) xx = x + (shp_width - i - 1), yy = y + (shp_height - j - 1);
                if (turn == 3) xx = x + j, yy = y + (shp_height - i - 1) + (shp_width - shp_height);

                coord[coordCnt] = { (short)xx,(short)yy };
                coordCnt++;
            }
}

void TField::Put(TScreenMap& scr)
{
    for (int i = 0; i < fld_width; i++)
        for (int j = 0; j < fld_height; j++)
            scr[j][i * 2] = scr[j][i * 2 + 1] = fld[j][i]; /*Выводим измененное игровое поле*/
}


void TField::Burning()
{
    for (int j = fld_height - 1; j >= 0; j--)
    {
        static bool fillLine;
        fillLine = true;
        for (int i = 0; i < fld_width; i++)
            if (fld[j][i] != c_figDwn)
                fillLine = false;
        if (fillLine)
        {
            for (int y = j; y >= 1; y--)
                memcpy(fld[y], fld[y - 1], sizeof(fld[y]));
            score += 20;
            return;
        }
    }
}


void TGame::Loop()
{
    char buf[80];
    while (figure.exists)
    {
        PlayerControl();
        figure.Move(dx,dy);
        Show();
        if (GetKeyState(VK_ESCAPE) < 0) break;
        Sleep(50);
    }
    if (!figure.exists)
    {   
        screen.Clear();
        screen.Put("GAME  OVER", scr_height / 2, scr_width / 2 - 5);
        sprintf_s(buf, "Score: %d", score);
        screen.Put(buf, scr_height / 2 + 2, scr_width / 2 - 4);
        screen.Show();
        while (1)
        {
            if (GetKeyState(VK_ESCAPE) < 0) break;
            Sleep(50);
        }
    }
}


int main()
{
    char command[1000];
    sprintf_s(command, "mode con cols=%d lines=%d", scr_width, scr_height);
    system(command);

    srand(time(0));


    TGame game;

    game.Loop();

    return 0;
}

Последний раз редактировалось BDA; 09.01.2024 в 02:46.
Timurkh77 на форуме Ответить с цитированием
Старый 09.01.2024, 03:07   #10
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Цитата:
Сообщение от Timurkh77 Посмотреть сообщение
Почему не воспринимает screen в этой функции.
Потому что screen это приватное поле класса TGame, о котором метод класса TFigure ничего не знает и не имеет доступа. Можно конечно передать ссылку на screen по аналогии с field, но лучше перенести логику уровней в TGame. Ну или отказаться от ООП, засунув всю логику в один класс, а другие классы/структуры использовать только для красивых имен полей.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Game Over в Тетрисе. Delphi 7 Divia Общие вопросы Delphi 2 06.12.2021 09:50
Алгоритм вращения фигуры в тетрисе Joose Помощь студентам 11 14.07.2013 19:34
таблица рекордов в тетрисе! Юлия11 C++ Builder 10 12.06.2013 10:34
GraphABC фигура dosha Помощь студентам 6 11.03.2013 19:31
фигура-грани lex1398 Помощь студентам 2 28.08.2010 09:54