Особенности использования массивов в данной программе
Пояснительная Записка к
Курсовой Работе
«Карточная Игра Дурак»
Выполнил: студент гр. 0.251
Харламов Артем Глебович
Принял:
Череповец, 2006.
1. Постановка задачи
Целью курсовой работы является создание и отладка программы «карточная игра Дурак» на языке программирования высокого уровня Pascal, целью, которой является развлечение и проведения досуга. В ней должны быть реализованы следующие функции:
- Оформление в графическом режиме (Все отображаемые на экране объекты должны быть нарисованы с помощью графики, а не псевдографики)
- Обработка карт, колоды, козыря (Каждая карта должна четко идентифицироваться и иметь определенное изображение)
- Интеллект компьютера (наличие простейшей стратегии)
- Управление картами с помощью мыши
- Сброс, перемешивание
2. Краткая теория
2.1. Хранение изображений, Загрузка и Прорисовка карты
Хранение изображений различных карт осуществляется с помощью текстового файла содержащего закодированную информацию. Файл представляет собой набор цифр, располагающихся по две в строке. При активации процедуры прорисовки карты определяется, какой именно файл будет использован для прорисовки, а затем файл открывается для чтения. Также при активации задаются начальные координаты карты. После того как файл открыт, начинается цикл прорисовки. В начале этого цикла читается первое число в строке, оно определяет сколько следующих пикселов будут закрашены цветом, содержащимся во втором файле в строке. Заданной переменой присваивается значение первого числа в строке и при каждом последующей прорисовке пиксела уменьшается на 1. Когда заданная переменная становится равной нулю, считывается вторая строка из файла. Сам же цикл прорисовки состоит из двух частей: прорисовки общего для всех фона карты и прорисовка самого символа. Символ карты состоит из двух частей (номинала и масти), которые хранятся в отдельных файлах. Чтобы правильно нарисовать карту, используется два цикла For. Первый цикл с количеством итераций равным высоте карты в пикселах и второй с количеством итераций равным ширине карты в пикселах. При прорисовке к начальным координатам прибавляются номера итерации (первого к Y – координатам, второй к Х - координатм).
2.2. Мышь
Программа, работающая с устройством "мышь" в операционной системе MS-DOS, должна использовать прерывание с номером 51 ( в десятичной системе счисления, но привычнее использовать шестнадцатеричное $33). Это специальное прерывание. Оно представляет 36 функций, обеспечивающих настройку устройства "мышь" и его указателя, а также сообщающих информацию о событиях. Все эти функции требуют заполнения регистров процессора перед вызовом их. В частности, номер функции всегда заносится в регистр AX. И в регистрах процессора функции "возвращают" информацию. Тогда обращение к регистрам процессора производится с помощью переменной типа REGISTERS, которая описана в модуле DOS.
Для вызова прерывания нужно заполнить регистры процессора так, как указано в описании функции, и вызвать процедуру intr. Ей передаются два параметра:
1. номер прерывания;
2. имя переменной типа REGISTERS
Сначала нужно проверить поддерживается ли мышь на данной ЭВМ. Для этого используется функция с номером 0. Эта функция проверяет, имеется ли поддержка мыши на данной ЭВМ, и если имеется, то в регистр AX будет записано число $FFFF. Если нет, то 0, но не обязательно. В регистр BX. В него записывается количество кнопок мыши.
Если мышь имеется, эта функция выполняет следующие действия в текстовом режиме
- перемещает указатель мыши в центр экрана;
- прячет указатель мыши. Для того, чтобы его показать, используется функция с номером 1;
- очищает "область исключения" перемещения указателя мыши, установленную функцией $10. В пределах это прямоугольной области указатель курсора мыши не виден;
- устанавливает вид курсора "по умолчанию". Его изменяет функция $0A;
- разрешает перемещение указателя мыши по всей области экрана. Его ограничивает функция номер 7;
- устанавливает отображение курсора мыши на первую видеостраницу. Напомню, что в текстовом режиме 8 видеостраниц. Первая имеет номер 0;
- устанавливает "обычную" скорость перемещения указателя мыши. То есть, на какое расстояние перемещается указатель мыши при движении манипулятора. А также устанавливает значение интервала между "двойными кликами" по умолчанию. (То есть при двойном щелчке манипулятор может переместится немного, но это не считается). Такие параметры изменяются с помощью функции номер $1A. Если перед вызовом функции был установлен графический режим, то устанавливается указатель в виде стрелки для данного режима. Для того, чтобы определить, не произошло ли чего с мышью, в этой программе используется функция с номером 3 "Опросить положение и состояние кнопок" ( Здесь reg - переменная типа REGISTERS). Если нажата левая клавиша мыши, то reg.BX and 1 = 1, тогда в CX будет содержаться X координата (горизонтальная) курсора мыши, а в DX будет содержаться Y координата (вертикальная) курсора мыши.
3. Описание программы
3.1. Структурная схема
Меню | Игра | |||||||
Прорисовка Карт | Ход | Управление Игрой | ||||||
Выбор | Кор- рекция | |||||||
Основными блоками программы являются: Меню и Игра. Через Меню осуществляется запуск и выход из блока Игра. Также с помощью Меню вводится значимая для Игры переменная – количество игроков. Игра же в свою очередь состоит из трех подблоков: Прорисовка карт, Ход и Управление игрой. Из названий подблоков достаточно ясно какие функции они осуществляют (Прорисовка – рисует, Управление – управляет ходом игры с помощью мыши и различных «флагов»). Ход также делится на две части: Выбор и Коррекция. В зависимости от того ходит ли компьютер или игрок, блок Выбор либо производит обработку карт компьютера, либо принимает и обрабатывает сигнал от мыши. После Выбора блок Коррекция проверяет выбранную карту на соответствие ситуации и оценивает допустимость хода, если ход невозможен, то появляется предупреждение.
3.2. Математическая постановка задачи
3.2.1. Перемешивание колоды – случайное распределение чисел от 1 до 36 в массиве, состоящем из 36 элементов. Поочередно присваиваем значения от 1 до 36 случайному элементу с номером n массива A[1..36]. Случайность выбора элемента осуществляем с помощью функции Random и процедуры Randomize. Если же значение элемента А[n] отлично от нуля то повторяем процедуру выбора случайного элемента до тех пор пока все значения не будут распределены в массиве А.
3.2.2. Определение карты – Разделение числа на две части путем деления на 9. Целая часть определяет масть, остаток от деления определяет номинал. Карты находящиеся в руках игроков обозначаются значениями в массивах (для каждого игрока он свой). При обращении программы к карте считывается значение из массива (p:=B[n]). Для определения ее масти происходит целочисленное деление значения на 9 (m:=p div 9), так как карт всего 36, значение m может варьироваться в пределах четырех значений (от 0 до 3). Так что можно принять каждое из этих значений за определенную масть. Для определения номинала требуется получить остаток от деления на 9, он будет находиться в промежутке от 0 до 8 (n:=p mod 9).
3.2.3. Прорисовка карты – открытие определенного файла, содержащего закодированное изображение, в зависимости от номинала и масти карты. После определения масти карты, используя оператор case, присваиваем переменой файлового типа выбранный файл содержащий закодированный рисунок данной масти (Assign(F,*.txt)). Соответственно производим обработку номинала карты и после этого проверяем значение масти, если эта масть «черная», то рисунок номинала должен быть загружен из файла с черным номиналом, если масть «красная» - то и номинал красный.
3.2.4. Количество игроков (2-4) – формируется последовательность хода в зависимости от переменной, обозначающей количество игроков. Значение данной переменной задается в стартовом меню, в зависимости от неё изменяются различные флаги и маркеры контролирующие процесс и порядок хода, подкидывания и ответа. Используется два маркера: первый регулирует ход и ответ игрока, а второй порядок подкидывания. Значение маркера после окончания хода возрастает на 1 или 2,в зависимости от различных условий. Для определения активного игрока значение маркера делится на количество игроков минус один (case (mark1 mod (Numplayers-1)) of).
3.2.5. Определение игрока, ходящего первым – определение козыря и поиск игрока, обладающего картой наименьшего номинала и той же масти, что и козырь. Значение козыря определяется после перемешивания колоды, значение первой карты становится значением козыря (koz:=A[36]). Затем происходит поиск карт, с результатом целочисленного деления на 9 равным результату такого же деления значения представляющего козырь, в массивах содержащих значения карт, находящихся в руках игроков. После того как такие карты найдены, происходит проверка на самый маленький номинал, то есть выбирается карта с наименьшим значением остатка от деления на 9, для массива первого игрока. Эта карта считается минимальной, после этого происходит проверка номиналов карт следующего игрока, только теперь номиналы сравниваются с минимумом, и если значение остатка от деления меньше, чем минимум, то значение этой карты становится минимумом. И так далее для каждого игрока. После определения минимума, находится игрок, обладающий картой со значением равным минимуму, и маркеру, управляющему порядком хода, присваивается определенное значение.
3.2.6. Простейшая стратегия компьютера – определение хода, подкидывания и ответного хода, путем поиска карты, с нужной мастью и наименьшего номинала из разрешенных. Компьютер проверяет все значения карт, содержащихся в массиве его руки, и присваивает значение с наименьшим остатком от деления на 9 переменой, обозначающей минимум, потом производит ход этой картой. При ответном ходе компьютер присваивает все карты с результатом целочисленного деления на 9 равным результату того же деления последней и с большим остатком от деления на 9 карты, последней положенной на стол, временному массиву. После этого он выбирает карту с наименьшим номиналом из этого временного массива и производит ответный ход. Если же таких карт не оказалось и последняя карта на столе козырь, то компьютер забирает все карты находящиеся на столе в этот момент, если же нет, то компьютер повторяет выше описанную операцию для карт с результатом целочисленного деления на 9 равным результату, того же деления козыря. При подкидывании компьютер присваивает все карты с остатком от деления на 9 равным остатку от того же деления всех карт находящихся на столе временному массиву. После этого он выбирает карту с наименьшим номиналом из этого временного с результатом целочисленного деления на 9 не равному результату того же деления значения козыря и производит подкидывание.
3.2.7. Управление мышью – проверка координат при нажатии на левую клавишу мыши и проверка соответствия этих координат координатам карт игрока. При активации какого либо вида хода игрока включается цикл, оканчивающийся при нажатии левой клавиши мыши или определенных клавиш клавиатуры. Если был нажат Esc тогда программа выходит из всех циклов и выходит из программы, если был нажат пробел, то считается, что игрок отказывается от действия и происходят дальнейшие действия, если же была нажата левая клавиша мыши, то проверяется, где она была нажата, если она была нажата в поле изображения карт, то проверяется какая карта была именно выбрана, карта проверяется на соответствие различным условиям, в зависимости вида хода, и если карта удовлетворяет этим условия, то производится ход. Если же мышь была нажата не в поле карт. То цикл продолжается, и ожидаются другие действия.
3.2.8. Определение победителя – после каждого хода компьютер проверяет, если количество карт в колоде равно нулю, то проверяет наличие карт в руках игроков, и если они равны нулю, то присваивает переменным, связанным с этим
3.3. Описание входных и выходных данных
3.3.1. Входные данные – определение координат мыши, нажатия левой клавиши мыши и клавиш клавиатуры. При перемещении мыши ее координаты считываются и курсор перерисовывается. При нажатии на левую клавишу мыши срабатывает триггер и в некоторые переменные записываются горизонтальные вертикальные координаты мыши. Функция Keypressed:Boolean возвращает true, если нажата любая клавиша. Функция Readkey: char; Возвращает ASCII код символа нажатой клавиши. Для клавиш, не сопоставленных символам, вернется #0. Такие клавиши (например, функциональные, управления курсором и т.д.) определяются расширенным скан-кодом. Для обычных буквенно-цифровых клавиш скан-код (код сканирования) равен ASCII-коду символа. В расширенном скан-коде значимым является второй байт, который считывается вторым вызовом функции Readkey.Код в этом случае будет
key:=ReadKey;{ чтение первого байта кода}
If c=#0 then key:=ReadKey {если нажата не буквенно-цифровая клавиша, то в key будет значение расширенного скан-кода}
3.3.2. Выходные данные – изменения изображения на экране (прорисовка карт, поля и колоды; пояснительный и пригласительный текст). При произведении некоторых манипуляции старое изображение на экране стирается и появляется новое, содержание этого изображения зависит от произведенных манипуляций. Изображение может поменяться из-за появления новой карты, в случае хода, или наоборот отчистки стола, при взятии или окончании хода, или выведения пояснительного или пригласительного текста («Ход противника», «Вы подкидываете»). Также смена изображения происходит при начале или окончании игры.
3.4. Структуры данных
3.4.1. Формат TXT
Формат txt посимвольно хранит, содержащуюся в нем информацию. Каждый символ обозначается своим кодом из ASCII – таблицы. Информация разбита на строки различной длины заканчивающиеся кодом клавиши Enter. Также формат txt частично хранит форматирование (шрифт). При считывании из файла формата txt, считывается сочетание символов до первого пробела, при считывании строки, до первого конца строки.
3.4.2. Массивы
Массив - структура данных состоящая из последовательно расположенных в памяти однотипных элементов.
Объявление массивов
Type <Имя массива>=arrray[<диапазон индексов>] of <тип элемента>
В качестве имени массива может выступать любое не зарезервированное слово или сочетание символов.
В качестве диапазона индексов может выступать диапазон основанный на любом перечислимом типе. В случае с многомерным массивом задаётся не один диапазон индексов а несколько, не существует ограничения на сочетание диапазонов т.е. возможны двумерные массивы с одним диапазоном основанным на символьном типе(Char) и другим, основанным, к примеру, на типе integer.
В качестве типа элемента можно использовать любой тип.
Пример объявления :
Type arr=array[1..10] of integer;
Var z,x:arr;
Или
Var z:array[1..10] of word;
Использование массивов.
Для массивов при совпадении типов определена операция присвоения одного массива другому. Стандартные функции модуля System: Low и High возвращают минимальное и максимальное значение индекса массива.
Возможны также и операции над отдельными элементами массива выполняющиеся также как и операции над переменными типа соответствующего типу элементов массива. В общем виде элемент массива A представляется как переменная с именем A[i] где i индекс данного элемента в массиве, в случае одномерного массива, и A[i,j,k] где i, j и k индексы элементов для трёхмерного массива, аналогично и для других многомерных массивов.
Пример использования:
Z[1]:=1;
For i:=1 to 9 do Z[i+1]:=z[1]+z[i];
Особенности использования массивов в данной программе.
Целесообразность применения массивов в данной программе обусловлена необходимостью обработки достаточно большого количества однотипных данных, а конкретно значения карт. Из этого логически следуют особенности работы с массивами в данной программе: Количество элементов массивов одинаково и равно 36 (для хранения максимального количества карт). Существует несколько параллельных массивов для хранения информации о каждом игроке и колоде, что значительно упрощает доступ к ним, что в свою очередь значительно облегчает процедуры поиска и изменения нужных карт.
3.5. Описание функционирования системы
Началом программы является меню. В нем могут быть заданы требуемые позже переменные, может быть осуществлен выход из программы, или ее запуск. После запуска программы происходит операция перемешивания колоды. Она случайным образом присваивает массиву целочисленных значений, состоящему из 36 элементов, значения карт от 1 до 36. После этого происходит раздача карт, так, чтобы в руках у каждого из игроков находилось по 6 карт. Затем назначается козырь и выбирается игрок имеющий карту с наименьшим номиналом и той же масти, что и козырь, и значение маркера становится равным номеру игрока минус 1. После этого начинается цикл ходов, заканчивающийся при условии победы. Сначала прорисовывается стол и карты на руках игроков. Прорисовка будет повторяться после каждого из ходов. Затем происходит взятие карт, кому нужны. После этого, в зависимости от того ходит ли компьютер или игрок, делается выбор карты и анализируется выбор игрока, также игрок может отказаться от хода. Если ход был сделан, игрок с маркером, большим на один, чем у ходившего, отвечает, если же он не отвечает, то он берет карты, которые находятся на столе, и цикл начинается заново. Если произошел ответ, то начинается подкидывание и продолжается пока все игроки не спасуют или игрок не сможет ответить. Когда ход заканчивается главный маркер передается и цикл начинается заново. После того, как цикл кончится, происходит конец игры, и вновь открывается меню.
3.6. Описание основных алгоритмов
3.6.1. Искусственный интеллект
Искусственный интеллект в данной программе осуществляется с помощью набора различных процедур. Каждая из этих процедур отвечает за определенный вид выбора вариантов хода компьютера в определенных игровых ситуациях. Главным принципом этих процедур является выбор карты с наименьшим значением номинала и допустимой в данных условиях. Для этого используется временные массивы, в которых накапливаются промежуточные выборы, и временные переменные содержащие текущий минимум. Также в этих процедурах содержится огромное количество флагов, с помощью, которых удается избежать ошибочных выборов. Эти процедуры в основном отличаются друг от друга лишь флагами и условиями включения во временный массив.
3.6.2. Расшифровка и прорисовка карты на экране.
Хранение изображений различных карт осуществляется с помощью текстового файла содержащего закодированную информацию. Файл представляет собой набор цифр, располагающихся по две в строке. При активации процедуры прорисовки карты определяется, какой именно файл будет использован для прорисовки, а затем файл открывается для чтения. Также при активации задаются начальные координаты карты. После того как файл открыт, начинается цикл прорисовки. В начале этого цикла читается первое число в строке, оно определяет сколько следующих пикселов будут закрашены цветом, содержащимся во втором файле в строке. Заданной переменой присваивается значение первого числа в строке и при каждом последующей прорисовке пиксела уменьшается на 1. Когда заданная переменная становится равной нулю, считывается вторая строка из файла. Сам же цикл прорисовки состоит из двух частей: прорисовки общего для всех фона карты и прорисовка самого символа. Символ карты состоит из двух частей (номинала и масти), которые хранятся в отдельных файлах. Чтобы правильно нарисовать карту, используется два цикла For. Первый цикл с количеством итераций равным высоте карты в пикселах и второй с количеством итераций равным ширине карты в пикселах. При прорисовке к начальным координатам прибавляются номера итерации (первого к Y – координатам, второй к Х - координатам).
3.6.3. Процедура хода
Сначала выбирается игрок, который будет ходить первым. Определяется игрок, обладающий козырем наименьшего номинала. После этого маркеру №1 присваивается значение равное порядковому номеру игрока (игрок – 0, компьютер №1 – 1, и т.д.). Затем начинается цикл хода. То есть ход осуществляет игрок с номером равным остатку от деления маркера №1 на количество игроков. После этого начинается подцикл ответа-подкидывания. То есть игрок, с номером равным остатку от деления маркера №1 плюс один на количество игроков, осуществляет ответ, далее следуют подкидывания и продолжаются до того момента, пока все игроки не откажутся подкидывать или игрок не откажется отвечать. Процедура подкидывания осуществляется по очереди всеми игроками, кроме отбивающегося. То есть при запуске подцикла ответ-подкидывание маркер №2 приобретает значение маркера №1, после каждого подкидывания или паса возрастает на один, если остаток от деления маркера №2 стал равен значению номера отбивающегося игрока, то он повторно увеличивается на один. Если отбивающийся игрок отказался отвечать, то он забирает карты, находящиеся на столе, и значение маркера №1 увеличивается на два. Если же все остальные игроки отказались подкидывать, то карты со стола уничтожаются, а маркер №1 увеличивается на 1.
3.7. Описание стандартных и нестандартных подпрограмм
· Процедура Img (x,y,s:integer)
Сначала открывает изображение фона карты и рисует его, начиная с координат X и Y. Затем загружает из файла изображение номинала карты в зависимости от результата остатка от деления на 9 и прорисовывает его, начиная с координат X+5 и Y+5. После чего загружает из файла изображение масти карты в зависимости от результата целочисленного деления на 9 и рисует, начиная с координат X+20 и Y+5. Данная процедура используется при прорисовке карт игрока, а также карт на столе и козыря.
· Процедура Img1 (x,y:integer)
Рисует изображение рубашки карты, с помощью встроенной процедуры Bar. Начинает прорисовку из координат X и Y. Используется для прорисовки карт компьютеров и карт, находящихся в колоде.
· Процедура Hit (x : integer)
Перерисовывает карты находящиеся на игровом поле, и добавляет карту со значением Х, используя процедуру Img, убавляя количество карт на руке, сходившего игрока. Также перерисовывает карты находящиеся в руках игрока и компьютеров. Рисует колоду и козырь, пока количество карт в колоде больше нуля, а козырь не взят.
· Процедура Сlear (x : integer)
Перерисовывает карты находящиеся на игровом поле. Также перерисовывает карты находящиеся в руках игрока и компьютеров и выводит на экран поясняющую, либо побудительную надпись, используя встроенную процедуру OutTextXY, в зависимости от значения Х. Облегчает понимание и улучшает восприятие процесса игры.
· Процедура Draw (x : integer)
Совершает набор карт в руку тех игроков, у которых на руках в данный момент менее 6 карт. Изменяет флаги, отвечающие за наличие козыря и за окончание колоды. Зависит от переменной Х, которая обозначает количество играющих компьютеров.
· Процедура Pturn
Запускает цикл, прерывающийся при нажатии на клавишу мыши. Затем запускает проверку на координаты мыши в момент щелчка, если координаты соответствуют полю карт игрока, то считываются координаты щелчка мыши. Далее вычисляется на какой именно карте был сделан щелчок и производится процедура Hit от этой карты. Данная процедура непосредственно осуществляет ход игрока.
· Процедура Сturn
В зависимости от маркера выбирается, какой именно компьютер будет ходить. Выбранный компьютер производит поиск в принадлежащих ему картах наименьшей по номиналу и производит процедуру Hit от нее. Данная процедура осуществляет простейшую тактику компьютера.
· Процедура Pback
Запускает цикл, прерывающийся при нажатии на клавишу мыши или на клавишу клавиатуры. Если была нажата клавиши мыши, то запускается проверка на координаты мыши в момент щелчка, если координаты соответствуют полю карт игрока, то считываются координаты щелчка мыши. Далее вычисляется на какой именно карте был сделан щелчок. Затем осуществляется проверка корректности хода. Если ход правильный, то производится процедура Hit от этой карты, если нет, то выдается сообщение о некорректности хода. Если же была нажата какая-либо клавиша, то в зависимости от ASCII – кода клавиши, либо происходит выход из программы, либо пропускается ход. Данная процедура непосредственно осуществляет ответный ход игрока.
· Процедура Сback
В зависимости от маркера производит поиск в картах принадлежащих определенному компьютеру, наименьшей из допустимых карт для хода и производит процедуру Hit от нее. Если же таких карт не обнаружено. То компьютер пасует и забирает карты со стола. Данная процедура осуществляет простейшую тактику компьютера.
· Процедура Padd
Запускает цикл, прерывающийся при нажатии на клавишу мыши или на клавишу клавиатуры. Если была нажата клавиши мыши, то запускается проверка на координаты мыши в момент щелчка, если координаты соответствуют полю карт игрока, то считываются координаты щелчка мыши. Далее вычисляется, на какой именно карте был сделан щелчок. Затем осуществляется проверка корректности хода. Если ход правильный, то производится процедура Hit от этой карты, если нет, то выдается сообщение о некорректности хода. Если же была нажата какая-либо клавиша, то в зависимости от ASCII – кода клавиши, либо происходит выход из программы, либо пропускается ход. Данная процедура непосредственно осуществляет ответный ход игрока.
· Процедура Сadd
В зависимости от маркера производит поиск в картах принадлежащих определенному компьютеру, наименьшей из допустимых карт для хода и производит процедуру Hit от нее. Если же таких карт не обнаружено. То компьютер пасует, передает маркер другому игроку и появляется надпись об отказе компьютера подкидывать. Данная процедура осуществляет простейшую тактику компьютера.
4. Заключение
В заключении хочу сказать, что все пункты, содержавшиеся в Техническом Задании, были выполнены. Но несмотря на это, программа все же требует некоторой доработки. Код программы до конца не оптимизирован, можно сократить объем кода, путем унифицирования некоторых процедур, отвечающих за интеллект компьютера. То есть можно вывести основные алгоритмы нахождения хода компьютером в отдельные процедуры, а при инициализации процедуры хода компьютера лишь присваивать переменные, связанные с этим компьютером, временным переменным, а при выходе, уже обработанные временные данные присваивать обратно. Также простейшая стратегия компьютера требует большой доработки, чтобы хотя бы как-то соответствовать уровню игры даже начинающих игроков. Это можно осуществить путем усложнения проверки хода, введя массив карт вышедших из игры. Также следует ввести огромное количество флагов (окончание колоды, о карты, предположительно находящиеся в руке игрока или другого компьютера) и временных массивов. Все это поможет компьютеру лучше анализировать ситуацию и принимать более эффективные решения. Графика тоже не на самом высоком уровне. Должно быть убрано «моргание», с помощью изменения активной и визуальной страницы. Также можно ввести картинки для каждой карты, но либо это займет много времени для кодировки в формат, используемый данной программой, либо придется «научить» программу читать файлы bmp, либо использовать спрайты, и тогда можно будет даже показать передвижение карты из колоды в руку, и из руки на стол. Еще следует найти более рациональный способ перемешивания колоды, так как тот способ, который используется в данной программе, занимает слишком много времени, из-за того, что при приближении количества занятых мест в массиве, случайно «попасть» в пустой элемент становится слишком трудно.