main.cpp 

001      // Author Malte Pagel
002      
003      
004      #include <cstdlib>
005      #include <cstdio>
006      #include <iostream>
007      #include <stdio.h>
008      #include <time.h>
009      
010      
using namespace std;
011      
012      
#include "KnightPosition.h"
013      
014      
015      #define ASK_USER 1
016      
017      #define COL_MIN 5
018      #define COL_MAX 16
019      #define DEFAULT_COLS 8
020      
021      
022      
void ask_user(void);
023      
024      
char letters[] = { 'A''B''C''D''E''F''G''H''I''J''K''L''M''N''O''P' };
025      
026      
int cols;
027      
int column;
028      
int row;
029      
030      
031      
void ask_user () {
032          
int i;
033          
char c;
034      
035          
cout << endl;
036      
037          
cout << "How many rows resp. columns (" << COL_MIN << " - " << COL_MAX << ")?" << endl;
038          
scanf("%d", &i);
039          if ( 
COL_MIN || COL_MAX ) {
040              
cout << "Invalid value! Taking " << DEFAULT_COLS << endl;
041              
cols DEFAULT_COLS;
042          }
043          else
044              
cols i;
045      
046      
047          
cout << "Start in which column ('A' to '" << (letters[cols 1]) << "')?" << endl;
048          
scanf("%s", &c);
049          
= (int) 97;
050          if ( 
>= && cols )
051              
column i;
052          else {
053              
= (int) 65;
054              if ( 
>= && cols )
055                  
column i;
056              else {
057                  
column rand() % cols;
058                  
cout << "Invalid value! Taking " << letters[column] << endl;
059              }
060          }
061      
062      
063          
cout << "Start in which row (1 to " << cols << ")?" << endl;
064          
scanf("%d", &i);
065          if ( 
&& <= cols )
066              
row 1;
067          else {
068              
row rand() % cols;
069              
cout << "Invalid value! Taking " << (row 1) << endl;
070          }
071      }
072      
073      
074      
int main (int argcchar** argv) {
075      
076          
KnightPosition start_position;
077          
KnightPosition *** complete_collection;
078          
int ij;
079      
080          
time_t t;
081          
time(&t);
082          
srand((unsigned intt);
083      
084          if ( 
ASK_USER )
085              
ask_user();
086          else {
087              
cols DEFAULT_COLS;
088              
column rand() % cols;
089              
row rand() % cols;
090          }
091      
092          
093          
complete_collection = new KnightPosition**[cols];
094          for ( 
0colsi++ )
095              
complete_collection[i] = new KnightPosition*[cols];
096          for ( 
0colsi++ )
097              for ( 
0colsj++ )
098                  
complete_collection[i][j] = NULL;
099      
100          
101          
start_position = new KnightPosition(columnrowcolscomplete_collection);
102      
103          
104          
delete[](complete_collection);
105      
106      
107          
108          
start_position->set_knight_and_start_search(NULL);
109      
110      
111          
112          
int ** show_collection = new int*[cols];
113          for ( 
0colsi++ ) {
114              
show_collection[i] = new int[cols];
115              for ( 
0colsj++ )
116                  
show_collection[i][j] = 0;
117          }
118          
0;
119          
KnightPosition position start_position;
120          
KnightPosition position_to_delete;
121          do {
122              
show_collection[cols position->row 1][position->column] = ++i;
123              
position_to_delete position;
124              if ( 
position->next_position )
125                  
position position->next_position;
126              
delete(position_to_delete);
127          }
128          while ( 
position->next_position );
129          
delete(position);
130          
show_collection[cols position->row 1][position->column] = ++i;
131      
132      
133          
134          
cout << endl;
135          for ( 
0colsi++ ) {
136              
printf("%2d", (cols i));
137              
cout << " |";
138              for ( 
0colsj++ )
139                  
printf("%5d"show_collection[i][j]);
140              
cout << endl;
141          }
142          
cout << "     ";
143          for ( 
0colsi++ )
144              
cout << "-----";
145          
cout << endl;
146          
printf("%4s"" ");
147          for ( 
0colsi++ )
148              
printf("%5c"letters[i]);
149          
cout << endl;
150          
151          
152          
153      
#ifdef _WIN32
154          
char c 'n';
155          while ( 
!= 'y' ) {
156              
cout << "Quit application [y/n]?" << endl;
157              
scanf("%s", &c);
158          }
159      
#endif
160      
161      
162          
return 0;
163      }
164       



 KnightPosition.h 

01      // File: KnightPosition.h
02      
03      
04      
05      #ifndef KNIGHTPOSITION_H
06      #define        KNIGHTPOSITION_H
07      
08      #include <iostream>
09      #include <cmath>
10      #include <cstdlib>
11      
12      
using namespace std;
13      
14      
15      
16      
#define MEMORY_LIMIT 4096
17      
18      
19      
class KnightPosition {
20              
21      public:
22              
KnightPosition(intintintKnightPosition***);
23              
virtual ~KnightPosition();
24              
25              
26              static 
int knight_count;
27              static 
int knight_number;
28              static 
long memory_count;
29              
30              
31              
int has_knight;
32              
int columnrow;
33              
int center_distance;
34              
35              
36              
KnightPosition next_position;
37              
38              
39              
void set_knight_and_start_search(KnightPosition*);
40              
int get_num_possibilities(void);
41              
void another_try_from_above(void);
42              
43      private:
44              static 
char letters[];
45              
46              
47              static 
int cols;
48              
49              
50              static 
int reachable_positions_offset_set;
51              
52              
53              
KnightPosition previous_position;
54              
55              
56              
struct reachable_position_pointer {
57                      
KnightPosition possible_position;
58                      
int heuristic;
59                      
struct reachable_position_pointer next;
60                      
struct reachable_position_pointer basic_next;
61              };
62              
struct reachable_position_pointer first_collected_position;
63              
struct reachable_position_pointer last_collected_position;
64              
65              
struct reachable_position_pointer first_position_to_try;
66              
struct reachable_position_pointer last_position_to_try;
67              
68              
69              
int lower_or_equalreachable_positions_offset;
70              
71              
72              
void fill_reachable_positions(KnightPosition***);
73              
void add_to_reachable_positions(KnightPosition*);
74              
void order_reachable_positions(void);
75              
void do_search(void);
76              
void go_back(void);
77      };
78      
79      
#endif        
80       



 KnightPosition.cpp 

001      // File: KnightPosition.cpp
002      
003      
004      
005      #include "KnightPosition.h"
006      
007      
008      
int KnightPosition::knight_count 0;
009      
int KnightPosition::knight_number 0;
010      
int KnightPosition::cols 0;
011      
long KnightPosition::memory_count 0;
012      
char KnightPosition::letters[] = { 'A''B''C''D''E''F''G''H''I''J''K''L''M''N''O''P' };
013      
int KnightPosition::reachable_positions_offset_set 0;
014      
015      
016      
KnightPosition::KnightPosition(int columnint rowint num_colsKnightPosition*** collection) {
017              
018          
collection[column][row] = this;
019              
020          
this->column column;
021          
this->row row;
022              
023          if ( !
cols )
024              
cols num_cols;
025              
026          
has_knight 0;
027              
028          
next_position NULL;
029          
previous_position NULL;
030              
031          
first_collected_position NULL;
032          
last_collected_position NULL;
033              
034          
035          
center_distance abs((cols 1) - (column) - (row));
036              
037          if ( !
reachable_positions_offset_set ) {
038              if ( 
column ) {
039                  if ( 
row )
040                      
reachable_positions_offset 4;
041                  else
042                      
reachable_positions_offset 6;
043              }
044              else {
045                  if ( 
row )
046                      
reachable_positions_offset 2;
047                              else
048                                      
reachable_positions_offset 0;
049                      }
050              
reachable_positions_offset_set 1;
051          }
052              
053          
fill_reachable_positions(collection);
054              
055          
knight_count++;
056      
057          
lower_or_equal = ( rand() % (cols cols center_distance knight_count) == ) ? 0;
058              
059          
//cout << "KnightPosition number " << knight_count << " constructed at " << letters[column] << (row + 1) << endl;
060      
}
061      
062      
063      
KnightPosition::~KnightPosition() {
064              
065          
struct reachable_position_pointer tmp_position, * next_tmp_position;
066              
067          if ( !
first_collected_position )
068              return;
069              
070          
tmp_position first_collected_position->basic_next;
071          while ( 
tmp_position ) {
072              
next_tmp_position first_collected_position->basic_next->basic_next;
073              
first_collected_position->basic_next next_tmp_position;
074              
delete(tmp_position);
075              
tmp_position next_tmp_position;
076          }
077          
delete(first_collected_position->basic_next);
078          
delete(first_collected_position);
079          
first_collected_position NULL;
080              
081          
//cout << "KnightPosition " << (cols * cols - --knight_count) << " at " << letters[column] << (row + 1) << " destroyed" << endl;
082      
}
083      
084      
085      
int KnightPosition::get_num_possibilities () {
086          
int possibilities 0;
087              
088          if ( !
first_collected_position )
089              return 
0;
090              
091          
struct reachable_position_pointer tmp_position first_collected_position;
092          while ( 
tmp_position ) {
093              if ( !
tmp_position->possible_position->has_knight )
094                  
possibilities++;
095              
tmp_position tmp_position->basic_next;
096          }
097              
098          return 
possibilities;
099      }
100      
101      
102      
void KnightPosition::order_reachable_positions () {
103              
104          
int possibilitiessuccess;
105              
106          
struct reachable_position_pointer tmp_position_to_add;
107          
struct reachable_position_pointer tmp_tmp_position;
108          
struct reachable_position_pointer tmp_tmp_tmp_position;
109              
110          
struct reachable_position_pointer tmp_position first_collected_position;
111              
112          while ( 
tmp_position != NULL ) {
113                      
114              
possibilities tmp_position->possible_position->get_num_possibilities();
115                      
116              if ( !
tmp_position->possible_position->has_knight ) {
117                              
118                  if ( !
possibilities )
119                      
possibilities cols 8;
120                              
121                  
tmp_position_to_add tmp_position;
122                  
tmp_position_to_add->possible_position tmp_position->possible_position;
123                  
tmp_position_to_add->heuristic cols possibilities tmp_position->possible_position->center_distance;
124                  
tmp_position_to_add->next NULL;
125                              
126                  if ( !
first_position_to_try ) {
127                      
first_position_to_try tmp_position_to_add;
128                      
last_position_to_try first_position_to_try;
129                  }
130                  else {
131                      
tmp_tmp_position first_position_to_try;
132                      
success 0;
133                      while ( 
tmp_tmp_position && !success ) {
134                          if ( 
tmp_position_to_add->heuristic tmp_tmp_position->heuristic || (lower_or_equal && tmp_position_to_add->heuristic == tmp_tmp_position->heuristic) ) {
135                              if ( 
tmp_tmp_position == first_position_to_try ) {
136                                  
tmp_position_to_add->next tmp_tmp_position;
137                                  
first_position_to_try tmp_position_to_add;
138                                  
success 1;
139                              }
140                              else {
141                                  
tmp_tmp_tmp_position first_position_to_try;
142                                  while ( 
tmp_tmp_tmp_position->next != tmp_tmp_position )
143                                      
tmp_tmp_tmp_position tmp_tmp_tmp_position->next;
144                                  
tmp_position_to_add->next tmp_tmp_tmp_position->next;
145                                  
tmp_tmp_tmp_position->next tmp_position_to_add;
146                                  
success 1;
147                              }
148                          }
149                          
tmp_tmp_position tmp_tmp_position->next;
150                      }
151                      if ( !
success ) {
152                          
last_position_to_try->next tmp_position_to_add;
153                          
last_position_to_try tmp_position_to_add;
154                      }
155                  }
156              }
157                      
158              
tmp_position tmp_position->basic_next;
159          }
160      }
161      
162      
163      
void KnightPosition::do_search () {
164          
struct reachable_position_pointer position_to_try first_position_to_try;
165              
166          
next_position position_to_try->possible_position;
167              
168          
first_position_to_try = (first_position_to_try->next) ? first_position_to_try->next NULL;
169              
170          if ( 
knight_number >= (cols cols 1) ) {
171              
cout << endl;
172              
cout << "\t**********" << endl;
173              
cout << "\t* SOLVED *" << endl;
174              
cout << "\t**********" << endl;
175              
cout << endl;
176              return;
177          }
178              
179          
next_position->set_knight_and_start_search(this);
180      }
181      
182      
183      
void KnightPosition::another_try_from_above () {
184          
next_position->next_position NULL;
185              
186          if ( !
first_position_to_try ) {
187              
go_back();
188              return;
189          }
190              
191          if ( 
memory_count MEMORY_LIMIT || (memory_count && knight_number == 1) ) {
192              if ( 
knight_number == )
193                  
cout << "Does not seem to be solvable" << endl;
194              else
195                  
cout << "Too much recursion, I'm giving up; knights: " << knight_number << " / " << (cols cols) << endl;
196              return;
197          }
198              
199          
cout << "I am at " << letters[column] << (row 1) << " at step " << knight_number << " (" << memory_count << " tries)" << endl;
200          
cout << "I came from " << letters[next_position->column] << (next_position->row 1) << endl;
201          
cout << "I want to try " << letters[first_position_to_try->possible_position->column] << (first_position_to_try->possible_position->row 1) << endl;
202          
cout << "---" << endl;
203              
204          
do_search();
205      }
206      
207      
208      
void KnightPosition::go_back () {
209          
memory_count++;
210          
knight_number--;
211          
has_knight 0;
212          
previous_position->another_try_from_above();
213      }
214      
215      
216      
void KnightPosition::set_knight_and_start_search (KnightPositionlast_position) {
217          
knight_number++;
218          
has_knight 1;
219          
previous_position last_position;
220              
221          
last_position_to_try NULL;
222          
first_position_to_try NULL;
223              
224          
order_reachable_positions();
225              
226          if ( !
first_position_to_try ) {
227              
go_back();
228              return;
229          }
230              
231          
do_search();
232      }
233      
234      
235      
void KnightPosition::add_to_reachable_positions (KnightPositionposition) {
236              
237          
struct reachable_position_pointer position_data = new reachable_position_pointer;
238              
239          
position_data->possible_position position;
240          
position_data->heuristic 0;
241          
position_data->next NULL;
242          
position_data->basic_next NULL;
243              
244          if ( !
first_collected_position ) {
245              
first_collected_position position_data;
246              
last_collected_position first_collected_position;
247          }
248          else {
249              
last_collected_position->basic_next position_data;
250              
last_collected_position position_data;
251          }
252      }
253      
254      
void KnightPosition::fill_reachable_positions (KnightPosition*** collection) {
255          
int x_move[] = { 1221, -1, -2, -2, -11221, -1, -};
256          
int y_move[] = { -2, -11221, -1, -2, -2, -1122};
257          
int ixy;
258          
KnightPosition tmp_position;
259              
260          for ( 
reachable_positions_offset< (reachable_positions_offset); i++ ) {
261              
column x_move[i];
262              
row y_move[i];
263                      
264              if ( 
|| > (cols 1) || || > (cols 1) )
265                  continue;
266              if ( !
collection[x][y] ) {
267                  
tmp_position = new KnightPosition(xycolscollection);
268                  
add_to_reachable_positions(tmp_position);
269              }
270              else
271                  
add_to_reachable_positions(collection[x][y]);
272          }
273      }
274