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

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

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль

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

Ответ
 
Опции темы Поиск в этой теме
Старый 25.12.2013, 22:38   #1
Xobotun
Пользователь
 
Регистрация: 25.12.2013
Сообщений: 12
По умолчанию Символы другого цвета в консольном режиме Delphi

Обычно я просто гуглю и нахожу то, что надо, но в этот раз такой способ не прокатил...
Собственно в чём вопрос: реально ли, пользуясь стандартными библиотеками винды и дельфи, выводить в консольном режиме символы разных цветов (желательно произвольных) так, чтобы каждый символ имел свой собственный цвет? (не свойства->цвет текста-> выбрать один из нескольких, а один символ - один #RRGGBB)
Просто неделю до Нового Года вообще ничего не делать как-то не комильфо, а просто играть в компьютер - явно не выход, даже если есть прорва других занятий... А почему дельфи - это единственный на данный момент язык, которым я более-менее владею.

P.S. Немног граммар-наци. Еще освоиться не успел, а уже критикую... При регистрации над строкой, где надо ответить на вопрос - "Семь в квадрате (цифрой)" или "Тридцать три процента от трехсот (цифрой)", надо, по-хорошему, заменить "цифрой" на "числом"
Xobotun вне форума Ответить с цитированием
Старый 25.12.2013, 23:07   #2
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Код:
program Project1;

{$APPTYPE CONSOLE}

uses
  SysUtils, Windows;

var Con: Integer;
    Coord: TCoord;

begin

  Con:=GetStdHandle(STD_OUTPUT_HANDLE);

  Coord.x:=10; Coord.y:=10;
  SetConsoleTextAttribute(Con,$D8);
  SetConsoleCursorPosition(Con,Coord);
  write('Color Text');

  Coord.x:=10; Coord.y:=15;
  SetConsoleTextAttribute(Con,$8D);
  SetConsoleCursorPosition(Con,Coord);
  write('Color Text');

  ReadLn;

end.
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 25.12.2013, 23:24   #3
Xobotun
Пользователь
 
Регистрация: 25.12.2013
Сообщений: 12
По умолчанию

Благодарю, это как раз почти то, что мне было нужно. Насколько я понял, второй параметр SetConsoleTextAttribute записывается как [0..15] + [0..15]*16 и представляет из себя все комбинации цветов текста и цветов фона?
Да, действительно, на лекциях этого нет, а если искать, то надо иметь хоть отдалённое представление об искомом предмете...
Спасибо!
Xobotun вне форума Ответить с цитированием
Старый 26.12.2013, 07:02   #4
Vapaamies
Просветитель
Участник клуба
 
Аватар для Vapaamies
 
Регистрация: 26.12.2012
Сообщений: 1,844
По умолчанию

Цитата:
Сообщение от Xobotun Посмотреть сообщение
Да, действительно, на лекциях этого нет, а если искать, то надо иметь хоть отдалённое представление об искомом предмете...
Могу добавить, что соответствующий раздел Platform SDK носит название Console API, там же описаны константы цвета, в Delphi -- в модуле Windows (WinAPI.Windows в модных версиях), если не путаю.
В разработке: воспроизводственный контур ИТ
Vapaamies вне форума Ответить с цитированием
Старый 27.12.2013, 18:10   #5
Xobotun
Пользователь
 
Регистрация: 25.12.2013
Сообщений: 12
По умолчанию

Уф.
Бьюсь уже часа полтора, но не нашел ни малейшей зацепки.
Ситуация такая: имеется объект-массив, в котором может измениться произвольная ячейка. Так при изменении, скажем, с 10 на 10-5 = 5, значение меняется, но при повторном вычитании пятёрки она вычитается из тех же самых десяти...
Собственно, сам код (тут ограничение в 5000 символов, поэтому архивом):
Код:
unit DDClasses;

interface
Uses windows;    //I use windows! Bwa-ha-ha!
const drawoffset:byte = 3;
      worldwidth:byte = 60; //due do strange errors, change values in Tworld.world: array[...] too!
      worldheight:byte= 20;
      worlddepth:byte = 80;
      legitsymbols: set of char = ['w','a','s','d','q','z'];
Type  TTile = object
          private
        value,life,color:word;
          public
        procedure Init(const depth: integer);
        procedure Draw(const coord:Tcoord);
        procedure Generate(const depth: integer);
        procedure Dig;
      end;

      Tplayer = object
          private
          const
        defdrill:word = 5;
        deffuel:word = 50;
          var
        score:longint;
        drill,fuel:word;
        x,y,z:byte;
        isFlying: boolean;
          public
        procedure Init;
        procedure Draw;

      end;

      TWorld = object
          private
        world: array[1..60,1..20,1..80] of TTile;
        player: Tplayer;
          public
        procedure Init;
        procedure Draw;
        function depth:byte;
        procedure ApplyGravity;
        procedure MovePlayer(var c:char);
        procedure Drill(tile:TTile);      //ptm = Place To Move
      end;

implementation

function Tworld.depth;
  begin
    Result := player.z;
  end;

Procedure Tworld.MovePlayer;
  Var ptm: TTile; //Place To Move
  begin
  if (player.fuel>0) then begin

    player.fuel:=player.fuel-1;
    case c of
      'a':  begin
              ptm:=world[player.x-1,player.y,player.z];
              if (player.x<>1) then
                begin
                  if (ptm.value=0) then                 //first we check if it possible to move in
                    player.x:=player.x-1;
                  player.isFlying:=false;
                  drill(ptm);                                //then we drill. It helps us not to fall into the possible hole:)
                end;
            //break;
            end;
    end;
    c:='ы';
    if player.z=1 then player.fuel:=player.deffuel;
    
    end;  //end of player.fuel>0
  end;

Procedure Tworld.Drill(tile: TTile);
  begin
    if tile.value <>0 then
                    begin
                      if (tile.life>0) then tile.life:=tile.life-player.drill;
                      if (tile.life<=0) then begin
                        player.score:=player.score+tile.value;
                        tile.dig;
                      end;
                    end;
  end;

Procedure TTile.dig;
  begin
    value:=0; //making it air :)
    life:=0;
    color:=0;
  end;


end.
Вложения
Тип файла: rar Dwarf digger.rar (99.7 Кб, 8 просмотров)
Xobotun вне форума Ответить с цитированием
Старый 27.12.2013, 18:13   #6
Xobotun
Пользователь
 
Регистрация: 25.12.2013
Сообщений: 12
По умолчанию

Ну, и чтоб два раза не встатвать, вопорс:
Как мне сделать _нормальный_ посимвольный ввод? без кучи лишних энтеров, а как в классическом Borland Pascal'е?
Xobotun вне форума Ответить с цитированием
Старый 27.12.2013, 21:00   #7
Xobotun
Пользователь
 
Регистрация: 25.12.2013
Сообщений: 12
По умолчанию

Всё, разобрался. Я грешил на передачу не по адресу, а по значению в какой-то процедуре, но никак не мог отыскать это место.
И только что, после питья чая, я понял - я искал то что надо, но не там, где надо!
Код:
Var ptm: TTile;
ptm:=world[player.x-1,player.y,player.z];
Красиво, но тупо. Надо было делать указатель, а не новый объект...
Xobotun вне форума Ответить с цитированием
Старый 28.12.2013, 09:06   #8
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

Во-первых, имхо, теме место в "создание и обсуждение игр" (даже если это студзадание)
Во-вторых, Вам серьёзно помогут ресурсы, направленные на создание рогаликов - из русскоязычных, пожалуй единственный www.rlgclub.ru
В-третьих, конкретно для дельфи есть годные решения по "опаскаливанию" консольной работы, см. например сюда http://programmersforum.ru/showthread.php?t=224636 да и вообще можно пройтись поиском по форуму - уже многое обсуждалось (в т.ч русский текст в консоли, если надумаешь). По указанному направлению есть и ответ на вопрос как сделать readkey (правда там модуль староват, и виндовые декларации в новых дельфях чутка поменялись, если сами не разберётесь, как там пофиксить несколько строк, могу посодействовать)


Ну и ещё, вот кодревью:
1. обязательно использовать устаревший object ? о class не думали ? Между прочим, проблема которую описываете в последнем посте, как раз бы решалась за счёт "компиляторного механизма" классов и их экземпляров (экземпляры и есть указатели и их присвоение это не копирование данных, а присвоение указателя), и вы бы не искали её так долго.
2. в чём проблема константы размеров мира использовать в декларации массива?
что за //due do strange errors, change values in Tworld.world: array[...] too!
3. Зачем извечная копипаста GetStdHandle(STD_OUTPUT_HANDLE) ? может надо просто запомнить в переменную? Хотя если задействовать модуль из совета выше, то эти все функции вообще уйдут в небытие, останутся только "говорящие"
4. тут нет выхода за размер массива если стоять на "нижнем" слое?
while (world[player.x,player.y,player.z+1].value=0)
или мир окружён непроходимыми границами , которые в массиве есть и на них нельзя встать , вроде в коде не увидел чего-то такого.
5. довольно много копипасты и непонятного , "магического" кода, я понимаю, что с этим сложновато бороться на начальном этапе, и всё же советую избавляться от копипасты потихоньку - больше разбивать на подпрограммы и вводить типы. http://www.gunsmoker.ru/2011/01/blog-post.html
6. Ну и, как обычно, индентация и кодстайл, http://www.gunsmoker.ru/2010/07/blog-post.html

зы. c:='ы'; лол
phomm вне форума Ответить с цитированием
Старый 28.12.2013, 14:04   #9
Xobotun
Пользователь
 
Регистрация: 25.12.2013
Сообщений: 12
По умолчанию

Спасибо за развернутую и конструктивную критику.
Да, с выбором раздела я облажался; дошло это до меня не сразу, а тема уже была опубликована. Ну, если мыслить логически, всё верно: я одновременно и новичок в программировании, и студент, и мне нужна помощь. Соответственно, почему бы и не поместить в раздел "Новички в программировании > Помощь студентам"...
За все ссылки - спасибо, в частности, за последние две - нашёл ещё большее количество недоразумений у себя в коде; с удивлением обнаружил, что моё форматирование кода для более приятного чтения, оказывается, основано на уже существующем стандарте, осталось лишь "доделать" мелкие неприятности (после нового года покажу этот стандарт одногруппникам, пусть радуются)

Спасибо и за ревью
1. Вот насчет object'ов и class'ов, думаю, вина института: до вашего комментария я полагал, что object'ы - наследие Паскаля для консольного режима, а class'ы - для VCL режима Дельфи. Сейчас я поменяю и верну эту кривую часть кода с указателем в нормальное состояние.
2. А проблема с массивами и константами есть: вот на такой строчке
Код:
 
world: array[1..worldwidth,1..worldheight,1..worlddepth] of TTile;
выдаёт сразу три ошибки:
Код:
[Pascal Error] DDClasses.pas(46): E2026 Constant expression expected
[Pascal Error] DDClasses.pas(46): E2026 Constant expression expected
[Pascal Error] DDClasses.pas(46): E2026 Constant expression expected
[Pascal Fatal Error] DD.dpr(8): F2063 Could not compile used unit 'DDClasses.pas'
Быстро погуглив нашел: "Constant expression expected.В этом месте должна стоять константа или константное выражение, например константа выбора в структуре Case." Почесав затылок, вернул числа и добавил комментарий.

Возможно, проблема кроется в кривости самой IDE, которой я пользуюсь: это Borland Turbo Delphi 2005 года, запущенная на седьмой винде, из-за чего приходится каждые несколько десятков строчек нажимать Ctrl+S. Даже в институте на Windows Server 2003 постоянно вылетают сообщения типа "Personality is noy supported", "Invalid pointer operation" при перемещении каретки в текстовом поле посредством мыши, "Access read violation at address ..." при проверке компилятором правильности кода... Так что пытаясь кодить в такой штуке, меня корректность моего кода волнует меньше, чем осознание того, что сейчас я напишу ещё одну строчку, а оно возьмёт и внезапно вылетит... Особенно странно выглядит табличка при запуске
Код:
---------------------------
bds.exe - Диск отсутствует
---------------------------
В устройстве нет диска. Вставьте диск в устройство \Device\Harddisk5\DR17. 
---------------------------
Отмена   Повторить   Продолжить   
---------------------------
3 и 5. Эта копипаста и есть магический код... Изо всей строчки SetConsoleCursorPosition(GetStdHand le(STD_OUTPUT_HANDLE),coord); я пользуюсь лишь coord, и, поскольку для меня у этой процедуры есть лишь один параметр, я решил не заморачиваться созданием "укороченной версии". А как воспользоваться советом Vapaamies, я, к сожалению, не понял. Модуль windows, мне что-то подсказывает, системный, значит если я пойду менять константы, то это хорошим ничем не кончится...

4. Есть небольшая проверка, но проваливаться под уровень это не мешает (в отладчике, разумеется. Просто так - не получается). Самое странное то, что даже за границами массива по оси z уровень генерируется (только не смотрите на генератор, мне от этого стыдно) и существует, но состоит из одной лишь меди. Подъем выглядит очень сюрреалистично... А потом - стенка 80 уровня и вниз - никак Да, в методе ApplyGravity можно "провалиться" с последнего на первый уровень...

6. А еще у меня в IDE нет автоматического форматирования, так что всё ручками (ну или оно та-ак глубоко запрятано...)
Вложения
Тип файла: rar Dwarf digger.rar (107.4 Кб, 7 просмотров)

Последний раз редактировалось Xobotun; 28.12.2013 в 15:26.
Xobotun вне форума Ответить с цитированием
Старый 29.12.2013, 11:21   #10
phomm
personality
Старожил
 
Аватар для phomm
 
Регистрация: 28.04.2009
Сообщений: 2,899
По умолчанию

1. Обджект, класс никак не связаны с консольным или всл-режимом. Это легко определить логическим путём - ведь есть программы не консольные и не оконные (которые выполняют свою работу и закрываются, без участия пользователя) - какие там были бы доступны средства ООП, если обджекты и классы уже заняты ? Из такой постановки следует, что связи быть не должно.
Посему, если будете идти по пути изучения ооп на классах (а сейчас это стандарт, особенно для дельфи), то вот http://delphikingdom.ru/lyceum/seminar.asp?ID=6 там ООП начиная с 3 главы, но бывает полезно прочитать вообще всё.
2. Я догадался по комментарию, о чём и написал ) Оказывается, проблема действительно есть, а причина - типизированные константы, уберите :byte в декларации констант и всё будет гуд, тем более что компилятор (емнип) сам определяет достаточные размеры для констант в исполняемом файле, смысл пользоваться типизированными константами есть только в небольшом количестве задач.

