Автоматоны Pawn

В языке Pawn есть механизм состояний(автоматон) — это такая система, которая позволяет определить несколько копий одной функции для использования в различных условиях. Я начну объяснять с примера, ибо так получится более наглядно, а ниже подробно опишу эту систему.

Пример

Допустим нам нужно сохранить данные игрока и данные гонок, а также сообщить об этом игрокам и гонщикам соответственно. При обычной реализации код выглядит грязновато:

#include <a_samp>
 
forward data_Save(type);
forward message_Save(type);
 
enum {
	players,
	races
}
 
main() {
	data_Save(players);
	message_Save(players);
}
 
public data_Save(type)
{
	switch (type) {
		case players: {
			// saving
		}
		case races: {
			// saving
		}
	}
}
public message_Save(type)
{
	switch (type) {
		case players: {
			// send message to player
		}
		case races: {
			// send message to racers
		}
	}
}

А реализация с помощью автоматонов выглядит очень элегантно:

#include <a_samp>
 
forward data_Save();
 
main() {
	state dataType:players;
	data_Save();
	message_Save();
}
 
public data_Save() <dataType:players>
{
	// saving
}
 
public data_Save() <dataType:races>
{
	// saving
}
 
public message_Save() <dataType:players>
{
	// send message to players
}
 
public message_Save() <dataType:races>
{
	// send message to racers
}

Читать дальше

Архитектура Pawn(SA-MP) проекта

В этой статье я хочу посоветовать Pawn скриптерам как нужно устраивать внутреннюю часть вашего SA-MP проекта. Далеко не секрет, что большая часть скриптеров хранят свои режимы всего в одном .pwn файле. Эта мода пошла от режимов Pen и God Father. На самом деле, это очень не правильное решение. Потому что, при увеличении количества кода проекта, его сложность в дальнейшей модификации значительно усложняется.
Чтобы избежать значительного усложнения проекта при его модификации, вам достаточно правильно спроектировать архитектуру вашего проекта до его реализации, или провести рефакторинг уже существующего проекта.

Подготовка

 
У нас есть каталог projects/, в котором будут храниться все наши Pawn проекты. Конечно, вам потребуется компилятор, лучше всего компилятор не хранить в каждом проекте, а вынести в отдельный каталог compiler/. Проекты будут храниться в каталогах projects/project_1, projects/project_2, где project_1 и project_2 — названия ваших проектов.
В итоге, наша площадка для разработки должна выглядеть следующим образом:

├── compiler
│   ├── includes
│   │   ├── a_http.inc
│   │   ├── a_mysql.inc
│   │   ├── a_npc.inc
│   │   ├── a_objects.inc
│   │   ├── a_players.inc
│   │   ├── a_sampdb.inc
│   │   ├── a_samp.inc
│   │   ├── a_vehicles.inc
│   │   ├── core.inc
│   │   ├── datagram.inc
│   │   ├── file.inc
│   │   ├── float.inc
│   │   ├── string.inc
│   │   └── time.inc
│   ├── libpawnc.dll
│   ├── pawncc.exe
│   └── pawnc.dll
├── project_1
└── project_2

Стоит отметить, что стандартные библиотеки компилятора несовместимы с таким расположением каталогов, поэтому файл a_samp.inc придётся немного переделать. Нужно заменить скобки вида <>, на двойные кавычки. Например #include <core> мы заменим на #include "core"
Вот все заменённые строки:

#include "core"
#include "float"
#include "string"
#include "file"
#include "time"
#include "datagram"
#include "a_players"
#include "a_vehicles"
#include "a_objects"
#include "a_sampdb"
#include "a_http"

Читать дальше

Формирование двумерного массива из одномерного

Задача: ввести одномерный массив. Например:

2 9 4 -2 9 8 6 3 0 -4 5 1

Сформировать двумерный массив по заданному правилу:

1 5 -4 0
3 6 8 9
-2 4 9 2

В двумерном массиве найти значение минимального элемента. Вывести массивы и результат на экран.
 
Решение на C++:

#include <iostream>
 
#define ARRAY_ROWS 3
#define ARRAY_COLUMNS 4
#define ARRAY_SIZE (ARRAY_ROWS * ARRAY_COLUMNS)
 
void input_data(int *array);
void array_proc(int *array_first, int **array_second);
void print_min_value(int **array);
void print_arrays(int *array_first, int **array_second);
 
int main()
{
    // ввод данных
    int *array_first = new int [ARRAY_SIZE];
    input_data(array_first);
 
    // формирование двумерного массива по правилу
    int **array_second = new int *[ARRAY_ROWS];
    for (int i = 0; i < ARRAY_ROWS; i++) {
        array_second[i] = new int [ARRAY_COLUMNS];
    }
 
    array_proc(array_first, array_second);
 
    // вывод результата
    print_arrays(array_first, array_second);
    print_min_value(array_second);
    return 0;
}
 
void input_data(int *array)
{
    for (int i = 0; i < ARRAY_SIZE; i++) {
        std::cout << "Введи элемент №" << i << ": ";
        std::cin >> array[i];
    }
}
 
void array_proc(int *array_first, int **array_second)
{
    int i, j;
    for (i = 0; i < ARRAY_ROWS; i++) {
        for (j = 0; j < ARRAY_COLUMNS; j++) {
            array_second[i][j] = array_first[ARRAY_ROWS * ARRAY_COLUMNS - i * ARRAY_COLUMNS - j - 1];
        }
    }
}
 
void print_min_value(int **array)
{
    int i, j, min = array[0][0];
    for (i = 0; i < ARRAY_ROWS; i++) {
        for (j = 0; j < ARRAY_COLUMNS; j++) {
            if (min > array[i][j]) {
                min = array[i][j];
            }
        }
    }
    std::cout << "Минимальное значение: " << min << std::endl;
}
 
void print_arrays(int *array_first, int **array_second)
{
    int i, j;
    std::cout << "Одномерный массив: ";
    for (i = 0; i < ARRAY_SIZE; i++) {
        std::cout << array_first[i] << " ";
    }
    std::cout << std::endl;
 
    std::cout << "Двумерный массив: " << std::endl;
    for (i = 0; i < ARRAY_ROWS; i++) {
        std::cout << "    ";
        for (j = 0; j < ARRAY_COLUMNS; j++) {
            std::cout << array_second[i][j] << " ";
        }
        std::cout << std::endl;
    }
    std::cout << std::endl;
}

Несколько операций с двумерными массивами

Задача: ввести двумерный массив размерностью 6х5. Рассчитать в одной функции сумму и среднее арифметическое элементов заданного столбца двумерного массива, расположенных между двумя заданными индексами. Написать функцию умножения элементов произвольной строки на квадратный корень из первого значения в данной строке. Ввод массива и исходных данных выполнить в функции ввода, вывод массива и результатов – в функции вывода.
 
Решение на C++:

#include <iostream>
#include <math.h>
 
#define ARRAY_ROWS 6
#define ARRAY_COLUMNS 5
 
int **create_array();
void input_data(int **array);
void array_sum_arif(int **array, int &sum, float &arif);
void array_proc(int **input_array, int **output_array);
void output_data(int **array, int sum, float arif);
void print_array(int **array);
 
int main()
{
    // ввод данных
    int **input_array = create_array();
    input_data(input_array);
 
    // нахождение суммы и среднего арифметического
    int sum;
    float arif;
    array_sum_arif(input_array, sum, arif);
 
    // умножение элементов строки на корень нулевого элемента
    int **output_array = create_array();
    array_proc(input_array, output_array);
 
    // вывод данных
    print_array(input_array);
    output_data(output_array, sum, arif);
    return 0;
}
 
int **create_array()
{
    int **array = new int *[ARRAY_ROWS];
 
    // выделим память для каждого элемента массива
    for (int i = 0; i < ARRAY_ROWS; i++) {
        array[i] = new int [ARRAY_COLUMNS];
    }
 
    return array;
}
 
void input_data(int **array)
{
    int i, j;
    for (i = 0; i < ARRAY_ROWS; i++) {
        for (j = 0; j < ARRAY_COLUMNS; j++) {
            std::cout << "Введи значение элемента " << i << ", " << j << ": ";
            std::cin >> array[i][j];
        }
    }
}
 
void print_array(int **array)
{
    std::cout << "Массив: " << std::endl;
 
    int i, j;
    for (i = 0; i < ARRAY_ROWS; i++) {
        std::cout << i << ": ";
        for (j = 0; j < ARRAY_COLUMNS; j++) {
            std::cout << array[i][j] << " ";
        }
        std::cout << std::endl;
    }
 
    std::cout << std::endl;
}
 
void output_data(int **array, int sum, float arif)
{
    std::cout << "Результат: " << std::endl;
    print_array(array);
    std::cout << "Сумма: " << sum << std::endl;
    std::cout << "Среднее арифметическое: " << arif << std::endl;
    std::cout << std::endl;
}
 
void array_sum_arif(int **array, int &sum, float &arif)
{
    int column;
    std::cout << "Введите столбец для суммы и среднего арифметического: ";
    std::cin >> column;
 
    int row_up;
    std::cout << "Введите верхнюю границу для суммы и среднего арифметического: ";
    std::cin >> row_up;
 
    int row_down;
    std::cout << "Введите нижнюю границу для суммы и среднего арифметического: ";
    std::cin >> row_down;
 
    sum = 0;
    for (int i = row_up; i <= row_down; i++) {
        sum += array[i][column];
    }
    arif = ((float)sum) / ((float)(row_down - row_up + 1));
}
 
void array_proc(int **input_array, int **output_array)
{
    int row;
    std::cout << "Введите строку для умножения на корень из первого элемента: ";
    std::cin >> row;
 
    int i, j;
    for (i = 0; i < ARRAY_ROWS; i++) {
        for (j = 0; j < ARRAY_COLUMNS; j++) {
            if (row == i) {
                output_array[row][j] = input_array[row][j] * sqrt(input_array[row][0]);
            } else {
                output_array[i][j] = input_array[i][j];
            }
        }
    }
}

Минимальное и максимальное значение в массиве

Попросили решить несколько задач, я решил выложить их сюда, может быть это будет полезно многим.
 
Задача: ввести два одномерных массива равной длинны, сформировать третий по правилу Сi = Ai / max(B). Для каждого массива вычислить значение минимального элемента. Вывести на экран все массивы и результат.
 
Решение на C++:

#include <iostream>
 
float array_max(float array[], int a_size);
float array_min(float array[], int a_size);
void print_result(float array[], int array_size, int num);
void input_array(float *array, int array_size, int num);
 
int main()
{
    int array_size;
    std::cout << "Введи размер массивов: ";
    std::cin >> array_size;
 
    float *array_a = new float [array_size];
    input_array(array_a, array_size, 1);
 
    float *array_b = new float [array_size];
    input_array(array_b, array_size, 2);
 
    float *array_c = new float [array_size];
    float b_max = array_max(array_b, array_size);
    for (int i = 0; i < array_size; i++) {
        array_c[i] = array_a[i] / b_max;
    }
 
    print_result(array_a, array_size, 0);
    print_result(array_b, array_size, 1);
    print_result(array_c, array_size, 2);
    return 0;
}
 
 
void input_array(float *array, int array_size, int num)
{
    for (int i = 0; i < array_size; i++) {
        std::cout << "Введи значение " << i << " для массива №" << num << ": ";
        std::cin >> array[i];
    }
}
 
float array_max(float array[], int a_size)
{
    float max = array[0];
    for (int i = 1; i < a_size; i++) {
        if (max < array[i]) {
            max = array[i];
        }
    }
    return max;
}
 
float array_min(float array[], int a_size)
{
    float min = array[0];
    for (int i = 1; i < a_size; i++) {
        if (min > array[i]) {
            min = array[i];
        }
    }
    return min;
}
 
void print_result(float array[], int array_size, int num)
{
    float min_a = array_min(array, array_size);
 
    std::cout << "Массив №" << num << "(минимальное - " << min_a << "): ";
 
    for (int i = 0; i < array_size; i++) {
        std::cout << array[i] << " ";
    }
 
    std::cout << std::endl;
}

Bonch.Docs — Конспекты университетских лекций

Создал сайт, с которого можно скачать все мои конспекты лекций университета СПб ГУТ им. проф. Бонч-Бруевича, факультета ИСиТ(группа ИСТ-23). В будущем, возможно, там появятся другие полезные файлы, например: лабораторные работы, курсовые работы и так далее.

Дизайн сделал с использованием Twitter Bootstrap, серверная часть написана на PHP с использованием паттерна MVC (в основном для повышения собственных навыков при работе с MVC), БД — MySQL. На написание ушло два полных вечера :) . В общем — тестируйте и предлагайте новые возможности для сайта.

Ссылка: http://bonch.ziggi.org/

