python控制台小游戏_Python 学习笔记,制作控制台窗口小游戏-2048

1. 声明文档为 utf-8 编码#-*- coding: utf-8 -*-

2. 引入 curses,然后画棋盘第一行

curses 是控制台的图形界面#-*- coding: utf-8 -*-

import curses

def main(stdscr):

curses.use_default_colors()

stdscr.addstr('+------' * 4 + '+')

stdscr.addstr('\n')

stdscr.addstr('| ' * 4 + '|')

stdscr.addstr('\n')

stdscr.addstr('| ' * 4 + '|')

stdscr.addstr('\n')

stdscr.addstr('+------' * 4 + '+')

stdscr.addstr('\n')

stdscr.getch()

curses.wrapper(main)

3. 画出棋盘的另外三行

声明方法使代码看起来简洁一些#-*- coding: utf-8 -*-

import curses, time

def main(stdscr):

def cast(string): # 打印一行文本到控制台

stdscr.addstr(string + '\n')

def draw_hor_separator(): # 打印横向分割线

cast('+------' * 4 + '+')

def draw_row(): # 打印显示数字的格子

cast('| ' * 4 + '|')

curses.use_default_colors() # 设置控制台窗口的颜色

draw_hor_separator() # +------+------+------+------+

draw_row() # | | | | |

draw_hor_separator() # +------+------+------+------+

draw_row() # | | | | |

draw_hor_separator() # +------+------+------+------+

draw_row() # | | | | |

draw_hor_separator() # +------+------+------+------+

draw_row() # | | | | |

draw_hor_separator() # +------+------+------+------+

stdscr.getch() # 等待用户输入后结束

curses.wrapper(main)

4. 在格子中显示数字,并保持格子形状不变形

这个需求主要改动 draw_row() 方法,我们将一行的数字值传给该方法,并在方法中输出出来#-*- coding: utf-8 -*-

import curses, time

def main(stdscr):

def cast(string): # 打印一行文本到控制台

stdscr.addstr(string + '\n')

def draw_hor_separator(): # 打印横向分割线

cast('+------' * 4 + '+')

def draw_row(row): # 打印显示数字的格子

# 将每列数字

cast(''.join([('|' + '{:^6}'.format(cell if cell > 0 else '')) for cell in row]) + '|')

curses.use_default_colors() # 设置控制台窗口的颜色

draw_hor_separator() # +------+------+------+------+

draw_row([0, 0, 0, 0]) # | | | | |

draw_hor_separator() # +------+------+------+------+

draw_row([2, 4, 8, 16]) # | 2 | 4 | 8 | 16 |

draw_hor_separator() # +------+------+------+------+

draw_row([32, 64, 128, 256]) # | 32 | 64 | 128 | 256 |

draw_hor_separator() # +------+------+------+------+

draw_row([512, 1024, 2048, 4096]) # | 512 | 1024 | 2048 | 4096 |

draw_hor_separator() # +------+------+------+------+

stdscr.getch() # 等待用户输入后结束

curses.wrapper(main)

5. 接收控制台指令

2048 游戏有6个按键操作:w, s, a, d 控制数字平移方向

r 放弃当前游戏,重置棋盘

q 退出游戏

接收指令通过 stdscr.getch() 方法实现# stdscr.getch() # 等待用户输入后结束

char = ''

while char != 'q': # q 按下后退出

char = chr(stdscr.getch())

# if char == 'w':

# if char == 's':

# if char == 'a':

# if char == 'd':

# if char == 'r':

6. 初始化棋盘

将棋盘数据用二维数组对象存储起来,并且增加初始化、向上下左右移动、判断是否可移动方法game 。第一步先实现向左的移动和判断#-*- coding: utf-8 -*-

import curses

from random import randrange, choice

def main(stdscr):

cells = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]

def cast(string): # 打印一行文本到控制台

stdscr.addstr(string + '\n')

def draw_hor_separator(): # 打印横向分割线

