Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.54/35: Рейтинг темы: голосов - 35, средняя оценка - 4.54
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116

Тетрис на c++

03.08.2013, 21:13. Показов 7111. Ответов 10
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Я решил проверить свои скудные знания языка и написать всем известную игру тетрис. Вот что получилось.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>
#include <locale.h>
#include <conio.h>
#include <Windows.h>
 
using namespace std;
 
static char field[10][10] = {"         ",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#########" }; //y x
bool Run = true;
float timer;
 
void Draw(){
    system("cls");
    for (int i =0; i<10;i++){
        cout << field[i] << endl;
    }
}
 
class Block{
public:
    Block(char imag, int x, int y){
        xP = x; yP = y; image = imag;
    }
    char image;
    int xP, yP;
 
    void Block::Input();
 
    static void Turn(Block block){
        switch(field[block.yP+1][block.xP]){
            case ' ':
                field[block.yP][block.xP] = ' ';
                block.yP += 1;
                field[block.yP][block.xP] = block.image;
            break;
        }
    }
};
 
void Block::Input(){
    for (int i =0; i < 10; i++){
        for (int j =0 ; j< 10; j++){
            switch(field[j][i]){
                case 'O':
                    if (GetAsyncKeyState(VK_LEFT) != 0){
                        int j2 = j++;
                        switch (field[i][j2]){
                            case ' ':
                                field[i][j] = ' ';
                                j = j2;
                                field[i][j] = 'O';
                                break;
                        }
                    }
                    if (GetAsyncKeyState(VK_RIGHT) != 0){
                        int j2 = j--;
                        switch (field[i][j2]){
                            case ' ':
                                field[i][j] = ' ';
                                j = j2;
                                field[i][j] = 'O';
                                break;
                        }
                    }
                break;
            }
        }
    }
}
 
 
 
int main(){
    setlocale(LC_ALL,"RUS");
    static Block block1('H',5,0);
    {
    while (Run){
        timer += 0.01f;
        if (timer >= 150000){
            Block::Turn(block1);
            Draw();
            timer =0;
        }
    }
    }
    return 0;
}

Но только она не работает должным образом. То есть не падает блок. нельзя двигать его по бокам.
В чем ошибка? и насколько правильнен код? и как написать лучше?

Добавлено через 7 минут
да и как можно записать без static, а то это меня напрягает, все таки статик для всех параметры одинаковы, а мне надо будет сделать для каждого объекта копию его класса, чтобы как бы параметры типа координаты и значка были лично для этого объекта. все таки надо сделать спавн блоков
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
03.08.2013, 21:13
Ответы с готовыми решениями:

Тетрис на C++
Вот надо написать тетрис на курсовую. Проблема в том, что незнаю с чего начать. Есть , что то вроде гайдов по написанию подобного? И еще,...

Тетрис на С++
Помогите доработать игру. запутался с _kbhit() и _getch() нужно сделать чтобы фигура постоянно падала, а во время нажатия клавиш смещалась....

Тетрис
Здравствуйте. Задали написать курсовую Тетрис,используя класы. Вроде все было хорошо, но при одной из компиляций обрушилось очень много...

10
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
04.08.2013, 03:25
Цитата Сообщение от Gomg Посмотреть сообщение
Но только она не работает должным образом. То есть не падает блок. нельзя двигать его по бокам.
В чем ошибка? и насколько правильнен код? и как написать лучше?
Блок перемещать нужно. У тебя есть поле 10 на 10, блок у тебя вверху появляется проверяй возможно ли его опустить на клетку вниз делаешь опускание, затем делаешь задержку на секунду или больше потом снова опускание, что бы оно плавно двигалось, просто в цикле изменяй координаты блока по вертикальной оси на -1. Что бы в бок перемещать по горизонтальной оси изменяй координаты на -1 или +1.
Повороты наверно делаются просто для какждого блока в зависимости от формы там ге, квадрат или палка программируешь как она будет отображатся после поворота, короче как изменит свое состояния не знаю но похоже самое тяжолое это сделать поворот хотя кто его знает, да тут наверно каждый блок должен хранить состояние поля.

И вообще структуру программы если б я делал я б сделал все в одном классе, просто при начале хода сделал бы рандомный выбор функций фигур, функция палки, функция квадрата и.тд и запрограммировал бы каждую функцию и они б уже до конца обработали поле без создания там разных классов, так просто мне эта мелкая программа яснее представляется.
По такому циклу яб делал: рандомно выбираешь какой блок выпадет, это рандомиш число, а затем в swtich определяешь фунцию которая изменяет координаты поля каждая по своему или квадрат или палка, и в цикле доводит до конца пока вниз не опустится, наверно как то в этот период нужно обрабатывать три события вправа влево поворот. Село на низ проверяешь заполнены ли строки массива, удаляешь заполненые строки, затем снова делаешь рандомный выбор функции и так пока буде место свободное в массиве, ну например две верхних строки свободные. как токо они не свободны, то выводишь типо пользователь проиграл.

В принципе тут не сильно понятно как события ловить в период падения, я просто как события ловить вообще не знаю, но сама реализация и алгоритм я б по такому делал, мне так кажется намного проще чем разбивать на классы.

Добавлено через 2 минуты
Gomg, Ты тут написал 90 строк кода и спрашиваешь почему оно не работает, когда там должно быть строк примерно 1.5к
0
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116
04.08.2013, 08:44  [ТС]
так почему-то не назначается массиву символ по измененной y++ координате
C++
1
2
3
4
5
6
7
8
9
static void Turn(Block block){
        switch(field[block.yP+1][block.xP]){
            case ' ':
                field[block.yP][block.xP] = ' ';
                block.yP += 1;
                field[block.yP][block.xP] = block.image;
            break;
        }
    }
так и я все-таки не узнал ответы на вопросы про статик и т.д. Да и мне кажется делая классы намного удобнее будет и проще. Да и вообще я еще не задумываюсь о поворотах, я делаю только блок из одного элемента.

Добавлено через 1 час 5 минут
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#include <iostream>
#include <locale.h>
#include <conio.h>
#include <Windows.h>
 
using namespace std;
 
static char field[10][10] = {"         ",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#       #",
                             "#########" }; //y x
bool Run = true;
float timer;
 
void Draw(){
    system("cls");
    for (int i =0; i<10;i++){
        cout << field[i] << endl;
    }
}
 
class Block{
public:
    Block(char imag, int x, int y){
        xP = x; yP = y; image = imag;
    }
    char image;
    int xP, yP;
};
void Turn(Block &block){
        switch(field[block.yP+1][block.xP]){
            case ' ':
                field[block.yP][block.xP] = ' ';
                block.yP += 1;
                field[block.yP][block.xP] = block.image;
            break;
        }
}
 
void Input(Block block){
    int i2 = 0;
    for (int i =0; i < 10; i++){
        for (int j =0 ; j< 10; j++){
            switch(field[j][i]){
                case 'O':
                    if (GetAsyncKeyState(VK_LEFT) != 0){
                    i2 = i++;
                        switch (field[j][i2]){
                            case ' ':
                                field[j][i2] = block.image;
                                field[j][i] = ' ';
                                i = i2;
                                Draw();
                                break;
                            default: break;
                        }
                    }
                    if (GetAsyncKeyState(VK_RIGHT) != 0){
                        int i2 = i--;
                        switch (field[j][i2]){
                            case ' ':
                                field[j][i2] = block.image;
                                field[j][i] = ' ';
                                i = i2;
                                Draw();
                                break;
                            default: break;
                        }
                    }
                break;
            }
        }
    }
}
 
 
 
int main(){
    setlocale(LC_ALL,"RUS");
    Block block1('O',5,0);
    {
    while (Run){
        timer += 0.01f;
        if (timer >= 150000){
            Turn(block1);
            Draw();
            Input(block1);
            //if (
            timer =0;
        }
    }
    }
    return 0;
}
вот я написал код ,но блок только падает. не сдвигается
0
Неэпический
 Аватар для Croessmah
18144 / 10728 / 2066
Регистрация: 27.09.2012
Сообщений: 27,026
Записей в блоге: 1
04.08.2013, 08:47
Во-первых, так никогда не делают:
C++
1
2
        timer += 0.01f;
        if (timer >= 150000){
Это У Вас не таймер получается, а счетчик итераций какой-то...
0
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
04.08.2013, 12:24
Цитата Сообщение от Gomg Посмотреть сообщение
вот я написал код ,но блок только падает. не сдвигается
Выведи на экран после cдвига поле и сделай exit(1); и посмотри что у тебя произошло с блоком. Я честно не люблю в чужой код разбирать.
0
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116
04.08.2013, 16:46  [ТС]
Цитата Сообщение от Croessmah Посмотреть сообщение
Во-первых, так никогда не делают:
а как делают то?
Цитата Сообщение от ninja2 Посмотреть сообщение
Выведи на экран после cдвига поле и сделай exit(1);
просто выключается программа и все.
0
1 / 1 / 0
Регистрация: 23.06.2013
Сообщений: 13
04.08.2013, 17:12
Цитата Сообщение от Gomg Посмотреть сообщение
а как делают то?
Например так:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#define TIME_GAME_TIK   0.03f   //величина игрового тика времени в абсолютном выражении, лучше сделать через конст, но для консольки и так пойдёт.
//глобальные переменные
float currTime  = 0.0f;         //(float)timeGetTime(); - для получения текущего времени
static float lastTime = 0.0f;   //значение времени в предидущей итерации (т.е. lastTime = старое значение currTime)
float timeDelta = 0.0f;         //вычисляется так: timeDelta=(currTime - lastTime)*0.001f; разница времени между итерациями
float timeElapsedGame = 0.0f;   //счётчик игрового дискрета времени
 
//функция обработки дискрета времени
inline void Timing() //но можно и не инлайнить
{
    currTime  = (float)timeGetTime();           //получение текущего времени
    timeDelta = (currTime - lastTime)*0.001f;   //вычисление прошедшего между проходами цикла. 0.001f - перевод милисекунд в секунды
    timeElapsedGame+=timeDelta;                 //счётчик игрового дискрета времени
}
 
...
 
...main...
{
....
    lastTime = (float)timeGetTime();        //начальное значение времени на предидущей итерации будет совпадать с  текущим, что очевидно
    while(true) //Главный цикл. только не забудь описать условия выхода ;)
    {
        Timing();   //формировани игрового времени timeElapsedGame
        if(timeElapsedGame>=TIME_GAME_TIK) //если прошёл 1 тик игрового времени, то :
        {
             //всё, что должно происходить в игре
             timeElapsedGame = 0.0f;    //обнуление счётчика игрового дискрета времени - важно, иначе только первая итерация будет по таймеру
        }
        lastTime = currTime;    //запись устаревшего значения текущего времени currTime в lastTime
 
    }
}
У меня работае эта конструкция давно и надёжно. Позволяет делать параллельно несколько независимых таймеров, считать FPS, моделировать тики ИИ и прочее.
1
1 / 1 / 2
Регистрация: 13.01.2013
Сообщений: 71
04.08.2013, 17:12
да с поворотами и проверкой на столкновения фигур тут заморочки
0
1 / 1 / 0
Регистрация: 23.06.2013
Сообщений: 13
04.08.2013, 17:34
извини, забыл сказать: надо подключить ctime перед использованием timeGetTime
#include <ctime>
0
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116
05.08.2013, 08:39  [ТС]
1>main.obj : error LNK2019: ссылка на неразрешенный внешний символ __imp__timeGetTime@0 в функции "void __cdecl Time(void)" (?Time@@YAXXZ)

вот что выходит после этого. и define почему-то не работает. пишет что что-то пустое, хотя значение есть. Пришлось писать просто const float TIME_TICK

Добавлено через 27 секунд
<ctime> есть
0
1 / 1 / 0
Регистрация: 23.06.2013
Сообщений: 13
06.08.2013, 22:57
Gomg, извини,что не отвечал (не мог добраться к инету...)
на самом деле надо подключать не <ctime> а <Windows.h> и подключить в Project / ... Propertes / Configuration propertes / Linker / Input в строке Additional Dependences библиотеку winmm.lib. В этой строке перечислены библиотеки, кот. подключаются по умолчанию. Судя по всему winmm.lib у тебя там не записан.

Вот код простого примерчика использования этой функции. Программа отмеряет время между вводами данных с клавиатуры и выводит на экран
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "stdafx.h"    //у меня это лепится визардом автоматически
#include <locale>     // чтобы работала локализация (русские буквы в консоли были норм.)
#include <iostream> // ввод вывод
#include <Windows.h> // согласно хелпу по этой функции
 
using namespace std;            //включаем всё пространство имён std. (не очень хорошо, но для теста терпимо)
 
int main()
{
    setlocale(LC_ALL,"russian");    //включает русский шрифт в консоли. Требует locale.h
    float currTime  =(float)timeGetTime();
    float lasttime = currTime;
    char key = ' ';
    while (key!='q')
    {
        currTime  =(float)timeGetTime();
        cout << "для продолжения - любая клавиша           q - выход, ";
        cin >> key;
        cout << "Пауза = " << (currTime-lasttime)*0.001 << endl;
        lasttime = currTime;
    }
    return 0;
}
вот фрагмент хелпа по функции

timeGetTime Function
The timeGetTime function retrieves the system time, in milliseconds. The system time is the time elapsed since Windows was started.
Syntax
DWORD timeGetTime(void);
Parameters
This function has no parameters.
Return Value
Returns the system time, in milliseconds.
Remarks
The only difference between this function and the timeGetSystemTime function is that timeGetSystemTime uses the MMTIME structure to return the system time. The timeGetTime function has less overhead than timeGetSystemTime.
Note that the value returned by the timeGetTime function is a DWORD value. The return value wraps around to 0 every 2^32 milliseconds, which is about 49.71 days. This can cause problems in code that directly uses the timeGetTime return value in computations, particularly where the value is used to control code execution. You should always use the difference between two timeGetTime return values in computations.

Requirements
Minimum supported client Windows 2000 Professional
Minimum supported server Windows 2000 Server
Header Mmsystem.h (include Windows.h)
Library Winmm.lib
DLL Winmm.dll

See Also
Multimedia Timers
Multimedia Timer Functions
Send comments about this topic to Microsoft
Build date: 10/9/2009

[/SPOILER]
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
06.08.2013, 22:57
Помогаю со студенческими работами здесь

Тетрис
Напишите программу, которая выводит на консоль 2 фигуры из тетриса, анимирует их падение вниз по стрелке вниз и поворот по стрелке вверх. ...

Тетрис
Пишу на c++ for DOS! Вобщем не могу сделать передвижение фигуры влево или вправо при нажатии на клавишу. Вот код падения фигуры в...

Тетрис
Задали сделать тетрис на Турбо СИ но незнаю даже с чего начать....только учить начали и уже курсак((

Оцените тетрис
Написано коряво, но это первый блин. Мне бы очень хотелось его дошлифовать до красивого внешнего и внутреннего содержания. Если участники...

Тетрис на mvc
Здрасти евриван) Как Вы? Все у Вас в порядке?) Думаю да) А я опять к Вам со своими проблемами( Наверное уже достал Вас хи-хи) Ладно, сразу...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru