Форум программистов, компьютерный форум CyberForum.ru

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
Рейтинг: Рейтинг темы: голосов - 14, средняя оценка - 4.93
Gomg
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116
#1

Тетрис на c++ - C++

03.08.2013, 21:13. Просмотров 1987. Ответов 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, а то это меня напрягает, все таки статик для всех параметры одинаковы, а мне надо будет сделать для каждого объекта копию его класса, чтобы как бы параметры типа координаты и значка были лично для этого объекта. все таки надо сделать спавн блоков
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
03.08.2013, 21:13
Здравствуйте! Я подобрал для вас темы с ответами на вопрос Тетрис на c++ (C++):

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

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

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

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

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

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

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

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

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

Добавлено через 2 минуты
Gomg, Ты тут написал 90 строк кода и спрашиваешь почему оно не работает, когда там должно быть строк примерно 1.5к
Gomg
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116
04.08.2013, 08:44  [ТС] #3
так почему-то не назначается массиву символ по измененной 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;
}
вот я написал код ,но блок только падает. не сдвигается
Croessmah
Модератор
Эксперт CЭксперт С++
13132 / 7395 / 828
Регистрация: 27.09.2012
Сообщений: 18,226
Записей в блоге: 3
Завершенные тесты: 1
04.08.2013, 08:47 #4
Во-первых, так никогда не делают:
C++
1
2
        timer += 0.01f;
        if (timer >= 150000){
Это У Вас не таймер получается, а счетчик итераций какой-то...
ninja2
231 / 187 / 7
Регистрация: 26.09.2012
Сообщений: 2,018
Завершенные тесты: 1
04.08.2013, 12:24 #5
Цитата Сообщение от Gomg Посмотреть сообщение
вот я написал код ,но блок только падает. не сдвигается
Выведи на экран после cдвига поле и сделай exit(1); и посмотри что у тебя произошло с блоком. Я честно не люблю в чужой код разбирать.
Gomg
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116
04.08.2013, 16:46  [ТС] #6
Цитата Сообщение от Croessmah Посмотреть сообщение
Во-первых, так никогда не делают:
а как делают то?
Цитата Сообщение от ninja2 Посмотреть сообщение
Выведи на экран после cдвига поле и сделай exit(1);
просто выключается программа и все.
jorik567
1 / 1 / 0
Регистрация: 23.06.2013
Сообщений: 13
04.08.2013, 17:12 #7
Цитата Сообщение от 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, моделировать тики ИИ и прочее.
rizr
1 / 1 / 0
Регистрация: 13.01.2013
Сообщений: 71
04.08.2013, 17:12 #8
да с поворотами и проверкой на столкновения фигур тут заморочки
jorik567
1 / 1 / 0
Регистрация: 23.06.2013
Сообщений: 13
04.08.2013, 17:34 #9
извини, забыл сказать: надо подключить ctime перед использованием timeGetTime
#include <ctime>
Gomg
5 / 5 / 0
Регистрация: 28.06.2013
Сообщений: 116
05.08.2013, 08:39  [ТС] #10
1>main.obj : error LNK2019: ссылка на неразрешенный внешний символ __imp__timeGetTime@0 в функции "void __cdecl Time(void)" (?Time@@YAXXZ)

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

Добавлено через 27 секунд
<ctime> есть
jorik567
1 / 1 / 0
Регистрация: 23.06.2013
Сообщений: 13
06.08.2013, 22:57 #11
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]
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
06.08.2013, 22:57
Привет! Вот еще темы с ответами:

Игра тетрис - C++
Помогите, ребята. Мне нужно сдать курсовую по игре тетрис, может есть у кого самый простой тетрис, где падают фигуры, или какой-то анолог...

Консольный Тетрис на С++ - C++
Написать консольный Тетрис на С++ используя процедурное программирование(без классов и go to). Реализовать: 1) меню 2) уровни...

Тетрис: начало - C++
Здравствуйте. Захотелось мне сделать тетрис. Консольный, некрасивый, но рабочий. Так как мой скилл программирования невысок, то решил...

Тетрис и многопоточность - C++
Здравствуйте. Взялся я за тетрис, немного написал, а потом понял, что мне нужны два потока. Вот зачем: у меня игровое поле — двумерный...


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

Или воспользуйтесь поиском по форуму:
Yandex
Объявления
06.08.2013, 22:57
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2017, vBulletin Solutions, Inc.
Рейтинг@Mail.ru