cast('+------' * 4 + '+')

def draw_row(row): # 打印显示数字的格子

# 将每列数字

cast(''.join([('|' + '{:^6}'.format(cell if cell > 0 else '')) for cell in row]) + '|')

def draw_game():

global cells

stdscr.clear()

for row in cells:

draw_hor_separator() # +------+------+------+------+

draw_row(row) # | | | | |

draw_hor_separator()

def init_game(): # 清空棋盘

global cells

cells = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]

def spawn(): # 随机生成一个数字,放到数值为0的位置

global cells

new_element = 4 if randrange(100) > 89 else 2 # 0.1 的概率出现4

(i, j) = choice([(i, j) for i in range(4) for j in range(4)])

(i, j) = choice([(i, j) for i in range(4) for j in range(4) if cells[i][j] == 0])

cells[i][j] = new_element

def move_is_possible(direction): # direction 'w', 's', 'a', 'd'

def row_is_left_movable(row):

def change(i):

if row[i] == 0 and row[i + 1] != 0:

return True

if row[i] != 0 and row[i + 1] == row[i]:

return True

return False

return any(change(i) for i in range(len(row) - 1))

global cells

return any(row_is_left_movable(row) for row in cells)

def move(direction): # 移动格子,贴边 > 合并 > 贴边

def move_row_left(row): # 向左移动,其他方向的判断为先旋转至向左,再判断,再还原至初始方向

def tighten(row): # 贴边

new_row = [i for i in row if i != 0]

new_row += [0 for i in range(4 - len(new_row))]

return new_row

def merge(row): # 合并

pair = False # 是否可合并

new_row = [] # 合并后的结果

for i in range(len(row)):

if pair: # 已找到可合并的单元格,进行合并

new_row.append(2 * row[i])

pair = False

else: # 未找到合并的单元格,查找下一个可合并的单元格

if i + 1 < 4 and row[i] == row[i + 1]: # 找到了下一个可合并的单元格对

pair = True

new_row.append(0)

else:

new_row.append(row[i])

return new_row

return tighten(merge(tighten(row)))

if move_is_possible(direction):

global cells

cells = [move_row_left(row) for row in cells]

spawn()

draw_game()

return True

else:

return False

curses.use_default_colors() # 设置控制台窗口的颜色

# stdscr.getch() # 等待用户输入后结束

char = ''

while char != 'q': # q 按下后退出

char = chr(stdscr.getch())

# if char == 'w':

# if char == 's':

if char == 'a':

move('a')

# if char == 'd':

if char == 'r':

init_game()

spawn()

spawn()

draw_game()

curses.wrapper(main)

7. 增加其他几个方向向右 = 反转->向左->反转

向上 = 对折->向左->对折

向下 = 对折->向右->对折

反转的实现return [row[::-1] for row in field]

对折的实现return [list(row) for row in zip(*field)]

修改 move 方法def move(direction): # 移动格子,贴边 > 合并 > 贴边

...

if move_is_possible(direction):

global cells

if direction == 'a':

cells = [move_row_left(row) for row in cells]

elif direction == 'd':

cells = invert([move_row_left(row) for row in invert(cells)])

elif direction == 'w':

cells = transpose([move_row_left(row) for row in transpose(cells)])

elif direction == 's':

cells = transpose(invert([move_row_left(row) for row in invert(transpose(cells))]))

spawn()

draw_game()

return True

else:

return False

修改 move_is_possible 方法def move_is_possible(direction): # direction 'w', 's', 'a', 'd'

...

if direction == 'a':

return any(row_is_left_movable(row) for row in cells)

elif direction == 'd':

return any(row_is_left_movable(row) for row in invert(cells))

elif direction == 'w':

return any(row_is_left_movable(row) for row in transpose(cells))

elif direction == 's':

return any(row_is_left_movable(row) for row in invert(transpose(cells)))

return False

演示效果

完整代码#-*- coding: utf-8 -*-

import curses

from random import randrange, choice

