Knight's Tour Generator
Tourneys and the Fast Generation and Obfuscation of Closed Knight's Tours
DivideAndConquer.cpp
Go to the documentation of this file.
1 
4 // MIT License
5 //
6 // Copyright (c) 2019 Ian Parberry
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
12 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 //
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 // IN THE SOFTWARE.
25 
26 #include "DivideAndConquer.h"
27 
29 
31 } //constructor
32 
36 
38  b.MakeDirected(); //the generation algorithm requires a directed board
39  Generate(b, t, CRect(0, b.GetWidth(), 0, b.GetHeight())); //the whole board
40  b.MakeUndirected(); //return an undirected board
41 } //Generate
42 
51 
53  if(b.IsUndirected())return; //enforce requirement that the board is directed
54 
55  const int w = rect.m_nRight - rect.m_nLeft;
56  const int h = rect.m_nBottom - rect.m_nTop;
57 
58  if(w < 12 || h < 12) //base of recursion
59  GenerateBaseCase(b, rect);
60 
61  else{ //split into four quadrants and generate a knight's tour in each
62  const int midx = Split(rect.m_nLeft, rect.m_nRight);
63  const int midy = Split(rect.m_nTop, rect.m_nBottom);
64 
65  const CRect r0(rect.m_nLeft, midx, rect.m_nTop, midy); //quadrant 0
66  const CRect r1(midx, rect.m_nRight, rect.m_nTop, midy); //quadrant 1
67  const CRect r2(rect.m_nLeft, midx, midy, rect.m_nBottom); //quadrant 2
68  const CRect r3(midx, rect.m_nRight, midy, rect.m_nBottom); //quadrant 3
69 
70  Generate(b, t, r0); //recurse on quadrant 0
71  Generate(b, t, r1); //recurse on quadrant 1
72  Generate(b, t, r2); //recurse on quadrant 2
73  Generate(b, t, r3); //recurse on quadrant 3
74 
75  if(t == CycleType::Tour) //join the quadrants
76  Join(b, midx, midy);
77  } //else
78 } //Generate
79 
85 
86 int CDivideAndConquer::Split(int left, int right){
87  return (left + right)/2 - ((right - left)%4 == 2? 1: 0);
88 } //Split
89 
106 
107 void CDivideAndConquer::Join(CBoard& b, int midx, int midy){
108  if(b.IsUndirected())return; //enforce requirement that the board is directed
109 
110  const int w = b.GetWidth();
111 
112  //delete moves A, B, C, D (see the figure in the Doxygen-generated docs).
113 
114  const int A_left = (midy - 1)*w + midx - 3;
115  const int A_right = (midy - 2)*w + midx - 1;
116 
117  const int B_left = (midy - 1)*w + midx;
118  const int B_right = (midy - 3)*w + midx + 1;
119 
120  const int C_left = (midy + 1)*w + midx;
121  const int C_right = midy*w + midx + 2;
122 
123  const int D_left = (midy + 2)*w + midx - 2;
124  const int D_right = midy*w + midx - 1;
125 
126  b.DeleteMove(A_left, A_right);
127  b.DeleteMove(B_left, B_right);
128  b.DeleteMove(C_left, C_right);
129  b.DeleteMove(D_left, D_right);
130 
131  //replace them with new moves
132 
133  b.InsertDirectedMove(A_right, B_right);
134  b.InsertDirectedMove(B_left, C_right);
135  b.InsertDirectedMove(C_left, D_left);
136  b.InsertDirectedMove(D_right, A_left);
137 } //Join
138 
142 
144  const int w = rect.m_nRight - rect.m_nLeft; //width of tile
145  const int h = rect.m_nBottom - rect.m_nTop; //height of tile
146 
147  const int x = rect.m_nLeft; //column of cell for left of tile
148  const int y = rect.m_nTop; //row of cell for top of tile
149 
150  //copy the correct tile on a case-by-case basis
151 
152  if(w == 6 && h == 6)
153  b.CopyToSubBoard(*m_pTile6x6, x, y);
154 
155  else if(w == 8 && h == 6)
156  b.CopyToSubBoard(*m_pTile8x6, x, y);
157 
158  else if(w == 6 && h == 8)
159  b.CopyToSubBoard(*m_pTile6x8, x, y);
160 
161  else if(w == 8 && h == 8)
162  b.CopyToSubBoard(*m_pTile8x8, x, y);
163 
164  else if(w == 10 && h == 8)
165  b.CopyToSubBoard(*m_pTile10x8, x, y);
166 
167  else if(w == 8 && h == 10)
168  b.CopyToSubBoard(*m_pTile8x10, x, y);
169 
170  else if(w == 10 && h == 10)
171  b.CopyToSubBoard(*m_pTile10x10, x, y);
172 
173  else if(w == 12 && h == 10)
174  b.CopyToSubBoard(*m_pTile12x10, x, y);
175 
176  else if(w == 10 && h == 12)
177  b.CopyToSubBoard(*m_pTile10x12, x, y);
178 } //GenerateBaseCase
int m_nTop
Top-most vertical co-ordinate.
Definition: Structs.h:104
void Join(CBoard &b, int midx, int midy)
Join 4 sub-boards.
int m_nLeft
Left-most horizontal co-ordinate.
Definition: Structs.h:101
Rectangle.
Definition: Structs.h:100
bool InsertDirectedMove(int src, int dest)
Insert a directed move.
Definition: BaseBoard.cpp:501
int GetHeight()
Get height.
Definition: BaseBoard.cpp:801
CBoard * m_pTile8x8
Pointer to an 8x8 chessboard.
Definition: Tile.h:61
void GenerateBaseCase(CBoard &b, const CRect &rect)
Base of recursion.
CBoard * m_pTile8x10
Pointer to an 8x10 chessboard.
Definition: Tile.h:62
bool DeleteMove(int src, int dest)
Delete a move.
Definition: BaseBoard.cpp:528
Header for the divide-and conquer generator CDivideAndConquer.
void Generate(CBoard &b, CycleType t, const CRect &rect)
Recursion.
void MakeDirected()
Make into a directed board.
Definition: BaseBoard.cpp:335
bool IsUndirected()
Undirected board test.
Definition: BaseBoard.cpp:327
CBoard * m_pTile8x6
Pointer to an 8x6 chessboard.
Definition: Tile.h:60
int Split(int left, int right)
Split coordinates nearly in half.
CDivideAndConquer()
Constructor.
CBoard * m_pTile6x8
Pointer to a 6x8 chessboard.
Definition: Tile.h:58
Chessboard.
Definition: Board.h:42
CBoard * m_pTile10x12
Pointer to a 10x12 chessboard.
Definition: Tile.h:66
int m_nRight
Right-most horizontal co-ordinate.
Definition: Structs.h:102
CBoard * m_pTile6x6
Pointer to a 6x6 chessboard.
Definition: Tile.h:57
CBoard * m_pTile10x8
Pointer to a 10x8 chessboard.
Definition: Tile.h:64
void CopyToSubBoard(CBaseBoard &b, int x, int y)
Copy to sub-board.
Definition: BaseBoard.cpp:443
void MakeUndirected()
Make into an undirected board.
Definition: BaseBoard.cpp:351
Base tours for the divide-and-conquer generation algorithm.
Definition: Tile.h:41
CBoard * m_pTile12x10
Pointer to a 12x10 chessboard.
Definition: Tile.h:68
int m_nBottom
Bottom-most vertical co-ordinate.
Definition: Structs.h:105
int GetWidth()
Get width.
Definition: BaseBoard.cpp:794
CycleType
Cycle type.
Definition: Defines.h:58
CBoard * m_pTile10x10
Pointer to a 10x10 chessboard.
Definition: Tile.h:65