Skip to content

Commit 4236fee

Browse files
committed
Добавлен пример игры Сапёр
1 parent 2d5ba12 commit 4236fee

File tree

1 file changed

+167
-0
lines changed

1 file changed

+167
-0
lines changed

examples/game/minesweeper.own

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
use "std"
2+
use "math"
3+
use "types"
4+
use "canvasfx"
5+
6+
// Constants
7+
CELL_NONE = -100
8+
CELL_MINE = -200
9+
// Colors
10+
BACKGROUND_COLOR = Color.new(#FF283593)
11+
OPENED_CELL_COLOR = Color.new(0xFF9FA8DA)
12+
DEFAULT_CELL_COLOR = Color.new(#FF5C6BC0)
13+
MINE_CELL_COLOR = Color.new(#FF1A237E)
14+
FLAG_COLOR = Color.new(#FF7A231E)
15+
16+
// Parameters
17+
WIDTH = 400 HEIGHT = 400
18+
TABLE_WIDTH = 6
19+
TABLE_HEIGHT = 6
20+
21+
// Other
22+
isGameFinished = false
23+
gridStepX = WIDTH / double(TABLE_WIDTH)
24+
gridStepY = HEIGHT / double(TABLE_HEIGHT)
25+
26+
// Graphics and event listeners initialization
27+
g = window("MineSweeper", WIDTH, HEIGHT)
28+
addEventHandler(Events.MOUSE_CLICKED, ::onMouseClicked)
29+
30+
// Create table with mines
31+
TABLE = []
32+
FLAGS = []
33+
newGame()
34+
def newGame() {
35+
isGameFinished = false
36+
TABLE = newarray(TABLE_HEIGHT, TABLE_WIDTH)
37+
FLAGS = newarray(TABLE_HEIGHT, TABLE_WIDTH)
38+
for i = 0, i < TABLE_WIDTH, i++
39+
for j = 0, j < TABLE_HEIGHT, j++
40+
TABLE[j][i] = CELL_NONE
41+
maxMines = int(sqrt(rand(1, 4) * TABLE_WIDTH * TABLE_HEIGHT))
42+
for i = 0, i < maxMines, i++
43+
TABLE[rand(TABLE_HEIGHT)][rand(TABLE_WIDTH)] = CELL_MINE
44+
45+
g.setStroke(Color.DARKSLATEGREY)
46+
g.setLineWidth(5)
47+
g.setTextAlign(TextAlignment.CENTER)
48+
g.setFill(BACKGROUND_COLOR)
49+
g.fillRect(0, 0, WIDTH, HEIGHT)
50+
drawGameTable()
51+
}
52+
53+
def drawGameTable(showBombs = false) {
54+
for i = 0, i < TABLE_WIDTH, i++ {
55+
for j = 0, j < TABLE_HEIGHT, j++ {
56+
match TABLE[j][i] {
57+
case CELL_NONE: g.setFill(DEFAULT_CELL_COLOR)
58+
case CELL_MINE if showBombs: g.setFill(MINE_CELL_COLOR)
59+
case CELL_MINE if !showBombs: g.setFill(DEFAULT_CELL_COLOR)
60+
case _ : g.setFill(OPENED_CELL_COLOR)
61+
}
62+
if (FLAGS[j][i] && (TABLE[j][i] == CELL_NONE || TABLE[j][i] == CELL_MINE) {
63+
g.setFill(FLAG_COLOR)
64+
}
65+
g.fillRect(i * gridStepX + 1, j * gridStepY + 1, gridStepX - 2, gridStepY - 2)
66+
if (TABLE[j][i] >= 0) {
67+
g.setFill(Color.BLACK)
68+
g.fillText(TABLE[j][i], i * gridStepX + gridStepX / 2, j * gridStepY + gridStepY / 2)
69+
}
70+
}
71+
}
72+
}
73+
74+
def drawWin() {
75+
drawGameTable(true)
76+
g.setFill(Color.new(#60FFFFFF))
77+
g.fillRect(0, 0, WIDTH, HEIGHT)
78+
g.setFill(Color.DARKGREEN)
79+
g.fillText("YOU WIN", WIDTH / 2, HEIGHT / 2)
80+
}
81+
82+
def drawGameOver() {
83+
drawGameTable(true)
84+
g.setFill(Color.new(#60000000))
85+
g.fillRect(0, 0, WIDTH, HEIGHT)
86+
g.setFill(Color.PINK)
87+
g.fillText("Game Over", WIDTH / 2, HEIGHT / 2)
88+
}
89+
90+
91+
def onMouseClicked(e) {
92+
if (isGameFinished) {
93+
newGame()
94+
return 0
95+
}
96+
tableX = int(e.x / gridStepX)
97+
tableY = int(e.y / gridStepY)
98+
if (tableX < 0 || tableY < 0 ||
99+
tableX >= TABLE_WIDTH || tableY >= TABLE_HEIGHT) return 0
100+
101+
if (e.button == MouseButton.SECONDARY) {
102+
FLAGS[tableY][tableX] = 1 - FLAGS[tableY][tableX]
103+
drawGameTable()
104+
return 0
105+
}
106+
if (TABLE[tableY][tableX] == CELL_MINE) {
107+
isGameFinished = true
108+
drawGameOver()
109+
return 0
110+
}
111+
updateCell(tableX, tableY)
112+
if (gameFinished()) {
113+
isGameFinished = true
114+
drawWin()
115+
return 0
116+
}
117+
drawGameTable()
118+
}
119+
120+
def updateCell(tx, ty, visited = []) {
121+
if (tx < 0 || ty < 0 ||
122+
tx >= TABLE_WIDTH || ty >= TABLE_HEIGHT) return visited
123+
for v : visited {
124+
if [tx, ty] == v return visited
125+
}
126+
minesCount = calculateMinesCount(tx, ty)
127+
TABLE[ty][tx] = minesCount
128+
if (minesCount != 0) return visited
129+
visited ::= [tx, ty]
130+
if (tx >= 1 && ty >= 1) visited = updateCell(tx - 1, ty - 1, visited)
131+
if (ty >= 1) visited = updateCell(tx, ty - 1, visited)
132+
if (tx < WIDTH - 1 && ty >= 1) visited = updateCell(tx + 1, ty - 1, visited)
133+
134+
if (tx >= 1) visited = updateCell(tx - 1, ty, visited)
135+
if (tx < WIDTH - 1) visited = updateCell(tx + 1, ty, visited)
136+
137+
if (tx >= 1 && ty < HEIGHT - 1) visited = updateCell(tx - 1, ty + 1, visited)
138+
if (ty < HEIGHT - 1) visited = updateCell(tx, ty + 1, visited)
139+
if (tx < WIDTH - 1 && ty < HEIGHT - 1) visited = updateCell(tx + 1, ty + 1, visited)
140+
return visited
141+
}
142+
143+
def calculateMinesCount(x, y) {
144+
count = 0
145+
for dx = -1, dx <= 1, dx++ {
146+
for dy = -1, dy <= 1, dy++ {
147+
// Skip center [x, y] cell
148+
if ( (dx == 0) && (dy == 0) ) continue
149+
150+
xx = x + dx
151+
yy = y + dy
152+
if (xx < 0 || yy < 0 ||
153+
xx >= TABLE_WIDTH || yy >= TABLE_HEIGHT) continue
154+
count += (TABLE[yy][xx] == CELL_MINE ? 1 : 0)
155+
}
156+
}
157+
return count
158+
}
159+
160+
def gameFinished() {
161+
for i = 0, i < TABLE_WIDTH, i++ {
162+
for j = 0, j < TABLE_HEIGHT, j++ {
163+
if (TABLE[j][i] == CELL_NONE) return false
164+
}
165+
}
166+
return true
167+
}

0 commit comments

Comments
 (0)