/tutorial/knight.e
Specman e | 185 lines | 148 code | 21 blank | 16 comment | 14 complexity | 97ee68e0dea92b0da2affb34c984322a MD5 | raw file
1class KNIGHT 2 -- 3 -- The classic KNIGHT problem on a N times N square chessboard. The knight have to pass on 4 -- all places of the chessboard once a time. For instance, here is solution for a 7 X 7 5 -- chessboard, knight starting at position <1,1>: 6 -- 7 -- 1 28 37 24 3 26 17 8 -- 36 39 2 27 18 11 4 9 -- 29 42 23 38 25 16 9 10 -- 40 35 30 19 10 5 12 11 -- 43 22 41 32 15 8 47 12 -- 34 31 20 45 48 13 6 13 -- 21 44 33 14 7 46 49 14 -- 15 16insert 17 ARGUMENTS 18 redefine print_on 19 end 20 21create {ANY} 22 make 23 24feature {} 25 make 26 local 27 size, line, column: INTEGER 28 do 29 if argument_count >= 1 and then argument(1).is_integer then 30 size := argument(1).to_integer 31 end 32 if not size.in_range(chess_minimum, chess_maximum) then 33 size := ask("Chess-board size: ", chess_minimum, chess_maximum) 34 end 35 36 if argument_count >= 2 and then argument(2).is_integer then 37 line := argument(2).to_integer 38 end 39 40 if not line.in_range(1, size) then 41 line := ask("Start line: ", 1, size) 42 end 43 44 if argument_count >= 3 and then argument(3).is_integer then 45 column := argument(3).to_integer 46 end 47 48 if not column.in_range(1, size) then 49 column := ask("Start column: ", 1, size) 50 end 51 52 knight(size, line, column) 53 end 54 55 chess_minimum: INTEGER 3 56 57 chess_maximum: INTEGER 24 58 59 chessboard: ARRAY2[INTEGER] 60 61 nb_tries: INTEGER 62 63 line_move: FAST_ARRAY[INTEGER] 64 once 65 Result := {FAST_ARRAY[INTEGER] << -2, -1, 1, 2, 2, 1, -1, -2 >> } 66 end 67 68 column_move: FAST_ARRAY[INTEGER] 69 once 70 Result := {FAST_ARRAY[INTEGER] << 1, 2, 2, 1, -1, -2, -2, -1 >> } 71 end 72 73 knight (size, line, column: INTEGER) 74 require 75 size >= 3 76 1 <= line 77 line <= size 78 1 <= column 79 column <= size 80 do 81 create chessboard.make(1, size, 1, size) 82 chessboard.put(1, line, column) 83 if solution(line, column) then 84 Current.print_on(std_output) 85 else 86 io.put_string("Sorry, there is no solution.%N") 87 end 88 89 io.put_string("%NNumber of tries : ") 90 io.put_integer(nb_tries) 91 io.put_new_line 92 end 93 94 solution (line, column: INTEGER): BOOLEAN 95 local 96 value, i: INTEGER 97 do 98 if chessboard.count = chessboard.item(line, column) then 99 Result := True 100 else 101 from 102 i := line_move.lower 103 value := chessboard.item(line, column) 104 until 105 Result or else i > line_move.upper 106 loop 107 Result := try(line + line_move.item(i), column + column_move.item(i), value) 108 i := i + 1 109 end 110 end 111 end 112 113 try (line, column, value: INTEGER): BOOLEAN 114 -- Try to place the knight by used cross back-tracking method. 115 do 116 nb_tries := nb_tries + 1 117 if chessboard.valid_index(line, column) then 118 if chessboard.item(line, column) = 0 then 119 chessboard.put(value + 1, line, column) 120 Result := solution(line, column) 121 if not Result then 122 chessboard.put(0, line, column) 123 end 124 end 125 end 126 end 127 128 ask (s: STRING; min, max: INTEGER): INTEGER 129 -- Ask for question `s' until the answer is in range `min' `max'. 130 local 131 stop: BOOLEAN 132 do 133 from 134 until 135 stop 136 loop 137 io.put_string(s) 138 io.flush 139 io.read_integer 140 Result := io.last_integer 141 if Result < min then 142 io.put_string("Value too small.%N") 143 elseif max < Result then 144 io.put_string("Value too big.%N") 145 else 146 stop := True 147 end 148 end 149 end 150 151feature {ANY} 152 print_on (file: OUTPUT_STREAM) 153 -- Display the chessboard. 154 local 155 line, column: INTEGER; separator: STRING 156 do 157 from 158 create separator.make_filled(' ', 3 * chessboard.upper1 + 1) 159 separator.fill_with('-') 160 separator.extend('%N') 161 file.put_string(separator) 162 line := chessboard.lower1 163 until 164 line > chessboard.upper1 165 loop 166 from 167 column := chessboard.lower2 168 until 169 column > chessboard.upper2 170 loop 171 if chessboard.item(line, column) < 10 then 172 file.put_string("| ") 173 else 174 file.put_character('|') 175 end 176 file.put_integer(chessboard.item(line, column)) 177 column := column + 1 178 end 179 file.put_string("|%N") 180 file.put_string(separator) 181 line := line + 1 182 end 183 end 184 185end -- class KNIGHT