Трубодельфи не трогал, но читал что жутко глючная. Мой выбор дельфи2007, бывает, конечно, подлагивает, но в целом, очень редки опасные лаги, зато для меня самый оптимальный инструмент, ибо сие есть самая последняя неюникодная иде. С фичами типа рефакторинга, xml-документация с кодинсайтом, управления билд-конфигурациями и билд-ивентами, есть inline и ReportMemoryLeaksOnShutDown. Иногда использую дельфихе2, когда юникодность нужна или неважна, там есть и другие полезные фичи, типа профилировщика (какая-то из крупных редакций).

3,4,5 уже так понимаю, сами проработаете и частично проработали, так что молодцом. Единственно, ничего не сказали про модуль spcrt ? пробовали ? readkey мастхев.
6. автоформатирование в иде появилось в дельфихе , но оно доступно через плагины/эксперты, подробно описывал тут http://programmersforum.ru/showthread.php?t=248866
в статье по ссылке, что я давал в первом посте, вроде тоже есть

Теперь по обновлению кода.
1. Не увидел уменьшения магии. Совет - прочитать про enumerations , как минимум сюда : dirt,copper,silver,gold,diamond,air и сюда: value, color, life они просятся
2. Из того , что легко отрефакторить - Много однотипного кода для перемещения, я бы сделал функцию для wasd принимающую dx dy - уже прилично бы сократив код и издержки на его модификацию. довольно много кода по управлению консолью однотипного, тоже можно было бы обернуть удобно, хотя может использование модуля spcrt и так сократит эти издержки.
3. По сути игры - я бы советовал юзать не полный рандом, а с определённой закономерностью - чтобы образовывались "залежи"
4. И ещё не понятно, чего делать, ну углубился, поднялся, накопал плюшек и получил очки. Чего ещё пока не понятно, и вечно перспектива не долететь до верха ) если жадничать с бурением
phomm вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
выполнить в консольном режиме на С++ Артур31 Помощь студентам 6 09.11.2012 17:07
написать программу из формул Delphi в консольном режиме Ramil999 Помощь студентам 9 05.10.2011 06:43
Програма для Delphi в консольным режиме dima992 Помощь студентам 3 08.02.2011 14:10
Задача на работу с массивом + char (Delphi в консольном режиме) [COOLER] Помощь студентам 9 02.01.2010 20:16
Как сделать границы формы другого цвета,формы?? Дима я Общие вопросы Delphi 3 22.06.2009 07:24