python 实现 2048 游戏 （二）

• 用户输入小写的 w s a d 对应上下左右
• 该移动方向上允许移动

```def game(board, stdscr, rscore):
global score
global change

# curses.noecho()
# 屏幕不显示用户输入的字符
curses.noecho()
while 1:

# stdscr.getch()
# 读取用户输入的字符
order = stdscr.getch()

# move()对用户移动的响应
current_board, change = move(order, board)
# change 为 1 随机产生 2 或 4
if change:
current_board = choice(board)

# 打印棋盘
print_board(stdscr, current_board, rscore)

# 当棋盘被填满，判断是否游戏结束
if (current_board != 0).all():
fail(current_board)

# win 为 1 打印获胜提示
if win:

basic 函数用来执行移动与碰撞的操作。move_{up,down,right,left} 函数用来实现各个方向上的 basic 函数操作。move 函数用来响应用户指令，实现各个方向上的移动。

• 4 与 0 不交换 [2 2 0 4]
• 0 与 2 交换 [2 0 2 4]
• 0 与 2 交换 [0 2 2 4]
• flag = 1 且 score + = 0

• 4 与 2 不交换 [0 2 2 4]

• 0 不变 [0 0 4 4]
• flag = 1 且 score += 100

• 不变 [0 0 0 8]
• 不变 [0 0 0 8]
• flag = 1 且 score += 100

• 不变
• 不变
• 不变
• flag = 0 且 score += 0

```# A 为 4*4 的矩阵
# 转置操作
A.T
# 逆置操作
A[::-1,::-1]```

```# 基础移动
def basic(board):
global score
global win
# 以右移为基础移动

for i in range(4):
flag = 1
while flag:
flag = 0
j = 2
while j >= 0:
if board[i, j] != 0:
if board[i, j + 1] == board[i, j]:
board[i, j + 1] = 2 * board[i, j]
if board[i, j + 1] == 2048:
win = 1
board[i, j] = 0
score += 100
flag = 1

elif board[i, j + 1] == 0:
temp = board[i, j]
board[i, j] = board[i, j + 1]
board[i, j + 1] = temp
flag = 1

j -= 1
return board

# 右移
def move_right(board):
return basic(board)

# 上移
def move_up(board):
# 逆置 + 转置
board = board[::-1, ::-1].T
board = basic(board)
board = board[::-1, ::-1].T
return board

# 左移
def move_left(board):
# 逆置
board = board[::-1, ::-1]
board = basic(board)
board = board[::-1, ::-1]
return board

# 下移
def move_down(board):
# 转置
board = board.T
board = basic(board)
board = board.T
return board

# 移动
def move(order, board):
# ord 求码值
global score
global win
change = 1
tempboard = copy.deepcopy(board)

# 退出游戏
if order == ord('q'):
save_score(score)
exit()
# 重置游戏
elif order == ord('r'):
win = 0
save_score(score)
score = 0
stdscr.clear()
wrapper(main)
# 胜利后，只有退出和重置游戏
elif win:
change = 0
newboard = tempboard
return newboard, change
# 上下左右移动
elif order == ord('w'):
newboard = move_up(board)
elif order == ord('s'):
newboard = move_down(board)
elif order == ord('a'):
newboard = move_left(board)
elif order == ord('d'):
newboard = move_right(board)

# 按其他键程序不响应
else:
newboard = board

if (newboard == tempboard).all():
change = 0

return newboard, change```

```# 随机产生 2 或 4
def choice(board):
udict = {}
# 统计0的个数
count = 0
for i in range(4):
for j in range(4):
# board[i,j] 为 0
# eg. {0:(1,3),1:(2,1),3:(3,2)}
# 根据 key 可以获得元素 0 在棋盘上的位置
if not board[i, j]:
udict[count] = (i, j)
count += 1
# np.random.randint(0, count)
# 产生 [0,count) 范围内的随机数
random_number = np.random.randint(0, count)
# np.random.choice([2,2,2,4])
# 随机选取列表 [2,2,2,4] 中的元素
two_or_four = np.random.choice([2, 2, 2, 4])
# 更改棋盘上 0 元素为随机数
board[udict[random_number]] = two_or_four
return board```

```# 加载最高分
return rank_score

# 保存最高分
def save_score(score):
if score > rscore:
np.save(FILENAME, score)

# 比较当前分数与当前最高分
def compare_score(score, rscore):
if score > rscore:
rscore = score
return rscore```

```# 打印棋盘
def print_board(stdscr, board, rscore):
global score
rscore = compare_score(score, rscore)

# stdscr.clear()
# 清除屏幕
# 打印字符串
stdscr.clear()
for i in range(4):
for j in range(4):
if board[i, j]:
else:

```import numpy as np
import curses
import copy
import os
from curses import wrapper

stdscr = curses.initscr()
# 分数
score = 0
# 判断是否获胜
win = 0
#
FILENAME = 'out.npy'

# 初始化
def init():
# 初始化棋盘
# 初始棋盘 2 或 4 的随机数字
if FILENAME not in os.listdir():
np.save(FILENAME, 0)
init_board = choice(np.zeros((4, 4), dtype=np.int))
return init_board

# 主程序
def main(stdscr):
# 初始化程序
init_board = init()
# 打印棋盘
print_board(stdscr, init_board, rscore)
# 游戏主进程
game(init_board, stdscr, rscore)

if __name__ == "__main__":
wrapper(main)```

0 条评论

• 快来算一算你写了多少行代码

前面我们一直在介绍图形界面，这次换个口味，在命令行实现代码行数统计程序。本程序共 135 行，其中 18 行空行、110 行有效代码、7行注释，大小为 7.71...

• Python 实现简易版成绩管理系统

上一次，公众号介绍了如何使用 Python 实现单链表，下面让我们一探单链表的简单应用：在命令行，实现简易版成绩管理系统。

• 动画演示广度优先算法寻找最短路径

上一节，我们刚刚介绍了使用深度优先算法(DFS)解决迷宫问题，这一节我们来介绍广度优先算法(BFS)。BFS 算法与 DFS 十分相似，唯一的区别就是 DFS ...

• leetcode419. Battleships in a Board

假设有一个2D板，在板上用X表示战舰，已知板上任意两个战舰体之间一定会用.隔开，因此不会出现两个X相邻的情况。现在要求用O(N)的时间复杂度和O(1)的空间复杂...

• leetcode: 37. Sudoku Solver

…and its solution numbers marked in red.

• Swift 有效的数独 - LeetCode

判断一个数独是否有效，根据：Sudoku Puzzles - The Rules。 (数独规则： 每一行不能有重复的数字；每一列不能有重复的数字；将数独框划分...

• LeetCode 999. 车的可用捕获量

在一个 8 x 8 的棋盘上，有一个白色车（rook）。也可能有空方块，白色的象（bishop）和黑色的卒（pawn）。它们分别以字符 “R”，“.”，“B” ...

• LeetCode 130. 被围绕的区域（图的BFS/DFS）

解释: 任何边界上的 ‘O’ 都不会被填充为 ‘X’。 任何不在边界上，或不与边界上的 ‘O’ 相连的 ‘O’ 最终都会被填充为 ‘X’。如果两个元素在水平或...