Надо заметить, что модели данных не имеют отношения к самому Silverlight и следовательно их можно применять в других проектах. В данном случае мы будем писать модель на C#. В каталоге Models, добавим новый элемент класса C#.
Назовем
его GameBoard.cs.
Это будет главный файл игровой модели.
- namespace MemoryCards.Models
- {
- public class GameBoard
- {
- public int nSizeWidth;//кол-во карточек по ширине
- public int nSizeHeight;//кол-во карточек по высоте
- public int nCountCell;//всего карточек
- public Models.Card[] arrBoard;//игровая доска - массив карточек
- public int nCountOpenCard;//кол-во текущих открытых карточек
- public int nCountImages = 26;//кол-во уникальных изображений
- public bool bEndGame = false;//конец игры
- public int nCountTryOpen = 0;//попыток открывания карточек
- Первые три свойства определяют размерность игровой доски. Свойство arrBoard — это одномерный массив карточек (для простоты оперирования), описывающий все карточки на поле размером M*N. При помощи специальных простых функций, мы сможем обращаться к элементам этого массива по координатам (x,y) (см. раздел «Вспомогательные функции»). Сами карточки опишем в отдельном файле класса C#, с названием Card.cs. Этот файл-класс добавил на случай, если для карточек потребуется дополнительный функционал. Вообще лучше всегда отдельные классы описывать в отдельных файлах.
- Содержимое Card.cs содержит только структуру данных: индекс картинки, признак открыта, признак решена.
- public struct Card
- {
- public int nImageIndex;
- public bool bOpen;
- public bool bComplit;
- }
- nCountOpenCard, nCountTryOpen — это счетчики действий пользователя, bEndGame - конец игры, с этими параметрами все понятно. nCountImages - количество отдельных картинок в файле изображений. Для начала, я взял просто набор букв из английского алфавита и сделал из них одно изображение 1300*50 точек:
Файл должен быть в формате PNG (Silverlight, насколько мне известно, поддерживает на данный момент только два типа файлов PNG и JPEG, из них только первый поддерживает прозрачный цвет). Файл назвал a_z.png и поместил в каталог Images. В разделе визуализации игры, мы будем загружать этот файл, выделять отдельные буквы-картинки и выводить на экран.- После объявления свойств игровой доски, нужно произвести ее инициализацию. Задача заключается в том, чтобы заполнить поле случайными парными изображениями, то есть в массив arrImages заполнить поле nImageIndex значениями от 0 до 25. Вот код инициализации:
- public GameBoard(int nW, int nH)
- {
- nSizeWidth = nW;
- nSizeHeight = nH;
- nCountCell = nSizeWidth * nSizeHeight;
- nCountOpenCard = 0;
- arrBoard = new Models.Card[nCountCell];
- //генерация случайных неповторяющихся карточек
- //создаем массив индексов изображений и перемешиваем его
- int[] arrImages = new int[nCountImages];
- for (int n = 0; n < nCountImages; n++) arrImages[n] = n;
- arrImages=shuffleArrInt(arrImages);
- //инициализация карточек доски
- for (int n = 0; n < nCountCell; n++)
- {
- arrBoard[n].nImageIndex = -1;
- //arrBoard[n].bOpen = false;
- //arrBoard[n].bComplit = false;
- }
- //прерывание выполнения, если недостаточно количества изображений для полноценного заполнения доски
- if (nCountCell/2 > nCountImages) throw (new ArgumentOutOfRangeException("count cells > images"));
- //заполняем доску парными изображениями из перемешанного массива индексов изображений
- for (int n = 0; n < nCountCell; n += 2)
- arrBoard[n].nImageIndex = arrBoard[n + 1].nImageIndex = arrImages[n/2];
- //перемешиваем карточки на доске
- shuffle();
- }
- На вход конструктора подаем ширину и высоту поля, определяем нужные свойства. Затем создаем массив индексов отдельных картинок от 0 до 25 и перемешиваем его, чтобы затем последовательно заполнить массив карточек парными значениями arrBoard[n].nImageIndex = arrBoard[n + 1].nImageIndex = arrImages[n/2] — который затем также перемешиваем. Функции shuffleArrInt(arrImages) и shuffle() работают аналогично. Простой алгоритм, переставляет достаточное (кол-во элементов*2) количество раз, 2 случайных элемента массива:
- int[] shuffleArrInt(int[] arrInt)
- {
- Random rand = new Random();
- for (int n = 0; n < arrInt.GetLength(0)*2; n++)
- {
- int n1 = rand.Next(arrInt.GetLength(0));
- int n2 = rand.Next(arrInt.GetLength(0));
- if (n1 != n2)
- {
- int nTemp = arrInt[n1];
- arrInt[n1] = arrInt[n2];
- arrInt[n2] = nTemp;
- }
- }
- return arrInt;
- }
- Осталось рассмотреть игровую логику модели. Требуется определить ее реакцию при открывании карточки, а также проверку состояния игры на правильность решения.
- Для наглядности сразу приведу код открытия карточки:
- public void openCard(int nIndex)
- {
- if (arrBoard[nIndex].bOpen == false)
- {
- if (nCountOpenCard < 2)
- {
- arrBoard[nIndex].bOpen = true;
- nCountTryOpen++;
- nCountOpenCard++;
- }else
- {
- for (int n = 0; n < nCountCell; n++)
- arrBoard[n].bOpen = false;
- arrBoard[nIndex].bOpen = true;
- nCountTryOpen++;
- nCountOpenCard = 1;
- }
- }else
- arrBoard[nIndex].bOpen = false;
- solve();
- }
- Как видно, на вход функции принимаем индекс карточки. Если карточка открыта, то просто закрываем ее. Если закрыта, то проверяем количество уже открытых карточек и в зависимости от этого открываем карточки и меняем счетчики модели. Затем запускаем функцию проверки решения solve(). Смысл функции в том, чтобы найти две открытые карточки и если они найдены установить им признак завершения. Затем подсчитать завершенные карточки и в случае, если их количество равно общему количеству карточек, то установить признак завершения игры.
- void solve()
- {
- int[] arrOpenCard = new int[2];
- arrOpenCard[0] = arrOpenCard[1] = -1;
- int ni = 0;
- for (int n = 0; n < nCountCell; n++)
- if (arrBoard[n].bOpen == true) arrOpenCard[ni++] = n;
- if (arrOpenCard[0] != -1 && arrOpenCard[1] != -1)
- if (arrBoard[arrOpenCard[0]].nImageIndex == arrBoard[arrOpenCard[1]].nImageIndex)
- {
- arrBoard[arrOpenCard[0]].bOpen = false;
- arrBoard[arrOpenCard[1]].bOpen = false;
- arrBoard[arrOpenCard[0]].bComplit = true;
- arrBoard[arrOpenCard[1]].bComplit = true;
- }
- int nCountComplit = 0;
- for (int n = 0; n < nCountCell; n++)
- if (arrBoard[n].bComplit == true) nCountComplit++;
- if (nCountComplit == nCountCell) bEndGame = true;
- }
- namespace MemoryCards.Models
Комментариев нет:
Отправить комментарий
Да, я внимательно слушаю