2 * Copyright 2007-2012, Axel Dörfler, axeld@pinc-software.de.
3 * Distributed under the terms of the MIT License.
7 #include "SudokuField.h"
22 for (int32 number
= 9; number
> 0; number
--) {
23 text
[i
++] = set
& (1UL << (number
- 1)) ? number
+ '0' : '-';
34 SudokuField::field::field()
47 SudokuField::SudokuField(uint32 size
)
52 fFields
= new (std::nothrow
) field
[fSize
* fSize
];
53 fMaxMask
= (1UL << fSize
) - 1;
57 SudokuField::SudokuField(const BMessage
* archive
)
59 if (archive
->FindInt32("block size", (int32
*)&fBlockSize
) != B_OK
)
62 fSize
= fBlockSize
* fBlockSize
;
63 fMaxMask
= (1UL << fSize
) - 1;
65 uint32 count
= fSize
* fSize
;
66 fFields
= new (std::nothrow
) field
[count
];
70 for (uint32 i
= 0; i
< count
; i
++) {
71 struct field
& field
= fFields
[i
];
73 if (archive
->FindInt32("value", i
, (int32
*)&field
.value
) != B_OK
74 || archive
->FindInt32("valid mask", i
,
75 (int32
*)&field
.valid_mask
) != B_OK
76 || archive
->FindInt32("hint mask", i
,
77 (int32
*)&field
.hint_mask
) != B_OK
78 || archive
->FindInt32("flags", i
, (int32
*)&field
.flags
) != B_OK
)
84 SudokuField::SudokuField(const SudokuField
& other
)
88 fBlockSize
= other
.fBlockSize
;
89 fMaxMask
= other
.fMaxMask
;
91 fFields
= new (std::nothrow
) field
[fSize
* fSize
];
93 memcpy(fFields
, other
.fFields
, sizeof(field
) * fSize
* fSize
);
97 SudokuField::~SudokuField()
104 SudokuField::InitCheck()
108 return fFields
== NULL
? B_NO_MEMORY
: B_OK
;
113 SudokuField::Archive(BMessage
* archive
, bool deep
) const
115 status_t status
= BArchivable::Archive(archive
, deep
);
117 archive
->AddInt32("block size", fBlockSize
);
121 uint32 count
= fSize
* fSize
;
122 for (uint32 i
= 0; i
< count
&& status
== B_OK
; i
++) {
123 struct field
& field
= fFields
[i
];
124 status
= archive
->AddInt32("value", field
.value
);
126 status
= archive
->AddInt32("valid mask", field
.valid_mask
);
128 status
= archive
->AddInt32("hint mask", field
.hint_mask
);
130 status
= archive
->AddInt32("flags", field
.flags
);
137 /*static*/ SudokuField
*
138 SudokuField::Instantiate(BMessage
* archive
)
140 if (!validate_instantiation(archive
, "SudokuField"))
143 return new SudokuField(archive
);
150 for (uint32 y
= 0; y
< fSize
; y
++) {
151 for (uint32 x
= 0; x
< fSize
; x
++) {
152 struct field
& field
= _FieldAt(x
, y
);
156 field
.valid_mask
= fMaxMask
;
163 SudokuField::SetTo(char base
, const char* data
)
165 if (data
!= NULL
&& strlen(data
) < fSize
* fSize
)
175 for (uint32 y
= 0; y
< fSize
; y
++) {
176 for (uint32 x
= 0; x
< fSize
; x
++) {
177 uint32 value
= data
[i
++] - base
;
179 struct field
& field
= _FieldAt(x
, y
);
181 field
.flags
= kInitialValue
;
186 for (uint32 y
= 0; y
< fSize
; y
++) {
187 for (uint32 x
= 0; x
< fSize
; x
++) {
188 _ComputeValidMask(x
, y
, false);
197 SudokuField::SetTo(const SudokuField
* field
)
204 for (uint32 y
= 0; y
< fSize
; y
++) {
205 for (uint32 x
= 0; x
< fSize
; x
++) {
206 _FieldAt(x
, y
) = field
->_FieldAt(x
, y
);
215 for (uint32 y
= 0; y
< fSize
; y
++) {
216 for (uint32 x
= 0; x
< fSize
; x
++) {
217 if (x
!= 0 && x
% fBlockSize
== 0)
219 printf("%" B_PRIu32
, ValueAt(x
, y
));
227 SudokuField::IsSolved() const
229 for (uint32 y
= 0; y
< fSize
; y
++) {
230 for (uint32 x
= 0; x
< fSize
; x
++) {
231 if (!_ValidValueAt(x
, y
))
241 SudokuField::IsEmpty() const
243 for (uint32 y
= 0; y
< fSize
; y
++) {
244 for (uint32 x
= 0; x
< fSize
; x
++) {
245 if (ValueAt(x
, y
) != 0)
255 SudokuField::IsValueCompleted(uint32 value
) const
258 for (uint32 y
= 0; y
< fSize
; y
++) {
259 for (uint32 x
= 0; x
< fSize
; x
++) {
260 if (ValueAt(x
, y
) == value
)
265 return count
== Size();
270 SudokuField::SetHintMaskAt(uint32 x
, uint32 y
, uint32 hintMask
)
272 _FieldAt(x
, y
).hint_mask
= hintMask
;
277 SudokuField::HintMaskAt(uint32 x
, uint32 y
) const
279 return _FieldAt(x
, y
).hint_mask
;
284 SudokuField::HasHint(uint32 x
, uint32 y
, uint32 value
) const
286 return (_FieldAt(x
, y
).hint_mask
& (1UL << (value
- 1))) != 0;
291 SudokuField::SetValidMaskAt(uint32 x
, uint32 y
, uint32 validMask
)
293 _FieldAt(x
, y
).valid_mask
= validMask
& fMaxMask
;
298 SudokuField::ValidMaskAt(uint32 x
, uint32 y
) const
300 return _FieldAt(x
, y
).valid_mask
;
305 SudokuField::IsValid(uint32 x
, uint32 y
, uint32 value
) const
307 return (_FieldAt(x
, y
).valid_mask
& (1UL << (value
- 1))) != 0;
312 SudokuField::SetFlagsAt(uint32 x
, uint32 y
, uint32 flags
)
314 _FieldAt(x
, y
).flags
= flags
;
319 SudokuField::FlagsAt(uint32 x
, uint32 y
) const
321 return _FieldAt(x
, y
).flags
;
326 SudokuField::IsInitialValue(uint32 x
, uint32 y
) const
328 return (_FieldAt(x
, y
).flags
& kInitialValue
) != 0;
333 SudokuField::SetValueAt(uint32 x
, uint32 y
, uint32 value
, bool setSolved
)
335 _FieldAt(x
, y
).value
= value
;
336 _FieldAt(x
, y
).hint_mask
= 0;
337 _UpdateValidMaskChanged(x
, y
, setSolved
);
342 SudokuField::ValueAt(uint32 x
, uint32 y
) const
344 return _FieldAt(x
, y
).value
;
349 SudokuField::_ValidValueAt(uint32 x
, uint32 y
) const
351 uint32 value
= _FieldAt(x
, y
).value
;
355 value
= 1UL << (value
- 1);
356 return (_FieldAt(x
, y
).valid_mask
& value
) != 0;
361 SudokuField::_ComputeValidMask(uint32 x
, uint32 y
, bool setSolved
)
368 uint32 foundMask
= 0;
369 for (uint32 i
= 0; i
< fSize
; i
++) {
370 uint32 value
= ValueAt(i
, y
);
371 if (value
&& _ValidValueAt(i
, y
))
372 foundMask
|= 1UL << (value
- 1);
377 for (uint32 i
= 0; i
< fSize
; i
++) {
378 uint32 value
= ValueAt(x
, i
);
379 if (value
&& _ValidValueAt(x
, i
))
380 foundMask
|= 1UL << (value
- 1);
385 uint32 offsetX
= x
/ fBlockSize
* fBlockSize
;
386 uint32 offsetY
= y
/ fBlockSize
* fBlockSize
;
388 for (uint32 partY
= 0; partY
< fBlockSize
; partY
++) {
389 for (uint32 partX
= 0; partX
< fBlockSize
; partX
++) {
390 uint32 value
= ValueAt(partX
+ offsetX
, partY
+ offsetY
);
391 if (value
&& _ValidValueAt(partX
+ offsetX
, partY
+ offsetY
))
392 foundMask
|= 1UL << (value
- 1);
396 SetValidMaskAt(x
, y
, ~foundMask
);
399 // find the one set bit, if not more
401 for (uint32 i
= 0; i
< fSize
; i
++) {
402 if ((foundMask
& (1UL << i
)) == 0) {
412 SetValueAt(x
, y
, value
, true);
418 SudokuField::_UpdateValidMaskChanged(uint32 x
, uint32 y
, bool setSolved
)
422 for (uint32 i
= 0; i
< fSize
; i
++) {
423 _ComputeValidMask(i
, y
, setSolved
);
428 for (uint32 i
= 0; i
< fSize
; i
++) {
432 _ComputeValidMask(x
, i
, setSolved
);
437 uint32 offsetX
= x
/ fBlockSize
* fBlockSize
;
438 uint32 offsetY
= y
/ fBlockSize
* fBlockSize
;
440 for (uint32 partY
= 0; partY
< fBlockSize
; partY
++) {
441 for (uint32 partX
= 0; partX
< fBlockSize
; partX
++) {
442 if (partX
+ offsetX
== x
|| partY
+ offsetY
== y
)
445 _ComputeValidMask(partX
+ offsetX
, partY
+ offsetY
, setSolved
);
451 const SudokuField::field
&
452 SudokuField::_FieldAt(uint32 x
, uint32 y
) const
454 if (x
>= fSize
|| y
>= fSize
)
455 debugger("field outside bounds");
457 return fFields
[x
+ y
* fSize
];
462 SudokuField::_FieldAt(uint32 x
, uint32 y
)
464 if (x
>= fSize
|| y
>= fSize
)
465 debugger("field outside bounds");
467 return fFields
[x
+ y
* fSize
];