minesweeper

Minesweeper in Python and pygame
Log | Files | Refs | README

commit 84d4d22666d7dd6c2bd904098c0ae0a0696b420f
Author: sej <sej@sejdt.localhost>
Date:   Sun, 13 Oct 2024 21:51:55 +0200

Initial commit

Diffstat:
Adata.py | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aminestryger.py | 142+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 272 insertions(+), 0 deletions(-)

diff --git a/data.py b/data.py @@ -0,0 +1,130 @@ +import random + +class Minestryger(): + + + def __init__(self, w, h, b): + if type(w) != int: + raise TypeError("Bredden skal være af typen int (heltal)") + if type(h) != int: + raise TypeError("Højden skal være af typen int (heltal)") + if type(b) != int: + raise TypeError("Antallet af bomber skal være af typen int (heltal)") + + if b+9 > w*h: + raise ValueError("Der kan ikke være flere bomber på pladen end pladens størrelse.") + self.w = w + self.h = h + self.b = b + self.grid = [[ -2 for _ in range(self.w)] for _ in range(self.h)] + self.flag = [[ 0 for _ in range(self.w)] for _ in range(self.h)] + #self.gen_grid() + self.state = 0 #når state = 0 er der ikke nogle bomber på spillepladen + #når state = 1 er spillet i gang + #når state = 2 er spillet tabt + #når state = 3 er spillet vundet + print("h: {}".format(self.h)) + print("w: {}".format(self.w)) + print("b: {}".format(self.w)) + #self.pg() + + def uncover(self, x, y): + if self.on_grid(x, y): + if self.grid[y][x] < 0 and self.flag[y][x] != 1: + if self.grid[y][x] == -1: + print("Du døde") + self.state = 2 + elif self.grid[y][x] == -2: + print("uncovering") + b = self.surrounding(x, y) + self.grid[y][x] = b + if b == 0: + for i in range(-1, 2): + for u in range(-1, 2): + self.uncover(x + u, y + i) + self.win_cond() + + def mm_uncover(self, x, y): + if self.on_grid(x, y): + sflag = self.surrounding(x, y, f = True) #beregn omkringliggende flag + if sflag == self.grid[y][x]: + for i in range(-1, 2): + for u in range(-1, 2): + self.uncover(x + u, y + i) + + def surrounding(self, x, y, f = False): + if f: + g = self.flag + c = 1 + + elif not f: + g = self.grid + c = -1 + + s = 0 + for i in range(-1, 2): + for u in range(-1, 2): + dy = y + i + if dy < 0: + continue + dx = x + u + if dx < 0: + continue + try: + q = g[dy][dx] + if q == c: + s += 1 + except: + q = 0 #hvis koordinatet falder uden for spillepladen + #self.pg() + return s + + def pg(self): + for row in self.flag: + print(row) + for row in self.grid: + print(row) + + def gen_grid(self, sx, sy): + # negative tal er undiscovered tiles, -1 for bombe, -2 for fri + # positive tal angiver antallet af omkringliggende bomber + # nul er discovered frit felt uden omkringliggende bomber + if self.on_grid(sx, sy): + miner = set() + print( sx -1, sx +1 ) + print( sy -1, sy +1) + while len(miner) < self.b: + rx = random.randint(0,self.w-1) + ry = random.randint(0,self.h-1) + if not (sx - 1 <= rx <= sx + 1 and sy - 1 <= ry <= sy + 1): + #if sx != rx or sy != ry: + self.grid[ry][rx] = -1 + miner.add((rx,ry)) + self.state = 1 + + def set_flag(self, x, y): + if self.on_grid(x, y): + if self.flag[y][x] != 1 and not self.grid[y][x] >= 0: + self.flag[y][x] = 1 + else: + self.flag[y][x] = 0 + + def get_remaining_bombs(self): + total = 0 + for x in range(self.w): + for y in range(self.h): + total += self.flag[y][x] + + return total + + def on_grid(self, x, y): + if 0 <= x < self.w and 0 <= y < self.h: + return True + else: + return False + + def win_cond(self): + for row in self.grid: + if -2 in row: + return + self.state = 3 diff --git a/minestryger.py b/minestryger.py @@ -0,0 +1,142 @@ +#!/usr/bin/env python3 +import pygame as pg +from data import Minestryger +import argparse +import sys + +#commandline parametre +parser = argparse.ArgumentParser(description = "Minestryger") +parser.add_argument('-d', action='store_true', help='Slå demotilstand til der gør at bomber vises') +parser.add_argument('-wh', nargs=2, metavar=('W', 'H'), type=int, help='Bredde og højde') +parser.add_argument('-b', type=int, help='Antal bomber') +parser.add_argument('-c', type=int, help='Cellestørrelse') +parser.add_argument('--overwrite-recursion-limit', metavar='limit', type=int, help='Til store spilleplader med relativt få bomber. Eget ansvar.') + +oargs = parser.parse_args() #oprindelige argumenter + +args = vars(oargs) #dict til argumenter +print(args) +print(len(sys.argv)) + +if len(sys.argv) == 1: #hvis programmet køres uden parametre + spil = Minestryger(9, 9, 10) +else: + spil = Minestryger(args["wh"][0], args["wh"][1], args["b"]) #giver fejl hvis parametrene mangler eller er forkerte + +if oargs.c: + cs = args["c"] #cellestørrelse +else: + cs = 20 + +if oargs.overwrite_recursion_limit: + sys.setrecursionlimit(oargs.overwrite_recursion_limit) #til store spilleplader med relativt få bomber + +#opsætning af pygame +pg.init() +screen = pg.display.set_mode(( 500 if spil.w * cs < 500 else spil.w * cs, spil.h * cs +50)) #bredden er mindst 500px +screen.fill((0,0,0)) +clock = pg.time.Clock() + +#fonts +font = pg.font.SysFont(None, int(cs*1.8)) +text = [] +farver = [(255,255,255),(0,0,255), (0,123,0), (255,0,0), (0,0,123), (123,0,0), (0,123,123), (0,0,0), (123,123,13)] +for i in range(9): + tal = font.render(str(i), True, farver[i]) + text.append(tal) + +font2 = pg.font.SysFont(None, 25) + +tab_text = font2.render("Desværre tabte du spillet. Tryk her for at starte forfra.", True, (255,255,255)) +vind_text = font2.render("Tillykke! Du vandt spillet. Tryk her for at starte forfra.", True, (255,255,255)) + + +def draw_game(): + pg.draw.rect(screen, (255,255,255), pg.Rect(0, 0, pg.display.get_window_size()[0], pg.display.get_window_size()[1])) + for x in range(spil.w): + for y in range(spil.h): + if spil.grid[y][x] < 0: + pg.draw.rect(screen, (120,120,120), pg.Rect(x * cs, y * cs, cs, cs)) + + if spil.grid[y][x] == 0: + pg.draw.rect(screen, (255,255,255), pg.Rect(x * cs, y * cs, cs, cs)) + + if oargs.d: + if spil.grid[y][x] == -1: + pg.draw.rect(screen, (12,120,120), pg.Rect(x * cs, y * cs, cs, cs)) + + if spil.flag[y][x] == 1: + pg.draw.rect(screen, (120,0,0), pg.Rect(x * cs, y * cs, cs, cs)) + + if spil.grid[y][x] > 0: + t = spil.grid[y][x] + screen.blit(text[t], (x * cs,y * cs)) + #pg.draw.rect(screen, (0,0,255), pg.Rect(x*80, y*80, 80, 80)) + + pg.draw.rect(screen, (0,0,0), pg.Rect(0, cs * spil.h, pg.display.get_window_size()[0], 50)) #underbaren + tb = spil.get_remaining_bombs() + tbt = font2.render("{} / {}".format(tb, spil.b), True, (255,255,255)) + screen.blit(tbt, (0,spil.h * cs+25)) + + +def draw_bombs(): + for x in range(spil.w): + for y in range(spil.h): + if spil.grid[y][x] == -1: + pg.draw.rect(screen, (12,12,12), pg.Rect(x * cs, y * cs, cs, cs)) + if spil.flag[y][x] == 1 and spil.grid[y][x] == -1: + pg.draw.rect(screen, (50,110,255), pg.Rect(x * cs, y * cs, cs, cs)) + elif spil.flag[y][x] == 1: + pg.draw.rect(screen, (255,0,0), pg.Rect(x * cs, y * cs, cs, cs)) + +def draw_loss(): + pg.draw.rect(screen, (0,0,0), pg.Rect(0, cs * spil.h, pg.display.get_window_size()[0], 50)) #underbaren + screen.blit(tab_text, (0,spil.h * cs)) + +def draw_win(): + pg.draw.rect(screen, (0,0,0), pg.Rect(0, cs * spil.h, pg.display.get_window_size()[0], 50)) #underbaren + screen.blit(vind_text, (0, spil.h * cs)) + +draw_game() +while spil.state != -1: #game loop +#tilstandsmaskine + pg.display.update() + events = pg.event.get() + for event in events: #håndtér input + if event.type == pg.MOUSEBUTTONUP: + mx, my = pg.mouse.get_pos() + cx = mx // cs # x-koordinat på celle + cy = my // cs # y-koordinat på celle + if event.button == 1: #venstreklik + if spil.state == 0: + spil.gen_grid(cx, cy) + if spil.state == 1: + spil.uncover(cx, cy) + if spil.state == 2 or spil.state == 3: + if my > spil.h *cs: + if len(sys.argv) == 1: + spil = Minestryger(9, 9, 10) #hvis programmet køres uden parametre + else: + spil = Minestryger(args["wh"][0], args["wh"][1], args["b"]) + + if event.button == 3: #højreklik + if spil.state == 1: + spil.set_flag(cx, cy) + + if event.button == 2: #middleklik + if spil.state == 1: + spil.mm_uncover(cx, cy) + draw_game() + + if event.type == pg.QUIT: + spil.state = -1 + + if spil.state == 2: + draw_loss() + draw_bombs() + + if spil.state == 3: + draw_bombs() + draw_win() + + clock.tick(60)