132 lines
2.5 KiB
Go
132 lines
2.5 KiB
Go
package minesweeper
|
|
|
|
import (
|
|
"image/color"
|
|
|
|
"golang.org/x/exp/rand"
|
|
)
|
|
|
|
func RandomUntilNoBomb(cellCount int, bombIndexes map[int]struct{}) int {
|
|
r := rand.Intn(cellCount)
|
|
|
|
loop := true
|
|
for loop {
|
|
if _, ok := bombIndexes[r]; !ok {
|
|
loop = false
|
|
}
|
|
r = rand.Intn(cellCount)
|
|
}
|
|
return r
|
|
}
|
|
|
|
func (g *Game) XYToIndex(x int, y int) int {
|
|
index := y*(g.columns) + x
|
|
return index
|
|
}
|
|
|
|
func (g *Game) IndexToXY(index int) (int, int) {
|
|
x := index % (g.columns)
|
|
y := index / (g.columns)
|
|
return x, y
|
|
}
|
|
|
|
func (g *Game) CursorPosToIndex(x int, y int) int {
|
|
logicX := x / g.CellSize
|
|
logicY := y / g.CellSize
|
|
|
|
return g.XYToIndex(logicX, logicY)
|
|
}
|
|
|
|
func (g *Game) CalcNeighbourBombs(index int) int {
|
|
bombs := 0
|
|
|
|
g.applyNeighbours(index, func(i int) {
|
|
if g.cells[i].cellType == BOMB {
|
|
bombs += 1
|
|
}
|
|
})
|
|
|
|
return bombs
|
|
}
|
|
|
|
func (g *Game) SetBomblessNeighboursToOpen(index int) {
|
|
g.applyNeighbours(index, func(i int) {
|
|
if g.cells[i].bombNeighbours == 0 && g.cells[i].state != OPEN {
|
|
g.cells[i].state = OPEN
|
|
g.SetBomblessNeighboursToOpen(i)
|
|
} else if g.cells[i].cellType != BOMB {
|
|
g.cells[i].state = OPEN
|
|
}
|
|
})
|
|
}
|
|
|
|
func (g *Game) applyNeighbours(index int, f func(index int)) {
|
|
posX, posY := g.IndexToXY(index)
|
|
for x := -1; x <= 1; x++ {
|
|
for y := -1; y <= 1; y++ {
|
|
if posX+x < 0 || posX+x >= g.rows {
|
|
continue
|
|
}
|
|
if posY+y < 0 || posY+y >= g.columns {
|
|
continue
|
|
}
|
|
|
|
i := g.XYToIndex(posX+x, posY+y)
|
|
f(i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func MatchColor(state State) color.Color {
|
|
switch state {
|
|
case OPEN:
|
|
return OPEN_COLOR
|
|
case DARK:
|
|
return DARK_COLOR
|
|
case FLAG:
|
|
return FLAG_COLOR
|
|
default:
|
|
return color.Black
|
|
}
|
|
}
|
|
|
|
func (g *Game) SetupCells() ([]Cell, map[int]struct{}) {
|
|
cellCount := (g.columns * g.rows)
|
|
bombs := float64(cellCount) * (float64(g.bombPercentage) / 100)
|
|
cells := make([]Cell, 0)
|
|
|
|
bombIndexes := make(map[int]struct{})
|
|
|
|
for range int(bombs) {
|
|
r := RandomUntilNoBomb(cellCount, bombIndexes)
|
|
bombIndexes[r] = struct{}{}
|
|
}
|
|
|
|
index := 0
|
|
for x := range g.columns {
|
|
for y := range g.rows {
|
|
cellType := NO_BOMB
|
|
cellColor := color.RGBA{120, 120, 120, 255}
|
|
if _, isBomb := bombIndexes[index]; isBomb {
|
|
cellType = BOMB
|
|
cellColor = color.RGBA{255, 0, 0, 255}
|
|
}
|
|
|
|
cells = append(cells, Cell{
|
|
top: float32(x * g.CellSize),
|
|
left: float32(y * g.CellSize),
|
|
color: cellColor,
|
|
cellType: cellType,
|
|
state: DARK,
|
|
})
|
|
index += 1
|
|
}
|
|
}
|
|
|
|
for i := range cells {
|
|
cells[i].bombNeighbours = g.CalcNeighbourBombs(i)
|
|
}
|
|
|
|
return cells, bombIndexes
|
|
}
|