File desk.c added (mode: 100644) (index 0000000..b1ea7e2) |
|
1 |
|
#include "desk.h" |
|
2 |
|
|
|
3 |
|
Cell new_cell(int8_t y, int8_t x) |
|
4 |
|
{ |
|
5 |
|
Cell c; |
|
6 |
|
c.y = y; |
|
7 |
|
c.x = x; |
|
8 |
|
return c; |
|
9 |
|
} |
|
10 |
|
|
|
11 |
|
void display_cell(Cell cell) |
|
12 |
|
{ |
|
13 |
|
printf("y:%d, x:%d", cell.y, cell.x); |
|
14 |
|
} |
|
15 |
|
|
|
16 |
|
Desk *create_desk() |
|
17 |
|
{ |
|
18 |
|
Desk *d; |
|
19 |
|
int y=0,x; |
|
20 |
|
d = malloc(sizeof(Desk)); |
|
21 |
|
for(;y<CHESS_ROWS;y++) |
|
22 |
|
for(x=0;x<CHESS_ROWS;x++) |
|
23 |
|
d->desk[y][x] = NonChecked; |
|
24 |
|
/* becose 0, 0 -- start point */ |
|
25 |
|
d->desk[0][0] = Checked; |
|
26 |
|
return d; |
|
27 |
|
} |
|
28 |
|
|
|
29 |
|
void display_desk(Desk *d) |
|
30 |
|
{ |
|
31 |
|
int y=0, x; |
|
32 |
|
for(;y<CHESS_ROWS;y++) { |
|
33 |
|
for(x=0;x<CHESS_ROWS;x++) { |
|
34 |
|
switch(d->desk[y][x]) { |
|
35 |
|
case NonChecked: |
|
36 |
|
printf("."); |
|
37 |
|
break; |
|
38 |
|
case Checked: |
|
39 |
|
printf("X"); |
|
40 |
|
break; |
|
41 |
|
} |
|
42 |
|
if(x+1<CHESS_ROWS) |
|
43 |
|
printf(" "); |
|
44 |
|
} |
|
45 |
|
printf("\n"); |
|
46 |
|
} |
|
47 |
|
printf("\n"); |
|
48 |
|
} |
|
49 |
|
|
|
50 |
|
int desk_is_full(Desk *d) |
|
51 |
|
{ |
|
52 |
|
int y = 0, x; |
|
53 |
|
for(;y<CHESS_ROWS;y++) |
|
54 |
|
for(x=0;x<CHESS_ROWS;x++) |
|
55 |
|
if(d->desk[y][x] == NonChecked) |
|
56 |
|
return FALSE; |
|
57 |
|
return TRUE; |
|
58 |
|
} |
|
59 |
|
|
|
60 |
|
|
|
61 |
|
void check_on_desk(Desk *d, Cell c) |
|
62 |
|
{ |
|
63 |
|
d->desk[c.y][c.x] = Checked; |
|
64 |
|
} |
|
65 |
|
|
|
66 |
|
void uncheck_from_desk(Desk *d, Cell c) |
|
67 |
|
{ |
|
68 |
|
d->desk[c.y][c.x] = NonChecked; |
|
69 |
|
} |
|
70 |
|
|
|
71 |
|
CellPassed check_desk_occupation(Desk *d, Cell cell) |
|
72 |
|
{ |
|
73 |
|
if(d->desk[cell.y][cell.x] == Checked) |
|
74 |
|
return Checked; |
|
75 |
|
else |
|
76 |
|
return NonChecked; |
|
77 |
|
} |
|
78 |
|
|
|
79 |
|
int equals_cell(Cell f_cell, Cell s_cell) |
|
80 |
|
{ |
|
81 |
|
if(f_cell.x == s_cell.x && f_cell.y == s_cell.y) |
|
82 |
|
return TRUE; |
|
83 |
|
return FALSE; |
|
84 |
|
} |
|
85 |
|
|
|
86 |
|
Desk *debug_desk() |
|
87 |
|
{ |
|
88 |
|
Desk *d; |
|
89 |
|
int y=0,x; |
|
90 |
|
d = malloc(sizeof(Desk)); |
|
91 |
|
for(;y<CHESS_ROWS;y++) |
|
92 |
|
for(x=0;x<CHESS_ROWS;x++) |
|
93 |
|
d->desk[y][x] = Checked; |
|
94 |
|
return d; |
|
95 |
|
|
|
96 |
|
} |
File desk.h added (mode: 100644) (index 0000000..ec94b56) |
|
1 |
|
#pragma once |
|
2 |
|
#include <stdio.h> |
|
3 |
|
#include <stdlib.h> |
|
4 |
|
#include <stdint.h> |
|
5 |
|
|
|
6 |
|
#define TRUE 1 |
|
7 |
|
#define FALSE 0 |
|
8 |
|
#define CHESS_ROWS 5 |
|
9 |
|
#define FIRST_POINT 0, 0 |
|
10 |
|
#define ROUTES_NUM 8 |
|
11 |
|
|
|
12 |
|
typedef struct CellStruct { |
|
13 |
|
int8_t y, |
|
14 |
|
x; |
|
15 |
|
} Cell; |
|
16 |
|
|
|
17 |
|
typedef enum CellPassedEnum { |
|
18 |
|
NonChecked, Checked |
|
19 |
|
} CellPassed; |
|
20 |
|
|
|
21 |
|
typedef struct DeskStruct { |
|
22 |
|
CellPassed desk[CHESS_ROWS][CHESS_ROWS]; |
|
23 |
|
} Desk; |
|
24 |
|
|
|
25 |
|
/* desk */ |
|
26 |
|
Desk *create_desk(); |
|
27 |
|
void display_desk(Desk *d); |
|
28 |
|
CellPassed check_desk_occupation(Desk *d, Cell cell); |
|
29 |
|
|
|
30 |
|
void check_on_desk(Desk *d, Cell c); |
|
31 |
|
void uncheck_from_desk(Desk *d, Cell c); |
|
32 |
|
int desk_is_full(Desk *d); |
|
33 |
|
Desk *debug_desk(); |
|
34 |
|
|
|
35 |
|
/* cell */ |
|
36 |
|
Cell new_cell(int8_t y, int8_t x); |
|
37 |
|
void display_cell(Cell cell); |
|
38 |
|
int equals_cell(Cell f_cell, Cell s_cell); |
File history.c added (mode: 100644) (index 0000000..6816e7d) |
|
1 |
|
#include "history.h" |
|
2 |
|
|
|
3 |
|
History *create_history() |
|
4 |
|
{ |
|
5 |
|
History *h; |
|
6 |
|
h = malloc(sizeof(History)); |
|
7 |
|
h->cell = new_cell(FIRST_POINT); |
|
8 |
|
h->trys = 0; |
|
9 |
|
h->prev = NULL; |
|
10 |
|
h->next = NULL; |
|
11 |
|
return h; |
|
12 |
|
} |
|
13 |
|
|
|
14 |
|
void display_history(History *h) |
|
15 |
|
{ |
|
16 |
|
int i = 0; |
|
17 |
|
hist_to_start(&h); |
|
18 |
|
for(;h;i++) { |
|
19 |
|
printf("%d:\ncell:", i); |
|
20 |
|
display_cell(h->cell); |
|
21 |
|
printf("\ntrys:%d\nprev:%ld\nnext:%ld\n", |
|
22 |
|
h->trys, (long)(h->prev), (long)(h->next) |
|
23 |
|
); |
|
24 |
|
h = h->next; |
|
25 |
|
} |
|
26 |
|
} |
|
27 |
|
|
|
28 |
|
void draw_history(History *h) |
|
29 |
|
{ |
|
30 |
|
Desk *d = create_desk(); |
|
31 |
|
hist_to_start(&h); |
|
32 |
|
for(;h->next;h=h->next) { |
|
33 |
|
check_on_desk(d, h->cell); |
|
34 |
|
display_desk(d); |
|
35 |
|
} |
|
36 |
|
} |
|
37 |
|
|
|
38 |
|
void hist_to_end(History **h) |
|
39 |
|
{ |
|
40 |
|
for(;(*h)->next;*h=(*h)->next); |
|
41 |
|
} |
|
42 |
|
|
|
43 |
|
void hist_to_start(History **h) |
|
44 |
|
{ |
|
45 |
|
for(;(*h)->prev;*h=(*h)->prev); |
|
46 |
|
} |
|
47 |
|
|
|
48 |
|
void add_to_history(History **h) |
|
49 |
|
{ |
|
50 |
|
History *t = *h; |
|
51 |
|
hist_to_end(&t); |
|
52 |
|
t->next = create_history(); |
|
53 |
|
t->next->prev = t; |
|
54 |
|
*h = t->next; |
|
55 |
|
} |
|
56 |
|
|
|
57 |
|
void add_cell_to_history(History **h, Cell cell) |
|
58 |
|
{ |
|
59 |
|
add_to_history(h); |
|
60 |
|
(*h)->cell = cell; |
|
61 |
|
} |
|
62 |
|
|
|
63 |
|
void remove_from_history(History **h) |
|
64 |
|
{ |
|
65 |
|
History *t; |
|
66 |
|
hist_to_end(h); |
|
67 |
|
t = *h; |
|
68 |
|
if(!(t->prev)) { |
|
69 |
|
printf("last history level destroyed\n"); |
|
70 |
|
exit(5); |
|
71 |
|
} |
|
72 |
|
t = t->prev; |
|
73 |
|
free(t->next); |
|
74 |
|
t->next = NULL; |
|
75 |
|
*h = t; |
|
76 |
|
} |
|
77 |
|
|
|
78 |
|
void clean_history(History *h) |
|
79 |
|
{ |
|
80 |
|
hist_to_end(&h); |
|
81 |
|
for(;h->prev;) { |
|
82 |
|
h = h->prev; |
|
83 |
|
free(h->next); |
|
84 |
|
} |
|
85 |
|
free(h); |
|
86 |
|
} |
File history.h added (mode: 100644) (index 0000000..3819988) |
|
1 |
|
#pragma once |
|
2 |
|
#include "desk.h" |
|
3 |
|
|
|
4 |
|
typedef struct HistoryStruct { |
|
5 |
|
Cell cell; |
|
6 |
|
int8_t trys; |
|
7 |
|
struct HistoryStruct *prev, |
|
8 |
|
*next; |
|
9 |
|
} History; |
|
10 |
|
|
|
11 |
|
History *create_history(); |
|
12 |
|
void draw_history(History *h); |
|
13 |
|
void hist_to_start(History **h); |
|
14 |
|
void hist_to_end(History **h); |
|
15 |
|
|
|
16 |
|
void add_to_history(History **h); |
|
17 |
|
void add_cell_to_history(History **h, Cell cell); |
|
18 |
|
void remove_from_history(History **h); |
|
19 |
|
|
|
20 |
|
void display_history(History *h); |
|
21 |
|
void clean_history(History *h); |
File horse.c added (mode: 100644) (index 0000000..be0866a) |
|
1 |
|
#include "horse.h" |
|
2 |
|
|
|
3 |
|
int handling_cell(Cell cell); |
|
4 |
|
int handling_coord_num(int num); |
|
5 |
|
int history_to_cell(History *history, Cell *cell); |
|
6 |
|
|
|
7 |
|
int handling_history_to_new_cell(Desk *d, History *hist, Cell *ret_cell) |
|
8 |
|
{ |
|
9 |
|
int e; |
|
10 |
|
Cell n_cell; |
|
11 |
|
hist_to_end(&hist); |
|
12 |
|
for(;;) { |
|
13 |
|
if(hist->trys>=ROUTES_NUM) |
|
14 |
|
return NOWAY; |
|
15 |
|
e = history_to_cell(hist, &n_cell); |
|
16 |
|
hist->trys++; |
|
17 |
|
|
|
18 |
|
/* handling errors */ |
|
19 |
|
e = handling_cell(n_cell); |
|
20 |
|
if(e == UnCorrectCoord) |
|
21 |
|
continue; |
|
22 |
|
e = check_desk_occupation(d, n_cell); |
|
23 |
|
if(e == Checked) |
|
24 |
|
continue; |
|
25 |
|
|
|
26 |
|
*ret_cell = n_cell; |
|
27 |
|
return EXIST_WAY; |
|
28 |
|
} |
|
29 |
|
} |
|
30 |
|
|
|
31 |
|
int handling_cell(Cell cell) |
|
32 |
|
{ |
|
33 |
|
int e; |
|
34 |
|
e = handling_coord_num(cell.y); |
|
35 |
|
if(e) |
|
36 |
|
return UnCorrectCoord; |
|
37 |
|
e = handling_coord_num(cell.x); |
|
38 |
|
if(e) |
|
39 |
|
return UnCorrectCoord; |
|
40 |
|
return CorrectCoord; |
|
41 |
|
} |
|
42 |
|
|
|
43 |
|
int handling_coord_num(int num) |
|
44 |
|
{ |
|
45 |
|
if(num<0 || num>=CHESS_ROWS) |
|
46 |
|
return UnCorrectCoord; |
|
47 |
|
return CorrectCoord; |
|
48 |
|
} |
|
49 |
|
|
|
50 |
|
int history_to_cell(History *history, Cell *cell) |
|
51 |
|
{ |
|
52 |
|
int y = history->cell.y, x = history->cell.x; |
|
53 |
|
Cell n_cell; |
|
54 |
|
switch(history->trys) { |
|
55 |
|
case 0: |
|
56 |
|
n_cell = new_cell(2+y, 1+x); |
|
57 |
|
break; |
|
58 |
|
case 1: |
|
59 |
|
n_cell = new_cell(-2+y, 1+x); |
|
60 |
|
break; |
|
61 |
|
case 2: |
|
62 |
|
n_cell = new_cell(2+y, -1+x); |
|
63 |
|
break; |
|
64 |
|
case 3: |
|
65 |
|
n_cell = new_cell(-2+y, -1+x); |
|
66 |
|
break; |
|
67 |
|
case 4: |
|
68 |
|
n_cell = new_cell(1+y, 2+x); |
|
69 |
|
break; |
|
70 |
|
case 5: |
|
71 |
|
n_cell = new_cell(-1+y, 2+x); |
|
72 |
|
break; |
|
73 |
|
case 6: |
|
74 |
|
n_cell = new_cell(1+y, -2+x); |
|
75 |
|
break; |
|
76 |
|
case 7: |
|
77 |
|
n_cell = new_cell(-1+y, -2+x); |
|
78 |
|
break; |
|
79 |
|
default: |
|
80 |
|
printf("error: number trying bigger then number routies\n"); |
|
81 |
|
exit(2); |
|
82 |
|
} |
|
83 |
|
*cell = n_cell; |
|
84 |
|
return ExistTrys; |
|
85 |
|
} |
|
86 |
|
|
|
87 |
|
void display_horse(History *hist, Desk *d) |
|
88 |
|
{ |
|
89 |
|
int y=0, x; |
|
90 |
|
hist_to_end(&hist); |
|
91 |
|
for(;y<CHESS_ROWS;y++) { |
|
92 |
|
for(x=0;x<CHESS_ROWS;x++) { |
|
93 |
|
if(y == hist->cell.y && x == hist->cell.x) { |
|
94 |
|
printf("O"); |
|
95 |
|
} |
|
96 |
|
else { |
|
97 |
|
switch(d->desk[y][x]) { |
|
98 |
|
case NonChecked: |
|
99 |
|
printf("."); |
|
100 |
|
break; |
|
101 |
|
case Checked: |
|
102 |
|
printf("X"); |
|
103 |
|
break; |
|
104 |
|
} |
|
105 |
|
} |
|
106 |
|
if(x+1<CHESS_ROWS) |
|
107 |
|
printf(" "); |
|
108 |
|
} |
|
109 |
|
printf("\n"); |
|
110 |
|
} |
|
111 |
|
printf("\n"); |
|
112 |
|
} |
|
113 |
|
|
|
114 |
|
int closed_optimization(Desk *d, History *h) |
|
115 |
|
{ |
|
116 |
|
History *n_hist = create_history(); |
|
117 |
|
int y = 0, x, i, e, way; |
|
118 |
|
Cell n_cell; |
|
119 |
|
hist_to_end(&h); |
|
120 |
|
for(;y<CHESS_ROWS;y++) { |
|
121 |
|
for(x=0;x<CHESS_ROWS;x++) { |
|
122 |
|
if(d->desk[y][x] == NonChecked) { |
|
123 |
|
n_hist->cell = new_cell(y, x); |
|
124 |
|
n_hist->trys = 0; |
|
125 |
|
way = NOWAY; |
|
126 |
|
for(i=0;i<ROUTES_NUM;i++,n_hist->trys++) { |
|
127 |
|
history_to_cell(n_hist, &n_cell); |
|
128 |
|
|
|
129 |
|
e = handling_cell(n_cell); |
|
130 |
|
if(e == UnCorrectCoord) |
|
131 |
|
continue; |
|
132 |
|
e = check_desk_occupation(d, n_cell); |
|
133 |
|
if(e == NonChecked) { |
|
134 |
|
way = EXIST_WAY; |
|
135 |
|
break; |
|
136 |
|
} |
|
137 |
|
if(equals_cell(n_cell, h->cell)) { |
|
138 |
|
way = EXIST_WAY; |
|
139 |
|
break; |
|
140 |
|
} |
|
141 |
|
} |
|
142 |
|
if(way == NOWAY) |
|
143 |
|
return CLOSED_CELL; |
|
144 |
|
} |
|
145 |
|
} |
|
146 |
|
} |
|
147 |
|
return UNCLOSED_CELLS; |
|
148 |
|
} |
|
149 |
|
|
File main.c added (mode: 100644) (index 0000000..1753b92) |
|
1 |
|
#include "horse.h" |
|
2 |
|
|
|
3 |
|
void return_back(Desk *d, History **h); |
|
4 |
|
void mark_cell(Desk *d, History **h, Cell cell); |
|
5 |
|
void success_full_desk(Desk *d, History *h, uint64_t iter); |
|
6 |
|
void exit_chess(Desk *d, History *h, int exit_code); |
|
7 |
|
|
|
8 |
|
int main() |
|
9 |
|
{ |
|
10 |
|
History *hist = create_history(); |
|
11 |
|
Desk *desk = create_desk(); |
|
12 |
|
Cell n_cell; |
|
13 |
|
uint64_t iter = 0; |
|
14 |
|
int new_cell_err, full_desk; |
|
15 |
|
/* int closed_cell; */ |
|
16 |
|
|
|
17 |
|
/* main loop */ |
|
18 |
|
while(TRUE) { |
|
19 |
|
/* debug */ |
|
20 |
|
/* display_horse(hist, desk); */ |
|
21 |
|
|
|
22 |
|
new_cell_err = handling_history_to_new_cell(desk, hist, &n_cell); |
|
23 |
|
iter++; |
|
24 |
|
|
|
25 |
|
/* optimization */ |
|
26 |
|
/* closed_cell = closed_optimization(desk, hist); |
|
27 |
|
if(closed_cell == CLOSED_CELL) { |
|
28 |
|
return_back(desk, &hist); |
|
29 |
|
} else */ |
|
30 |
|
/* handling */ |
|
31 |
|
switch(new_cell_err) { |
|
32 |
|
case EXIST_WAY: |
|
33 |
|
mark_cell(desk, &hist, n_cell); |
|
34 |
|
break; |
|
35 |
|
case NOWAY: |
|
36 |
|
full_desk = desk_is_full(desk); |
|
37 |
|
if(full_desk) { |
|
38 |
|
success_full_desk(desk, hist, iter); |
|
39 |
|
} |
|
40 |
|
return_back(desk, &hist); |
|
41 |
|
break; |
|
42 |
|
} |
|
43 |
|
} |
|
44 |
|
|
|
45 |
|
return EXIT_SUCCESS; |
|
46 |
|
} |
|
47 |
|
|
|
48 |
|
void return_back(Desk *d, History **h) |
|
49 |
|
{ |
|
50 |
|
Cell cell; |
|
51 |
|
CellPassed cell_p; |
|
52 |
|
hist_to_end(h); |
|
53 |
|
cell = (*h)->cell; |
|
54 |
|
cell_p = check_desk_occupation(d, cell); |
|
55 |
|
if(cell_p == NonChecked) { |
|
56 |
|
printf("error: returning back cell is unchecked"); |
|
57 |
|
exit(6); |
|
58 |
|
} |
|
59 |
|
|
|
60 |
|
remove_from_history(h); |
|
61 |
|
uncheck_from_desk(d, cell); |
|
62 |
|
} |
|
63 |
|
|
|
64 |
|
void mark_cell(Desk *d, History **h, Cell cell) |
|
65 |
|
{ |
|
66 |
|
CellPassed cell_p = check_desk_occupation(d, cell); |
|
67 |
|
hist_to_end(h); |
|
68 |
|
if(cell_p == Checked) { |
|
69 |
|
printf("error: marking cell is checked"); |
|
70 |
|
exit(8); |
|
71 |
|
} |
|
72 |
|
|
|
73 |
|
add_cell_to_history(h, cell); |
|
74 |
|
check_on_desk(d, cell); |
|
75 |
|
} |
|
76 |
|
|
|
77 |
|
void success_full_desk(Desk *d, History *h, uint64_t iter) |
|
78 |
|
{ |
|
79 |
|
printf("iteration: %lu\n", iter); |
|
80 |
|
display_desk(d); |
|
81 |
|
display_history(h); |
|
82 |
|
draw_history(h); |
|
83 |
|
|
|
84 |
|
exit_chess(d, h, EXIT_SUCCESS); |
|
85 |
|
} |
|
86 |
|
|
|
87 |
|
void exit_chess(Desk *d, History *h, int exit_code) |
|
88 |
|
{ |
|
89 |
|
clean_history(h); |
|
90 |
|
free(d); |
|
91 |
|
|
|
92 |
|
exit(exit_code); |
|
93 |
|
} |