#  HueFiend, by Nils Veidis, 2017
#  First independent coding project (UC Berkeley)

difficulty = {"Beginner": 4, "Easy": 5, "Medium": 8, "Hard": 10} #value=how many squares per row
valid_difficulty = False #has the user selected a valid difficulty ("Beginner", "Easy", ...)

while valid_difficulty == False:
difficulty_selected = input("Select a difficulty: Beginner, Easy, Medium, or Hard? ")
if difficulty_selected in difficulty:
valid_difficulty = True
else:
print("Please select Beginner, Easy, Medium, or Hard.")

if valid_difficulty == True: #user chooses both corner colors w R G B values
color1 = []
color2 = []
RGB = ["R", "G", "B"]
for value in RGB:
not_color_chosen = True
while not_color_chosen:
color_selected = input("Input "+ value +" value of first color: ")
if not color_selected.isalpha() and int(color_selected) <= 255 and int(color_selected) >= 0:
color1.append(int(color_selected))
not_color_chosen = False
else:
print("Please insert an R G B value between 0 and 255.")
for value in RGB:
not_color_chosen = True
while not_color_chosen:
color_selected = input("Input "+ value +" value of second color: ")
if not color_selected.isalpha() and int(color_selected) <= 255 and int(color_selected) >= 0:
color2.append(int(color_selected))
not_color_chosen = False
else:
print("Please insert an R G B value between 0 and 255.")

import random #for board shuffling
import copy #for ".deepcopy" function of game_winning_board

import pygame
pygame.init()

BLACK = (  0,   0,   0)
WHITE = (255, 255, 255)

screen_width = 800
screen_height = 800
size = [screen_width, screen_height]
screen = pygame.display.set_mode(size)
pygame.display.set_caption("I Love Hue")

margin = 0 #thickness of borders / outline

square_width = (screen_width / difficulty[difficulty_selected])-margin
square_height = (screen_height / difficulty[difficulty_selected])-margin

grid = [] #a list of coordinates that corresponds to the grid size selected
#(e.g. (0,0) = upper left block, (0,1) = 1 block to the right, (1,0) = one block below)
for x in range(difficulty[difficulty_selected]):
n = 0
while n != difficulty[difficulty_selected]:
grid.append([x])
n += 1
y = 0
for lst in grid[:]:
if y < difficulty[difficulty_selected]:
lst.append(y)
y += 1
elif y >= difficulty[difficulty_selected]:
y = 0
lst.append(y)
y += 1

grid_colors = [] #live grid (mutable)
game_winning_grid = [] #fixed correctly completed grid (fixed)

