From 29dc2a19ea0dc90485d048d4bc2356e15900d85a Mon Sep 17 00:00:00 2001 From: Skullheadx <94652084+Skullheadx@users.noreply.github.com> Date: Fri, 2 Jun 2023 22:26:30 -0400 Subject: [PATCH] polish --- README.md | 5 +- assets/1.png | Bin 0 -> 398 bytes assets/2.png | Bin 0 -> 399 bytes assets/3.png | Bin 0 -> 396 bytes assets/4.png | Bin 0 -> 400 bytes assets/5.png | Bin 0 -> 399 bytes assets/6.png | Bin 0 -> 398 bytes assets/7.png | Bin 0 -> 396 bytes assets/8.png | Bin 0 -> 396 bytes assets/bomb.png | Bin 0 -> 434 bytes assets/empty.png | Bin 0 -> 354 bytes assets/explosion.png | Bin 0 -> 434 bytes assets/flag.png | Bin 0 -> 395 bytes assets/minesweeper.png | Bin 0 -> 929 bytes assets/outline.png | Bin 0 -> 390 bytes assets/undiscovered.png | Bin 0 -> 371 bytes assets/undiscovered_bomb.png | Bin 0 -> 457 bytes game.py | 42 +++--- grid.py | 248 ++++++++++++++++++++--------------- main.py | 33 +++-- menus.py | 70 +++++----- setup.py | 7 +- 22 files changed, 221 insertions(+), 184 deletions(-) create mode 100644 assets/1.png create mode 100644 assets/2.png create mode 100644 assets/3.png create mode 100644 assets/4.png create mode 100644 assets/5.png create mode 100644 assets/6.png create mode 100644 assets/7.png create mode 100644 assets/8.png create mode 100644 assets/bomb.png create mode 100644 assets/empty.png create mode 100644 assets/explosion.png create mode 100644 assets/flag.png create mode 100644 assets/minesweeper.png create mode 100644 assets/outline.png create mode 100644 assets/undiscovered.png create mode 100644 assets/undiscovered_bomb.png diff --git a/README.md b/README.md index 46dc5b0..6e272d3 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,5 @@ # Minesweeper - + +## CREDITS + +assets: https://kia.itch.io/16x16-tileset-for-minesweeper \ No newline at end of file diff --git a/assets/1.png b/assets/1.png new file mode 100644 index 0000000000000000000000000000000000000000..868d97ae67f1431b10415347eb9356a9fe679dd7 GIT binary patch literal 398 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;Gl0Z&=PgZPU|>-4ba4#fxSq_x%EZRb#^%P;w35-I!1O=_ zM^iSVa+s{bVul(8&f>r=s*@QQ7*tDKBT7;dOH!?pi&7IyQW=a4jEr>+%ybQmLktY9 zj7_YJ%(M**tPBj^&We16q9HdwB{QuOw}v^#ABHh7FlfMSD9OxCEiOsSEnqOTG&j&S gFw`|L3;~;MWnciYWZf38t02#Ky85}Sb4q9e0DYcfPyhe` literal 0 HcmV?d00001 diff --git a/assets/2.png b/assets/2.png new file mode 100644 index 0000000000000000000000000000000000000000..e492676a5afd02760b16dc7b88f9e6dbf3fa0dbe GIT binary patch literal 399 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;gI(xbXY`DLfkD~R#W95AdNKzq6B|1ln;TD4Hsgc`41zq| z2{C#*Sj1!%7BjSVakhu&)+#YDFsPQeMwFx^mZVxG7o{eaq%s&87#ZstnCTiAhZq=I z8Jk!cnQ0psSQ!|+ofY{CMMG|WN@iLmZVhveKMZ4FV9Oov iV5nri%D@0($+|6GR~Z->7(8A5T-G@yGywplDq=qX literal 0 HcmV?d00001 diff --git a/assets/3.png b/assets/3.png new file mode 100644 index 0000000000000000000000000000000000000000..cfccd11dc200a6f0b70e866f461c64b365d308db GIT binary patch literal 396 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;D}cn_#CIit9OLQY7{YNqnS+&yjh&6nji)J_v4d58#si%W zmSubs0vV=G;NsQQ%-zkvz@S><8c~vxSdwa$T$GwvlFDFYU}UUoV5Vze9AaQ-Wo%+) zWTtIkU}a$Nc2?vo6b-rgDVb@NxHZf<{xFPzfk6XqLrG?CYH>+oZUKX#rMZEwfuXK} eVF=i4D+2?FCF{0$U1eZkVDNPHb6Mw<&;$TsA7YyT literal 0 HcmV?d00001 diff --git a/assets/4.png b/assets/4.png new file mode 100644 index 0000000000000000000000000000000000000000..57a52b3907c266a44f4895c31963a1dfc01527db GIT binary patch literal 400 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;8-T=m_RBtEU|>-3ba4#fxSq_x%EZRb#^&ae#5f@#h(RbO zA&Jq4$0^|zgCr|MrV1zT-A(?X3=9maC9V-ADTyViR>?)Fi6yBFMg~U4x&~&t2F4)< zhE~QVRz_yp1_o9J25)CYzCzKEo1c=IR*74~oZ}C}7#J8d;5L+G=B5^xB<2<{7+RVe j=o%R68W@Iv&9*WyfLO9_i`P{K1_lOCS3j3^P6&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;Gk_ey?LPGc0|SGyr;B3<$Ms|mRwg!fHa0h&rfkNJga$z# z?gW-_X5}zhg~bf9mpJx&_dmJHz`&qd;u=wsl30>zm0XmXSdz+MWME{hYhb2pU>ss# zXk~0-Wn`vpU|?ln@OD<@D-;d6`6-!cmAEy`IsPz=fq_8-ZbM0CZfbE!Vr~J0p{2Qj hu7RPhfnf;PY%2o;h$ZW`c!6BS;OXk;vd$@?2>=iTV+8;J literal 0 HcmV?d00001 diff --git a/assets/6.png b/assets/6.png new file mode 100644 index 0000000000000000000000000000000000000000..711d2e87c14093beaa67a38beb504aaa08db30d8 GIT binary patch literal 398 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;gIuVPy`0I5fq_BE)5S4_<9ad&D-#<#8=D(XQzqkt2T2XW z3G0}8T3y*sXfOl?aAZ$D+x~=sfkCyzHKHUXu_VnC}Q!>*kach`!{9zaa1A_+KhLX(O)Z&uF+yVweOLGHV i14CT{!w|69Rt5$TOV(}iy2`-7z~JfX=d#Wzp$P!CsAMw$ literal 0 HcmV?d00001 diff --git a/assets/7.png b/assets/7.png new file mode 100644 index 0000000000000000000000000000000000000000..9db50037e725b15cf86652600d7faca1644088d2 GIT binary patch literal 396 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;D}Wqvs%_U95bf#W7{YNqnS+&yjh&6nji)J_v4d58hExED zj+KKOBSXh0&gJUQ>{=KY7*tDKBT7;dOH!?pi&7IyQW=a4jEr>+%ybQmLktY9j7_YJ z%(M**tPBj^&We16q9HdwB{QuOw}v^#ABHh7FlfMSD9OxCEiOsSEnqOTG&j&SFw`|L d3;~;MWnciYWZf38s|*Yb44$rjF6*2UngD}5V!Z$W literal 0 HcmV?d00001 diff --git a/assets/8.png b/assets/8.png new file mode 100644 index 0000000000000000000000000000000000000000..a6132a84bf6c8185b3ec4360a5abe8e8484d467b GIT binary patch literal 396 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`fy6 zVl3j@335$xqF)&U1A_w;8-N_KDoxi9M0>h8hHzX@=3r%FV`pP?<7vuf>*4 z_6YK2V5m}KU}$JzVEDzrz|io5fuYoZf#FpG1B2BJ1_tqhIlBUF7#J8t1AIbU85kIf zBE!C&Ra=v-W@%}uprG*o|NmUMLp%%&42&f~e!&b5&u*lFI7!~_E^LWuJ8Bsi7}!fZ zeO=j~voSNuE1S$e#}9H=a-v@u0|SEt6f=N;f#y~aW$WqU7{YNqIl+Og$H_;ajbSn4 zjI_c8rtS@GZEOv!PK^vo3S5FoygaQ2PRoX6ME`i6-?W}TqdCA|}I z3=9maC9V-ADTyViR>?)Fi6yBFMg~U4x&~&t2F4)r2<1_o9J2H!q*tVPj~ zo1c=IR*73f`x*m51_lNVxD6$lxv9k^iMa&~hL+|Ax(0^228JPEv#ksaAeOA#;&m0| NKTlUbmvv4FO#pqZaPa^D literal 0 HcmV?d00001 diff --git a/assets/empty.png b/assets/empty.png new file mode 100644 index 0000000000000000000000000000000000000000..ed005e1b04baa1b4a01b4dfe51f0242baf434fb7 GIT binary patch literal 354 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdMg|532J?PsvQH#I0e@@rPjy3=A4@8%i>BQ;SOy pa|;*@EzJ#d4GeV+3`4+XTNxNYELpe3>nbSlJYD@<);T3K0RW;%RB8YK literal 0 HcmV?d00001 diff --git a/assets/explosion.png b/assets/explosion.png new file mode 100644 index 0000000000000000000000000000000000000000..a326251a67aa3a4a8c1fb29bc2499017f4ca5452 GIT binary patch literal 434 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7&v6p!Iy0SlKV`h}M zR{tCp335$xqF)&U1A_w;8!#|1Fihm&ZDU|yaPxF=4B@z*oWQ^=rjVABz!=2G=#ch+ zMPcGIsRIXQh@L#4uq%r*z%09of!X;Qix}In4I&EDLq%3}w_arQ;NoET%H_br#1LT4 z{?DPy$C!bELAAs+q9i4;B-JXpC^fMpmBGls$XM6FOxM6T#K6$X*wD(bP0l+XkKK4Ni6 literal 0 HcmV?d00001 diff --git a/assets/flag.png b/assets/flag.png new file mode 100644 index 0000000000000000000000000000000000000000..0757b988c5810f0c167cca3179cd485abcd5d80f GIT binary patch literal 395 zcmeAS@N?(olHy`uVBq!ia0y~yU=RRdCT0c(hNQXTpBNYzSkfJR9T^xl_H+M9WMyDr zP)PO&@?~JCQe$9fXklRZ#lXPO@PdJ%)PRBERRRNp)eHs(@q#(K0&N%=7s4a*JP{x|Nnp8W1cw-3=E7VL4Lsu4$p3+fjCLt?k>!NJU$@X*h@TpUD=0{ dT?4}qu-R4yP)pWr@wy7~h^MQc%Q~loCII3AVfz38 literal 0 HcmV?d00001 diff --git a/assets/minesweeper.png b/assets/minesweeper.png new file mode 100644 index 0000000000000000000000000000000000000000..3c7f8e10f303c64d823db6eec8e3672b759a4cf8 GIT binary patch literal 929 zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hEk44ofy`glX=O&z#Q%A z;uumf=WVoYx0Itq9gotCPqUIA@=X(oUeeu^xO+>v;#pU*H-}nRzxgAodFj?KX1>Xn z_HQUqcp1c@-qfh-&U1rf<4lpX5}ES!wDPj@p56R1o8>>B+w=Z&orUpo2Tsc>+5Rt9 za*@5VOblB@4{pmn^e=V&Q@gg8-74RLY;;+g1|iH|a!7E4>iTdU&03?=Az$TXFZheuw>JS9+RrTTSWx-5t6$U**5e zi=5V~z`?gJ^}@-AucH$>dOt2cc*(zDJ>x!9a=s7`>!wjsXyr=qiL4O4c9{%AJ%J}>PnDlO{v{qzcM#kkTbHuzrCzJ zXkkjr)u~s48dRS?{cUQuf9=D=bN8(0nkD|cCHL?F{f36Q(<6hH91Shk%)V_F*(>W5 zz5b!ZP2mk~Zo18_7h(_3zQN-vIqlZ57b1ZlrC8J5+ZonxJo)i|q}}w^3x;w0u)bpETYToVUVXg>l#9*QZ`P zU2Qxha>AMMa&k%>OR1A(zevz3Myq)dy|R;B>{iCaxGZaUDK#OC*E5EtyJ-@`Wv&@+ z54Rs~?Qi&GqpQ?3yt>&37)yc9O-QK|KdFM7kvx0qJJnw2qi=@Ue@?i*>JI6 zBjNw;7oG)AU(B3v)86gTf%#{JPqI2TXg@cdwtt`Mr2XIfTN+FX-XDMce&_6ODI5$9 z$Cob++V3xaKWFi>5A&H+8JCF~^g*4 z_6YK2V5m}KU}$JzVEDzrz|io5fuYoZf#FpG1B2BJ1_tqhIlBUF7#JA%1AIbUch`rn z$yN(9QZtqj|NsBL_{G`s3=9m6N#5=*Ed3cb0~r_?*h@TpUD=3o!Qi^#suc_j3?iN`jv*Y^lM@&iFJ8D{aH=!Zfq@}@t>F36|4Q>27#LJb zTq8*4 z_6YK2V5m}KU}$JzVEDzrz|io5fuYoZf#FpG1B2BJ1_tqhIlBUF7#J9&1AIbUL3$Jv ziXy`-EiJ>0)Qn}sznxWEldbmu|Nr!jpJW&q7#K@}{DK)Ap4~_Tagw~J zU|=ut^mS!_&c@6rud_tq@;s2^k`w*P7#J8Fpcv#}hJcewO$-bSex5FlAsp9}6C9YD znhc~4C9xQ?I52fJ9coihRCIK7PIT<(={5-9J0ZYn)@tO!ypX5EOyMPmnMZ(+56hVZ z5gkEB=@SZS&onx+G+7uJ9<#EuD$GvqV_;xVEpd$~Nl7e8wMs5ZO)N=eFfuSQ)-^EG zH82h_Ftjo@v@$W#HZZUIrf%Q~loCIBMZb+-Tj literal 0 HcmV?d00001 diff --git a/game.py b/game.py index a01a8c2..715833c 100644 --- a/game.py +++ b/game.py @@ -4,27 +4,29 @@ from grid import Grid class Game: - def __init__(self): - self.grid = Grid(10, 10, 5) - self.game_over = False + def __init__(self): + self.grid = Grid(25, 25, 100) + self.game_over = False - def update(self, delta): - for event in pygame.event.get(): - if event.type == pygame.QUIT: - return COMMAND_EXIT - if event.type == pygame.KEYDOWN: - if event.key == pygame.K_r: - return COMMAND_RESTART + def update(self, delta): + for event in pygame.event.get(): + if event.type == pygame.QUIT: + return COMMAND_EXIT + if event.type == pygame.KEYDOWN: + if event.key == pygame.K_r: + return COMMAND_RESTART - mouse_pos = pygame.mouse.get_pos() - mouse_button = pygame.mouse.get_pressed() - if self.grid.update(delta, mouse_pos, mouse_button): - return COMMAND_LOSE - if self.grid.win(): - return COMMAND_WIN + mouse_pos = pygame.mouse.get_pos() + mouse_button = pygame.mouse.get_pressed() + if self.grid.update(delta, mouse_pos, mouse_button): + for bomb in self.grid.bombs: + bomb.reveal() + return COMMAND_LOSE + if self.grid.win(): + return COMMAND_WIN - return COMMAND_NONE + return COMMAND_NONE - def draw(self, screen): - screen.fill(BLACK) - self.grid.draw(screen) + def draw(self, screen): + screen.fill(BLACK) + self.grid.draw(screen) diff --git a/grid.py b/grid.py index 5a43186..c562536 100644 --- a/grid.py +++ b/grid.py @@ -4,114 +4,146 @@ from setup import * class Grid: - def __init__(self, length, height, bomb_count): - self.length, self.height = length, height - self.grid = [[Cell(j, i) for j in range(self.length)] for i in range(self.height)] - - self.bomb_count = bomb_count - self.place_bombs(self.bomb_count) - - self.mouse_cooldown = 0 - - for row in self.grid: - for cell in row: - neighbors = [] - for i in range(-1, 2): - for j in range(-1, 2): - x = int(cell.position.x // Cell.cell_size + i) - y = int(cell.position.y // Cell.cell_size + j) - if 0 <= y < self.height and 0 <= x < self.length and not (i == 0 and j == 0): - neighbors.append(self.grid[y][x]) - cell.give_number(neighbors) - - def update(self, delta, mouse_pos, mouse_button): - if self.mouse_cooldown > 0: - self.mouse_cooldown -= delta - return False - - for row in self.grid: - for cell in row: - if cell.position.x <= mouse_pos[0] <= cell.position.x + Cell.cell_size and cell.position.y <= mouse_pos[1] <= cell.position.y + Cell.cell_size: - if mouse_button[0] == 1: - self.mouse_cooldown = 0.2 - if cell.update(self.grid, self.height, self.length): - return True - elif mouse_button[2] == 1: - if not cell.discovered: - cell.flagged = not cell.flagged - self.mouse_cooldown = 0.2 - return False - - def win(self): - for row in self.grid: - for cell in row: - if not cell.is_bomb and not cell.discovered: - return False - return True - - def draw(self, screen): - for row in self.grid: - for cell in row: - cell.draw(screen) - - def place_bombs(self, bomb_count): - while bomb_count > 0: - x = random.randint(0, self.length - 1) - y = random.randint(0, self.height - 1) - if not self.grid[y][x].is_bomb: - self.grid[y][x].is_bomb = True - bomb_count -= 1 + def __init__(self, length, height, bomb_count): + self.length, self.height = length, height + self.position = pygame.Vector2(SCREEN_WIDTH / 2 - Cell.cell_size * self.length / 2, + SCREEN_HEIGHT / 2 - Cell.cell_size * self.height / 2) + self.grid = [[Cell(self.position.x, self.position.y, j, i) for j in range(self.length)] for i in + range(self.height)] + + self.bomb_count = bomb_count + self.place_bombs(self.bomb_count) + + self.mouse_cooldown = 0 + + self.bombs = [] + + for row in self.grid: + for cell in row: + neighbors = [] + for i in range(-1, 2): + for j in range(-1, 2): + x = int(cell.grid_position.x + j) + y = int(cell.grid_position.y + i) + if 0 <= y < self.height and 0 <= x < self.length and not (i == 0 and j == 0): + neighbors.append(self.grid[y][x]) + cell.give_number(neighbors) + if cell.is_bomb: + self.bombs.append(cell) + + def update(self, delta, mouse_pos, mouse_button): + if self.mouse_cooldown > 0: + self.mouse_cooldown -= delta + return False + + for row in self.grid: + for cell in row: + if cell.position.x <= mouse_pos[0] <= cell.position.x + Cell.cell_size and cell.position.y <= mouse_pos[ + 1] <= cell.position.y + Cell.cell_size: + if mouse_button[0] == 1: + self.mouse_cooldown = 0.2 + if cell.update(self.grid, self.height, self.length): + return True + elif mouse_button[2] == 1: + if not cell.discovered: + cell.flagged = not cell.flagged + self.mouse_cooldown = 0.2 + return False + + def win(self): + for row in self.grid: + for cell in row: + if not cell.is_bomb and not cell.discovered: + return False + return True + + def draw(self, screen): + pygame.draw.rect(screen, BACKGROUND, ( + self.position.x - 2, self.position.y - 2, self.length * Cell.cell_size + 4, + self.height * Cell.cell_size + 4)) + pygame.draw.rect(screen, BORDER, ( + self.position.x - 2, self.position.y - 2, self.length * Cell.cell_size + 4, + self.height * Cell.cell_size + 4), + 2) + for row in self.grid: + for cell in row: + cell.draw(screen) + + def place_bombs(self, bomb_count): + while bomb_count > 0: + x = random.randint(0, self.length - 1) + y = random.randint(0, self.height - 1) + if not self.grid[y][x].is_bomb: + self.grid[y][x].is_bomb = True + bomb_count -= 1 class Cell: - cell_size = 25 - font = pygame.font.SysFont("Arial", 20) - - def __init__(self, x, y): - self.position = pygame.Vector2(x * self.cell_size, y * self.cell_size) - self.is_bomb = False - self.flagged = False - self.number = 0 - self.discovered = False - self.color = GRAY - self.text = None - - def update(self, grid, height, length): - if self.discovered or self.flagged: - return False - self.discovered = True - self.color = GREEN - if self.is_bomb: - self.color = RED - return True - - if self.number == 0: - for i in range(-1, 2): - for j in range(-1, 2): - x = int(self.position.x // self.cell_size + i) - y = int(self.position.y // self.cell_size + j) - if 0 <= y < height and 0 <= x < length and not (i == 0 and j == 0): - if not grid[y][x].discovered and not grid[y][x].flagged: - grid[y][x].update(grid, height, length) - - return False - - def give_number(self, neighbors): - if self.is_bomb: - return - for neighbor in neighbors: - if neighbor.is_bomb: - self.number += 1 - - self.text = self.font.render(str(self.number), True, BLACK) - - def draw(self, screen): - display_color = self.color - if self.flagged: - display_color = BLUE - - pygame.draw.rect(screen, display_color, (self.position.x, self.position.y, self.cell_size, self.cell_size)) - pygame.draw.rect(screen, BLACK, (self.position.x, self.position.y, self.cell_size, self.cell_size), 1) - if self.discovered and self.number > 0: - screen.blit(self.text, self.text.get_rect( - center=(self.position.x + self.cell_size / 2, self.position.y + self.cell_size / 2))) + cell_size = 25 + numbers = { + 0: pygame.transform.scale(pygame.image.load("assets/empty.png"), (cell_size, cell_size)), + 1: pygame.transform.scale(pygame.image.load("assets/1.png"), (cell_size, cell_size)), + 2: pygame.transform.scale(pygame.image.load("assets/2.png"), (cell_size, cell_size)), + 3: pygame.transform.scale(pygame.image.load("assets/3.png"), (cell_size, cell_size)), + 4: pygame.transform.scale(pygame.image.load("assets/4.png"), (cell_size, cell_size)), + 5: pygame.transform.scale(pygame.image.load("assets/5.png"), (cell_size, cell_size)), + 6: pygame.transform.scale(pygame.image.load("assets/6.png"), (cell_size, cell_size)), + 7: pygame.transform.scale(pygame.image.load("assets/7.png"), (cell_size, cell_size)), + 8: pygame.transform.scale(pygame.image.load("assets/8.png"), (cell_size, cell_size)), + } + + flag = pygame.transform.scale(pygame.image.load("assets/flag.png"), (cell_size, cell_size)) + undiscovered = pygame.transform.scale(pygame.image.load("assets/undiscovered.png"), (cell_size, cell_size)) + explosion = pygame.transform.scale(pygame.image.load("assets/explosion.png"), (cell_size, cell_size)) + undiscovered_bomb = pygame.transform.scale(pygame.image.load("assets/undiscovered_bomb.png"), + (cell_size, cell_size)) + + def __init__(self, pos_x, pos_y, x, y): + self.position = pygame.Vector2(pos_x + x * self.cell_size, pos_y + y * self.cell_size) + self.grid_position = pygame.Vector2(x, y) + self.is_bomb = False + self.flagged = False + self.number = 0 + self.discovered = False + self.revealed = False + + def update(self, grid, height, length): + if self.discovered or self.flagged: + return False + self.discovered = True + if self.is_bomb: + return True + + if self.number == 0: + for i in range(-1, 2): + for j in range(-1, 2): + x = int(self.grid_position.x + i) + y = int(self.grid_position.y + j) + if 0 <= y < height and 0 <= x < length and not (i == 0 and j == 0): + if not grid[y][x].discovered and not grid[y][x].flagged: + grid[y][x].update(grid, height, length) + return False + + def give_number(self, neighbors): + if self.is_bomb: + return + for neighbor in neighbors: + if neighbor.is_bomb: + self.number += 1 + + def reveal(self): + if not self.discovered: + self.revealed = True + + def draw(self, screen): + if self.revealed: + screen.blit(self.undiscovered_bomb, self.position) + elif self.discovered: + if self.is_bomb: + screen.blit(self.explosion, self.position) + else: + screen.blit(self.numbers[self.number], self.position) + else: + screen.blit(self.undiscovered, self.position) + if self.flagged: + screen.blit(self.flag, self.position) diff --git a/main.py b/main.py index 530f487..f39ec1b 100644 --- a/main.py +++ b/main.py @@ -4,25 +4,24 @@ from menus import Lose, Win def main(): - scene = Game() - is_running = True - delta = 0 - while is_running: - status = scene.update(delta) - scene.draw(screen) + scene = Game() + is_running = True + while is_running: + delta = clock.tick(60) / 1000 - if status == COMMAND_EXIT: - is_running = False - elif status == COMMAND_RESTART: - scene = Game() - elif status == COMMAND_WIN: - scene = Win(screen) - elif status == COMMAND_LOSE: - scene = Lose(screen) + status = scene.update(delta) + scene.draw(screen) + pygame.display.update() - pygame.display.update() - delta = clock.tick(60) / 1000 + if status == COMMAND_EXIT: + is_running = False + elif status == COMMAND_RESTART: + scene = Game() + elif status == COMMAND_WIN: + scene = Win(screen) + elif status == COMMAND_LOSE: + scene = Lose(screen) if __name__ == "__main__": - main() + main() diff --git a/menus.py b/menus.py index 67a8aec..8aa28cf 100644 --- a/menus.py +++ b/menus.py @@ -2,45 +2,45 @@ from setup import * class Menu: - title = pygame.font.SysFont("Arial", 30) - subtitle = pygame.font.SysFont("Arial", 20) - padding = 10 - - def __init__(self, screen, title, subtitle, text_color=RED): - self.bg = screen.copy() - self.titleText = self.title.render(title, True, text_color) - self.subtitleText = self.subtitle.render(subtitle, True, text_color) - - def update(self, delta): - for event in pygame.event.get(): - if event.type == pygame.QUIT: - return COMMAND_EXIT - elif event.type == pygame.KEYDOWN: - if event.key == pygame.K_r: - return COMMAND_RESTART - return COMMAND_NONE - - def draw(self, screen): - screen.blit(self.bg, (0, 0)) - titleRect = self.titleText.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)) - subtitleRect = self.subtitleText.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 50)) - boxRect = pygame.Rect(min(titleRect.x, subtitleRect.x) - self.padding, - min(titleRect.y, subtitleRect.y) - self.padding, - max(titleRect.width, subtitleRect.width) + self.padding * 2, - titleRect.height / 2 + subtitleRect.height / 2 + abs( - titleRect.y - subtitleRect.y) + self.padding * 2) - pygame.draw.rect(screen, BLACK, boxRect) - pygame.draw.rect(screen, GRAY, boxRect, 4) - screen.blit(self.titleText, titleRect) - screen.blit(self.subtitleText, subtitleRect) + title = pygame.font.SysFont("Arial", 30) + subtitle = pygame.font.SysFont("Arial", 20) + padding = 10 + + def __init__(self, screen, title, subtitle, text_color=RED): + self.bg = screen.copy() + self.titleText = self.title.render(title, True, text_color) + self.subtitleText = self.subtitle.render(subtitle, True, text_color) + + def update(self, delta): + for event in pygame.event.get(): + if event.type == pygame.QUIT: + return COMMAND_EXIT + elif event.type == pygame.KEYDOWN: + if event.key == pygame.K_r: + return COMMAND_RESTART + return COMMAND_NONE + + def draw(self, screen): + screen.blit(self.bg, (0, 0)) + titleRect = self.titleText.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2)) + subtitleRect = self.subtitleText.get_rect(center=(SCREEN_WIDTH / 2, SCREEN_HEIGHT / 2 + 50)) + boxRect = pygame.Rect(min(titleRect.x, subtitleRect.x) - self.padding, + min(titleRect.y, subtitleRect.y) - self.padding, + max(titleRect.width, subtitleRect.width) + self.padding * 2, + titleRect.height / 2 + subtitleRect.height / 2 + abs( + titleRect.y - subtitleRect.y) + self.padding * 2) + pygame.draw.rect(screen, BLACK, boxRect) + pygame.draw.rect(screen, GRAY, boxRect, 4) + screen.blit(self.titleText, titleRect) + screen.blit(self.subtitleText, subtitleRect) class Lose(Menu): - def __init__(self, screen): - super().__init__(screen, "You Lose!", "Press R to restart") + def __init__(self, screen): + super().__init__(screen, "You Lose!", "Press R to restart") class Win(Menu): - def __init__(self, screen): - super().__init__(screen, "You Win!", "Press R to play again", GREEN) + def __init__(self, screen): + super().__init__(screen, "You Win!", "Press R to play again", GREEN) diff --git a/setup.py b/setup.py index 694ac4b..b3cfcce 100644 --- a/setup.py +++ b/setup.py @@ -1,10 +1,10 @@ import pygame pygame.init() -SCREEN_WIDTH = 800 -SCREEN_HEIGHT = 600 +SCREEN_WIDTH, SCREEN_HEIGHT = pygame.display.Info().current_h - 60, pygame.display.Info().current_h - 60 screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT)) pygame.display.set_caption("Minesweeper") +pygame.display.set_icon(pygame.image.load("assets/bomb.png")) clock = pygame.time.Clock() RED = (255, 0, 0) @@ -13,7 +13,8 @@ BLUE = (0, 0, 255) BLACK = (0, 0, 0) WHITE = (255, 255, 255) GRAY = (128, 128, 128) - +BACKGROUND = (51, 28, 23) +BORDER = (187, 127, 87) COMMAND_EXIT = 0 COMMAND_RESTART = 1 -- 2.54.0