Skip to content

Instantly share code, notes, and snippets.

@nakagami
Last active September 1, 2017 23:37
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save nakagami/fb68c6186a26e9a0bee7c6f868a5b3ac to your computer and use it in GitHub Desktop.
Save nakagami/fb68c6186a26e9a0bee7c6f868a5b3ac to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
################################################################################
# MIT License
#
# Copyright (c) 2017 Hajime Nakagami<nakagami@gmail.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
################################################################################
import random
class SameGame:
def __init__(self, width, height):
self.width = width
self.height = height
self.score = 0
self.board = [random.randint(1, 5) for _ in range(width * height)]
def count(self, mark):
return self.board.count(mark)
def _find_neighbors(self, selected, mark):
neighbors = set()
for i in range(len(self.board)):
if self.board[i] != mark or i in selected:
continue
for x, y in [(-1, 0), (0, 1), (1, 0), (0, -1)]:
idx = i + x * self.width + y
if idx < 0 or idx >= self.width * self.height:
continue
if self.board[idx] == mark and idx in selected:
neighbors.add(i)
return neighbors
def select(self, idx):
assert idx >= 0 and idx < len(self.board)
mark = self.board[idx]
selected = set()
if mark == 0:
return selected
selected.add(idx)
neighbors = self._find_neighbors(selected, mark)
while neighbors:
selected |= neighbors
neighbors = self._find_neighbors(selected, mark)
if len(selected) == 1:
return set()
else:
return selected
def _drop(self, idx):
i = idx - self.width
while i >= 0 and self.board[i] == 0:
i -= self.width
if i >= 0:
self.board[idx] = self.board[i]
self.board[i] = 0
def _shift(self, pos):
i = pos
while i < self.width:
if self.board[(self.height -1) * self.width + i] != 0:
break
i += 1
if i != self.width:
for j in range(self.height):
self.board[j * self.width + pos] = self.board[j * self.width + i]
self.board[j * self.width + i] = 0
def pick(self, idx):
selected = self.select(idx)
if selected:
for idx in selected:
self.board[idx] = 0
for i in reversed(range(len(self.board))):
if self.board[i] == 0 and (i - self.width) >= 0:
self._drop(i)
for i in range(self.width):
if self.board[(self.height -1) * self.width + i] == 0:
self._shift(i)
self.score += (len(selected) -2) ** 2
#-------------------------------------------------------------------------------
MARKS = [
'\x1b[30;40m \x1b[0m',
'\x1b[31;40m@\x1b[0m',
'\x1b[32;40m*\x1b[0m',
'\x1b[33;40mX\x1b[0m',
'\x1b[34;40m%\x1b[0m',
'\x1b[36;40mO\x1b[0m',
]
def print_board(samegame):
print('\n ', end='')
for i in range(samegame.width):
print('{} '.format(chr(97+i)), end='')
print('\n +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+')
n = 0
for i, row in enumerate(samegame.board):
if i % samegame.width == 0:
print(' %d|' % ((i % samegame.width)+n), end='')
n += 1
print(
MARKS[samegame.board[i]],
end='|\n' if i % samegame.width == (samegame.width-1) else '\x1b[30;40m \x1b[0m'
)
print(' +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+')
print('score:{}'.format(samegame.score))
def input_idx():
while True:
s = input('[a-t][0-9]?')
if len(s) == 2 and s[0] in list('abcdefghijklmnopqrst') and s[1] in list('0123456789'):
break
return (ord(s[0]) - 97) + (ord(s[1]) - 48) * 20
def start_console(samegame):
while samegame.count(0) < samegame.width * samegame.height:
print_board(samegame)
idx = input_idx()
samegame.pick(idx)
if __name__ == "__main__":
samegame = SameGame(20, 10)
start_console(samegame)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment