Python实现2048小游戏

server/2024/12/3 4:01:39/

2048是一个单人益智游戏,目标是移动和合并数字,以达到2048。

1. 实现效果

Python实现2048小游戏

2. 游戏规则

简单地理解一下规则

基本规则:

  • 4x4棋盘,每个格可包含一个2的倍数的数字,初始时为空,表示0。
  • 游戏开始时,格中会随机生成两个数,数字通常为2或4。
  • 可通过键盘的上下左右方向来驱使所有的块向同一方向移,直至无法移动。
  • 移动过程,途遇相同数字,二者合并后的数字为原来的两倍,且仅合并一对为1个数字。
  • 移动后,随机生成一个新的2或4方块。
  • 每次合并方块时,得分会增加,得分等于合并后新方块的数字。
  • 游戏结束:网格中没有空位置且没有可以合并的方块时game over
  • 重启游戏:点击“Restart”按钮可以重启游戏。
  • 高分记录:可以查看之前的高分,并可以输入姓名记录自己的得分。

其他规则:

  1. 实现游戏规则。
  2. 使用图形函数生成界面等。 【分数+游戏局+重玩+分数排行】
  3. 用文件存储用户的进度。【游戏进度实时记录于save_game.txt便于继续残局】
  4. 用户开始新游戏时,先检测是否有历史记录,有的话可以继续未完成的游戏,也可以重新开始。
  5. 实现用户排名功能,要求能够将排名信息进行保存,存至文件永久保存。【存至high_scores.json文件】
  6. 当新用户的成绩需要插入排名列表时,要能够修改原列表信息:如果是同一用户需要更新成绩,则覆盖原成绩。【Score按钮】
  7. 可以插入、修改、删除排名信息。【Score按钮,点击显示弹窗,当中的排名信息可以增删改】

3. 环境配置

程序中会用到的库:

python">import tkinter as tk
import random
import json
import os

其中os、json和random是python的内置库,不需要安装,tkinter是标准库之一,通常也不需要单独安装。

4. 代码实现

变量说明

python"># 设置游戏参数
self.grid_size = 4 # 4×4格
self.score = 0     # 当前局的分数
self.high_score = self.load_highest_score() # 最高分记录
self.tile_values = [[0] * self.grid_size for _ in range(self.grid_size)] # 数字块初始值为 0
self.game_over = False # 判断游戏是否结束的标志

游戏界面

