Το πρόβλημα των βασιλισσών

Το πρόβλημα των βασιλισσών

Βρείτε τις πιθανές θέσεις σε μια σκακιέρα όπου 8 βασίλισσες είναι τοποθετημένες έτσι ώστε καμία να μην απειλείται από την άλλη.


Ένα γνωστό σε πολλούς πρόβλημα το οποίο δεν είναι και πολύ εύκολο.

Φανταστείτε τώρα η σκακιέρα να μην είναι 8x8 αλλά 15x15 ή οτιδήποτε άλλο και έστω οι βασίλισσες 13. το πρόβλημα θα γίνει αρκετά δύσκολο για όλους μας.

Το παρακάτω πρόγραμμα δίνει όλες τις λύσεις για 1-15 βασίλισσες και για σκακιέρα 1x1 έως 100x100, αρκεί βέβαια να υπάρχει λύση. Μην ζητήσει κανείς την λύση για 6 βασίλισσες και σκακιέρα 3x3, σίγουρα δεν υπάρχει!

Οι θέσεις των βασιλισσών θα εμφανιστούν με κόκκινο χρώμα. Ενώ με μαύρο τις θέσεις εκείνες που ελέγχουν μία ή παραπάνω βασίλισσες και με μπλε εκείνες που είναι τελείως ελεύθερες

Δεν θα πω τίποτα για τον κώδικα – ούτως η άλλος σε μερικά σημεία είναι «ελαφρώς» ακατανόητος ακόμα και για μένα που το έγραψα πριν λίγους μήνες !

Θα πώς όμως αρκετά για την επόμενη έκδοση του προγράμματος σε κάποιο άλλο σημείο. Προς το παρόν σας δίνω τον κώδικα το οποίο έχει μερικά προβληματάκια και που θα τα σχολιάσουμε σε επόμενο tutorial.

Γραμμένο σε Visual Basic 6

DefInt A-Z

Private queens ‘= 5 ‘1-15
Private MAX ‘= 4 ‘megethos skakieras
Private PINAK(100, 100) As Long ‘max tablo=100

Private pause

Private Sub Command1_Click()

If queens <> Val(Combo1.Text) Or (MAX <> Val(Combo2.Text)) Then
‘MsgBox “rtg”
Erase PINAK()
End If

queens = Combo1.Text
MAX = Combo2.Text
Pic.AutoRedraw = True
Pic.Cls

pause = 0


‘*** dokimes

‘PINAK(1, 2) = 2 ^ (8 + 0)
‘PINAK(2, 3) = 2 ^ (8 + 1)
‘PINAK(3, 4) = 2 ^ (8 + 2)
‘PINAK(4, 5) = 2 ^ (8 + 3)
‘PINAK(5, 6) = 2 ^ (8 + 4)
‘PINAK(6, 7) = 2 ^ (8 + 5)
‘PINAK(7, 8) = 2 ^ (8 + 6)
‘PINAK(8, 1) = 2 ^ (8 + 7)

Call FIND(0) ‘ εκκίνηση

End Sub

Private Function FIND(LEVEL)

param = queens
‘MsgBox PINAK(1, 1)

Do
DoEvents
If pause = 0 Then Exit Do

Loop

start:

‘MsgBox LEVEL
‘MsgBox (2 ^ (2 * queens) – 2 ^ (queens))

If LEVEL = queens Then
kl = 0
‘Pic.Cls

For y = 1 To MAX
For x = 1 To MAX

ISO = Pic.ScaleWidth / (MAX + 2)

Pic.DrawWidth = 12
Pic.Circle (x * ISO, y * ISO), ISO / 5, Pic.BackColor

If PINAK(y, x) And (2 ^ param – 1) Then Pic.Circle (x * ISO, y * ISO), ISO / 5, RGB(0, 0, 0)

If PINAK(y, x) And (2 ^ (2 * param) – 2 ^ (param)) Then ‘65280 gia 8 basilises
Pic.Circle (x * ISO, y * ISO), ISO / 5, RGB(200, 0, 0)
fg$ = LTrim$(Str$(Log(PINAK(y, x) And (2 ^ (2 * param) – 2 ^ (param))) / Log(2) – (param – 1)))
SX = Pic.TextWidth(fg$)
SY = Pic.TextHeight(” “)
Pic.CurrentX = x * ISO – SX / 2
Pic.CurrentY = y * ISO – SY / 2
Pic.ForeColor = RGB(255, 255, 255)
Pic.Print fg$

