Вход/Регистрация
Создание игр для мобильных телефонов
вернуться

Моррисон Майкл

Шрифт:

Метод update начинается с проверки завершения игры и, если это так, то начинается новая игра. Обратите внимание, что перезапуск игры выполняется методом newGame, а также отправкой сообщения NewGame другому образу игры. Если новая игра не начата, то проверяются нажатия клавиш Влево, Вправо и Огонь. Обратите внимание, что нажатия клавиш обрабатываются, пока игра запущена.

Стрелки Влево и Вправо изменяют значение переменной curSlot в соответствии с выбранной колонкой игровой доски. Код для обработки нажатия клавиши Огонь намного интереснее, ее нажатие говорит о совершении хода, в результате вызывается метод makeMove. Об этом методе вы узнаете чуть позже. Независимо от нажатия клавиши Огонь в конце метода update выполняется обновление спрайта стрелки в соответствии с изменениями переменной curSlot.

В листинге 15.7 приведен код метода draw, который отвечает за графику мидлета Connect 4.

Листинг 15.7. Метод draw класса C4Canvas отвечает за графику мидлета Connect 4

private void draw(Graphics g) {

// заполнить фон

g.setColor(128, 128, 128); // серый

g.fillRect(0, 0, getWidth, getHeight);

// вывести статусное сообщение

g.setColor(0, 0, 0); // черные

g.setFont(Font.getFont(Font.FACE_SYSTEM, Font.STYLE_BOLD, Font.SIZE_MEDIUM));

g.drawString(status, getWidth / 2, 2, Graphics.TOP | Graphics.HCENTER); //Строка статусных сообщений располагается в верхней части игрового экрана

if (!gameOver && myMove) { //Вывести стрелку, если игра продолжается и ход принадлежит игроку

// вывести стрелку

arrowSprite.paint(g);

}

// вывести фишку

for (int i = 0; i < 7; i++)

for (int j = 0; j < 6; j++)

switch(gameState.board[i][j]) {

case 0:

g.drawImage(piece[0],

(getWidth * (i + 1)) / 8 – (piece[0].getWidth / 2), //Вывести фишки игрока сервера

((getHeight – 33) * (6 – j)) / 7 – (piece[0].getHeight / 2) + 33,

Graphics.TOP | Graphics.LEFT);

break;

case 1:

g.drawImage(piece[1],

(getWidth * (i + 1)) / 8 – (piece[0].getWidth / 2), //Вывести фишки игрока клиента

((getHeight – 33) * (6 – j)) / 7 – (piece[1].getHeight / 2) + 33,

Graphics.TOP | Graphics.LEFT);

break;

default:

g.setColor(255, 255, 255); // белый //Вывести свободные ячейки

g.fillArc((getWidth * (i + 1)) / 8 – (piece[0].getWidth / 2),

((getHeight – 33) * (6 – j)) / 7 – (piece[0].getHeight / 2) + 33,

piece[0].getWidth, piece[0].getHeight, 0, 360);

break;

}

// вывести графику на экран

flushGraphics;

}

Метод draw начинается с заливки фона игрового экрана. Затем в нижней части экрана появляется игровое статусное сообщение. Если игра запущена и ход принадлежит игроку, то спрайт стрелки выводится под строкой статуса. Оставшаяся часть метода draw выводит фишки и пустые ячейки на игровой доске. Значение 0 на игровой доске соответствует фишке красного цвета – игрока серверного приложения, а значение 1 – фишке синего цвета, принадлежащей игроку клиентского приложения.

Метод newGame вызывается для запуска новой игры, его задача – инициализировать игровые переменные и обновить строку состояния. В листинге 15.8 приведен код этого метода.

Листинг 15.8. Метод newGame класса C4Canvas запускает новую игру Connect 4

public void newGame {

// Initialize the game variables

gameOver = false;

curSlot = 0;

gameState = new C4State;

// Update the status message

status = myMove ? "Your turn." : "Waiting for player\'s move...";

}