python">"""创建游戏界面"""
# 组件部分
# 上层:构建框架frame 包含2个文本标签:当前分数score和最高分数Highest Score
self.frame = tk.Frame(self.root, bg="#faf8ef", padx=10, pady=10)
self.frame.pack(pady=20)
# 分数标签 在frame中加score标签 显示当前游戏分数
self.score_label = tk.Label(self.frame, text=f"Score: {self.score}", font=("Arial", 18), bg="#faf8ef")
self.score_label.grid(row=0, column=0,padx=10,)
# 最高分标签 在frame中加high_score标签 显示最高游戏分数
self.high_score_label = tk.Label(self.frame, text=f"Highest Score: {self.high_score}", font=("Arial", 18),bg="#faf8ef")
self.high_score_label.grid(row=0, column=1,padx=10,)
# 中层:创建画布 画布用于绘制游戏块
self.canvas = tk.Canvas(self.root, width=400, height=400, highlightthickness=0)
self.canvas.pack()
# 下层:构建框架frame1 包含2个按钮, 1个标签:重来按钮restart+信息按钮Scores+游戏结束标签
self.frame1 = tk.Frame(self.root, bg="#faf8ef")
self.frame1.pack(pady=20)
self.restart_button = tk.Button(self.frame1, text="Restart", command=self.restart_game, font=("Arial", 16),bg="#8f7a66", fg="white", relief=tk.FLAT)
self.high_scores_button = tk.Button(self.frame1, text="Scores", command=self.show_high_scores,font=("Arial", 16), bg="#8f7a66", fg="white", relief=tk.FLAT)
# 布局按钮
self.restart_button.grid(row=0, column=0, padx=20)
self.high_scores_button.grid(row=0, column=1, padx=20)

棋盘绘制

python">tile_colors = {0: "#D9D5D1", 2: "#eee4da", 4: "#ede0c8", 8: "#f2b179",16: "#f59563", 32: "#f67c5f", 64: "#f67c5f", 128: "#f9f6f2",256: "#f9f6f2", 512: "#f9f6f2", 1024: "#f9f6f2", 2048: "#f9f6f2",} # 数字砖块颜色渐变

数字块背景色渐变
不同的数字格子背景颜色不同

假设值,看一下配色

{"tiles": [[2, 4, 6, 16], [32, 64, 128, 256], [512, 1024, 2048, 4096], [8192, 16384, 32768, 65536]], "score": 11223243436}

2 ~ 2048有设置配色,后面更大的数就默认了,不过为了颜色不太杂乱,设置的颜色也少。

在这里插入图片描述

块的数字值设置

python"># 绘制每个方块
for y in range(self.grid_size):for x in range(self.grid_size):value = self.tile_values[y][x] # 块的数字值color = tile_colors.get(value, "#cdc1b4")  # 默认颜色self.canvas.create_rectangle(x * 100 + 5, y * 100 + 5, (x + 1) * 100 - 5, (y + 1) * 100 - 5, fill=color, outline="#bfb3a0", width=8, tags='tile') # 画布绘制正方形块 初始块 就是0的状态, 此时砖块无数值if value != 0: # 当 value ≥ 0 给砖块加入数值文字self.canvas.create_text(x * 100 + 50, y * 100 + 50,text=str(value), font=("Arial", 24), fill="#776e65")

分数显示部分

python">self.high_score = self.load_highest_score()
self.high_score_label.config(text=f"Highest Score: {self.high_score}")

存在一个问题, 就是第一次运行时, 文件不存在, 然后获取最高分数是从文档获取的,所以这个时候会是0。

python">def load_highest_score(self):"""加载最高分"""if os.path.exists("high_scores.json"):with open("high_scores.json", "r") as f:high_scores = json.load(f)if high_scores:return high_scores[0][1]  # 返回最高分return 0

因此,预防第一局时, 还没有历史记录, 最高分数睡懒觉 设置为当没有最高分数时让最高分数跟随当前分数score。

几个特殊情况的最高分数值显示:一个是初始时没有文档最高值记录,此时应跟随score。然后我存入一最高分,① 游戏未结束,并不restart继续玩,此时应仍旧跟随;② 此时若restart 应从文档中取;③ 若此时我继续玩一会又restart 此时应从文档中取。

python">self.high_score = self.load_highest_score()
if self.high_score==0 or self.score > self.high_score:self.high_score_label.config(text=f"Highest Score: {self.score}")
else:self.high_score_label.config(text=f"Highest Score: {self.high_score}")

动作部分

随机新数
在空白方块上生成一个新的数字方块(2或4)

python">def spawn_tile(self):empty_tiles = [(x, y) for x in range(self.grid_size) for y in range(self.grid_size) ifself.tile_values[y][x] == 0]if empty_tiles:x, y = random.choice(empty_tiles)self.tile_values[y][x] = random.choice([2, 4]) # 一般是2或者4这种比较小的数值

上下左右

python">def move(self, direction):"""根据方向移动方块并合并"""original_tiles = [row[:] for row in self.tile_values]  # 记录原始状态merged = [[False] * self.grid_size for _ in range(self.grid_size)]if direction == "Left":for x in range(self.grid_size):self.tile_values[x] = self.merge_row_left(self.tile_values[x])elif direction == "Right":for i in range(self.grid_size):self.tile_values[i] = self.merge_row_left(self.tile_values[i][::-1])[::-1]elif direction == "Up":for j in range(self.grid_size):col = [self.tile_values[i][j] for i in range(self.grid_size)]merged_col = self.merge_row_left(col)for i in range(self.grid_size):self.tile_values[i][j] = merged_col[i]elif direction == "Down":for j in range(self.grid_size):col = [self.tile_values[i][j] for i in range(self.grid_size)]merged_col = self.merge_row_left(col[::-1])[::-1]for i in range(self.grid_size):self.tile_values[i][j] = merged_col[i]# 如果发生了移动或合并,则生成新的方块if original_tiles != self.tile_values:self.spawn_tile()

合并&积分

python">def merge_row_left(self, row):"""将给定行向左合并"""new_row = [num for num in row if num != 0]  # 去除零merged_row = []index = 0while index < len(new_row):# 如果相邻两个相同,则合并if index + 1 < len(new_row) and new_row[index] == new_row[index + 1]:merged_value = new_row[index] * 2merged_row.append(merged_value)  # 添加合并后的值self.score += merged_value  # 更新分数index += 2  # 跳过下一个值else:merged_row.append(new_row[index])index += 1# 填充剩余的零while len(merged_row) < self.grid_size:merged_row.append(0)return merged_row

数据存储

游戏进度保存

在这里插入图片描述

python">def save_game(self):"""保存当前游戏状态 游戏实时存档"""data = {'tiles': self.tile_values, 'score': self.score}with open("save_game.txt", "w") as f:json.dump(data, f)

每移动一步都会被记录下来,所以中断游戏的时候,用户下次再玩,开始新游戏时,加载游戏时,会先检测是否有历史记录,有的话可以继续未完成的游戏,也可以重新开始。
在这里插入图片描述

游戏加载

python">def load_game(self):"""加载游戏状态 先查看是否存在残局, 有则恢复, 无则重开一局"""if os.path.exists("save_game.txt"):with open("save_game.txt", "r") as f:data = json.load(f)self.tile_values = data['tiles']self.score = data['score']else:self.restart_game()

高分保存

将用户排名信息进行保存,存至文件永久保存。

python">def save_high_scores(self, scores):"""保存高分记录"""with open("high_scores.json", "w") as f:json.dump(scores, f)

重来一局

game over判断

python">def check_game_over(self):"""检查游戏是否结束"""if any(0 in row for row in self.tile_values):return False  # 如果还有空方块,游戏未结束for i in range(self.grid_size):for j in range(self.grid_size):# 检查相邻方块是否可以合并if (i < self.grid_size - 1 and self.tile_values[i][j] == self.tile_values[i + 1][j]) or \(j < self.grid_size - 1 and self.tile_values[i][j] == self.tile_values[i][j + 1]):return False  # 还有可以合并的方块return True  # 无法再移动或合并,游戏结束

显示game over

python">def show_game_over(self):"""显示游戏结束的信息"""if not hasattr(self, 'game_over_label'):self.game_over_label = tk.Label(self.frame1, text="Game Over!", font=('Arial', 24), fg="red", bg="#faf8ef")self.game_over_label.grid(row=0, column=2, padx=20)

restart的话,这个game over的label就要清掉,但又不能影响下一局的判断,所以加了判断:

python">if not hasattr(self, 'game_over_label'):

游戏重来

python">def restart_game(self):"""重启游戏"""self.tile_values = [[0] * self.grid_size for _ in range(self.grid_size)]self.score = 0self.game_over = False# 清除游戏结束的标签(如果有的话)if hasattr(self, 'game_over_label'):self.game_over_label.destroy()  # 移除游戏结束的文本del self.game_over_label  # 删除引用self.spawn_tile()self.spawn_tile()  # 在两个随机位置生成方块self.draw_board()self.save_game()

分数排行

在这里插入图片描述

排行榜的分数增删( 包含改,同一个用户可以多次等级分数,会自动择高分)

python">def add_high_score(self, score_window):"""添加新的高分记录"""def submit_score():name = entry.get()if name:score_list = self.load_high_scores()exists = Falsefor i, (n, sc) in enumerate(score_list):if n == name:  # 如果名称已存在则更新分数score_list[i][1] = max(sc, self.score)exists = Truebreakif not exists:score_list.append([name, self.score])  # 新增高分score_list.sort(key=lambda x: x[1], reverse=True)  # 根据分数排序score_list = score_list[:10]  # 只保留前10名self.save_high_scores(score_list)score_window.destroy()  # 关闭添加窗口self.show_high_scores()  # 更新高分显示
def delete_high_score(self, name):"""删除某个玩家的高分记录"""score_list = self.load_high_scores()score_list = [item for item in score_list if item[0] != name]self.save_high_scores(score_list)self.show_high_scores()

完整代码

python">import tkinter as tk
import random
import json
import os
class Game2048:def __init__(self, root):self.root = root  # 主窗口root.title("2048 Game") # 窗口标题# 设置游戏参数self.grid_size = 4 # 4×4格self.score = 0     # 当前局的分数self.high_score = self.load_highest_score() # 最高分记录self.tile_values = [[0] * self.grid_size for _ in range(self.grid_size)] # 数字块初始值为 0self.game_over = False # 判断游戏是否结束的标志self.create_ui()  # 创建uiself.load_game()  # 加载游戏self.spawn_tile() # 随机新增数字块self.draw_board() # 绘制游戏局root.bind("<Key>", self.key_pressed) # 绑定键盘事件到root窗口def create_ui(self):"""创建游戏界面"""# 组件部分# 上层:构建框架frame 包含2个文本标签:当前分数score和最高分数Highest Scoreself.frame = tk.Frame(self.root, bg="#faf8ef", padx=10, pady=10)self.frame.pack(pady=20)# 分数标签 在frame中加score标签 显示当前游戏分数self.score_label = tk.Label(self.frame, text=f"Score: {self.score}", font=("Arial", 18), bg="#faf8ef")self.score_label.grid(row=0, column=0,padx=10,)# 最高分标签 在frame中加high_score标签 显示最高游戏分数self.high_score_label = tk.Label(self.frame, text=f"Highest Score: {self.high_score}", font=("Arial", 18),bg="#faf8ef")self.high_score_label.grid(row=0, column=1,padx=10,)# 中层:创建画布 画布用于绘制游戏块self.canvas = tk.Canvas(self.root, width=400, height=400, highlightthickness=0)self.canvas.pack()# 下层:构建框架frame1 包含2个按钮, 1个标签:重来按钮restart+信息按钮Scores+游戏结束标签self.frame1 = tk.Frame(self.root, bg="#faf8ef")self.frame1.pack(pady=20)self.restart_button = tk.Button(self.frame1, text="Restart", command=self.restart_game, font=("Arial", 16),bg="#8f7a66", fg="white", relief=tk.FLAT)self.high_scores_button = tk.Button(self.frame1, text="Scores", command=self.show_high_scores,font=("Arial", 16), bg="#8f7a66", fg="white", relief=tk.FLAT)# 布局按钮self.restart_button.grid(row=0, column=0, padx=20)self.high_scores_button.grid(row=0, column=1, padx=20)def draw_board(self):"""绘制棋盘"""self.canvas.delete("all")  # 清空画布tile_colors = {0: "#D9D5D1", 2: "#eee4da", 4: "#ede0c8", 8: "#f2b179",16: "#f59563", 32: "#f67c5f", 64: "#f67c5f", 128: "#f9f6f2",256: "#f9f6f2", 512: "#f9f6f2", 1024: "#f9f6f2", 2048: "#f9f6f2",} # 数字砖块颜色渐变# 绘制每个方块for y in range(self.grid_size):for x in range(self.grid_size):value = self.tile_values[y][x] # 块的数字值color = tile_colors.get(value, "#cdc1b4")  # 默认颜色self.canvas.create_rectangle(x * 100 + 5, y * 100 + 5, (x + 1) * 100 - 5, (y + 1) * 100 - 5, fill=color, outline="#bfb3a0", width=8, tags='tile') # 画布绘制正方形块 初始块 就是0的状态, 此时砖块无数值if value != 0: # 当 value ≥ 0 给砖块加入数值文字self.canvas.create_text(x * 100 + 50, y * 100 + 50,text=str(value), font=("Arial", 24), fill="#776e65")self.score_label.config(text=f"Score: {self.score}")self.high_score = self.load_highest_score()if self.high_score==0 or self.score > self.high_score:self.high_score_label.config(text=f"Highest Score: {self.score}")else:self.high_score_label.config(text=f"Highest Score: {self.high_score}")def load_game(self):"""加载游戏状态 先查看是否存在残局, 有则恢复, 无则重开一局"""if os.path.exists("save_game.txt"):with open("save_game.txt", "r") as f:data = json.load(f)self.tile_values = data['tiles']self.score = data['score']else:self.restart_game()def load_highest_score(self):"""加载最高分"""if os.path.exists("high_scores.json"):with open("high_scores.json", "r") as f:high_scores = json.load(f)if high_scores:return high_scores[0][1]  # 返回最高分return 0def save_game(self):"""保存当前游戏状态 游戏实时存档"""data = {'tiles': self.tile_values, 'score': self.score}with open("save_game.txt", "w") as f:json.dump(data, f)def spawn_tile(self):"""在空白方块上生成一个新的数字方块(2或4) 新增数字砖块 add new_tile"""empty_tiles = [(x, y) for x in range(self.grid_size) for y in range(self.grid_size) ifself.tile_values[y][x] == 0]if empty_tiles:x, y = random.choice(empty_tiles)self.tile_values[y][x] = random.choice([2, 4]) # 一般是2或者4这种比较小的数值def key_pressed(self, event):"""处理键盘按键事件"""if self.game_over:returnif event.keysym in ['Up', 'Down', 'Left', 'Right']:self.move(event.keysym)self.save_game()self.draw_board()if self.check_game_over():self.game_over = Trueself.show_game_over()def check_game_over(self):"""检查游戏是否结束"""if any(0 in row for row in self.tile_values):return False  # 如果还有空方块,游戏未结束for i in range(self.grid_size):for j in range(self.grid_size):# 检查相邻方块是否可以合并if (i < self.grid_size - 1 and self.tile_values[i][j] == self.tile_values[i + 1][j]) or \(j < self.grid_size - 1 and self.tile_values[i][j] == self.tile_values[i][j + 1]):return False  # 还有可以合并的方块return True  # 无法再移动或合并,游戏结束def show_game_over(self):"""显示游戏结束的信息"""if not hasattr(self, 'game_over_label'):self.game_over_label = tk.Label(self.frame1, text="Game Over!", font=('Arial', 24), fg="red", bg="#faf8ef")self.game_over_label.grid(row=0, column=2, padx=20)def move(self, direction):"""根据方向移动方块并合并"""original_tiles = [row[:] for row in self.tile_values]  # 记录原始状态merged = [[False] * self.grid_size for _ in range(self.grid_size)]if direction == "Left":for x in range(self.grid_size):self.tile_values[x] = self.merge_row_left(self.tile_values[x])elif direction == "Right":for i in range(self.grid_size):self.tile_values[i] = self.merge_row_left(self.tile_values[i][::-1])[::-1]elif direction == "Up":for j in range(self.grid_size):col = [self.tile_values[i][j] for i in range(self.grid_size)]merged_col = self.merge_row_left(col)for i in range(self.grid_size):self.tile_values[i][j] = merged_col[i]elif direction == "Down":for j in range(self.grid_size):col = [self.tile_values[i][j] for i in range(self.grid_size)]merged_col = self.merge_row_left(col[::-1])[::-1]for i in range(self.grid_size):self.tile_values[i][j] = merged_col[i]# 如果发生了移动或合并,则生成新的方块if original_tiles != self.tile_values:self.spawn_tile()def merge_row_left(self, row):"""将给定行向左合并"""new_row = [num for num in row if num != 0]  # 去除零merged_row = []index = 0while index < len(new_row):# 如果相邻两个相同,则合并if index + 1 < len(new_row) and new_row[index] == new_row[index + 1]:merged_value = new_row[index] * 2merged_row.append(merged_value)  # 添加合并后的值self.score += merged_value  # 更新分数index += 2  # 跳过下一个值else:merged_row.append(new_row[index])index += 1# 填充剩余的零while len(merged_row) < self.grid_size:merged_row.append(0)return merged_rowdef restart_game(self):"""重启游戏"""self.tile_values = [[0] * self.grid_size for _ in range(self.grid_size)]self.score = 0self.game_over = False# 清除游戏结束的标签(如果有的话)if hasattr(self, 'game_over_label'):self.game_over_label.destroy()  # 移除游戏结束的文本del self.game_over_label  # 删除引用self.spawn_tile()self.spawn_tile()  # 在两个随机位置生成方块self.draw_board()self.save_game()def show_high_scores(self):"""显示高分记录"""score_window = tk.Toplevel(self.root)score_window.title("Rank")score_window.configure(bg="#faf8ef")score_list = self.load_high_scores()for index, (name, score) in enumerate(score_list):frame = tk.Frame(score_window, bg="#faf8ef")frame.pack(pady=5)tk.Label(frame, text=f"{index + 1}. {name}: {score}", font=("Arial", 16), bg="#faf8ef", fg="#776e65").pack(side=tk.LEFT)delete_button = tk.Button(frame, text="Delete", command=lambda name=name: self.delete_high_score(name),font=("Arial", 12), bg="#f44336", fg="white", relief=tk.FLAT)delete_button.pack(side=tk.RIGHT)tk.Button(score_window, text="Add Score", command=lambda: self.add_high_score(score_window), font=("Arial", 16),bg="#8f7a66", fg="white", activebackground="#d6ccc6").pack(pady=10)def delete_high_score(self, name):"""删除某个玩家的高分记录"""score_list = self.load_high_scores()score_list = [item for item in score_list if item[0] != name]self.save_high_scores(score_list)self.show_high_scores()def load_high_scores(self):"""加载高分记录"""if os.path.exists("high_scores.json"):with open("high_scores.json", "r") as f:return json.load(f)return []def save_high_scores(self, scores):"""保存高分记录"""with open("high_scores.json", "w") as f:json.dump(scores, f)def add_high_score(self, score_window):"""添加新的高分记录"""def submit_score():name = entry.get()if name:score_list = self.load_high_scores()exists = Falsefor i, (n, sc) in enumerate(score_list):if n == name:  # 如果名称已存在则更新分数score_list[i][1] = max(sc, self.score)exists = Truebreakif not exists:score_list.append([name, self.score])  # 新增高分score_list.sort(key=lambda x: x[1], reverse=True)  # 根据分数排序score_list = score_list[:10]  # 只保留前10名self.save_high_scores(score_list)score_window.destroy()  # 关闭添加窗口self.show_high_scores()  # 更新高分显示# 弹出输入窗口entry_window = tk.Toplevel(score_window)entry_window.configure(bg="#faf8ef")tk.Label(entry_window, text="Enter Your Name:", bg="#faf8ef", fg="#776e65", font=("Arial", 16)).pack()entry = tk.Entry(entry_window, font=("Arial", 16))entry.pack(padx=10, pady=10)tk.Button(entry_window, text="Submit", command=submit_score, font=("Arial", 16),bg="#8f7a66", fg="white", activebackground="#d6ccc6").pack()if __name__ == "__main__":root = tk.Tk()game = Game2048(root)root.mainloop()

http://www.ppmy.cn/server/146922.html

相关文章

Shell脚本小练习

学习了这么长时间Shell脚本&#xff0c;总得来一次小小的练习吧&#xff0c;那么请看下文&#xff01; 1.用Shell写一个小计算器。 通过read命令获取用户输入的表达式&#xff0c;表达式的格式设定为操作数1 运算符 操作数2&#xff0c;例如53&#xff0c;然后利用设计的脚本…

unity中控制相机跟随物体移动

unity中控制相机跟随物体移动 Main Camera下添加组件&#xff08;follow target&#xff09; 脚本中定义 public Transform trans;将transform拖拽到trans中&#xff0c;让trans可以引用到transform数值&#xff08;方式1&#xff09; 因为属于当前GameObject下的脚本组件…

分布式锁的实现原理

作者&#xff1a;来自 vivo 互联网服务器团队- Xu Yaoming 介绍分布式锁的实现原理。 一、分布式锁概述 分布式锁&#xff0c;顾名思义&#xff0c;就是在分布式环境下使用的锁。众所周知&#xff0c;在并发编程中&#xff0c;我们经常需要借助并发控制工具&#xff0c;如 mu…

缓存使用规范学习

1.规范 size控制: string类型&#xff0c;控制在2KB以内 hash、list、set、zset类型的元素个数&#xff0c;不要超过5000 pipeline命令: 检查多参数命令的参数个数或pipeline命令个数&#xff0c;若值太大&#xff0c;建议减小&#xff08;codis proxy返回结果集超64K&…

为什么ai会用python开发

AI领域使用Python开发有几个主要原因&#xff1a; 简洁易读&#xff1a;Python语法简洁&#xff0c;容易理解&#xff0c;使得开发者能够专注于算法和模型的设计&#xff0c;而不是花费大量时间在语言本身的细节上。这对于快速开发和原型设计尤为重要。 强大的库支持&#xff…

Flink四大基石之CheckPoint

1、State Vs Checkpoint State:状态,是Flink中某一个Operator在某一个时刻的状态,如maxBy/sum,注意State存的是历史数据/状态,存在内存中。 Checkpoint:快照点, 是Flink中所有有状态的Operator在某一个时刻的State快照信息/存档信息。 一句话概括: Checkpoint就是State的快照…

reactivex.Observable 超时问题

下面代码测试可知&#xff1a;超时设置需要在map之后才有效&#xff0c;换句话说就是&#xff0c;超时只对超时设置之前的代码有用 import io.reactivex.Observable; import java.util.concurrent.TimeUnit;public class TimeoutTest {public static void main(String[] args…

Fortran mpi在Linux的安装

最近编译一个程序需要需要 Fortran mpi 编译器&#xff0c;则需要安装 Fortran编辑器和MPI库&#xff0c;以下是具体的安装步骤&#xff1a; 一、安装 Fortran 编译器&#xff08;gfortran&#xff09; 在conda环境中安装&#xff1a; conda install -c conda-forge gfortra…