def main(stdscr):

cells = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]

def cast(string): # 打印一行文本到控制台

stdscr.addstr(string + '\n')

def draw_hor_separator(): # 打印横向分割线

cast('+------' * 4 + '+')

def draw_row(row): # 打印显示数字的格子

cast(''.join([('|' + '{:^6}'.format(cell if cell > 0 else '')) for cell in row]) + '|')

def draw_game():

global cells

stdscr.clear()

for row in cells:

draw_hor_separator() # +------+------+------+------+

draw_row(row) # | | | | |

draw_hor_separator()

def init_game(): # 清空棋盘

global cells

cells = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]

def spawn(): # 随机生成一个数字,放到数值为0的位置

global cells

new_element = 4 if randrange(100) > 89 else 2 # 0.1 的概率出现4

(i, j) = choice([(i, j) for i in range(4) for j in range(4)])

(i, j) = choice([(i, j) for i in range(4) for j in range(4) if cells[i][j] == 0])

cells[i][j] = new_element

# 对角翻转

def transpose(field):

return [list(row) for row in zip(*field)]

# 水平翻转

def invert(field):

return [row[::-1] for row in field]

def move_is_possible(direction): # direction 'w', 's', 'a', 'd'

def row_is_left_movable(row):

def change(i):

if row[i] == 0 and row[i + 1] != 0:

return True

if row[i] != 0 and row[i + 1] == row[i]:

return True

return False

return any(change(i) for i in range(len(row) - 1))

global cells

if direction == 'a':

return any(row_is_left_movable(row) for row in cells)

elif direction == 'd':

return any(row_is_left_movable(row) for row in invert(cells))

elif direction == 'w':

return any(row_is_left_movable(row) for row in transpose(cells))

elif direction == 's':

return any(row_is_left_movable(row) for row in invert(transpose(cells)))

return False

def move(direction): # 移动格子,贴边 > 合并 > 贴边

def move_row_left(row): # 向左移动,其他方向的判断为先旋转至向左,再判断,再还原至初始方向

def tighten(row): # 贴边

new_row = [i for i in row if i != 0]

new_row += [0 for i in range(4 - len(new_row))]

return new_row

def merge(row): # 合并

pair = False # 是否可合并

new_row = [] # 合并后的结果

for i in range(len(row)):

if pair: # 已找到可合并的单元格,进行合并

new_row.append(2 * row[i])

pair = False

else: # 未找到合并的单元格,查找下一个可合并的单元格

if i + 1 < 4 and row[i] == row[i + 1]: # 找到了下一个可合并的单元格对

pair = True

new_row.append(0)

else:

new_row.append(row[i])

return new_row

return tighten(merge(tighten(row)))

if move_is_possible(direction):

global cells

if direction == 'a':

cells = [move_row_left(row) for row in cells]

elif direction == 'd':

cells = invert([move_row_left(row) for row in invert(cells)])

elif direction == 'w':

cells = transpose([move_row_left(row) for row in transpose(cells)])

elif direction == 's':

cells = transpose(invert([move_row_left(row) for row in invert(transpose(cells))]))

spawn()

draw_game()

return True

else:

return False

curses.use_default_colors() # 设置控制台窗口的颜色

# stdscr.getch() # 等待用户输入后结束

char = ''

while char != 'q': # q 按下后退出

char = chr(stdscr.getch())

if char == 'w':

move('w')

if char == 's':

move('s')

if char == 'a':

move('a')

if char == 'd':

move('d')

if char == 'r':

init_game()

spawn()

spawn()

draw_game()

curses.wrapper(main)

至此,游戏的主要内容都已经完成了。

8. 增加按键提示、分数、游戏胜利与失败判定

这一步主要是增加细节处理,最终完成 2048 小游戏。

效果演示

最终代码如下:#-*- coding: utf-8 -*-

import curses

from random import randrange, choice

cells = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]

score = 0

def main(stdscr):

def cast(string): # 打印一行文本到控制台