Этот код вполне очевидный, переменной gameOver присваивается значение false, переменной curSlot – 0, игровая доска обновляется при создании переменной gameState. Затем обновляется сообщение в строке статуса в соответствии с очередностью хода.

Вы уже несколько раз видели вызов метода receiveMessage (листинг 15.9), который отвечает за получение и обработку сообщений.

Листинг 15.9. Метод receiveMessage класса C4Canvas получает и обрабатывает сообщения, переданные по сети

public void receiveMessage(String message) {

if (gameOver) {

// проверка сообщения о запуске новой игры

if (message.equals("NewGame")) //Если получено сообщение NewGame, то начать новую игру

newGame;

}

else {

if (!myMove) {

// попытка получить сообщение с информацией о ходе

try {

// отобразить ход соперника

int slot = Integer.parseInt(message);

if (slot >= 0 && slot <= 6) { //Проверить, что сообщение содержит допустимое значение колонки (от 0 до 6), а затем выполнить ход

if (makeMove(isServer ? 1 : 0, slot))

myMove = true;

}

}

catch (NumberFormatException nfe) {

}

}

}

}

Этот метод вызывается как клиентом, так и сервером. Он обрабатывает сообщения, отправленные соперником.

Сетевое сообщение всегда содержит один из возможных типов информации – сообщение о начале новой игры, или сообщение о номере столбца, в который соперник поставил фишку. Если получено сообщение NewGame, то запускается новая игра. Если получен номер столбца, в который был сделан ход, то он передается в метод makeMove.

Метод makeMove – это последний интересный метод класса C4 Canvas. В листинге 15.10 приведен его код. Этот метод реализует большую часть логики мидлета Connect 4.

Листинг 15.10. Метод makeMove класса C4Canvas отображает ходы, сделанные в игре

private boolean makeMove(int player, int slot) {

// бросить фишку

if (gameState.dropPiece(player, slot) == -1) { //Попытаться бросить фишку в колонку, в случае неудачи возвратить значение false

// воспроизвести звук неправильного хода

try {

illegalPlayer.start;

}

catch (MediaException me) {

}

return false;

}

// воспроизвести звук корректного хода

try {

legalPlayer.start;

}

catch (MediaException me) {

}

// проверить, закончена ли игра

if (gameState.isWinner(player)) {

if ((isServer && (player == 0)) || (!isServer && (player == 1))) { //Проверить, выиграл ли игрок

// воспроизвести звук победы

try {

winPlayer.start;

}

catch (MediaException me) {

}

status = "You won!";

}

else { //Игрок проиграл

// воспроизвести звук поражения

try {

losePlayer.start;

}

catch (MediaException me) {

}

status = "You lost!";

}

gameOver = true;

}

else if (gameState.isTie) { //Проверить, закончилась ли игра ничьей

// воспроизвести звук ничьей

try {

losePlayer.start;

}

catch (MediaException me) {

}

status = "The game ended in a tie!";

gameOver = true;

}

else {

// обновить сообщение о статусе

status = myMove ? "Waiting for other player..." : "Your turn.";

}

return true;

}

Я знаю, что метод makeMove достаточно запутан, однако он не такой сложный, как это может показаться. Во-первых, важно отметить, что два параметра, принимаемых методом, – это игрок и номер столбца, в который совершается ход. Метод начинается с вызова dropPiece, в который передается переменная gameState. Этот метод пытается поместить фишку в выбранный столбец. Я говорю «пытается», потому что ход может быть невозможным из-за того, что столбец уже полон. В этом случае метод возвращает значение false, которое говорит о том, что ход сделать нельзя.

Если ход возможен, то метод makeMove воспроизводит звуковой файл и проверяет, завершает ли этот ход игру. В вызываемый метод isWinner передается объект, описывающий состояние игры, он проверяет, победил ли игрок, сделавший ход. Если да, то следует проверка, кто победил – игрок или его соперник. Затем обновляется статусное сообщение, а переменной gameOver присваивается значение true.

Игра Connect 4 может закончиться, когда на игровом поле не остается свободной ячейки, а никто из игроков не смог выставить 4 фишки в ряд. Чтобы определить ничью, достаточно вызвать метод isTie класса C4Canvas. Метод makeMove вызывает метод isTie и проверяет, окончилась ли игра ничьей.

Состояние игры Connect 4

Последний фрагмент головоломки с названием Connect 4 – это класс, описывающий детали игры Connect 4, например, положение фишек на игровой доске. Класс C4State моделирует текущее состояние игры Connect 4, он содержит следующие переменные:

private static boolean[][][] map;

private int[][] score = new int[2][winPlaces];

public static final int winPlaces = 69, maxPieces = 42, Empty = 2;

private int numPieces;

public int[][] board = new int[7][6];

Чтобы упростить разбор класса C4State, давайте начнем разговор с рассмотрения переменных winPlaces, maxPieces и Empty типа static final. Такое объявление говорит о том, что эти члены класса являются константами. Приведенное ниже уравнение используется для подсчета значения константы winPlaces, определяющей число возможных выигрышных комбинаций на доске:

winPlaces = 4*w*h – 3*w*n – 3*h*n + 3*h – 4*n + 2*n*n;

Это общее уравнение, которое можно применить к любой игре типа Connect X. В этом уравнении: w и h – ширина и высота доски в ячейках соответственно, а n – число фишек, которое необходимо выставить для победы. Поскольку в игре Connect 4 используется доска размером 7 6, при этом для победы необходимо выставить 4 фишки, то вы легко можете посчитать значение winPlaces и получите число 69. Как раз именно это значение и присваивается в классе C4State. Переменная maxPieces определяет максимальное число фишек, которое можно поставить на доску. Приведенное ниже уравнение позволяет вычислить это значение:

maxPieces = w*h;

Результат используется для определения ничьей. Ничья возникает, если все ячейки на доске заняты, а ни один из игроков не одержал победу.

Другая константа класса – это Empty, она соответствует свободному пространству на доске. Каждая ячейка на доске может содержать число 0, 1 или значение константы Empty – 2.

Возвращаясь к приведенному выше списку констант, переменная map – это трехмерный массив булевского типа, который содержит таблицу выигрышных положений. Чтобы лучше понять, как устроен массив map, представьте его двумерным массивом размером, равным размеру игровой доски. А теперь добавьте к нему третье измерение, присоединив к каждой ячейке массив выигрышных положений.

Каждая отдельная выигрышная комбинация в игре имеет свое уникальное положение в массиве (длинна массива выигрышных положений равна значению переменной winPlaces). Каждая ячейка массива содержит значение true или false в зависимости от того, лежит ли ячейка на пересечении выигрышной комбинации.

Давайте рассмотрим небольшой пример, чтобы понять, как работает массив map. Взгляните на верхний левый угол игровой доски (рис. 15.1). Давайте назовем это положение (0,0). Теперь представьте различные выигрышные комбинации, включающие это положение. Сдаетесь? Посмотрите на рис. 15.4.

Как вы видите, в положении (0,0) на доске имеет три выигрышных комбинации. Следовательно, массив для положения (0,0) отразит эти комбинации, установив значения соответствующих ячеек true, при этом значения во всех остальных ячейках будут false. Если выигрышные положения, показанные на рис. 15.4, будут в положениях 11–13, массив map инициализировался бы так:

  • Читать дальше
  • 1
  • ...
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • ...

Ебукер (ebooker) – онлайн-библиотека на русском языке. Книги доступны онлайн, без утомительной регистрации. Огромный выбор и удобный дизайн, позволяющий читать без проблем. Добавляйте сайт в закладки! Все произведения загружаются пользователями: если считаете, что ваши авторские права нарушены – используйте форму обратной связи.

Полезные ссылки

  • Моя полка

Контакты

  • chitat.ebooker@gmail.com

Подпишитесь на рассылку: