2
@fileOverview Lösen eines Spielbrettes.
3
@requires data_structure.js
4
@author Martin Kaistra, Duc-Hien Tran
7
Gibt für das angegebene Feld die angrenzenden leeren Felder zurück.
8
@param {Integer} inLine Zeilennummer des Feldes
9
@param {Integer} inColumn Spaltennummer des Feldes
12
Board.prototype.getSurroundingFreeFields = function(inLine, inColumn) {
14
var line, field, column;
16
if (inLine < this.size - 1) {
18
field = this.board_modified[line][inColumn];
19
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
20
freeFields[freeFields.length] = {"line": line, "column": inColumn, "field": field, "direction": "bottom"};
26
field = this.board_modified[line][inColumn];
27
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
28
freeFields[freeFields.length] = {"line": line, "column": inColumn, "field": field, "direction": "top"};
33
column = inColumn - 1;
34
field = this.board_modified[inLine][column];
35
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
36
freeFields[freeFields.length] = {"line": inLine, "column": column, "field": field, "direction": "left"};
40
if (inColumn < this.size - 1) {
41
column = inColumn + 1;
42
field = this.board_modified[inLine][column];
43
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
44
freeFields[freeFields.length] = {"line": inLine, "column": column, "field": field, "direction": "right"};
50
Gibt für das angegebene Feld zurück, wieviele Felder beleuchtet werden
51
würden, wenn eine Glühbirne dort gesetzt werden würde.
52
@param {Integer} inLine Zeilennummer des Feldes
53
@param {Integer} inColumn Spaltennummer des Feldes
56
Board.prototype.getLightableFields = function(inLine, inColumn) {
59
var line, field, column;
61
field = this.board_modified[inLine][inColumn];
62
if (field.type == EMPTY && !field.lit) {
68
if (inLine + 1 < this.size) {
69
while(line + 1 < this.size && this.board_modified[line + 1][column].type != BLACK) {
71
if (!this.board_modified[line][column].lit) {
80
if (inLine - 1 >= 0) {
81
while(line - 1 >= 0 && this.board_modified[line - 1][column].type != BLACK) {
83
if (!this.board_modified[line][column].lit) {
92
if (inColumn - 1 >= 0){
93
while(column - 1 >= 0 && this.board_modified[line][column - 1].type != BLACK) {
95
if (!this.board_modified[line][column].lit) {
103
if (inColumn + 1 < this.size){
104
while(column + 1 < this.size && this.board_modified[line][column + 1].type != BLACK) {
106
if (!this.board_modified[line][column].lit) {
115
Gibt für das angegebene Feld die größte angrenzende Zahl zurück.
116
@param {Integer} inLine Zeilennummer des Feldes
117
@param {Integer} inColumn Spaltennummer des Feldes
120
Board.prototype.getMaxSurroundingNumber = function(inLine, inColumn) {
121
var maxModNumber = 0;
123
if (!this.isOutside(inLine - 1, inColumn)) {
124
if (this.board_modified[inLine - 1][inColumn].type == BLACK &&
125
this.board_modified[inLine - 1][inColumn].number != NO_NUMBER) {
126
modNumber = this.board_modified[inLine - 1][inColumn].modified_number;
127
maxModNumber = maxModNumber < modNumber ? modNumber : maxModNumber;
130
if (!this.isOutside(inLine + 1, inColumn)) {
131
if (this.board_modified[inLine + 1][inColumn].type == BLACK &&
132
this.board_modified[inLine + 1][inColumn].number != NO_NUMBER) {
133
modNumber = this.board_modified[inLine + 1][inColumn].modified_number;
134
maxModNumber = maxModNumber < modNumber ? modNumber : maxModNumber;
137
if (!this.isOutside(inLine, inColumn - 1)) {
138
if (this.board_modified[inLine][inColumn - 1].type == BLACK &&
139
this.board_modified[inLine][inColumn - 1].number != NO_NUMBER) {
140
modNumber = this.board_modified[inLine][inColumn - 1].modified_number;
141
maxModNumber = maxModNumber < modNumber ? modNumber : maxModNumber;
144
if (!this.isOutside(inLine, inColumn + 1)) {
145
if (this.board_modified[inLine][inColumn + 1].type == BLACK &&
146
this.board_modified[inLine][inColumn + 1].number != NO_NUMBER) {
147
modNumber = this.board_modified[inLine][inColumn + 1].modified_number;
148
maxModNumber = maxModNumber < modNumber ? modNumber : maxModNumber;
154
Berechnet die minimale Differenz zwischen Zahlen der umgebenden Felder und der Anzahl der freien umgebenden Felder
155
@param {Integer} inLine Zeilennummer des Feldes
156
@param {Integer} inColumn Spaltennummer des Feldes
159
Board.prototype.getMinSurroundingNumberDifference = function(inLine, inColumn) {
160
var minDifNumber = 4; // smallest number of (Free fields - modNumber)
161
var freeFieldsNumber = 0;
163
if (!this.isOutside(inLine - 1, inColumn)) {
164
if (this.board_modified[inLine - 1][inColumn].type == BLACK &&
165
this.board_modified[inLine - 1][inColumn].number != NO_NUMBER) {
166
modNumber = this.board_modified[inLine - 1][inColumn].modified_number - 3;
167
freeFieldsNumber = this.getNumberSurroundingFreeFields(inLine - 1, inColumn);
168
minDifNumber = minDifNumber < (freeFieldsNumber - modNumber) ? minDifNumber : (freeFieldsNumber - modNumber);
171
if (!this.isOutside(inLine + 1, inColumn)) {
172
if (this.board_modified[inLine + 1][inColumn].type == BLACK &&
173
this.board_modified[inLine + 1][inColumn].number != NO_NUMBER) {
174
modNumber = this.board_modified[inLine + 1][inColumn].modified_number - 3;
175
freeFieldsNumber = this.getNumberSurroundingFreeFields(inLine + 1, inColumn);
176
minDifNumber = minDifNumber < (freeFieldsNumber - modNumber) ? minDifNumber : (freeFieldsNumber - modNumber);
179
if (!this.isOutside(inLine, inColumn - 1)) {
180
if (this.board_modified[inLine][inColumn - 1].type == BLACK &&
181
this.board_modified[inLine][inColumn - 1].number != NO_NUMBER) {
182
modNumber = this.board_modified[inLine][inColumn - 1].modified_number - 3;
183
freeFieldsNumber = this.getNumberSurroundingFreeFields(inLine, inColumn - 1);
184
minDifNumber = minDifNumber < (freeFieldsNumber - modNumber) ? minDifNumber : (freeFieldsNumber - modNumber);
187
if (!this.isOutside(inLine, inColumn + 1)) {
188
if (this.board_modified[inLine][inColumn + 1].type == BLACK &&
189
this.board_modified[inLine][inColumn + 1].number != NO_NUMBER) {
190
modNumber = this.board_modified[inLine][inColumn + 1].modified_number - 3;
191
freeFieldsNumber = this.getNumberSurroundingFreeFields(inLine, inColumn + 1);
192
minDifNumber = minDifNumber <= (freeFieldsNumber - modNumber) ? minDifNumber : (freeFieldsNumber - modNumber);
198
Gibt für das angegebene Feld die Anzahl der angrenzenden freien Felder zurück.
199
@param {Integer} inLine Zeilennummer des Feldes
200
@param {Integer} inColumn Spaltennummer des Feldes
203
Board.prototype.getNumberSurroundingFreeFields = function(inLine, inColumn) {
204
var freefieldsnumber = 0;
206
if (inLine < this.size - 1) {
208
field = this.board_modified[line][inColumn];
209
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
216
field = this.board_modified[line][inColumn];
217
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
223
column = inColumn - 1;
224
field = this.board_modified[inLine][column];
225
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
230
if (inColumn < this.size - 1) {
231
column = inColumn + 1;
232
field = this.board_modified[inLine][column];
233
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
237
return freefieldsnumber;
241
Gibt für das angegebene Feld zurück, ob dort keine Glühbirne gesetzt
242
werden kann. Prüft auch, ob das Feld innerhalb des Spielbretts liegt.
243
@param {Integer} inLine Zeilennummer des Feldes
244
@param {Integer} inColumn Spaltennummer des Feldes
247
Board.prototype.isInvalidToSetLightbulb = function(inLine, inColumn){
249
if (inLine < 0 || inLine > this.size - 1 || inColumn < 0 || inColumn > this.size - 1) {
250
// console.log("field is outside of board " + inLine + " " + inColumn);
253
field = this.board_modified[inLine][inColumn];
255
if(field.type != EMPTY || field.flag == IS_X || field.lit){
256
// console.log("NOT empty" + inLine + " " + inColumn);
259
// console.log("empty");
264
Gibt für das angegebene Feld zurück, ob es außerhalb des Spielbretts liegt.
265
@param {Integer} inLine Zeilennummer des Feldes
266
@param {Integer} inColumn Spaltennummer des Feldes
269
Board.prototype.isOutside = function(inLine, inColumn) { // is outside ?
270
if (inLine < 0 || inLine > this.size - 1 || inColumn < 0 || inColumn > this.size - 1) {
271
// console.log("field is outside of board " + inLine + " " + inColumn);
279
Gibt für das angegebene Feld zurück, ob es leer ist. Es darf aber beleuchtet oder
280
mit einem x belegt sein.
281
@param {Integer} inLine Zeilennummer des Feldes
282
@param {Integer} inColumn Spaltennummer des Feldes
285
Board.prototype.isEmpty = function(inLine, inColumn) { // do not care of X or lightened
287
if (!this.isOutside(inLine, inColumn)) {
288
field = this.board_modified[inLine][inColumn];
289
if (field.type == EMPTY){
299
Versucht das Spielbrett mit verschiedenen logischen Methoden zu lösen.
301
Board.prototype.solve = function() {
303
var solve_methods = {
304
1: this.solve_method1.bind(self),
305
2: this.solve_method2.bind(self),
306
3: this.solve_method3.bind(self),
307
4: this.solve_method4.bind(self),
308
5: this.solve_method5.bind(self),
309
6: this.solve_method6.bind(self),
310
7: this.solve_method7.bind(self),
311
8: this.solve_method8.bind(self),
312
9: this.solve_method9.bind(self),
313
10: this.solve_method10.bind(self),
314
11: this.solve_method11.bind(self),
315
12: this.solve_method12.bind(self),
316
13: this.solve_method13.bind(self),
317
14: this.solve_method14.bind(self),
318
15: this.solve_method15.bind(self),
319
16: this.solve_method16.bind(self),
320
17: this.solve_method17.bind(self),
321
18: this.solve_method18.bind(self)
323
var methodPointer = 1;
325
while (methodPointer <= 18 && counter < 1000) {
326
var modified = false;
327
for (var i = 0; i<this.size; i++) {
328
for (var j = 0; j<this.size; j++) {
329
modified = modified || solve_methods[methodPointer](i, j);
333
this.solution_properties.classic_methods[methodPointer] = true;
340
// console.log("Counter: " + counter);
345
@param {Integer} inLine Zeilennummer des Feldes
346
@param {Integer} inColumn Spaltennummer des Feldes
349
Board.prototype.solve_method1 = function(inLine, inColumn) {
350
var field = this.board_modified[inLine][inColumn];
351
if (field.type == BLACK && field.modified_number == FOUR) {
352
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
353
if (freeFields.length > 0) { // something else should not happen
354
for(var i in freeFields) {
355
this.setLightbulb(freeFields[i].line, freeFields[i].column);
365
@param {Integer} inLine Zeilennummer des Feldes
366
@param {Integer} inColumn Spaltennummer des Feldes
369
Board.prototype.solve_method2 = function(inLine, inColumn) {
370
var field = this.board_modified[inLine][inColumn];
371
if (field.type == BLACK && field.modified_number == ZERO) {
372
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
373
if (freeFields.length > 0) {
374
for(var i in freeFields) {
375
this.setX(freeFields[i].line, freeFields[i].column);
384
Ein 3er-Feld mit 3 angrenzenden freien Feldern.
385
@param {Integer} inLine Zeilennummer des Feldes
386
@param {Integer} inColumn Spaltennummer des Feldes
389
Board.prototype.solve_method3 = function(inLine, inColumn) {
390
var field = this.board_modified[inLine][inColumn];
391
if (field.type == BLACK && field.modified_number == THREE) {
392
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
393
if (freeFields.length == 3) {
394
for(var i in freeFields) {
395
this.setLightbulb(freeFields[i].line, freeFields[i].column);
404
Ein 3er-Feld mit 4 angrenzenden freien Feldern.
405
@param {Integer} inLine Zeilennummer des Feldes
406
@param {Integer} inColumn Spaltennummer des Feldes
409
Board.prototype.solve_method4 = function(inLine, inColumn) {
410
var field = this.board_modified[inLine][inColumn];
411
if (field.type == BLACK && field.modified_number == THREE) {
412
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
413
if (freeFields.length == 4) {
414
if ((this.board_modified[inLine - 1][inColumn - 1].flag == IS_X ||
415
this.board_modified[inLine - 1][inColumn - 1].type != EMPTY) &&
416
(this.board_modified[inLine + 1][inColumn - 1].flag == IS_X ||
417
this.board_modified[inLine + 1][inColumn - 1].type != EMPTY) &&
418
(this.board_modified[inLine - 1][inColumn + 1].flag == IS_X ||
419
this.board_modified[inLine - 1][inColumn + 1].type != EMPTY) &&
420
(this.board_modified[inLine + 1][inColumn + 1].flag == IS_X ||
421
this.board_modified[inLine + 1][inColumn + 1].type != EMPTY)) {
424
this.setX(inLine - 1, inColumn - 1);
425
this.setX(inLine + 1, inColumn - 1);
426
this.setX(inLine - 1, inColumn + 1);
427
this.setX(inLine + 1, inColumn + 1);
435
Ein 2er-Feld mit 2 angrenzenden freien Feldern.
436
@param {Integer} inLine Zeilennummer des Feldes
437
@param {Integer} inColumn Spaltennummer des Feldes
440
Board.prototype.solve_method5 = function(inLine, inColumn) {
441
var field = this.board_modified[inLine][inColumn];
442
if (field.type == BLACK && field.modified_number == TWO) {
443
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
444
if (freeFields.length == 2) {
445
for(var i in freeFields) {
446
this.setLightbulb(freeFields[i].line, freeFields[i].column);
455
Ein 2er-Feld mit 3 angrenzenden freien Feldern.
456
@param {Integer} inLine Zeilennummer des Feldes
457
@param {Integer} inColumn Spaltennummer des Feldes
460
Board.prototype.solve_method6 = function(inLine, inColumn) {
461
var field = this.board_modified[inLine][inColumn];
462
if (field.type == BLACK && field.modified_number == TWO) {
463
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
464
if (freeFields.length == 3) {
466
var dir_bottom = false;
467
var dir_left = false;
468
var dir_right = false;
469
for(var i in freeFields) {
470
if (freeFields[i].direction == "top") {
472
} else if (freeFields[i].direction == "bottom") {
474
} else if (freeFields[i].direction == "left") {
476
} else if (freeFields[i].direction == "right") {
481
if ((this.board_modified[inLine + 1][inColumn - 1].flag == IS_X ||
482
this.board_modified[inLine + 1][inColumn - 1].type != EMPTY) &&
483
(this.board_modified[inLine + 1][inColumn + 1].flag == IS_X ||
484
this.board_modified[inLine + 1][inColumn + 1].type != EMPTY)) {
487
this.setX(inLine + 1, inColumn - 1);
488
this.setX(inLine + 1, inColumn + 1);
489
} else if (!dir_bottom) {
490
if ((this.board_modified[inLine - 1][inColumn - 1].flag == IS_X ||
491
this.board_modified[inLine - 1][inColumn - 1].type != EMPTY) &&
492
(this.board_modified[inLine - 1][inColumn + 1].flag == IS_X ||
493
this.board_modified[inLine - 1][inColumn + 1].type != EMPTY)) {
496
this.setX(inLine - 1, inColumn - 1);
497
this.setX(inLine - 1, inColumn + 1);
498
} else if (!dir_left) {
499
if ((this.board_modified[inLine - 1][inColumn + 1].flag == IS_X ||
500
this.board_modified[inLine - 1][inColumn + 1].type != EMPTY) &&
501
(this.board_modified[inLine + 1][inColumn + 1].flag == IS_X ||
502
this.board_modified[inLine + 1][inColumn + 1].type != EMPTY)) {
505
this.setX(inLine - 1, inColumn + 1);
506
this.setX(inLine + 1, inColumn + 1);
507
} else if (!dir_right) {
508
if ((this.board_modified[inLine - 1][inColumn - 1].flag == IS_X ||
509
this.board_modified[inLine - 1][inColumn - 1].type != EMPTY) &&
510
(this.board_modified[inLine + 1][inColumn - 1].flag == IS_X ||
511
this.board_modified[inLine + 1][inColumn - 1].type != EMPTY)) {
514
this.setX(inLine - 1, inColumn - 1);
515
this.setX(inLine + 1, inColumn - 1);
518
console.log(inLine + "/" + inColumn);
527
Ein 1er-Feld mit 1 angrenzenden freien Feldern.
528
@param {Integer} inLine Zeilennummer des Feldes
529
@param {Integer} inColumn Spaltennummer des Feldes
532
Board.prototype.solve_method7 = function(inLine, inColumn) {
533
var field = this.board_modified[inLine][inColumn];
534
if (field.type == BLACK && field.modified_number == ONE) {
535
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
536
if (freeFields.length == 1) {
537
for(var i in freeFields) {
538
this.setLightbulb(freeFields[i].line, freeFields[i].column);
547
Ein 1er-Feld mit 2 angrenzenden freien Feldern.
548
@param {Integer} inLine Zeilennummer des Feldes
549
@param {Integer} inColumn Spaltennummer des Feldes
552
Board.prototype.solve_method8 = function(inLine, inColumn) {
553
var field = this.board_modified[inLine][inColumn];
554
if (field.type == BLACK && field.modified_number == ONE) {
555
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
556
if (freeFields.length == 2) {
558
var dir_bottom = false;
559
var dir_left = false;
560
var dir_right = false;
561
for(var i in freeFields) {
562
if (freeFields[i].direction == "top") {
564
} else if (freeFields[i].direction == "bottom") {
566
} else if (freeFields[i].direction == "left") {
568
} else if (freeFields[i].direction == "right") {
572
if (dir_top && dir_left) {
573
if (this.board_modified[inLine - 1][inColumn - 1].flag == IS_X ||
574
this.board_modified[inLine - 1][inColumn - 1].type != EMPTY) {
577
this.setX(inLine - 1, inColumn - 1);
579
} else if (dir_top && dir_right) {
580
if (this.board_modified[inLine - 1][inColumn + 1].flag == IS_X ||
581
this.board_modified[inLine - 1][inColumn + 1].type != EMPTY) {
584
this.setX(inLine - 1, inColumn + 1);
586
} else if (dir_right && dir_bottom) {
587
if (this.board_modified[inLine + 1][inColumn + 1].flag == IS_X ||
588
this.board_modified[inLine + 1][inColumn + 1].type != EMPTY) {
591
this.setX(inLine + 1, inColumn + 1);
593
} else if (dir_bottom && dir_left) {
594
if (this.board_modified[inLine + 1][inColumn - 1].flag == IS_X ||
595
this.board_modified[inLine + 1][inColumn - 1].type != EMPTY) {
598
this.setX(inLine + 1, inColumn - 1);
608
Ein Feld was nur genau durch sich selbst beleuchten werden kann.
609
@param {Integer} inLine Zeilennummer des Feldes
610
@param {Integer} inColumn Spaltennummer des Feldes
613
Board.prototype.solve_method9 = function(inLine, inColumn) {
614
var field = this.board_modified[inLine][inColumn];
616
if (field.type == EMPTY && !field.lit && (field.flag != IS_X)) {
621
if (inLine + 1 < this.size) {
622
while(line + 1 < this.size && this.board_modified[line + 1][column].type != BLACK) {
624
if (!this.board_modified[line][column].lit &&
625
this.board_modified[line][column].flag != IS_X) {
634
if (inLine - 1 >= 0) {
635
while(line - 1 >= 0 && this.board_modified[line - 1][column].type != BLACK) {
637
if (!this.board_modified[line][column].lit &&
638
this.board_modified[line][column].flag != IS_X) {
647
if (inColumn - 1 >= 0){
648
while(column - 1 >= 0 && this.board_modified[line][column - 1].type != BLACK) {
650
if (!this.board_modified[line][column].lit &&
651
this.board_modified[line][column].flag != IS_X) {
659
if (inColumn + 1 < this.size){
660
while(column + 1 < this.size && this.board_modified[line][column + 1].type != BLACK) {
662
if (!this.board_modified[line][column].lit &&
663
this.board_modified[line][column].flag != IS_X) {
669
this.setLightbulb(inLine, inColumn);
676
Ein Feld, was nur genau von einem anderen beleuchtet werden kann.
677
@param {Integer} inLine Zeilennummer des Feldes
678
@param {Integer} inColumn Spaltennummer des Feldes
681
Board.prototype.solve_method10 = function(inLine, inColumn) {
684
var emptyFieldColumn;
687
var field = this.board_modified[inLine][inColumn];
688
if (field.type == EMPTY && !field.lit && (field.flag == IS_X)) {
693
if (inLine + 1 < this.size) {
694
while(line + 1 < this.size && this.board_modified[line + 1][column].type != BLACK) {
696
if (!this.board_modified[line][column].lit &&
697
this.board_modified[line][column].flag != IS_X) {
702
emptyFieldLine = line;
703
emptyFieldColumn = column;
712
if (inLine - 1 >= 0) {
713
while(line - 1 >= 0 && this.board_modified[line - 1][column].type != BLACK) {
715
if (!this.board_modified[line][column].lit &&
716
this.board_modified[line][column].flag != IS_X) {
721
emptyFieldLine = line;
722
emptyFieldColumn = column;
731
if (inColumn - 1 >= 0){
732
while(column - 1 >= 0 && this.board_modified[line][column - 1].type != BLACK) {
734
if (!this.board_modified[line][column].lit &&
735
this.board_modified[line][column].flag != IS_X) {
740
emptyFieldLine = line;
741
emptyFieldColumn = column;
749
if (inColumn + 1 < this.size){
750
while(column + 1 < this.size && this.board_modified[line][column + 1].type != BLACK) {
752
if (!this.board_modified[line][column].lit &&
753
this.board_modified[line][column].flag != IS_X) {
758
emptyFieldLine = line;
759
emptyFieldColumn = column;
768
this.setLightbulb(emptyFieldLine, emptyFieldColumn);
775
Ein 2er-Feld mit 3 angrenzenden freien Feldern. (siehe planung.txt)
776
@param {Integer} inLine Zeilennummer des Feldes
777
@param {Integer} inColumn Spaltennummer des Feldes
780
Board.prototype.solve_method11 = function(inLine, inColumn) {
781
var field = this.board_modified[inLine][inColumn];
782
if (field.type == BLACK && field.modified_number == TWO) {
783
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
784
if (freeFields.length == 3) {
786
var dir_bottom = false;
787
var dir_left = false;
788
var dir_right = false;
789
for(var i in freeFields) {
790
if (freeFields[i].direction == "top") {
792
} else if (freeFields[i].direction == "bottom") {
794
} else if (freeFields[i].direction == "left") {
796
} else if (freeFields[i].direction == "right") {
801
if ((this.board_modified[inLine + 1][inColumn - 1].type == BLACK &&
802
this.board_modified[inLine + 1][inColumn - 1].modified_number == ONE)) {
803
this.setLightbulb(inLine, inColumn + 1);
804
this.setX(inLine + 1, inColumn - 2);
805
this.setX(inLine + 2, inColumn - 1);
808
if ((this.board_modified[inLine + 1][inColumn + 1].type == BLACK &&
809
this.board_modified[inLine + 1][inColumn + 1].modified_number == ONE)) {
810
this.setLightbulb(inLine, inColumn - 1);
811
this.setX(inLine + 1, inColumn + 2);
812
this.setX(inLine + 2, inColumn + 1);
815
} else if (!dir_bottom) {
816
if ((this.board_modified[inLine - 1][inColumn - 1].type == BLACK &&
817
this.board_modified[inLine - 1][inColumn - 1].modified_number == ONE)) {
818
this.setLightbulb(inLine, inColumn + 1);
819
this.setX(inLine - 1, inColumn - 2);
820
this.setX(inLine - 2, inColumn - 1);
823
if ((this.board_modified[inLine - 1][inColumn + 1].type == BLACK &&
824
this.board_modified[inLine - 1][inColumn + 1].modified_number == ONE)) {
825
this.setLightbulb(inLine, inColumn - 1);
826
this.setX(inLine - 1, inColumn + 2);
827
this.setX(inLine - 2, inColumn + 1);
830
} else if (!dir_left) {
831
if ((this.board_modified[inLine - 1][inColumn + 1].type == BLACK &&
832
this.board_modified[inLine - 1][inColumn + 1].modified_number == ONE)) {
833
this.setLightbulb(inLine + 1, inColumn);
834
this.setX(inLine - 1, inColumn + 2);
835
this.setX(inLine - 2, inColumn + 1);
838
if ((this.board_modified[inLine + 1][inColumn + 1].type == BLACK &&
839
this.board_modified[inLine + 1][inColumn + 1].modified_number == ONE)) {
840
this.setLightbulb(inLine - 1, inColumn);
841
this.setX(inLine + 1, inColumn + 2);
842
this.setX(inLine + 2, inColumn + 1);
845
} else if (!dir_right) {
846
if ((this.board_modified[inLine - 1][inColumn - 1].type == BLACK &&
847
this.board_modified[inLine - 1][inColumn - 1].modified_number == ONE)) {
848
this.setLightbulb(inLine + 1, inColumn);
849
this.setX(inLine - 1, inColumn - 2);
850
this.setX(inLine - 2, inColumn - 1);
853
if ((this.board_modified[inLine + 1][inColumn - 1].type == BLACK &&
854
this.board_modified[inLine + 1][inColumn - 1].modified_number == ONE)) {
855
this.setLightbulb(inLine - 1, inColumn);
856
this.setX(inLine + 1, inColumn - 2);
857
this.setX(inLine + 2, inColumn - 1);
867
Ein 3er-Feld mit 4 angrenzenden freien Feldern. (siehe planung.txt)
868
@param {Integer} inLine Zeilennummer des Feldes
869
@param {Integer} inColumn Spaltennummer des Feldes
872
Board.prototype.solve_method12 = function(inLine, inColumn) {
873
var field = this.board_modified[inLine][inColumn];
874
if (field.type == BLACK && field.modified_number == THREE) {
875
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
876
if (freeFields.length == 4) {
877
if ((this.board_modified[inLine - 1][inColumn - 1].type == BLACK &&
878
this.board_modified[inLine - 1][inColumn - 1].modified_number == ONE)) {
879
this.setLightbulb(inLine, inColumn + 1);
880
this.setLightbulb(inLine + 1, inColumn);
881
this.setX(inLine - 1, inColumn - 2);
882
this.setX(inLine - 2, inColumn - 1);
885
if ((this.board_modified[inLine - 1][inColumn + 1].type == BLACK &&
886
this.board_modified[inLine - 1][inColumn + 1].modified_number == ONE)) {
887
this.setLightbulb(inLine, inColumn - 1);
888
this.setLightbulb(inLine + 1, inColumn);
889
this.setX(inLine - 1, inColumn + 2);
890
this.setX(inLine - 2, inColumn + 1);
893
if ((this.board_modified[inLine + 1][inColumn - 1].type == BLACK &&
894
this.board_modified[inLine + 1][inColumn - 1].modified_number == ONE)) {
895
this.setLightbulb(inLine, inColumn + 1);
896
this.setLightbulb(inLine - 1, inColumn);
897
this.setX(inLine + 1, inColumn - 2);
898
this.setX(inLine + 2, inColumn - 1);
901
if ((this.board_modified[inLine + 1][inColumn + 1].type == BLACK &&
902
this.board_modified[inLine + 1][inColumn + 1].modified_number == ONE)) {
903
this.setLightbulb(inLine, inColumn - 1);
904
this.setLightbulb(inLine - 1, inColumn);
905
this.setX(inLine + 1, inColumn + 2);
906
this.setX(inLine + 2, inColumn + 1);
915
Ein 2er-Feld, das an ein anderes 2er-Feld direkt angrenzt.
916
@param {Integer} inLine Zeilennummer des Feldes
917
@param {Integer} inColumn Spaltennummer des Feldes
920
Board.prototype.solve_method13 = function(inLine, inColumn) {
921
var field = this.board_modified[inLine][inColumn];
922
if (field.type == BLACK && field.modified_number == TWO) {
923
if ((inLine > 0 && this.board_modified[inLine - 1][inColumn].type == BLACK &&
924
this.board_modified[inLine - 1][inColumn].modified_number == TWO)) {
925
this.setLightbulb(inLine - 2, inColumn); //zwei 2er am Rand nebeneinander ist unloesbar
926
this.setLightbulb(inLine + 1, inColumn);
929
if ((inColumn > 0 && this.board_modified[inLine][inColumn - 1].type == BLACK &&
930
this.board_modified[inLine][inColumn - 1].modified_number == TWO)) {
931
this.setLightbulb(inLine, inColumn - 2);
932
this.setLightbulb(inLine, inColumn + 1);
940
Ein freies Feld mit 2 gegenüberliegenden angrenzenden 3er-Feldern.
941
@param {Integer} inLine Zeilennummer des Feldes
942
@param {Integer} inColumn Spaltennummer des Feldes
945
Board.prototype.solve_method14 = function(inLine, inColumn) {
946
if (inLine > 0 && inLine < this.size - 1 && inColumn > 0 && inColumn < this.size - 1) {
947
var field = this.board_modified[inLine][inColumn];
948
if (field.type == EMPTY && field.flag != IS_X && !field.lit) {
949
if ((this.board_modified[inLine][inColumn - 1].type == EMPTY &&
950
!this.board_modified[inLine][inColumn - 1].lit) &&
951
(this.board_modified[inLine][inColumn + 1].type == EMPTY &&
952
!this.board_modified[inLine][inColumn + 1].lit) &&
953
(this.board_modified[inLine - 1][inColumn].type == BLACK &&
954
this.board_modified[inLine - 1][inColumn].modified_number == THREE) &&
955
(this.board_modified[inLine + 1][inColumn].type == BLACK &&
956
this.board_modified[inLine + 1][inColumn].modified_number == THREE)) {
957
this.setLightbulb(inLine, inColumn);
958
this.setLightbulb(inLine - 2, inColumn);
959
this.setLightbulb(inLine + 2, inColumn);
962
if ((this.board_modified[inLine - 1][inColumn].type == EMPTY &&
963
!this.board_modified[inLine - 1][inColumn].lit) &&
964
(this.board_modified[inLine + 1][inColumn].type == EMPTY &&
965
!this.board_modified[inLine + 1][inColumn].lit) &&
966
(this.board_modified[inLine][inColumn - 1].type == BLACK &&
967
this.board_modified[inLine][inColumn - 1].modified_number == THREE) &&
968
(this.board_modified[inLine][inColumn + 1].type == BLACK &&
969
this.board_modified[inLine][inColumn + 1].modified_number == THREE)) {
970
this.setLightbulb(inLine, inColumn);
971
this.setLightbulb(inLine, inColumn - 2);
972
this.setLightbulb(inLine, inColumn + 2);
981
Ein 1er-Feld mit 2 angrenzenden freien Feldern. (siehe planung.txt)
982
@param {Integer} inLine Zeilennummer des Feldes
983
@param {Integer} inColumn Spaltennummer des Feldes
986
Board.prototype.solve_method15 = function(inLine, inColumn) {
987
//console.log("solve_method15");
988
var return_flag1 = false;
989
var return_flag2 = false;
990
var field = this.board_modified[inLine][inColumn];
991
if (field.type == BLACK && field.modified_number == ONE) {
992
var freeFields = this.getSurroundingFreeFields(inLine, inColumn);
993
if (freeFields.length == 2) {
995
var dir_bottom = false;
996
var dir_left = false;
997
var dir_right = false;
998
for(var i in freeFields) {
999
if (freeFields[i].direction == "top") {
1001
} else if (freeFields[i].direction == "bottom") {
1003
} else if (freeFields[i].direction == "left") {
1005
} else if (freeFields[i].direction == "right") {
1009
if (dir_top && dir_left) {
1010
if (this.board_modified[inLine - 1][inColumn - 1].type == BLACK &&
1011
this.board_modified[inLine - 1][inColumn - 1].modified_number == ONE) {
1012
return_flag1 = this.setX(inLine - 2, inColumn - 1);
1013
return_flag2 = this.setX(inLine - 1, inColumn - 2);
1014
return (return_flag1 || return_flag2);
1016
} else if (dir_top && dir_right) {
1017
if (this.board_modified[inLine - 1][inColumn + 1].type == BLACK &&
1018
this.board_modified[inLine - 1][inColumn + 1].modified_number == ONE) {
1019
return_flag1 = this.setX(inLine - 1, inColumn + 2);
1020
return_flag2 = this.setX(inLine - 2, inColumn + 1);
1021
return (return_flag1 || return_flag2);
1023
} else if (dir_right && dir_bottom) {
1024
if (this.board_modified[inLine + 1][inColumn + 1].type == BLACK &&
1025
this.board_modified[inLine + 1][inColumn + 1].modified_number == ONE) {
1026
return_flag1 = this.setX(inLine + 1, inColumn + 2);
1027
return_flag2 = this.setX(inLine + 2, inColumn + 1);
1028
return (return_flag1 || return_flag2);
1030
} else if (dir_bottom && dir_left) {
1031
if (this.board_modified[inLine + 1][inColumn - 1].type == BLACK &&
1032
this.board_modified[inLine + 1][inColumn - 1].modified_number == ONE) {
1033
return_flag1 = this.setX(inLine + 1, inColumn - 2);
1034
return_flag2 = this.setX(inLine + 2, inColumn - 1);
1035
return (return_flag1 || return_flag2);
1045
Ein freies Feld mit 2 gegenüberliegenden angrenzenden 2er-Feldern.
1046
@param {Integer} inLine Zeilennummer des Feldes
1047
@param {Integer} inColumn Spaltennummer des Feldes
1050
Board.prototype.solve_method16 = function(inLine, inColumn) {
1051
var field = this.board_modified[inLine][inColumn];
1052
if (inLine > 0 && inLine < this.size - 1) {
1053
if (!this.isInvalidToSetLightbulb(inLine, inColumn)) { // looking for valid field.
1054
if ((this.board_modified[inLine - 1][inColumn].type == BLACK && // is top a 2-field?
1055
this.board_modified[inLine - 1][inColumn].modified_number == TWO) &&
1056
(this.board_modified[inLine + 1][inColumn].type == BLACK && // is bottom a 2-field?
1057
this.board_modified[inLine + 1][inColumn].modified_number == TWO)){
1058
if (this.isInvalidToSetLightbulb(inLine - 2, inColumn) || this.isInvalidToSetLightbulb(inLine + 2, inColumn)){ // is top or bottom of 2-field invalid ?
1059
if (this.isEmpty(inLine, inColumn - 1) == this.isEmpty(inLine, inColumn + 1)){ // are left and right fields the same type?
1060
this.setLightbulb(inLine, inColumn);
1063
}else if (this.isOutside(inLine, inColumn - 1) || this.isOutside(inLine, inColumn + 1)) {
1064
this.setLightbulb(inLine, inColumn);
1070
if(inColumn > 0 && inColumn < this.size - 1){
1071
if (!this.isInvalidToSetLightbulb(inLine, inColumn)) { // looking for valid field.
1072
if ((this.board_modified[inLine][inColumn - 1].type == BLACK && // is left a 2-field?
1073
this.board_modified[inLine][inColumn - 1].modified_number == TWO) &&
1074
(this.board_modified[inLine][inColumn + 1].type == BLACK && // is right a 2-field?
1075
this.board_modified[inLine][inColumn + 1].modified_number == TWO)){
1076
if (this.isInvalidToSetLightbulb(inLine, inColumn - 2) || this.isInvalidToSetLightbulb(inLine, inColumn + 2)){ // is left or right of 2-field invalid ?
1077
if (this.isEmpty(inLine - 1, inColumn) == this.isEmpty(inLine + 1, inColumn)){ // are top and bottom fields the same type?
1078
this.setLightbulb(inLine, inColumn);
1081
}else if (this.isOutside(inLine - 1, inColumn) || this.isOutside(inLine + 1, inColumn)) {
1082
this.setLightbulb(inLine, inColumn);
1092
Ein freies Feld mit 2 gegenüberliegenden angrenzenden Feldern; einmal 1er und einmal 3er.
1093
@param {Integer} inLine Zeilennummer des Feldes
1094
@param {Integer} inColumn Spaltennummer des Feldes
1097
Board.prototype.solve_method17 = function(inLine, inColumn) {
1098
if (inLine > 0 && inLine < this.size - 1 && inColumn > 0 && inColumn < this.size - 1) {
1099
var field = this.board_modified[inLine][inColumn];
1100
if (!this.isInvalidToSetLightbulb(inLine, inColumn)) { // looking for valid field?
1101
if ((this.board_modified[inLine - 1][inColumn].type == BLACK && // is top a 3-field?
1102
this.board_modified[inLine - 1][inColumn].modified_number == THREE) &&
1103
(this.board_modified[inLine + 1][inColumn].type == BLACK && // is bottom a 1-field?
1104
this.board_modified[inLine + 1][inColumn].modified_number == ONE)){
1105
if (this.isInvalidToSetLightbulb(inLine + 2, inColumn)){ // is bottom of 1-field invalid ?
1106
//console.log(inLine + " : " + inColumn);
1107
if (this.isEmpty(inLine, inColumn - 1) == this.isEmpty(inLine, inColumn + 1)){ // are left and right fields the same type?
1108
this.setLightbulb(inLine, inColumn);
1114
if (!this.isInvalidToSetLightbulb(inLine, inColumn)) { // looking for valid field?
1115
if ((this.board_modified[inLine - 1][inColumn].type == BLACK && // is top a 1-field?
1116
this.board_modified[inLine - 1][inColumn].modified_number == ONE) &&
1117
(this.board_modified[inLine + 1][inColumn].type == BLACK && // is bottom a 3-field?
1118
this.board_modified[inLine + 1][inColumn].modified_number == THREE)){
1119
if (this.isInvalidToSetLightbulb(inLine - 2, inColumn)){ // is top of 1-field invalid ?
1120
//console.log(inLine + " : " + inColumn);
1121
if (this.isEmpty(inLine, inColumn - 1) == this.isEmpty(inLine, inColumn + 1)){ // are left and right fields the same type?
1122
this.setLightbulb(inLine, inColumn);
1128
if (!this.isInvalidToSetLightbulb(inLine, inColumn)) { // looking for valid field?
1129
if ((this.board_modified[inLine][inColumn - 1].type == BLACK && // is left a 3-field?
1130
this.board_modified[inLine][inColumn - 1].modified_number == THREE) &&
1131
(this.board_modified[inLine][inColumn + 1].type == BLACK && // is right a 1-field?
1132
this.board_modified[inLine][inColumn + 1].modified_number == ONE)){
1133
if (this.isInvalidToSetLightbulb(inLine, inColumn + 2)){ // is right of 1-field invalid ?
1134
//console.log(inLine + " : " + inColumn);
1135
if (this.isEmpty(inLine - 1, inColumn) == this.isEmpty(inLine + 1, inColumn)){ // are left and right fields the same type?
1136
this.setLightbulb(inLine, inColumn);
1142
if (!this.isInvalidToSetLightbulb(inLine, inColumn)) { // looking for valid field?
1143
if ((this.board_modified[inLine][inColumn - 1].type == BLACK && // is left a 1-field?
1144
this.board_modified[inLine][inColumn - 1].modified_number == ONE) &&
1145
(this.board_modified[inLine][inColumn + 1].type == BLACK && // is right a 3-field?
1146
this.board_modified[inLine][inColumn + 1].modified_number == THREE)){
1147
if (this.isInvalidToSetLightbulb(inLine, inColumn - 2)){ // is left of 1-field invalid ?
1148
//console.log(inLine + " : " + inColumn);
1149
if (this.isEmpty(inLine - 1, inColumn) == this.isEmpty(inLine + 1, inColumn)){ // are left and right fields the same type?
1150
this.setLightbulb(inLine, inColumn);
1161
Ein Feld mit x, das von genau 2 anderen Feldern beleuchtet werden kann.
1162
@param {Integer} inLine Zeilennummer des Feldes
1163
@param {Integer} inColumn Spaltennummer des Feldes
1166
Board.prototype.solve_method18 = function(inLine, inColumn) {
1168
var emptyFieldOneLine;
1169
var emptyFieldOneColumn;
1170
var emptyFieldTwoLine;
1171
var emptyFieldTwoColumn;
1174
var probFieldColumn;
1177
var field = this.board_modified[inLine][inColumn];
1178
if (field.type == EMPTY && !field.lit && (field.flag == IS_X)) {
1183
if (inLine + 1 < this.size) {
1184
while(line + 1 < this.size && this.board_modified[line + 1][column].type != BLACK) {
1186
if (!this.board_modified[line][column].lit &&
1187
this.board_modified[line][column].flag != IS_X) {
1190
} else if (found === 0) {
1191
emptyFieldOneLine = line;
1192
emptyFieldOneColumn = column;
1193
} else if (found == 1) {
1194
emptyFieldTwoLine = line;
1195
emptyFieldTwoColumn = column;
1205
if (inLine - 1 >= 0) {
1206
while(line - 1 >= 0 && this.board_modified[line - 1][column].type != BLACK) {
1208
if (!this.board_modified[line][column].lit &&
1209
this.board_modified[line][column].flag != IS_X) {
1212
} else if (found === 0) {
1213
emptyFieldOneLine = line;
1214
emptyFieldOneColumn = column;
1215
} else if (found == 1) {
1216
emptyFieldTwoLine = line;
1217
emptyFieldTwoColumn = column;
1227
if (inColumn - 1 >= 0){
1228
while(column - 1 >= 0 && this.board_modified[line][column - 1].type != BLACK) {
1230
if (!this.board_modified[line][column].lit &&
1231
this.board_modified[line][column].flag != IS_X) {
1234
} else if (found === 0) {
1235
emptyFieldOneLine = line;
1236
emptyFieldOneColumn = column;
1237
} else if (found == 1) {
1238
emptyFieldTwoLine = line;
1239
emptyFieldTwoColumn = column;
1248
if (inColumn + 1 < this.size){
1249
while(column + 1 < this.size && this.board_modified[line][column + 1].type != BLACK) {
1251
if (!this.board_modified[line][column].lit &&
1252
this.board_modified[line][column].flag != IS_X) {
1255
} else if (found === 0) {
1256
emptyFieldOneLine = line;
1257
emptyFieldOneColumn = column;
1258
} else if (found == 1) {
1259
emptyFieldTwoLine = line;
1260
emptyFieldTwoColumn = column;
1270
if (emptyFieldOneLine == emptyFieldTwoLine || emptyFieldOneColumn == emptyFieldTwoColumn) {
1273
probFieldLine = (emptyFieldOneLine == inLine) ? emptyFieldTwoLine : emptyFieldOneLine;
1274
probFieldColumn = (emptyFieldOneColumn == inColumn) ? emptyFieldTwoColumn : emptyFieldOneColumn;
1276
this.setLightbulb(probFieldLine, probFieldColumn);
1277
if (this.board_modified[emptyFieldOneLine][emptyFieldOneColumn].lit &&
1278
this.board_modified[emptyFieldTwoLine][emptyFieldTwoColumn].lit) {
1279
this.removeLightbulb(probFieldLine, probFieldColumn);
1280
this.setX(probFieldLine, probFieldColumn);
1283
this.removeLightbulb(probFieldLine, probFieldColumn);
1289
Board.MAX_RECUR = 10;
1290
Board.prototype.recur_counter = 0;
1291
Board.backtrackingversion = 0;
1294
Versucht das Spielbrett mit Backtracking zusätzlich zu
1295
den logischen Methoden zu lösen.
1296
@param {Integer} recur Rekursionsstufe
1297
@return {Integer} Anzahl der gefundenen Lösungen
1299
Board.prototype.solve_backtracking = function (recur) {
1300
this.recur_counter++;
1301
if (recur > Board.MAX_RECUR) {
1304
this.solution_properties.max_recur = recur;
1314
console.log("====== Version 1." + Board.backtrackingversion + " ======");
1319
console.log("Gewonnen auf Stufe " + recur);
1321
console.log("------------------------------------------");
1323
// save last solution
1324
this.solution = this.copyBoard();
1328
// Select new field to try:
1330
var maxModNumber = 0;
1331
var minDifNumber = 4;
1333
outer: for (var i = 0; i<this.size; i++) {
1334
for (var j = 0; j<this.size; j++) {
1335
var field = this.board_modified[i][j];
1336
if (field.type == EMPTY && !field.lit && field.flag != IS_X) {
1337
if (Board.backtrackingversion === 0){
1338
if (this.getMaxSurroundingNumber(i, j) > maxModNumber) {
1339
maxModNumber = this.getMaxSurroundingNumber(i, j);
1340
selectedField = {line: i, column: j};
1341
// console.log(i + "/" + j);
1345
if (this.getMinSurroundingNumberDifference(i, j) < minDifNumber) {
1346
minDifNumber = this.getMinSurroundingNumberDifference(i, j);
1347
selectedField = {line: i, column: j};
1348
// console.log(i + "/" + j);
1352
if (this.getLightableFields(i, j) > maxN) {
1353
maxN = this.getLightableFields(i, j);
1354
selectedField1 = {line: i, column: j};
1359
selectedField = selectedField ? selectedField : selectedField1;
1360
if (!selectedField) {
1361
// console.log("no free field found");
1365
console.log(maxN + " auf Stufe " + recur + ": " + selectedField.line + "/" + selectedField.column);
1368
// try as X and then as LIGHTBULB
1369
var boardCopy = this.copyBoard();
1371
this.setX(selectedField.line, selectedField.column);
1372
var solvedAsX = this.solve_backtracking(recur + 1);
1374
if (solvedAsX > 1) {
1378
this.rollbackBoard(boardCopy);
1380
this.setLightbulb(selectedField.line, selectedField.column);
1381
var solvedAsLightbulb = this.solve_backtracking(recur + 1);
1382
if (solvedAsLightbulb < 0 && solvedAsX < 0) {
1384
} else if (solvedAsX <= 0) {
1385
return solvedAsLightbulb;
1386
} else if (solvedAsLightbulb <= 0) {
1389
return solvedAsX + solvedAsLightbulb;
b'\\ No newline at end of file'