IT评测·应用市场-qidao123.com
标题:
Rust + WebAssembly 实现康威生命游戏
[打印本页]
作者:
汕尾海湾
时间:
2025-3-18 11:41
标题:
Rust + WebAssembly 实现康威生命游戏
1. 设计思绪
1.1 选择有限的世界
康威生命游戏的世界是
无穷二维网格
,但由于
盘算机内存有限
,我们可以选择三种有限宇宙方案:
动态扩展
:仅存储“活跃区域”,按需扩展(可能无穷增长)。
固定大小,无边界扩展
:边界处的细胞会被“扫除”。
固定大小,环绕宇宙(Toroidal Universe (我们采用此方案)
环绕宇宙
(Toroidal Universe)答应
滑翔机(Gliders)
无穷运行,不会被边界限定:
上边界的细胞
连接到
下边界
左边界的细胞
连接到
右边界
2. Rust 代码实现
2.1 定义 Cell 结构
#[wasm_bindgen]
#[repr(u8)]
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum Cell {
Dead = 0,
Alive = 1,
}
复制代码
说明
:
#[repr(u8)]:让 Cell
占用 1 字节
,减少内存浪费。
Dead = 0, Alive = 1
:使得 Cell 可以
直接用整数加法盘算邻居数
。
2.2 定义 Universe
#[wasm_bindgen]
pub struct Universe {
width: u32,
height: u32,
cells: Vec<Cell>,
}
复制代码
说明
:
width、height:宇宙的
宽度和高度
cells: Vec<Cell>:存储全部
细胞状态
(0=死,1=活)
2.3 盘算网格索引
impl Universe {
fn get_index(&self, row: u32, column: u32) -> usize {
(row * self.width + column) as usize
}
}
复制代码
盘算
二维网格
在
一维数组
中的索引。
2.4 盘算活邻居数量
impl Universe {
fn live_neighbor_count(&self, row: u32, column: u32) -> u8 {
let mut count = 0;
for delta_row in [self.height - 1, 0, 1].iter().cloned() {
for delta_col in [self.width - 1, 0, 1].iter().cloned() {
if delta_row == 0 && delta_col == 0 {
continue;
}
let neighbor_row = (row + delta_row) % self.height;
let neighbor_col = (column + delta_col) % self.width;
let idx = self.get_index(neighbor_row, neighbor_col);
count += self.cells[idx] as u8;
}
}
count
}
}
复制代码
说明
:
利用 modulo 盘算
环绕宇宙
,确保邻居索引不会溢出。
避免 if 语句
,减少特殊情况处理,进步性能。
2.5 更新下一代状态
#[wasm_bindgen]
impl Universe {
pub fn tick(&mut self) {
let mut next = self.cells.clone();
for row in 0..self.height {
for col in 0..self.width {
let idx = self.get_index(row, col);
let cell = self.cells[idx];
let live_neighbors = self.live_neighbor_count(row, col);
let next_cell = match (cell, live_neighbors) {
(Cell::Alive, x) if x < 2 => Cell::Dead,
(Cell::Alive, 2) | (Cell::Alive, 3) => Cell::Alive,
(Cell::Alive, x) if x > 3 => Cell::Dead,
(Cell::Dead, 3) => Cell::Alive,
(otherwise, _) => otherwise,
};
next[idx] = next_cell;
}
}
self.cells = next;
}
}
复制代码
说明
:
规则翻译
:
活细胞 < 2 → 殒命(
过少
)
活细胞 = 2 or 3 → 存活(
繁衍
)
活细胞 > 3 → 殒命(
过分拥挤
)
死细胞 = 3 → 复活(
繁殖
)
2.6 初始化宇宙
#[wasm_bindgen]
impl Universe {
pub fn new() -> Universe {
let width = 64;
let height = 64;
let cells = (0..width * height)
.map(|i| if i % 2 == 0 || i % 7 == 0 { Cell::Alive } else { Cell::Dead })
.collect();
Universe {
width,
height,
cells,
}
}
pub fn render(&self) -> String {
self.to_string()
}
}
复制代码
初始化
:创建 64x64 网格,细胞
随机分布
。
实现 render()
:在 JavaScript 中调用,返回网格字符串。
3. JavaScript 前端
在 wasm-game-of-life/www/index.js 编写
Canvas 渲染
代码。
3.1 JavaScript 初始化
import { Universe, Cell, memory } from "wasm-game-of-life";
const CELL_SIZE = 5;
const GRID_COLOR = "#CCCCCC";
const DEAD_COLOR = "#FFFFFF";
const ALIVE_COLOR = "#000000";
const universe = Universe.new();
const width = universe.width();
const height = universe.height();
复制代码
3.2 绘制网格
const drawGrid = () => {
ctx.beginPath();
ctx.strokeStyle = GRID_COLOR;
for (let i = 0; i <= width; i++) {
ctx.moveTo(i * (CELL_SIZE + 1) + 1, 0);
ctx.lineTo(i * (CELL_SIZE + 1) + 1, (CELL_SIZE + 1) * height + 1);
}
for (let j = 0; j <= height; j++) {
ctx.moveTo(0, j * (CELL_SIZE + 1) + 1);
ctx.lineTo((CELL_SIZE + 1) * width + 1, j * (CELL_SIZE + 1) + 1);
}
ctx.stroke();
};
复制代码
3.3 读取 WebAssembly 内存
const drawCells = () => {
const cellsPtr = universe.cells();
const cells = new Uint8Array(memory.buffer, cellsPtr, width * height);
ctx.beginPath();
for (let row = 0; row < height; row++) {
for (let col = 0; col < width; col++) {
const idx = row * width + col;
ctx.fillStyle = cells[idx] === Cell.Dead ? DEAD_COLOR : ALIVE_COLOR;
ctx.fillRect(col * (CELL_SIZE + 1) + 1, row * (CELL_SIZE + 1) + 1, CELL_SIZE, CELL_SIZE);
}
}
ctx.stroke();
};
复制代码
3.4 动画渲染
const renderLoop = () => {
universe.tick();
drawGrid();
drawCells();
requestAnimationFrame(renderLoop);
};
drawGrid();
drawCells();
requestAnimationFrame(renderLoop);
复制代码
4.运行项目
wasm-pack build
cd www
npm install
npm run start
复制代码
打开
http://localhost:8080/
,你会看到
动态演化的生命游戏!
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
欢迎光临 IT评测·应用市场-qidao123.com (https://dis.qidao123.com/)
Powered by Discuz! X3.4