Вы находитесь на странице: 1из 9

Application.

c
#include "Application.h"

#include <stdio.h>
#include <X11/keysym.h>

#define CELL_SIZE 80
#define HORSE_SIZE 60

#define HORSE_COLOR "green"


#define BOARD_COLOR "grey"
#define BOARD_ATTACK_COLOR "red"

Application app;

void createColors() {
Colormap colormap = DefaultColormap(app.dpy, 0);

XParseColor(app.dpy, colormap, HORSE_COLOR,


&app.horseColor);
XParseColor(app.dpy, colormap, BOARD_COLOR,
&app.boardColor);
XParseColor(app.dpy, colormap, BOARD_ATTACK_COLOR,
&app.boardAttackColor);
получить значения RGB по названию цвета.
XAllocColor(app.dpy, colormap, &app.horseColor);
XAllocColor(app.dpy, colormap, &app.boardColor);
XAllocColor(app.dpy, colormap, &app.boardAttackColor);
распределение цветовых данных в ячейках цветовой карты с помощью
функции XAllocColor

void initMainWindow() {
XSetWindowAttributes attr;
unsigned long mask;
int src;
unsigned width;
unsigned height;

app.dpy = XOpenDisplay(NULL);
взаимодействие Х-клиента и Х-сервера
app.root = DefaultRootWindow(app.dpy);
родительское окно
src = DefaultScreen(app.dpy);
информация о номере родительского окна
app.depth = DefaultDepth(app.dpy, src);
оценка цветовых возможностей экрана

// calculate required window size


width = CELL_SIZE * 8;
height = CELL_SIZE * 8;

// create window
mask = CWOverrideRedirect;
attr.override_redirect = False;
app.window = XCreateWindow(app.dpy, app.root, 0, 0, width,
height, 1, app.depth,
InputOutput, CopyFromParent, mask, &attr);

XSelectInput(app.dpy, app.window, KeyPressMask);


XMapWindow(app.dpy, app.window);
}

void fillAppData() { заполнение данных приложения


app.cellSize = CELL_SIZE;
app.horseSize = HORSE_SIZE;
app.offset = (CELL_SIZE - HORSE_SIZE) / 2;
}

void appInit() { инициализация приложения


fillAppData();
initMainWindow();
createColors();
boardInit(&app.board);
XMapSubwindows(app.dpy, app.window);
}

void appDeinit() { деинициализация приложения


boardDeinit(&app.board);
XDestroyWindow(app.dpy, app.window);
XCloseDisplay(app.dpy);
}

void appRun() {
// selected horse
Horse* pSelectedHorse = NULL;

XEvent event;
int done = 0;

// get key code for Esc


unsigned keyEsc = XKeysymToKeycode(app.dpy, XK_Escape);

while (!done) {
XNextEvent(app.dpy, &event);

switch (event.type) {

case ButtonPress:
pSelectedHorse = boardPickHorse(&app.board,
event.xbutton.x, event.xbutton.y);
// нажмите кнопку на пустой ячейке платы
if (!pSelectedHorse) {
done = 1;
}
break;

case MotionNotify:
// move horse
// Я вычитаю половину размера лошади так что
указатель мыши находится в центре
if (pSelectedHorse) {
horseSetPosition(pSelectedHorse, event.xbutton.x
- app.horseSize / 2, event.xbutton.y - app.horseSize / 2);
}
break;

case ButtonRelease:
// put horse
if (pSelectedHorse) {
boardPutHorse(&app.board, pSelectedHorse,
event.xbutton.x, event.xbutton.y);
boardUpdate(&app.board);
pSelectedHorse = NULL;
}
break;

case KeyPress:
boardSetDefaultConfiguration(&app.board);
boardUpdate(&app.board);
break;

default:
break;
}

Board.c
#include "Board.h"
#include "Application.h"

#include <stdlib.h>

extern Application app;

int defaultHorsePositions[12][2] = {
{5, 1},
{1, 2},
{2, 2},
{4, 2},
{5, 2},
{2, 3},
{5, 4},
{2, 5},
{3, 5},
{5, 5},
{6, 5},
{2, 6},
};

void boardInit(Board* board) {


XSetWindowAttributes attr;
unsigned long mask;

// создание ячеек для windows


board->cells = malloc(sizeof(Window*) * 8);
for (int i = 0; i < 8; ++i) {
board->cells[i] = malloc(sizeof(Window) * 8);
}

// установить атрибуты окна


mask = CWOverrideRedirect;
attr.override_redirect = False;

// создание окна для доски


board->window = XCreateWindow(app.dpy, app.window, 0, 0, 8 *
app.cellSize, 8 * app.cellSize,
1, app.depth, InputOutput, CopyFromParent, mask, &attr);
XSelectInput(app.dpy, board->window, ButtonMotionMask |
ButtonPressMask | ButtonReleaseMask);

// создание окон для ячеек


for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 8; ++j) {
board->cells[i][j] = XCreateWindow(app.dpy, board-
>window, app.cellSize*j, app.cellSize*i,
app.cellSize, app.cellSize, 1, app.depth,
InputOutput, CopyFromParent, mask, &attr);
}
}

// инициализация лошадей
for (int i = 0; i < 12; ++i) {
horseInit(&board->horses[i], board);
}

XMapSubwindows(app.dpy, board->window);

boardSetDefaultConfiguration(board);
boardUpdate(board);
}
void boardDeinit(Board* board) {
// free cell windows
for (int i = 0; i <8; ++i) {
for (int j = 0; j < 8; ++j) {
XDestroyWindow(app.dpy, board->cells[i][j]);
}
free(board->cells[i]);
}
free(board->cells);

// deinit horses
for (int i = 0; i < 12; ++i) {
horseDeinit(&board->horses[i]);

// destroy board window


XDestroyWindow(app.dpy, board->window);
}

// указывается ячейка под атакой


int boardCellUnderAttack(Board* board, int row, int col) {
for (int i = 0; i < 12; ++i) {
if (horseIsCoordUnderAttack(&board->horses[i], row,
col)) {
return 1;
}
}
return 0;
}

void boardUpdate(Board* board) {


// очистить все ячейки
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 8; ++j) {
if (boardCellUnderAttack(board, j, i)) {
// ячейка находится под атакой
XSetWindowBackground(app.dpy, board-
>cells[i][j], app.boardAttackColor.pixel);
} else {
// ячейка не подвергается нападению
XSetWindowBackground(app.dpy, board-
>cells[i][j], app.boardColor.pixel);
}
// цвет окна обновления
XClearWindow(app.dpy, board->cells[i][j]);
}
}
}

