Записки программиста Программирование и не только

18Окт/120

Java API

Очень полезная ссылка.
Документация по всем стандартным классам языка
http://docs.oracle.com/javase/7/docs/api/index.html

Навигация как всегда на высоте.

Искать либо в индексе по имени функции/класса/пакета (справа вверху Index)
Либо по имени класса (слева All Classes)

Метки записи: Нет комментариев
11Окт/121

[Java] Подключаем чужие исходники в IntelliJ IDEA

По следам статьи

В статье предлагается попробовать себя в роли разработчика Рогалика (Rogue-like) - игрушки, в которых вместо графики используется ASCII символы.

Разберем, как же подключить правильно сторонние библиотеки, чтобы всё работало.

Необходимо скачать две (а не одну, как сказано в статье) библиотеки: jcurses и libjcsi
Для скачивания исходников для libjcsi понадобится SVN клиент (надо будет написать про них немного)
Или можно взять тут: http://axis.bplaced.net/wp-content/uploads/2012/10/libjcsi.zip
Качаем исходники (Source) и распаковываем их куда-нибудь. У меня это C:\JavaLib\jcurses и C:\JavaLib\libjcsi

Создаём новый модуль (или открываем старый) и добавляем туда новый класс Rogalic.

Заходим в File -> Project Structure
Раздел Module, вкладка Dependencies.

Жмём + -> Module

Выбираем Create module from existing sources и жмем "..."

Находим исходники

Жмем Next до упора и потом Finish (всё по умолчанию, все окна практически пустые)

Повторяем тоже самое для libjcsi

Теперь добавляем зависимости.
Жмем на модуль Net и затем справа на "+" -> Module dependency

Выбираем там Jcurses

Теперь выбираем наш родной модуль и повторяем операцию. Только теперь выбираем Net

Закрываем всё. Должно получиться как-то вот так

Теперь пишем в классе Rogalic следующее:

import java.util.ArrayList;
import java.util.Properties;

import net.slashie.libjcsi.CSIColor;
import net.slashie.libjcsi.CharKey;
import net.slashie.libjcsi.ConsoleSystemInterface;
import net.slashie.libjcsi.wswing.WSwingConsoleInterface;

public class Rogalic {
    private static Rogalic instance;
    private static ConsoleSystemInterface csi;
    private boolean stop;
    private int x,y;
    public static void main(String[] args)
    {
        Properties text = new Properties();
        text.setProperty("fontSize", "15");
        text.setProperty("font", "roguelike.ttf");
        csi = new WSwingConsoleInterface("RogueLike", text);
        instance = new Rogalic();
        instance.run();
    }

    public void run()
    {
        stop = false;
        x = 0; y = 0;
        while (!stop)
        {
            csi.cls();
            csi.print(x,y,'@', CSIColor.WHITE); // отрисовка игрока
            csi.refresh();
            handleKeys(); // обработка клавиатуры
        }
        System.exit(0);
    }

    private void handleKeys(){
        CharKey dir = csi.inkey();
        if(dir.isUpArrow()&& (y-1 >= 0)){
            y--;
        }
        if(dir.isDownArrow() && (y+1 < 25)){
            y++;
        }
        if(dir.isLeftArrow() && (x-1 >= 0)){
            x--;
        }
        if(dir.isRightArrow() && (x+1 < 80)){
            x++;
        }
        if(dir.code == CharKey.Q){
            stop = true;
        }
    }
}

Запускаем!
Если всё сделано правильно, то должно появиться окно с довольной "собакой (@) - главным героем всех Рогаликов. Ну, почти всех :)
Им можно шаволить курсорными стрелками.

Метки записи: , , 1 комментарий
9Окт/120

[Java] Консольный ввод/вывод

Любимое занятие - написание консольных диалоговых приложений :)

Во время работы метода System.in.read возможно возникновение исключений. Поэтому заключаем фрагмент кода, выполняющий эту функцию, в блок try-catch.

import java.util.StringTokenizer;    //добавляем класс для обработки строк

public class ioTest {
    public static void main(String args[]) {
        byte bKbd[] = new byte[256];		// буфер
        String szStr = "";					// итоговая строка
        StringTokenizer st;					// преобразователь

        System.out.print("Print here: ");
        try
        {
            // Метод read считывает символы с клавиатуры и записывает
			// их в массив байт с именем bKbd. Этот метод возвращает 
			// управление, когда пользователь закончил ввод и нажал 
			// клавишу <Enter>. При этом в переменную iCnt записывается 
			// количество прочитанных символов.
            int iCnt = System.in.read(bKbd);

            // Строка String содержит 16-разрядные символы Unicode.
            // Чтобы преобразовать массив байт в строку Unicode, мы
			// задаем значение старшего байта во втором параметре 
			// конструктора, равное нулю.
            szStr = new String(bKbd, 0, iCnt);

            // Удаление символов возврата каретки и перевода строки
			// выполняется при помощи класса StringTokenizer, предназначенного 
			// для разбора текстовых строк. Создавая объект этого класса,
			// мы передаем конструктору через второй параметр список 
			// символов-разделителей
            st = new StringTokenizer(szStr, "\r\n");

            // Метод nextElement возвращает первый элемент строки до разделителя,
			// то есть в нашем случае всю строку до символов возврата каретки и 
			// перевода строки.
            szStr = new String((String)st.nextElement());
        }
        catch(Exception ex)
        {
            System.out.println(ex.toString());
        }

        //чисто для красоты - разделяем строку на слова
        String v[] = szStr.split(" ");
        for(int j = 0; j < v.length; j++)
        {
            System.out.println(j + "-е слово: " + v[j]);
        }
    }
}

Как пользоваться:
Запускаем, внизу в консоли тыкаем в белое поле и набираем строку. Ввод заканчиваем нажатием клавиши

Как-то вот так:

Print here: Это странная консольная программа!
0-е слово: Это
1-е слово: странная
2-е слово: консольная
3-е слово: программа!

Process finished with exit code 0
Метки записи: , Нет комментариев
8Окт/121

[Java] Пример перегрузки методов. Тонкость в передаче параметров

С помощью перегрузки функций можно получить метод с одним именем, но разными реализациями.

Например, есть функция сортировки, которая принимает в качестве параметра целочисленный массив. Как научить её воспринимать и вещественные массивы?

Надо перегрузить функцию:

class Sort {
    void gnom_sort(int[] mas) {
        int p = 2;
        int i = 1;
        for (; i < mas.length; ) {
            if (mas[i - 1] <= mas[i]) {
                p++;
                i = p;
            } else {
                int a = mas[i];
                mas[i] = mas[i - 1];
                mas[i - 1] = a;
                i--;
                if (i == 0) {
                    p++;
                    i = p;
                }
            }
        }
    }

    void gnom_sort(double[] mas) {    //перегруженная функция
        int p = 2;
        int i = 1;
        for (; i < mas.length; ) {
            if (mas[i - 1] <= mas[i]) {
                p++;
                i = p;
            } else {
                double a = mas[i];
                mas[i] = mas[i - 1];
                mas[i - 1] = a;
                i--;
                if (i == 0) {
                    p++;
                    i = p;
                }
            }
        }
    }
}

class Hello {
    public static void main(String args[]) {
        int masI[] = {5, 5, 9, 8, 0, -5, 9, 10};
        double masD[] = {5.9, 5.7, 9.6, 8.9, 0.7, -5.6, 9.9, 10.0};
        Sort s1 = new Sort();
        s1.gnom_sort(masI);
        s1.gnom_sort(masD);        //для нас ничего не изменилось
}

А теперь обещанная тонкость
В Java в качестве параметров в функции передаются ссылки, а не значения. Кроме примитивных типов (int, long, float и т.п.).
Массив уже не является примитивным.
Что это значит. Это значит, что, передав объект (например тот же массив) в функцию, этот самый объект может быть в этой функции изменён безвозвратно.

Как пример. Создаём один массив и хотим проверить на нём несколько функций сортировки. Но после первой же функции массив станет отсортированный и дальнейшая его сортировка бессмысленна.

А вот как с этим жить дальше я пока не понимаю :(

Метки записи: , 1 комментарий
8Окт/120

[Java] Методы. Статические и нет. Вызов методов.

Итак, в предыдущей статье я написал пример реализации сортировки. Но написал я её в виде функции.

Теперь разберу как её использовать.

Из теории известно, что методы являются частью классов. Чтобы использовать метод без класса, его надо сделать статическим.

Пример с классом:

class Sort {
    void gnom_sort(int[] mas) {
        int p = 2;
        int i = 1;
        for (; i < mas.length; ) {
            if (mas[i - 1] <= mas[i]) {
                p++;
                i = p;
            } else {
                int a = mas[i];
                mas[i] = mas[i - 1];
                mas[i - 1] = a;
                i--;
                if (i == 0) {
                    p++;
                    i = p;
                }
            }
        }
    }
}

public class Hello {
	public static void main(String args[]) {
	int mas[] = {5, 5, 9, 8, 0, -5, 9, 10};
	Sort s1 = new Sort();
	s1.gnom_sort(mas);
}

Пример со статической функцией:

class Sort {
    static void gnom_sort(int[] mas) {
        int p = 2;
        int i = 1;
        for (; i < mas.length; ) {
            if (mas[i - 1] <= mas[i]) {
                p++;
                i = p;
            } else {
                int a = mas[i];
                mas[i] = mas[i - 1];
                mas[i - 1] = a;
                i--;
                if (i == 0) {
                    p++;
                    i = p;
                }
            }
        }
    }
}

public class Hello {
	public static void main(String args[]) {
	int mas[] = {5, 5, 9, 8, 0, -5, 9, 10};
	Sort.gnom_sort(mas);	//Не нужно создавать объект
}

Также, можно поместить функцию и внутрь основного класса и сделать её статической. Тогда можно вызывать её просто по имени:

public class Hello {
    static void gnom_sort(int[] mas) {
        int p = 2;
        int i = 1;
        for (; i < mas.length; ) {
            if (mas[i - 1] <= mas[i]) {
                p++;
                i = p;
            } else {
                int a = mas[i];
                mas[i] = mas[i - 1];
                mas[i - 1] = a;
                i--;
                if (i == 0) {
                    p++;
                    i = p;
                }
            }
        }
    }

    public static void main(String args[]) {
        int mas[] = {5, 5, 9, 8, 0, -5, 9, 10};
        gnom_sort(mas);	//Просто вызываем
}
Метки записи: , Нет комментариев
8Окт/120

Гномья сортировка (Gnome sort)

Гномья сортировка основана на технике, используемой обычным голландским садовым гномом (нидерл. tuinkabouter). Это метод, которым садовый гном сортирует линию цветочных горшков. По существу он смотрит на следующий и предыдущий садовые горшки: если они в правильном порядке, он шагает на один горшок вперёд, иначе он меняет их местами и шагает на один горшок назад. Граничные условия: если нет предыдущего горшка, он шагает вперёд; если нет следующего горшка, он закончил.
Дик Грун

Мой вариант реализации:

void gnom_sort(int[] mas) {
	int p = 2;
	int i = 1;
	for (; i < mas.length; ) {
		if (mas[i - 1] <= mas[i]) {
			p++;
			i = p;
		} else {
			int a = mas[i];
			mas[i] = mas[i - 1];
			mas[i - 1] = a;
			i--;
			if (i == 0) {
				p++;
				i = p;
			}
		}
	}
}
27Сен/120

Задачи по Java

http://codingbat.com/java
На английском. Сразу запускаются и проверяются.

26Сен/120

Сертификация Java

А вот тут можно попробовать пройти тестовый экзамен на сертификат http://www.certpal.com
Правда, он старенький, кажется.

25Сен/122

[Java] Классы. static и abstract

static
Иногда требуется создать метод, который можно было бы использовать вне какого-либо объекта.
Статические методы могут непосредственно обращаться только к другим статическим методам, в них ни в каком виде не допускается использование ссылок this и super.
Внутри статических методов недопустимы ссылки на не статические переменные объекта.
Переменные также могут иметь тип static, они подобны глобальным переменным, то есть доступны из любого места кода.

class Static {
	static int a = 3;
	static int b = 4;
	static void method(int x) {
		System.out.println("x = " + x);
		System.out.println("a = " + a);
		System.out.println("b = " + b); 
	}
}

Вызываем без создания экземпляра класса

Static.method(42);
System.out.println("StaticClass.b = " + Static.b);

Результат запуска этой программы

x = 42 
a = 3 
b = 4
StaticClass.b = 4

abstract
Бывают ситуации, когда нужно определить класс, в котором задана структура какой-либо абстракции, но полная реализация всех методов отсутствует. В таких случаях вы можете с помощью модификатора типа abstract объявить, что некоторые из методов обязательно должны быть замещены в подклассах. Любой класс, содержащий методы abstract, также должен быть объявлен, как abstract. Поскольку у таких классов отсутствует полная реализация, их представителей нельзя создавать с помощью оператора new. Кроме того, нельзя объявлять абстрактными конструкторы и статические методы. Любой подкласс абстрактного класса либо обязан предоставить реализацию всех абстрактных методов своего родителя, либо сам должен быть объявлен абстрактным.

abstract class A {
	abstract void callme();
	void metod() {
		System.out.println("Inside A's metoo method"); 
	} 
} 

class B extends A {
	void callme() {
		System.out.println("Inside B's callme method");
	} 
} 

class Abstract {
	public static void main(String args[]) {
		B b = new B(); 
		b.callme();
		b.metoo();
	} 
}
Метки записи: , 2 Комментарии
25Сен/120

[Java] Классы. Перегрузка, this, наследование, переопределение

  • Перегрузка методов
  • Оператор this
  • Наследование
  • Переопределение методов (override)
  • Всякое
  • Непонятные возможности