‘MsgBox fg$
‘MsgBox Log((PINAK(Y, X) And 65280) – 255) / Log(2)

kl = kl + 1
End If

Next x
Next y

Pic.Refresh

End If

If LEVEL = -1 Then MsgBox (“ADINATO na simvei”): End

If LEVEL = queens Then
‘MsgBox (“FOUND A SOLUTION!”)
FIND = LEVEL – 1: Exit Function
End If

‘VRES AN IPARXI IDI

find_x = 0
FIND_Y = 0

For y = 1 To MAX
For x = 1 To MAX

If (PINAK(y, x) And 2 ^ (LEVEL + queens)) Then
find_x = x
FIND_Y = y
Exit For
End If

Next x
Next y

‘If LEVEL = 7 Then MsgBox find_x
‘AN IPARXEI APEKATASTASI

If find_x > 0 Then

PINAK(FIND_Y, find_x) = PINAK(FIND_Y, find_x) Xor (2 ^ (LEVEL + queens))

For B = 1 To MAX
For a = 1 To MAX

If PINAK(B, a) And (2 ^ LEVEL) Then
PINAK(B, a) = PINAK(B, a) Xor (2 ^ LEVEL)
End If

Next a
Next B

End If

‘If LEVEL = 1 Then MsgBox find_x

‘VRES EPOMENI THESI

If FIND_Y = 0 Then FIND_Y = 1
find_x = find_x + 1
If find_x > MAX Then find_x = 1: FIND_Y = FIND_Y + 1
If FIND_Y > MAX Then
FIND = LEVEL – 1
Exit Function
End If

y = FIND_Y
x = find_x

‘MsgBox “X ” & X
‘MsgBox “Y ” & Y

Do

If x > MAX Then x = 1: y = y + 1
If y > MAX Then
FIND = LEVEL – 1
Exit Function
End If

‘ELENXOS AN APILEITAI

IS_APILI = False

If PINAK(y, x) > 0 Then IS_APILI = True

‘ AN DEN APILEITE TOTE

If IS_APILI = False Then

For X1 = 1 To MAX
PINAK(y, X1) = PINAK(y, X1) Or 2 ^ (LEVEL)
Next X1

‘KATHETA

For Y1 = 1 To MAX
PINAK(Y1, x) = PINAK(Y1, x) Or 2 ^ (LEVEL)
Next Y1

‘DIAGONIA
L_X = x – y + 1
For L_Y = 1 To MAX
L_X2 = 2 * x – L_X

‘DIAG_1

If L_X > 0 And L_X <= MAX Then
PINAK(L_Y, L_X) = PINAK(L_Y, L_X) Or 2 ^ (LEVEL)
End If

‘DIAG 2
If L_X2 > 0 And L_X2 <= MAX Then
PINAK(L_Y, L_X2) = PINAK(L_Y, L_X2) Or 2 ^ (LEVEL)
End If
L_X = L_X + 1
Next L_Y

PINAK(y, x) = PINAK(y, x) Or 2 ^ (LEVEL + queens)
PINAK(y, x) = PINAK(y, x) Or 2 ^ (LEVEL)

‘TELOS KATAXORISIS
LEVEL = FIND(LEVEL + 1)
‘If LEVEL = 7 Then MsgBox “a”

GoTo start
End If ‘TELOS TOU AN DEN APILITE
x = x + 1

Loop


End Function

Private Sub Command2_Click()

If pause = 0 Then pause = 1: Exit Sub
If pause = 1 Then pause = 0

End Sub

Private Sub Form_Load()

For a = 1 To 15
Combo1.AddItem a

Next
Combo1.ListIndex = 8

For a = 1 To 100
Combo2.AddItem a
Next

Combo2.ListIndex = 11

End Sub

Private Sub Form_Unload(Cancel As Integer)
End ‘αν και φαίνεται περιττό εντούτοις δεν είναι
Εnd Sub
Blog Widget by LinkWithin

Post to Twitter Post to Delicious Delicious



χωρίς σχόλια »

χωρίς σχόλια

RSS για τα σχόλια αυτού του άρθρου | TrackBack URL

γράψτε ένα σχόλιο