File: knight.e

package info (click to toggle)
smarteiffel 1.1-11
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 12,288 kB
  • ctags: 40,785
  • sloc: ansic: 35,791; lisp: 4,036; sh: 1,783; java: 895; ruby: 613; python: 209; makefile: 115; csh: 78; cpp: 50
file content (177 lines) | stat: -rw-r--r-- 5,033 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
class KNIGHT
   --
   -- The classic KNIGHT problem on a N times N square chessboard.
   -- The knight have to pass on all places of the chessboard once
   -- a time. For instance, here is solution for a 7 X 7 chesboard,
   -- knigth starting at position <1,1> :
   --
   --            1   28   37   24    3   26   17
   --           36   39    2   27   18   11    4
   --           29   42   23   38   25   16    9
   --           40   35   30   19   10    5   12
   --           43   22   41   32   15    8   47
   --           34   31   20   45   48   13    6
   --           21   44   33   14    7   46   49
   --

inherit ANY redefine print_on end;

creation make

feature

   make is
      local
         size, line, column: INTEGER;
      do
         if argument_count >= 1 and then argument(1).is_integer then
            size := argument(1).to_integer;
         end;
         if not size.in_range(chess_min,chess_max) then
            size := ask("Chess-board size: ",chess_min,chess_max);
         end;
         if argument_count >= 2 and then argument(2).is_integer then
            line := argument(2).to_integer;
         end;
         if not line.in_range(1,size) then
            line := ask("Start line: ",1,size);
         end
         if argument_count >= 3 and then argument(3).is_integer then
            column := argument(3).to_integer;
         end;
         if not column.in_range(1,size) then
            column := ask("Start column: ",1,size);
         end;
         knight(size,line,column)
      end;

feature {NONE}

   chess_min: INTEGER is 3;

   chess_max: INTEGER is 24;

   chessboard: ARRAY2[INTEGER];

   nb_tries: INTEGER;

   tl: ARRAY[INTEGER] is
      once
         Result := <<-2,-1,1,2,2,1,-1,-2>>;
      end;

   tc: ARRAY[INTEGER] is
      once
         Result := <<1,2,2,1,-1,-2,-2,-1>>;
      end;

   knight(size, line, column: INTEGER) is
      require
         size >= 3;
         1 <= line;
         line <= size;
         1 <= column;
         column <= size;
      do
         !!chessboard.make(1,size,1,size);
         chessboard.put(1,line,column);
         if solution(line,column) then
            print_on(std_output);
         else
            io.put_string("Sorry, there is no solution.%N");
         end;
         io.put_string("%NNumber of tries : ");
         io.put_integer(nb_tries);
         io.put_new_line;
      end;

   solution(line,column:INTEGER):BOOLEAN is
      local
         value,i : INTEGER;
      do
         if chessboard.count = chessboard.item(line,column) then
            Result := true;
         else
            from
               i := 1;
               value := chessboard.item(line,column);
            until
               Result or else i > 8
            loop
               Result := try(line+tl.item(i),column+tc.item(i),value);
               i := i + 1;
            end;
         end;
      end;

   try(line, column, value: INTEGER): BOOLEAN is
         -- Try to place the knight by used cross back-tracking method.
      do
         nb_tries := nb_tries + 1;
         if chessboard.valid_index(line,column) then
            if chessboard.item(line,column) = 0 then
               chessboard.put(value+1,line,column);
               Result := solution(line,column);
               if not Result then
                  chessboard.put(0,line,column)
               end;
            end;
         end
      end;

   ask(s:STRING; min, max: INTEGER):INTEGER is
         -- Ask for question `s' until the answer is in range `min' `max'.
      local
         stop: BOOLEAN;
      do
         from until stop
         loop
            io.put_string(s);
            io.flush;
            io.read_integer;
            Result := io.last_integer;
            if Result < min then
               io.put_string("Value too small.%N");
            elseif max < Result then
               io.put_string("Value too big.%N");
            else
               stop := true;
            end;
         end;
      end;

   print_on(file: OUTPUT_STREAM) is
         -- Display the cheesboard.
      local
         line,column : INTEGER;
         separator : STRING;
      do
         from
            create separator.make_filled(' ',3 * chessboard.upper1 + 1);
            separator.fill_with('-');
            separator.extend('%N')
            file.put_string(separator);
            line := chessboard.lower1
         until
            line > chessboard.upper1
         loop
            from
               column := chessboard.lower2
            until
               column > chessboard.upper2
            loop
               if chessboard.item(line,column) < 10 then
                  file.put_string("| ");
               else
                  file.put_character('|');
               end;
               file.put_integer(chessboard.item(line,column));
               column := column + 1;
            end;
            file.put_string("|%N");
            file.put_string(separator);
            line := line + 1;
         end;
      end;

end -- KNIGHT