Python--双人版2048(改善版)

注:此代码需要在shell下运行

import curses
from itertools import chain
from random import choice, randint


# 创建一个游戏类
class Gamefiled(object):
	# 游戏文件的属性
	def __init__(self, width=4, height=4, win_value=2048):
		self.width = width
		self.height = height
		self.win_value = win_value
		self.score1 = 0
		self.score2 = 0
		self.file1 = []
		self.file2 = []

	# 创建数据文件函数<以列表的方式保存>
	def recreate_file(self):
		self.file1 = [[0 for i in range(self.width)]for j in range(self.height)]
		self.file2 = [[0 for i in range(self.width)]for j in range(self.height)]
		self.create_random(self.file1)
		self.create_random(self.file1)
		self.create_random(self.file2)
		self.create_random(self.file2)

	# 在列表中随即生成数的函数
	def create_random(self, filed):
		while True:
			i, j = choice(range(self.width)), choice(range(self.height))
			if filed[i][j] == 0:
				filed[i][j] = 4 if randint(1, 100) > 90 else 2
				break

			# 按格式画棋盘

	def draw(self, stdscr):
		def draw_sep():
			line = '+' + '----+' * self.width
			stdscr.addstr(line + '\n')

		def draw_row(row):  # [2,0,2,0]
			draw_one_row = "".join(['|{:^4}'.format(num)
									if num != 0  else '|    ' for num in row]) + '|'
			stdscr.addstr(draw_one_row + '\n')

		stdscr.clear()  # 清屏
		# 打印分数
		stdscr.addstr('Player1_Score:' + str(self.score1) + '\n')
		# 画棋盘
		for row in self.file1:
			draw_sep()
			draw_row(row)
		draw_sep()
		stdscr.addstr('Player2_Score:' + str(self.score2) + '\n')

		for row in self.file2:
			draw_sep()
			draw_row(row)
		draw_sep()

		if self.is_win():
			if self.score1 > self.score2:
				stdscr.addstr('Palyer1 Win!' + '\n\n')
			elif self.score2 > self.score1:
				stdscr.addstr('Palyer2 Win!' + '\n\n')
			else:
				stdscr.addstr('DogFall!' + '\n')
		stdscr.addstr('1P:Up Down Left Right\n2P:W A S D\n(R)Restart(Q)Exit\n')

	# 定义判断输赢的函数<chain将多个列表内的值链成一个新列表>
	def is_win(self):
		return max(chain(*self.file1)) >= self.win_value or \
			   max(chain(*self.file2)) >= self.win_value or (not any([self.move_possible(direction) for direction in [
			'Up', 'Down', 'Right', 'Left']])) and (not any([self.move_possible1(direction)
															for direction in ['Up1', 'Down1', 'Right1', 'Left1']]))

	@staticmethod
	def invert(filed):
		return [row[::-1] for row in filed]

	@staticmethod
	def transpose(filed):
		return [list(row) for row in zip(*filed)]  # zip完成数组的置换

	# 定义判断是否可以移动的函数

	def move_possible(self, direction):
		def leftrow_move_possible(row):
			def is_move(i):
				if row[i] == 0 and row[i + 1] != 0:
					return True
				if row[i] == row[i + 1] != 0:
					return True
				return False

			return any([is_move(i) for i in range(len(row) - 1)])

		possible = {}
		possible['Left'] = lambda filed: any([leftrow_move_possible(row) for row in filed])
		possible['Right'] = lambda filed: possible['Left'](self.invert(filed))
		possible['Up'] = lambda filed: possible['Left'](self.transpose(filed))
		possible['Down'] = lambda filed: possible['Right'](self.transpose(filed))

		if direction in possible:
			return possible[direction](self.file1)
		else:
			return False

	def move_possible1(self, direction):
		def leftrow_move_possible(row):
			def is_move(i):
				if row[i] == 0 and row[i + 1] != 0:
					return True
				if row[i] == row[i + 1] != 0:
					return True
				return False

			return any([is_move(i) for i in range(len(row) - 1)])

		possible = {}
		possible['Left1'] = lambda filed: any([leftrow_move_possible(row) for row in filed])
		possible['Right1'] = lambda filed: possible['Left1'](self.invert(filed))
		possible['Up1'] = lambda filed: possible['Left1'](self.transpose(filed))
		possible['Down1'] = lambda filed: possible['Right1'](self.transpose(filed))
		if direction in possible:
			return possible[direction](self.file2)
		else:
			return False

		# 定义移动函数

	def move(self, direction):
		def leftrow_move(row):  # 一行的移动
			def tight(row):  # 步骤一:数字凑一块
				new_row = [i for i in row if i != 0]  # 对齐
				new_row += [0 for i in range(len(row) - len(new_row))]  # 补零
				return new_row

			def merge(row):  # 合并
				for i in range(len(row) - 1):
					if row[i] == row[i + 1]:
						row[i] *= 2
						row[i + 1] = 0
						self.score1 += row[i]
				return row

			return tight(merge(tight(row)))

		def leftrow_move1(row):  # 一行的移动
			def tight(row):  # 步骤一:数字凑一块
				new_row = [i for i in row if i != 0]  # 对齐
				new_row += [0 for i in range(len(row) - len(new_row))]  # 补零
				return new_row

			def merge(row):  # 合并
				for i in range(len(row) - 1):
					if row[i] == row[i + 1]:
						row[i] *= 2
						row[i + 1] = 0
						self.score2 += row[i]
				return row

			return tight(merge(tight(row)))

		moves = {}

		moves['Left'] = lambda filed: [leftrow_move(row) for row in filed]
		moves['Right'] = lambda filed: self.invert([leftrow_move(row) for row in self.invert(filed)])
		moves['Up'] = lambda filed: self.transpose([leftrow_move(row) for row in self.transpose(filed)])
		moves['Down'] = lambda filed: self.transpose(moves['Right'](self.transpose(filed)))
		moves1 = {}
		moves1['Left1'] = lambda filed: [leftrow_move1(row) for row in filed]
		moves1['Right1'] = lambda filed: self.invert([leftrow_move1(row) for row in self.invert(filed)])
		moves1['Up1'] = lambda filed: self.transpose([leftrow_move1(row) for row in self.transpose(filed)])
		moves1['Down1'] = lambda filed: self.transpose(moves1['Right1'](self.transpose(filed)))
		# 判断是否可移动

		if self.move_possible(direction):
			self.file1 = moves[direction](self.file1)
			self.create_random(self.file1)
			return True
		elif self.move_possible1(direction):
			self.file2 = moves1[direction](self.file2)
			self.create_random(self.file2)
			return True
		else:
			return False


		# 定义捕获用户操作的函数


