* Точка входа. Содержит все необходимые действия для одного игрового цикла



Дата09.05.2023
өлшемі11,35 Kb.
#91223

/**
* Точка входа. Содержит все необходимые действия для одного игрового цикла.
*/
public static void main(String[] args) {
initFields();
createInitialCells();

while(!endOfGame){

input();
logic();

graphicsModule.draw(gameField);


}

graphicsModule.destroy();

}

public class GameField {


/**
* Состояние всех ячеек поля.
*/
private int[][] theField;

/**
* Инициализирует поле и заполняет его нулями


*/
public GameField(){
theField = new int[COUNT_CELLS_X][Constants.COUNT_CELLS_Y];

for(int i=0; i
for(int j=0; jtheField[i][j]=0;
}
}
}

/**
* Возвращает состояние ячейки поля по координатам


*
* @param x Координата ячейки X
* @param y Координата ячейки Y
* @return Состояние выбранной ячейки
*/
public int getState(int x, int y){
return theField[x][y];
}

/**
* Изменяет состояние ячейки поля по координатам


*
* @param x Координата ячейки X
* @param y Координата ячейки Y
* @param state Новое состояние для этой ячейки
*/
public void setState(int x, int y, int state){
//TODO check input maybe?

theField[x][y] = state;


}

/**
* Изменяет столбец под номером i


*
* @param i Номер изменяемого столбца
* @param newColumn Массив новых состояний ячеек столбца
*/
public void setColumn(int i, int[] newColumn) {
theField[i] = newColumn;
}

/**
* Возвращает массив состояний ячеек столбца под номером i


*
* @param i Номер запрашиваемого столбца
* @return Массив состояний ячеек столбца
*/
public int[] getColumn(int i) {
return theField[i];
}

/**
* Изменяет строку под номером i


*
* @param i Номер изменяемой строки
* @param newLine Массив новых состояний ячеек строки
*/
public void setLine(int i, int[] newLine) {
for(int j = 0; j< COUNT_CELLS_X; j++){
theField[j][i] = newLine[j];
}
}

/**
* Возвращает массив состояний ячеек строки под номером i


*
* @param i Номер запрашиваемой строки
* @return Массив состояний ячеек строки
*/
public int[] getLine(int i) {
int[] ret = new int[COUNT_CELLS_X];

for(int j = 0; j< COUNT_CELLS_X; j++){


ret[j] = theField[j][i];
}

return ret;


}

}

/**


* Создаёт на поле начальные ячейки
*/
private static void createInitialCells() {
for(int i = 0; i < COUNT_INITITAL_CELLS; i++){
generateNewCell();
}
}

private static void generateNewCell() {


int state = (new Random().nextInt(100) <= Constants.CHANCE_OF_LUCKY_SPAWN)
? LUCKY_INITIAL_CELL_STATE
: INITIAL_CELL_STATE;

int randomX, randomY;

randomX = new Random().nextInt(Constants.COUNT_CELLS_X);
int currentX = randomX;

randomY = new Random().nextInt(Constants.COUNT_CELLS_Y);


int currentY = randomY;

boolean placed = false;


while(!placed){
if(gameField.getState(currentX, currentY) == 0) {
gameField.setState(currentX, currentY, state);
placed = true;
}else{
if(currentX+1 < Constants.COUNT_CELLS_X) {
currentX++;
}else{
currentX = 0;
if(currentY+1 < Constants.COUNT_CELLS_Y) {
currentY++;
}else{
currentY = 0;
}
}

if ((currentX == randomX) && (currentY==randomY) ) { //No place -> Something went wrong


ErrorCatcher.cellCreationFailure();
}
}
}

score += state;


}
private static void input() {
keyboardModule.update();

/* Определяем направление, в котором нужно будет произвести сдвиг */


direction = keyboardModule.lastDirectionKeyPressed();

endOfGame = endOfGame || graphicsModule.isCloseRequested() || keyboardModule.wasEscPressed();


}

public interface GraphicsModule {

/**
* Отрисовывает переданное игровое поле
*
* @param field Игровое поле, которое необходимо отрисовать
*/
void draw(GameField field);

/**
* @return Возвращает true, если в окне нажат "крестик"


*/
boolean isCloseRequested();

/**
* Заключительные действия, на случай, если модулю нужно подчистить за собой.


*/
void destroy();
}

public interface KeyboardHandleModule {

/**
* Считывание последних данных из стека событий, если можулю это необходимо
*/
void update();

/**
* @return Возвращает направление последней нажатой "стрелочки",


* либо AWAITING, если не было нажато ни одной
*/
ru.tproger.main.Direction lastDirectionKeyPressed();

/**
* @return Возвращает информацию о том, был ли нажат ESCAPE за последнюю итерацию


*/
boolean wasEscPressed();

}

private static void logic() {


if(direction!=Direction.AWAITING){
if(shift(direction)) generateNewCell();

direction=Direction.AWAITING;


}
}

public enum Direction {


AWAITING, UP, DOWN, LEFT, RIGHT
}

/**
* Изменяет gameField, сдвигая все ячейки в указанном направлении,


* вызывая shiftRow() для каждой строки/столбца (в зависимости от направления)
*
* @param direction Направление, в котором необходимо совершить сдвиг
* @return Возвращает true, если сдвиг прошёл успешно (поле изменилось)
*/
private static boolean shift(Direction direction) {
boolean ret = false;

switch(direction) {


case UP:
case DOWN:

/*По очереди сдвигаем числа всех столбцов в нужном направлении*/


for(int i = 0; i< Constants.COUNT_CELLS_X; i++){
/*Запрашиваем очередной столбец*/
int[] arg = gameField.getColumn(i);

/*В зависимости от направления сдвига, меняем или не меняем порядок чисел на противоположный*/


if(direction==Direction.UP){
int[] tmp = new int[arg.length];
for(int e = 0; e < tmp.length; e++){
tmp[e] = arg[tmp.length-e-1];
}
arg = tmp;
}

/*Пытаемся сдвинуть числа в этом столбце*/


ShiftRowResult result = shiftRow (arg);

/*Возвращаем линию в исходный порядок*/


if(direction==Direction.UP){
int[] tmp = new int[result.shiftedRow.length];
for(int e = 0; e < tmp.length; e++){
tmp[e] = result.shiftedRow[tmp.length-e-1];
}
result.shiftedRow = tmp;
}

/*Записываем изменённый столбец*/


gameField.setColumn(i, result.shiftedRow);

/*Если хоть одна линия была изменена, значит было изменено всё поле*/


ret = ret || result.didAnythingMove;
}
break;
case LEFT:
case RIGHT:

/*По очереди сдвигаем числа всех строк в нужном направлении*/


for(int i = 0; i< Constants.COUNT_CELLS_Y; i++){
/*Запрашиваем очередную строку*/
int[] arg = gameField.getLine(i);

/*В зависимости от направления сдвига, меняем или не меняем порядок чисел на противоположный*/


if(direction==Direction.RIGHT){
int[] tmp = new int[arg.length];
for(int e = 0; e < tmp.length; e++){
tmp[e] = arg[tmp.length-e-1];
}
arg = tmp;
}

/*Пытаемся сдвинуть числа в этом столбце*/


ShiftRowResult result = shiftRow (arg);

/*Возвращаем линию в исходный порядок*/


if(direction==Direction.RIGHT){
int[] tmp = new int[result.shiftedRow.length];
for(int e = 0; e < tmp.length; e++){
tmp[e] = result.shiftedRow[tmp.length-e-1];
}
result.shiftedRow = tmp;
}

/*Записываем изменённую строку*/


gameField.setLine(i, result.shiftedRow);

/*Если хоть одна линия была изменена, значит было изменено всё поле*/


ret = ret || result.didAnythingMove;
}

break;
default:


ErrorCatcher.shiftFailureWrongParam();
break;
}

return ret;


}

/**
* Результат работы метода сдвига shiftRow().


* Содержит изменённую строку и информацию о том, эквивалентна ли она начальной.
*/
private static class ShiftRowResult{
boolean didAnythingMove;
int[] shiftedRow;
}

private static ShiftRowResult shiftRow (int[] oldRow) {


ShiftRowResult ret = new ShiftRowResult();

int[] oldRowWithoutZeroes = new int[oldRow.length];


{
int q = 0;

for (int i = 0; i < oldRow.length; i++) {


if(oldRow[i] != 0){
if(q != i){
/*
* Это значит, что мы передвинули ячейку
* на место какого-то нуля (пустой плитки)
*/
ret.didAnythingMove = true;
}

oldRowWithoutZeroes[q] = oldRow[i];


q++;
}
}

}

ret.shiftedRow = new int[oldRowWithoutZeroes.length];



{
int q = 0;

{
int i = 0;


while (i < oldRowWithoutZeroes.length) {


if((i+1 < oldRowWithoutZeroes.length) && (oldRowWithoutZeroes[i] == oldRowWithoutZeroes[i + 1])
&& oldRowWithoutZeroes[i]!=0) { {
ret.didAnythingMove = true;
ret.shiftedRow[q] = oldRowWithoutZeroes[i] * 2;
i++;
} else {
ret.shiftedRow[q] = oldRowWithoutZeroes[i];
}

q++;
i++;


}

}
}

Достарыңызбен бөлісу:




©emirsaba.org 2024
әкімшілігінің қараңыз

    Басты бет