Установка и первичная настройка Arch Linux + Xfce, часть 3, пакеты

В этой статье я напишу пакеты, которые использую в работе.

Пакет, с помощью которого GRUB сможет определять все установленные ОС при генерации конфига:

sudo pacman -S os-prober

 
Браузеры:

sudo pacman -S firefox firefox-i18n-ru chromium opera

 
Мессенджеры:

sudo pacman -S pidgin skype

 
Торрент-клиент

sudo pacman -S transmission-gtk transmission-cli

 
Графика:

sudo pacman -S gimp pinta ristretto djview4

 
Офис:

sudo pacman -S libreoffice libreoffice-ru

 
Мультимедиа:

sudo pacman -S audacity deadbeef smplayer

 
FTP-клиент:

sudo pacman -S filezilla

 
Разработка:

sudo pacman -S geany apache php mysql phpmyadmin

 
Система:

sudo pacman -S gparted unetbootin

 
Облако:

sudo pacman -S dropbox ubuntuone-client

 
Инструменты:

sudo pacman -S p7zip unrar

 
Игры:

sudo pacman -S steam mari0

 
Всё вместе:

sudo pacman -S os-prober firefox firefox-i18n-ru chromium opera pidgin skype transmission-gtk transmission-cli gimp pinta ristretto djview4 libreoffice libreoffice-ru audacity deadbeef smplayer filezilla geany apache php mysql phpmyadmin gparted unetbootin dropbox ubuntuone-client p7zip unrar steam mari0

Google Glass на подходе

Очень интересное видео о Google Glass, рекомендую посмотреть.

Подробности здесь.

Установка и первичная настройка Arch Linux + Xfce, часть 2

В этой статье я покажу как сделать работу с bash терминалом более удобной, а также, покажу как нужно правильно устанавливать yaourt.

Цвета в терминале

 
Добавим подсветку имени пользователя для терминала, для этого откроем файл ~/.bashrc

$ nano ~/.bashrc

И заменим строку

PS1='[\u@\h \W]\$ '

строкой

PS1='\[\e[0;32m\]\u\[\e[m\] \[\e[0;37m\]\w\[\e[m\] \[\e[0;32m\]\$\[\e[m\] '

 
Сделаем похожее для root пользователя:
Откроем файл ~/.bashrc

# nano ~/.bashrc

И добавим строку

PS1='\[\e[0;31m\]\u\[\e[m\] \[\e[0;37m\]\w\[\e[m\] \[\e[0;31m\]\$\[\e[m\] '

Теперь, после следующего входа в bash, будет легко понять в каком пользователе вы сейчас находитесь, так как ваш пользователь будет выделяться зелёным(32) цветом, а профиль root пользователя красным(31).

Мышь в терминале

 
Иногда приходится работать в терминале, а не его эмуляторе. И с некоторыми программами, например Midnight Commander, там будет удобнее работать с мышью. Чтобы использовать мышь в терминале достаточно установить пакет gpm.

sudo pacman -S gpm

Читать дальше

Знакомство с html5 canvas

Появилось желание взяться за изучение «убийцы Flash’а» html5, а в частности элемента canvas. Это достаточно интересная технология, позволяющая создавать различные растровые 2d изображения средствами JavaScript. Просидев несколько часов за изучением технологии и вспоминании JavaScript, я написал небольшое интерактивное «приложение», которое, в первую очередь, предназначено для обучения меня и вас. Это обычные круги и прямоугольники, которые можно двигать мышью. Для ловли событий я использую jQuery, мне он кажется наиболее удобным.

Демо
Исходник

Логика работы

 
Принцип работы прост: сначала я записываю все создаваемые объекты в общий массив объектов и отрисовываю сцену. Затем в событии, выполняемом при нажатии на сцену, я определяю тип нажатого объекта и добавляю необходимую информацию(тип, номер и смещение курсора относительно начальной точки) о нажатом объекте в массив. После этого описывается событие, которое выполняется при перемещении мыши по сцене, в котором я обновляю координаты перемещаемого объекта в общем массиве объектов. Затем просто перерисовывается вся сцена. Ну и последнее событие, выполняемое при отпускании нажатой кнопки мыши, в котором я просто очищаю массив с информацией о выбранном объекте.

Очень может быть, что я допустил некоторые архитектурные ошибки, с радостью прочитаю ваши замечания и предложения.
Читать дальше