def get_action(stdscr):
	action = stdscr.getch()
	if action == curses.KEY_UP:
		return 'Up'
	if action == curses.KEY_DOWN:
		return 'Down'
	if action == curses.KEY_LEFT:
		return 'Left'
	if action == curses.KEY_RIGHT:
		return 'Right'
	if action == ord('w'):
		return 'Up1'
	if action == ord('s'):
		return 'Down1'
	if action == ord('a'):
		return 'Left1'
	if action == ord('d'):
		return 'Right1'
	if action == ord('r'):
		return 'Restart'
	if action == ord('q'):
		return 'Exit'


	# 主函数


def main(stdscr):
	# 调用游戏类

	def init():  # 初始化函数,创建数据并返回开始玩游戏的函数
		game_filed.recreate_file()
		return 'Game'

	def game():  # 游戏内函数
		game_filed.draw(stdscr)  # 画棋盘
		action = get_action(stdscr)  # 获取用户操作
		if action == 'Restart':  # 重置游戏
			return 'Init'
		if action == 'Exit':
			return 'Exit'
		if game_filed.move(action):  # 其他操作让其移动
			# 每次移动后判断输或者赢
			if game_filed.is_win():
				return 'Win'
		return 'Game'  # 再次返回游戏函数

	def not_game():  # 定义游戏外函数
		game_filed.draw(stdscr)  # 画棋盘
		while 1:
			action = get_action(stdscr)
			if action == 'Restart':  # 重置游戏
				return 'Init'
			if action == 'Exit':  # 退出
				return 'Exit'

	status_filed = {'Init': init,
					'Game': game,
					'Win': not_game,
					'GameOver': not_game
					}
	game_filed = Gamefiled(win_value=2048)

	status = 'Init'

	while status != "Exit":
		status = status_filed[status]()


curses.wrapper(main)

猜你喜欢

转载自blog.csdn.net/biu_biu_0329/article/details/80571811
今日推荐