stdscr.addstr(string + '\n')

def draw_hor_separator(): # 打印横向分割线

cast('+------' * 4 + '+')

def draw_row(row): # 打印显示数字的格子

cast(''.join([('|' + '{:^6}'.format(cell if cell > 0 else '')) for cell in row]) + '|')

def new_game():

init_game()

spawn()

spawn()

draw_game()

def draw_game():

global cells

stdscr.clear()

for row in cells:

draw_hor_separator() # +------+------+------+------+

draw_row(row) # | | | | |

draw_hor_separator()

cast('Score: ' + str(score))

if is_win():

cast("You win!")

elif is_gameover():

cast("Game over!")

else:

cast('(W)Up (S)Down (A)Left (D)Right')

cast('(R)Restart (Q)Exit')

def init_game(): # 清空棋盘

global cells

global score

cells = [[0,0,0,0],[0,0,0,0],[0,0,0,0],[0,0,0,0]]

score = 0

def spawn(): # 随机生成一个数字,放到数值为0的位置

global cells

new_element = 4 if randrange(100) > 89 else 2 # 0.1 的概率出现4

(i, j) = choice([(i, j) for i in range(4) for j in range(4)])

(i, j) = choice([(i, j) for i in range(4) for j in range(4) if cells[i][j] == 0])

cells[i][j] = new_element

# 对角翻转

def transpose(field):

return [list(row) for row in zip(*field)]

# 水平翻转

def invert(field):

return [row[::-1] for row in field]

def move_is_possible(direction): # direction 'w', 's', 'a', 'd'

def row_is_left_movable(row):

def change(i):

if row[i] == 0 and row[i + 1] != 0:

return True

if row[i] != 0 and row[i + 1] == row[i]:

return True

return False

return any(change(i) for i in range(len(row) - 1))

global cells

if direction == 'a':

return any(row_is_left_movable(row) for row in cells)

elif direction == 'd':

return any(row_is_left_movable(row) for row in invert(cells))

elif direction == 'w':

return any(row_is_left_movable(row) for row in transpose(cells))

elif direction == 's':

return any(row_is_left_movable(row) for row in invert(transpose(cells)))

return False

def move(direction): # 移动格子,贴边 > 合并 > 贴边

def move_row_left(row): # 向左移动,其他方向的判断为先旋转至向左,再判断,再还原至初始方向

def tighten(row): # 贴边

new_row = [i for i in row if i != 0]

new_row += [0 for i in range(4 - len(new_row))]

return new_row

def merge(row): # 合并

pair = False # 是否可合并

new_row = [] # 合并后的结果

for i in range(len(row)):

if pair: # 已找到可合并的单元格,进行合并

global score

new_row.append(2 * row[i])

score += 2 * row[i]

pair = False

else: # 未找到合并的单元格,查找下一个可合并的单元格

if i + 1 < 4 and row[i] == row[i + 1]: # 找到了下一个可合并的单元格对

pair = True

new_row.append(0)

else:

new_row.append(row[i])

return new_row

return tighten(merge(tighten(row)))

if move_is_possible(direction):

global cells

if direction == 'a':

cells = [move_row_left(row) for row in cells]

elif direction == 'd':

cells = invert([move_row_left(row) for row in invert(cells)])

elif direction == 'w':

cells = transpose([move_row_left(row) for row in transpose(cells)])

elif direction == 's':

cells = transpose(invert([move_row_left(row) for row in invert(transpose(cells))]))

spawn()

draw_game()

return True

else:

return False

def is_win():

global cells;

return any(any(i >= 2048 for i in row) for row in cells)

def is_gameover():

return not any(move_is_possible(move) for move in ['w','s','a','d'])

curses.use_default_colors() # 设置控制台窗口的颜色

new_game()

char = ''

while char != 'q':

char = chr(stdscr.getch())

if char in ['w','s','a','d']:

move(char)

if char == 'r':

new_game()

curses.wrapper(main)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值