RosettaCodeData/Task/N-queens-problem/Ring/n-queens-problem.ring

689 lines
17 KiB
Plaintext

load "stdlib.ring"
load "guilib.ring"
size = 8
newSize = size
count = 0
sizeBoard = 0
Queens = list(size)
Board = []
badBoard = []
win = null
nMoves = 0
oldx = 0
oldy = 0
bWidth = 0
bHeight = 0
moveX = 550 moveY = 140 ### Open Window on Screen Position
sizeX = 800 sizeY = 800 ### Size of Window
Button = null
cmbSize = null
Pink = newlist(size,size)
Tiles = newlist(size,size)
TitleMoves = null
lineSize = null
LayoutButtonRow = list(size)
LayoutButtonMain = null
WQueen = "WQueen.png"
oPic = new QPixmap("WQueen.png")
oPicGray = new QPixmap("Gray.png")
oPicGreen = new QPixmap("Green.png")
nMoves = 0
wwidth = 0
wheight = 0
WinWidth = 0
WinHeight = 0
C_Spacing = 2
C_ButtonFirstStyle = 'border-radius:1px; color:black; background-color: rgb(229,249,203) ;' ### Square pale
###'border-style: outset; border-width: 2px; border-radius: 2px; border-color: gray;'
C_ButtonSecondStyle = 'border-radius:1px; color:black; background-color: rgb(179,200,93); ' ### Square dark
###'border-style: outset; border-width: 2px; border-radius: 2px; border-color: darkGray; '
C_ButtonPinkStyle = 'border-radius:1px; color:black; background-color: rgb(255,179,191); ' ### light pink
###'border-style: outset; border-width: 2px; border-radius: 2px; border-color: darkGray; '
app = new qApp
{
DrawWidget()
newWindow(size)
exec()
}
### FUNCTIONS
###============================================================
Func DrawWidget()
### Global definition for win
win = new qWidget()
{
# Set the Window Icon
setWindowIcon(new qIcon(new qPixmap(WQueen)))
win.setminimumwidth(700)
win.setminimumheight(700)
Button = newList(size, size) ### Internal Array with Letters
setWindowTitle('Eight Queens Game')
setStyleSheet('background-color:White')
workHeight = win.height()
fontSize = 8 + (workHeight / 100)
move(moveX, moveY)
resize(700,700)
wwidth = win.width()
wheight = win.height()
bwidth = wwidth/size
bheight = wheight/size
myfilter = new qallevents(win)
myfilter.setResizeEvent("resizeBoard()")
installeventfilter(myfilter)
###----------------------------------------------
### Title Top Row - Moves Count
TitleMoves = new qLineEdit(win)
{
setStyleSheet("background-color:rgb(255,255,204)")
setFont(new qFont("Calibri",fontsize,100,0))
setAlignment( Qt_AlignHCenter)
setAlignment( Qt_AlignVCenter)
setText(" Moves: "+ nMoves)
}
sizeBtn = new QPushButton(win)
{
setStyleSheet("background-color:rgb(255,255,204)")
setFont(new qFont("Calibri",fontsize,100,0))
setText(" Enter size: ")
}
lineSize = new qLineEdit(win)
{
setStyleSheet("background-color:rgb(255,255,204)")
setFont(new qFont("Calibri",fontsize,100,0))
setAlignment( Qt_AlignHCenter)
setAlignment( Qt_AlignVCenter)
setreturnPressedEvent("newBoardSize()")
setText(" 8 ")
}
SolveGame = new QPushButton(win)
{
setStyleSheet("background-color:rgb(255,204,229)")
setFont(new qFont("Calibri",fontsize,100,0))
setText(" Solve ")
setClickEvent("solveGame()")
}
NewGame = new QPushButton(win)
{
setStyleSheet("background-color:rgb(255,204,229)")
setFont(new qFont("Calibri",fontsize,100,0))
setText(" New ")
setClickEvent("newGame()")
}
btnQuit = new QPushButton(win)
{
setStyleSheet("background-color:rgb(255,204,229)")
setFont(new qFont("Calibri",fontsize,100,0))
setText("Exit")
setClickEvent("pQuit()")
}
###------------------------------------------------
### QVBoxLayout lays out widgets in a vertical column, from top to bottom.
### Vertical
LayoutButtonMain = new QVBoxLayout()
LayoutButtonMain.setSpacing(C_Spacing)
LayoutButtonMain.setContentsMargins(5,5,5,5)
### Horizontal - TOP ROW
LayoutTitleRow = new QHBoxLayout()
{
setSpacing(C_Spacing)
setContentsMargins(0,0,0,0)
}
LayoutTitleRow.AddWidget(TitleMoves)
LayoutTitleRow.AddWidget(sizeBtn)
LayoutTitleRow.AddWidget(lineSize)
LayoutTitleRow.AddWidget(SolveGame)
LayoutTitleRow.AddWidget(NewGame)
LayoutTitleRow.AddWidget(btnQuit)
LayoutButtonMain.AddLayout(LayoutTitleRow)
###----------------------------------------------
### BUTTON ROWS
LayoutButtonRow = list(size)
### QHBoxLayout lays out widgets in a horizontal row, from left to right
odd = 1
for Row = 1 to size
LayoutButtonRow[Row] = new QHBoxLayout() ### Horizontal
{
setSpacing(C_Spacing)
setContentsmargins(0,0,0,0)
}
for Col = 1 to size
### Create Buttons
Button[Row][Col] = new QPushButton(win)
{
if odd % 2 = 0
setStyleSheet(C_ButtonFirstStyle)
odd++
else
setStyleSheet(C_ButtonSecondStyle)
odd++
ok
setClickEvent("UserLeftClick(" + string(Row) +
"," + string(Col) + ")")
setSizePolicy(1,1)
resize(bwidth,bheight)
}
### Widget - Add HORZ BOTTON
LayoutButtonRow[Row].AddWidget(Button[Row][Col])
next
if size % 2 = 0
odd++
ok
### Layout - Add ROW of BUTTONS
LayoutButtonMain.AddLayout(LayoutButtonRow[Row])
next
###-------------------------------------------------
setLayout(LayoutButtonMain)
show()
}
return
###============================================================
func newSize()
nSize = cmbSize.currentText()
nSize = number(nSize)
count = 0
newWindow(nSize)
###============================================================
func newBoardSize()
nrSize = number(lineSize.text())
newWindow(nrSize)
###============================================================
func newWindow(newSize)
for Row = 1 to size
for Col = 1 to size
Button[Row][Col].delete()
next
next
size = newSize
nMoves = 0
TitleMoves.settext(" Moves: 0")
Tiles = newlist(size,size)
for Row = 1 to size
for Col = 1 to size
Tiles[Row][Col] = 0
next
next
wwidth = win.width()
wheight = win.height()
bwidth = wwidth/size
bheight = wheight/size
win.resize(500,500)
Button = newlist(size,size)
Pink = newlist(size,size)
LayoutButtonRow = list(size)
### QHBoxLayout lays out widgets in a horizontal row, from left to right
odd = 1
for Row = 1 to size
LayoutButtonRow[Row] = new QHBoxLayout() ### Horizontal
{
setSpacing(C_Spacing)
setContentsmargins(0,0,0,0)
}
for Col = 1 to size
### Create Buttons
Button[Row][Col] = new QPushButton(win)
{
if odd % 2 = 1
setStyleSheet(C_ButtonFirstStyle)
odd++
else
setStyleSheet(C_ButtonSecondStyle)
odd++
ok
setClickEvent("UserLeftClick(" + string(Row) +
"," + string(Col) + ")")
setSizePolicy(1,1)
resize(bwidth,bheight)
}
### Widget - Add HORZ BOTTON
LayoutButtonRow[Row].AddWidget(Button[Row][Col])
next
if size % 2 = 0
odd++
ok
### Layout - Add ROW of BUTTONS
LayoutButtonMain.AddLayout(LayoutButtonRow[Row])
next
###-------------------------------------------------
win.setLayout(LayoutButtonMain)
###============================================================
func solveGame()
newWindow(size)
for Row = 1 to size
for Col = 1 to size
Tiles[Row][Col] = 0
next
next
bwidth = (win.width() -8 ) / size // <<< QT FIX because of Win Title
bheight = (win.height() -32) / size // <<< QT FIX because of Win Title
odd = 1
for Row = 1 to size
for Col = 1 to size
if odd % 2 = 1
setButtonImage(Button[Row][Col],oPicGray,bwidth-8,bheight)
odd++
else
setButtonImage(Button[Row][Col],oPicGreen,bwidth-8,bheight)
odd++
ok
next
if size % 2 = 0
odd++
ok
next
Queens = list(20)
n = size
count = count + 1
if count = 1
Board = []
queen(1,n)
ok
sizeBoard = len(Board)/size
num = random(sizeBoard-1) + 1
see "Solution = " + num + nl
for n = (num-1)*size+1 to num*size
x = Board[n][2]
y = Board[n][1]
Tiles[x][y] = 1
setButtonImage(Button[x][y],oPic,bwidth-8,bheight)
next
###============================================================
func prn(n)
for i = 1 to n
for j = 1 to n
if Queens[i] = j
add(Board,[i,j])
ok
next
next
###============================================================
func place(row,column)
for i = 1 to row-1
if Queens[i]=column
return 0
else
if fabs(Queens[i]-column) = fabs(i-row)
return 0
ok
ok
next
return 1
###============================================================
func queen(row,n)
for column = 1 to n
if place(row,column)
Queens[row] = column
if row = n
prn(n)
else
queen(row+1,n)
ok
ok
next
###============================================================
func newGame
newWindow(size)
return
###============================================================
func canPlace Row,Col
badBoard = []
add(badBoard,[Row,Col])
bwidth = (win.width() -8 ) / size // <<< QT FIX because of Win Title
bheight = (win.height() -32) / size // <<< QT FIX because of Win Title
cp1 = 1
for n = 1 to size
if Row < 9
if n != Col and Tiles[Row][n] = 1
cp1 = 0
add(badBoard,[Row,n])
exit
ok
ok
next
cp2 = 1
for n = 1 to size
if Col < 9
if n != Row and Tiles[n][Col] = 1
cp2 = 0
add(badBoard,[n,Col])
exit
ok
ok
next
cp3 = 1
for x = 1 to size
if Row + x < size + 1 and Col - x > 0
if Tiles[Row+x][Col-x] = 1
cp3 = 0
add(badBoard,[Row+x,Col-x])
exit
ok
ok
next
cp4 = 1
for x = 1 to size
if Row - x > 0 and Col + x < size + 1
if Tiles[Row-x][Col+x] = 1
cp4 = 0
add(badBoard,[Row-x,Col+x])
exit
ok
ok
next
cp5 = 1
for x = 1 to size
if Row + x < size + 1 and Col + x < size + 1
if Tiles[Row+x][Col+x] = 1
cp5 = 0
add(badBoard,[Row+x,Col+x])
exit
ok
ok
next
cp6 = 1
for x = 1 to size
if Row - x > 0 and Col - x > 0
if Tiles[Row-x][Col-x] = 1
cp6 = 0
add(badBoard,[Row-x,Col-x])
exit
ok
ok
next
cp7 = cp1 and cp2 and cp3 and cp4 and cp5 and cp6
return cp7
###============================================================
func resizeBoard
bwidth = (win.width() - 8) / size
bheight = (win.height() - 32) / size
for Row = 1 to size
for Col = 1 to size
if Tiles[Row][Col] = 1
setButtonImage(Button[Row][Col],oPic,bwidth - 8,bheight - 8)
ok
next
next
###============================================================
func UserLeftClick Row,Col
sleep(0.3)
Tiles[Row][Col] = 1
bWidthHeight()
bool = (Row = oldx) and (Col = oldy)
cp8 = canPlace(Row,Col)
if Pink[Row][Col] = 1
Pink[Row][Col] = 0
Tiles[Row][Col] = 0
if Row % 2 = 1 and Col % 2 = 1
Button[Row][Col].setStyleSheet(C_ButtonFirstStyle)
setButtonImage(Button[Row][Col],oPicGray,bwidth-8,bheight-8)
ok
if Row % 2 = 0 and Col % 2 = 0
Button[Row][Col].setStyleSheet(C_ButtonFirstStyle)
setButtonImage(Button[Row][Col],oPicGray,bwidth-8,bheight-8)
ok
if Row % 2 = 1 and Col % 2 = 0
Button[Row][Col].setStyleSheet(C_ButtonSecondStyle)
setButtonImage(Button[Row][Col],oPicGreen,bwidth-8,bheight-8)
ok
if Row % 2 = 0 and Col % 2 = 1
Button[Row][Col].setStyleSheet(C_ButtonSecondStyle)
setButtonImage(Button[Row][Col],oPicGreen,bwidth-8,bheight-8)
ok
checkBoard()
return
ok
if cp8 = 1 and bool = 0
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight-8)
Tiles[Row][Col] = 1
nMoves = nMoves + 1
oldx = Row
oldy = Col
TitleMoves.settext(" Moves: " + nMoves)
gameOver()
ok
if cp8 = 1 and bool = 1
if Row % 2 = 1 and Col % 2 = 1
setButtonImage(Button[Row][Col],oPicGray,bwidth-8,bheight-8)
ok
if Row % 2 = 0 and Col % 2 = 0
setButtonImage(Button[Row][Col],oPicGray,bwidth-8,bheight-8)
ok
if Row % 2 = 1 and Col % 2 = 0
setButtonImage(Button[Row][Col],oPicGreen,bwidth-8,bheight-8)
ok
if Row % 2 = 0 and Col % 2 = 1
setButtonImage(Button[Row][Col],oPicGreen,bwidth-8,bheight-8)
ok
Tiles[Row][Col] = 1
ok
for Row = 1 to size
for Col = 1 to size
if Tiles[Row][Col] = 1
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight-8)
ok
next
next
if cp8 = 0
pBadCell(Row,Col)
return
ok
###============================================================
func checkBoard()
for Row = 1 to size
for Col = 1 to size
if Pink[Row][Col] = 1
cp9 = canPlace(Row,Col)
if cp9 = 0
Button[Row][Col].setStyleSheet(C_ButtonPinkStyle)
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight)
else
if Row % 2 = 1 and Col % 2 = 1
Button[Row][Col].setStyleSheet(C_ButtonFirstStyle)
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight-8)
ok
if Row % 2 = 0 and Col % 2 = 0
Button[Row][Col].setStyleSheet(C_ButtonFirstStyle)
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight-8)
ok
if Row % 2 = 1 and Col % 2 = 0
Button[Row][Col].setStyleSheet(C_ButtonSecondStyle)
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight-8)
ok
if Row % 2 = 0 and Col % 2 = 1
Button[Row][Col].setStyleSheet(C_ButtonSecondStyle)
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight-8)
ok
ok
ok
next
next
###============================================================
func pBadCell(Row,Col)
for n = 1 to len(badBoard)
Row = badBoard[n][1]
Col = badBoard[n][2]
Pink[Row][Col] = 1
Button[Row][Col].setStyleSheet(C_ButtonPinkStyle)
setButtonImage(Button[Row][Col],oPic,bwidth-8,bheight)
next
###============================================================
func setButtonImage oBtn,oPixmap,width,height
oBtn { setIcon(new qicon(oPixmap.scaled(width(),height(),0,0)))
setIconSize(new QSize(width,height))
}
###============================================================
func bWidthHeight()
bWidth = (win.width() -8 ) / size
bHeight = (win.height() -32) / size
###============================================================
func msgBox cText
mb = new qMessageBox(win) {
setWindowTitle('Eight Queens')
setText(cText)
setstandardbuttons(QMessageBox_OK)
result = exec()
}
###============================================================
func pQuit()
win.close()
###============================================================
func gameOver
total = 0
for Row = 1 to size
for Col = 1 to size
if Tiles[Row][Col] = 1
total = total + 1
ok
next
next
if total = size
for Row = 1 to size
for Col = 1 to size
Button[Row][Col].setenabled(false)
next
next
msgBox("You Win!")
ok
###============================================================