import pygame
import sys
import os
import random
import timefrom pygame.locals import *import tkinterastkfrom tkinter import *import tkinter.messagebox # 要使用messagebox先要导入模块classEight_queen:
queens= 0sts= 0pows=None
def __init__(self,queens):
Eight_queen.queens=queens
Eight_queen.pows= [pow(queens,queens-i) for i in range(0,queens+1)]
Eight_queen.sts= 0@staticmethod
def check(rows):for row in range(1,len(rows)):for i inrange(row):if abs(rows[i] - rows[row]) in (0, row -i):returnrowreturn 0@staticmethod
def queen_next_rows():if Eight_queen.sts >= Eight_queen.pows[0]:returnNone
n=Eight_queen.queens
rows= [0]*nfor x in range(0,n):
rows[x]=(Eight_queen.sts%Eight_queen.pows[x])//Eight_queen.pows[x+1]
err_row =Eight_queen.check(rows)if err_row == 0:
Eight_queen.sts+= 1
return [0,rows]else:
Eight_queen.sts+= Eight_queen.pows[err_row+1]return [1,rows]classCMG: #画面显示管理
screen=None
map=None
gameAnswer=None
WHITE= (255, 255, 255)
GREEN= (0, 255, 0)
RED= (255, 0, 0)
YELLOW= (255, 255, 0)
blocksize= 0step= 0last_answer=None
backgr=None
screen_rect=None
def __init__(self,screen):#if CMG.screen == None:#print("#############OS.PATH=%s"%os.path.dirname(os.path.abspath(__file__)))
CMG.screen=screen
CMG.blocksize= 350//Eight_queen.queens
CMG.screen_rect =None
#如果存在对象成员
self.init_game_info()
def init_game_info(self):
pass
def printAll(self,res):#if CMG.step > len(CMG.gameAnswer):#returnrtn= res[0]
rows= res[1]if rtn == 0:
CMG.last_answer=rows[:]
CMG.screen.fill((0, 0, 0))
queens=Eight_queen.queensif CMG.screen_rect ==None:for x in range(0,queens+1):
end_pos= [(x*CMG.blocksize,0),(x*CMG.blocksize,queens*CMG.blocksize)]
pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)
end_pos= [(x*CMG.blocksize+400,0),(x*CMG.blocksize+400,queens*CMG.blocksize)]
pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)for y in range(0,queens+1):
end_pos= [(0,y*CMG.blocksize),(queens*CMG.blocksize,y*CMG.blocksize)]
pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)
end_pos= [(400,y*CMG.blocksize),(400+queens*CMG.blocksize,y*CMG.blocksize)]
pygame.draw.lines(CMG.screen, CMG.GREEN,0 , end_pos, 2)
select_rect= CMG.screen.subsurface(0,0,800,570)
CMG.screen_rect=select_rect.copy()else:
self.screen.blit(CMG.screen_rect,(0,0))for r in range(0,len(rows)):
y= r*CMG.blocksize + 3x= rows[r] *CMG.blocksize + 3pygame.draw.rect(CMG.screen, CMG.WHITE, ((x,y), (CMG.blocksize-6, CMG.blocksize-6)), 0)if CMG.last_answer !=None:
rows=CMG.last_answerfor r in range(0,len(rows)):
y= r*CMG.blocksize + 3x= rows[r] *CMG.blocksize + 403pygame.draw.rect(CMG.screen, CMG.YELLOW, ((x,y), (CMG.blocksize-6, CMG.blocksize-6)), 0)
#CMG.step+= 1def moveAll(self):
pass
#------------------------------------------------#tkinter,pygame混合区 START
#------------------------------------------------root=tk.Tk()
root.resizable(0,0)
embed= tk.Frame(root, width = 800, height = 570) #creates embed frame forpygame window
embed.grid(columnspan= (800), rowspan = 730) # Adds grid
embed.pack(side=TOP) #packs window to the left
buttonwin= tk.Frame(root, width = 800, height = 150)
buttonwin.pack(side=BOTTOM)
os.environ['SDL_WINDOWID'] =str(embed.winfo_id())
os.environ['SDL_VIDEODRIVER'] = 'windib'screen= pygame.display.set_mode((800,570))
#pygame.init()
pygame.display.init()
pygame.mixer.init()
#------------------------------------------------#tkinter,pygame混合区 END
#------------------------------------------------#参数,因为函数内要使用之外的变量,需要globe,因此全部打包classPARAM:
STATUS= 0TICK_NORMAL= 5TICK_STEP= 30#按钮动作区=====================================def get_input_data(inputcell,min,max):if inputcell.get().isdigit():
num= int(inputcell.get())if min<=num and num<=max:returnnumreturn -1def exit_game():globalparam
param.STATUS= 100def stop_game():globalparam
param.STATUS= 10def sel_game():globalparam
qs= get_input_data(inputqs,4,9)
speed= get_input_data(inputspd,11,99)if qs == -1 or speed == -1:return
else:
eq=Eight_queen(qs)
param.cmg=CMG(screen)
PARAM.TICK_STEP=speed
param.STATUS= 0#控件定义区=====================================button_stop_b= Button(buttonwin,text = '本次演示结束', width=11, command=stop_game)
button_stop_b.place(x=700,y=30)
btnwin_qs_l= tk.Label(buttonwin, text='皇后数(4-9):')
btnwin_qs_l.place(x=530,y=70)
inputqs=StringVar()
btnwin_qs_e= tk.Entry(buttonwin, show=None,width=2,textvariable =inputqs)
btnwin_qs_e.place(x=590,y=70)
btnwin_spd_l= tk.Label(buttonwin, text='演示速度(11-99):')
btnwin_spd_l.place(x=610,y=70)
inputspd=StringVar()
btnwin_spd_e= tk.Entry(buttonwin, show=None,width=3,textvariable =inputspd)
btnwin_spd_e.place(x=710,y=70)
button_sel_b= Button(buttonwin,text = '执行', width=7, command=sel_game)
button_sel_b.place(x=740,y=65)
button_exit_b= Button(buttonwin,text = '退出画面', width=7, command=exit_game)
button_exit_b.place(x=740,y=100)
#状态,参数,循环中使用,比如STATUS=0:初次进入,1:...100:退出
param=PARAM()
eq= Eight_queen(6)
param.cmg=CMG(screen)
#------------------------------------------------#主函数,使用pygame框架,无限LOOP对各种事件然后相应处理
#------------------------------------------------def main():globalparam
#pygame.mixer.music.play(-1)
clock=pygame.time.Clock()whileTrue:
#这段event代码是必须的,哪怕在这个程序中不需要,不执行的话整个框架转不动for event in pygame.event.get():if event.type ==QUIT:
sys.exit()
#画面按钮按下后,修改param.STATUS,实际动作这里实现if param.STATUS == 100:
#退出按钮if tk.messagebox.askokcancel('提示', '要退出画面吗'):breakparam.STATUS= 0elif param.STATUS== 10:
pass
elif param.STATUS== 0:
res=Eight_queen.queen_next_rows()if res !=None:
param.cmg.printAll(res)else:
STATUS= 10#显示游戏画面
pygame.display.flip()
#设置帧率:长期画面不操作,设置成最闲if param.STATUS == 0:
clock.tick(param.TICK_STEP)else:
clock.tick(param.TICK_NORMAL)
root.update()
main()