void boardSetDefaultConfiguration(Board* board) {


for (int i = 0; i < 12; ++i) {
horseSetCoords(&board->horses[i],
defaultHorsePositions[i][0], defaultHorsePositions[i][1]);
}
}

Horse* boardPickHorse(Board* board, int x, int y) {


// найдете строку и столбец
int row = x / app.cellSize;
int col = y / app.cellSize;

// find horse
for (int i = 0; i < 12; ++i) {
if (board->horses[i].col == col && board->horses[i].row
== row) {
return &board->horses[i];
}
}

// return null if horse is not found


return NULL;
}

void boardPutHorse(Board* board, Horse* horse, int x, int y) {


// find row and col
int row = x / app.cellSize;
int col = y / app.cellSize;

// если координата не свободна положите предыдущие конные


координаты в ряд и col
for (int i = 0; i < 12; ++i) {
if (board->horses[i].col == col && board->horses[i].row
== row) {
row = horse->row;
col = horse->col;
}
}

horseSetCoords(horse, row, col);


}

Horse.c
#include <stdlib.h>

#include "Horse.h"
#include "Application.h"
#include "Board.h"

extern Application app;

void horseInit(Horse* horse, Board* board) {


XSetWindowAttributes attr;
unsigned long mask;

// установить атрибуты окна


attr.override_redirect = False;
attr.background_pixel = app.horseColor.pixel;
mask = CWOverrideRedirect | CWBackPixel;

// создать окно
horse->window = XCreateWindow(app.dpy, board->window, 0, 0,
app.horseSize, app.horseSize,
1, app.depth, InputOutput, CopyFromParent, mask, &attr);

// установите значения по умолчанию для row и col


horse->row = 0;
horse->col = 0;
}

void horseDeinit(Horse* horse) {


XDestroyWindow(app.dpy, horse->window);
}

void horseSetCoords(Horse* horse, int row, int col) {


horse->row = row;
horse->col = col;
horseSetPosition(horse, app.offset + app.cellSize * row,
app.offset + app.cellSize * col);
}

void horseSetPosition(Horse* horse, int x, int y) {


XMoveResizeWindow(app.dpy, horse->window, x, y,
app.horseSize, app.horseSize);
}

int horseIsCoordUnderAttack(Horse* horse, int row, int col) {


// найти расстояние от лошади до указанной координаты для x
и y
int dx = abs(horse->row - row);
int dy = abs(horse->col - col);

if ((dx == 1 && dy == 2) || (dx == 2 && dy == 1)) {


return 1;
}

return 0;
}

Application.h
#ifndef APPLICATION_H
#define APPLICATION_H
#include "Board.h"

#include <X11/Xlib.h>

typedef struct {
Display *dpy;
Window window;
Window root;
unsigned depth;

unsigned cellSize;
unsigned horseSize;
unsigned offset; // смещение в ячейке для лошади

XColor boardColor; // обычный цвет доски


XColor boardAttackColor; // board color when under attack
XColor horseColor;

Board board;

} Application;

void appInit();
void appDeinit();
void appRun();

#endif

Board.h
#ifndef MATRIX_H
#define MATRIX_H

#include <X11/Xlib.h>

#include "Horse.h"

typedef struct Board {


Window window;
Window **cells;
Horse horses[12];
} Board;

void boardInit(Board* board);


void boardDeinit(Board* board);

void boardUpdate(Board* board); // обновляет клетки доски цвета


пустоты
void boardSetDefaultConfiguration(Board* board);

// возвращает указатель на лошадь или null, если в этой позиции


нет лошади
Horse* boardPickHorse(Board* board, int x, int y);
// ставит лошадь, если координата свободна, в противном случае
ставит лошадь на предыдущие позиции
void boardPutHorse(Board* board, Horse* horse, int x, int y);

#endif

Horse.h
#ifndef HORSE_H
#define HORSE_H

#include <X11/Xlib.h>

struct Board;

typedef struct {
Window window;
// координаты лошади на доске
int row;
int col;
} Horse ;

void horseInit(Horse* horse, struct Board* board);


void horseDeinit(Horse* horse);

// установить положение лошади на основе координат на доске


void horseSetCoords(Horse* horse, int row, int col);
// установить положение лошади относительно окна доски
void horseSetPosition(Horse* horse, int x, int y);

int horseIsCoordUnderAttack(Horse* horse, int row, int col);

#endif

Вам также может понравиться