square_x = 0 #connects coordinate number of square to RGB value
square_y = 0
def draw_row(row_number, leftmost_color, last_color):
global grid_colors
global game_winning_grid
global square_x
global square_y
left_color = leftmost_color[:]
end_color = last_color[:] #FIXED END
start_color = left_color[:] #FIXED STARTING COLOR
for r in range(difficulty[difficulty_selected]):
x_coord = (margin + square_width) * r + margin
y_coord = (margin + square_height) * int(row_number) + margin
pygame.draw.rect(screen, left_color, [x_coord, y_coord, square_width, square_height])
grid_colors.append([left_color, left_color, left_color, square_x, square_y])
left_color = abs(left_color - (abs(start_color - end_color)) // (difficulty[difficulty_selected]-1))
left_color = abs(left_color - (abs(start_color - end_color)) // (difficulty[difficulty_selected]-1))
left_color = abs(left_color - (abs(start_color - end_color)) // (difficulty[difficulty_selected]-1))
square_y += 1
square_x += 1
square_y = 0
game_winning_grid = copy.deepcopy(grid_colors[:])
pygame.display.update()

def draw_board(top_left, bottom_left, top_right, bottom_right):
global square_x
global square_y
tl_color = top_left[:] #FIXED STARTING COLOR (tl = top left)
tr_color = top_right[:] #FIXED ENDING COLOR (tr = top right)
for x in range(difficulty[difficulty_selected]):
draw_row(x, top_left, top_right)
top_left = top_left - (abs(tl_color - bottom_left)) // (difficulty[difficulty_selected]-1)
top_left = top_left - (abs(tl_color - bottom_left)) // (difficulty[difficulty_selected]-1)
top_left = top_left - (abs(tl_color - bottom_left)) // (difficulty[difficulty_selected]-1)
top_right = top_right - (abs(tr_color - bottom_right)) // (difficulty[difficulty_selected]-1)
top_right = top_right - (abs(tr_color - bottom_right)) // (difficulty[difficulty_selected]-1)
top_right = top_right - (abs(tr_color - bottom_right)) // (difficulty[difficulty_selected]-1)
square_x = 0
square_y = 0
pygame.display.update()

def grid_to_board(): #takes in grid_color list and translates the list contents (i.e. R B G values) to new visual board
global square_x
global square_y
global grid_colors
i = 0
for x in range(difficulty[difficulty_selected]):
for y in range(difficulty[difficulty_selected]):
x_coordinate = (screen_height // difficulty[difficulty_selected]) * y + margin
y_coordinate = (screen_width // difficulty[difficulty_selected]) * x + margin
pygame.draw.rect(screen, grid_colors[i][:3], [x_coordinate, y_coordinate, square_width, square_height])
#print(grid_colors[i][3:]) #TO CHECK IF COORDINATE RECORDING WORKS PROPERLY
i += 1
pygame.display.update()

def switch_board(first_block_coordinates, second_block_coordinates): #switches the locations of two valid square selections
global grid_colors
global moves
sq1 = False
sq2 = False
corner_squares = [0, (difficulty[difficulty_selected] - 1), ((difficulty[difficulty_selected]**2)-1) - (difficulty[difficulty_selected] - 1), difficulty[difficulty_selected]**2 - 1]
for num in range(difficulty[difficulty_selected]**2 - 1):
if num not in corner_squares:
if grid_colors[num] == first_block_coordinates and grid_colors[num] == first_block_coordinates:
sq1 = num
if grid_colors[num] == second_block_coordinates and grid_colors[num] == second_block_coordinates:
sq2 = num
if sq1 != False and sq2 != False:
grid_colors[sq1][:3], grid_colors[sq2][:3] = grid_colors[sq2][:3], grid_colors[sq1][:3]
grid_to_board()
else:
print("You cannot alter a corner square. They are your guide!")
moves -= 1 #don't want to count a move if the move was used on an invalid corner_square selection

def shuffle_board(): #randomizes the positions of all squares except four corners
four_corner_squares = [0, (difficulty[difficulty_selected] - 1), ((difficulty[difficulty_selected]**2)-1) - (difficulty[difficulty_selected] - 1), difficulty[difficulty_selected]**2 - 1]
for each_square in grid_colors[:]:
if each_square not in four_corner_squares:
first_square = random.randint(0, difficulty[difficulty_selected]**2-1)
second_square = random.randint(0, difficulty[difficulty_selected]**2-1)
if first_square not in four_corner_squares and second_square not in four_corner_squares:
grid_colors[first_square][:3], grid_colors[second_square][:3] = grid_colors[second_square][:3], grid_colors[first_square][:3]
pygame.display.update()

start_game = False
board_drawn = False
block_chosen = False

for event in pygame.event.get():
if event.type == pygame.QUIT:
pygame.quit()
sys.exit() #is supposed to exit the "system" / window - change "sys" to respective system name
elif board_drawn == False:
WHITE_upper_left = [255,255,255]
lower_left = color1
upper_right = color2
BLACK_lower_right = [0,0,0]
draw_board(list(WHITE_upper_left), list(lower_left), list(upper_right), list(BLACK_lower_right))
if event.type == pygame.MOUSEBUTTONDOWN:
shuffle_board()
grid_to_board()
board_drawn = True
start_game = True #STARTS NEXT "WHILE" LOOP

moves = 0

while start_game:
global row
global column
global row2
global column2
for event in pygame.event.get():
if event.type == pygame.QUIT:
moves = 0
pygame.quit()
sys.exit()
elif event.type == pygame.MOUSEBUTTONDOWN and block_chosen == False:
block_chosen = True
pos = pygame.mouse.get_pos()
column = pos // (square_width + margin)
row = pos // (square_height + margin)
block1_row = (screen_height // difficulty[difficulty_selected]) * row #LeftHand corner of block that the click is contained in (so selected rectangle draws in correct spot)
block1_column = (screen_width // difficulty[difficulty_selected]) * column
block_1 = [block1_row, block1_column]
pygame.draw.rect(screen, WHITE, [block_1 + margin, block_1 + margin, square_width, square_height], 2) #outlines the first selected square
pygame.display.update()
elif event.type == pygame.MOUSEBUTTONDOWN and block_chosen == True:
pos2 = pygame.mouse.get_pos()
column2 = pos2 // (square_width + margin)
row2 = pos2 // (square_height + margin)
switch_board([row, column], [row2, column2])
block_chosen = False
moves += 1
pygame.display.update()
if grid_colors[:] == game_winning_grid[:]:
print("CONGRATULATIONS! You completed the grid in "+ str(moves) +" moves!")
moves = 0
pygame.quit()
start_game = False