Data update
This commit is contained in:
parent
4d5544505c
commit
4924dd0264
3073 changed files with 55820 additions and 4408 deletions
130
Task/Sokoban/JavaScript/sokoban.js
Normal file
130
Task/Sokoban/JavaScript/sokoban.js
Normal file
|
|
@ -0,0 +1,130 @@
|
|||
class Sokoban {
|
||||
constructor(board) {
|
||||
this.nCols = board[0].length;
|
||||
let destBuf = '';
|
||||
let currBuf = '';
|
||||
|
||||
for (let r = 0; r < board.length; r++) {
|
||||
for (let c = 0; c < this.nCols; c++) {
|
||||
const ch = board[r].charAt(c);
|
||||
|
||||
destBuf += (ch !== '$' && ch !== '@') ? ch : ' ';
|
||||
currBuf += (ch !== '.') ? ch : ' ';
|
||||
|
||||
if (ch === '@') {
|
||||
this.playerX = c;
|
||||
this.playerY = r;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.destBoard = destBuf;
|
||||
this.currBoard = currBuf;
|
||||
}
|
||||
|
||||
move(x, y, dx, dy, trialBoard) {
|
||||
const newPlayerPos = (y + dy) * this.nCols + x + dx;
|
||||
|
||||
if (trialBoard.charAt(newPlayerPos) !== ' ') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const trial = trialBoard.split('');
|
||||
trial[y * this.nCols + x] = ' ';
|
||||
trial[newPlayerPos] = '@';
|
||||
|
||||
return trial.join('');
|
||||
}
|
||||
|
||||
push(x, y, dx, dy, trialBoard) {
|
||||
const newBoxPos = (y + 2 * dy) * this.nCols + x + 2 * dx;
|
||||
|
||||
if (trialBoard.charAt(newBoxPos) !== ' ') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const trial = trialBoard.split('');
|
||||
trial[y * this.nCols + x] = ' ';
|
||||
trial[(y + dy) * this.nCols + x + dx] = '@';
|
||||
trial[newBoxPos] = '$';
|
||||
|
||||
return trial.join('');
|
||||
}
|
||||
|
||||
isSolved(trialBoard) {
|
||||
for (let i = 0; i < trialBoard.length; i++) {
|
||||
if ((this.destBoard.charAt(i) === '.') !== (trialBoard.charAt(i) === '$')) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
solve() {
|
||||
class Board {
|
||||
constructor(cur, sol, x, y) {
|
||||
this.cur = cur;
|
||||
this.sol = sol;
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
|
||||
const dirLabels = [['u', 'U'], ['r', 'R'], ['d', 'D'], ['l', 'L']];
|
||||
const dirs = [[0, -1], [1, 0], [0, 1], [-1, 0]];
|
||||
|
||||
const history = new Set();
|
||||
const open = [];
|
||||
|
||||
history.add(this.currBoard);
|
||||
open.push(new Board(this.currBoard, "", this.playerX, this.playerY));
|
||||
|
||||
while (open.length > 0) {
|
||||
const item = open.shift(); // poll() equivalent
|
||||
const cur = item.cur;
|
||||
const sol = item.sol;
|
||||
const x = item.x;
|
||||
const y = item.y;
|
||||
|
||||
for (let i = 0; i < dirs.length; i++) {
|
||||
let trial = cur;
|
||||
const dx = dirs[i][0];
|
||||
const dy = dirs[i][1];
|
||||
|
||||
// are we standing next to a box?
|
||||
if (trial.charAt((y + dy) * this.nCols + x + dx) === '$') {
|
||||
// can we push it?
|
||||
trial = this.push(x, y, dx, dy, trial);
|
||||
if (trial !== null) {
|
||||
// or did we already try this one?
|
||||
if (!history.has(trial)) {
|
||||
const newSol = sol + dirLabels[i][1];
|
||||
|
||||
if (this.isSolved(trial)) {
|
||||
return newSol;
|
||||
}
|
||||
|
||||
open.push(new Board(trial, newSol, x + dx, y + dy));
|
||||
history.add(trial);
|
||||
}
|
||||
}
|
||||
// otherwise try changing position
|
||||
} else {
|
||||
trial = this.move(x, y, dx, dy, trial);
|
||||
if (trial !== null) {
|
||||
if (!history.has(trial)) {
|
||||
const newSol = sol + dirLabels[i][0];
|
||||
open.push(new Board(trial, newSol, x + dx, y + dy));
|
||||
history.add(trial);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "No solution";
|
||||
}
|
||||
}
|
||||
|
||||
// Example usage
|
||||
const level = "#######,# #,# #,#. # #,#. $$ #,#.$$ #,#.# @#,#######";
|
||||
const sokoban = new Sokoban(level.split(","));
|
||||
console.log(sokoban.solve());
|
||||
173
Task/Sokoban/Rust/sokoban.rs
Normal file
173
Task/Sokoban/Rust/sokoban.rs
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
use std::collections::{HashSet, VecDeque};
|
||||
use regex::Regex;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
struct Board {
|
||||
s_data: Vec<Vec<char>>,
|
||||
d_data: Vec<Vec<char>>,
|
||||
px: usize,
|
||||
py: usize,
|
||||
}
|
||||
|
||||
impl Board {
|
||||
fn new(board_str: &str) -> Self {
|
||||
let pattern = Regex::new(r"([^\n]+)\n?").unwrap();
|
||||
let mut data = Vec::new();
|
||||
let mut w = 0;
|
||||
|
||||
for cap in pattern.captures_iter(board_str) {
|
||||
let line = cap[1].to_string();
|
||||
w = w.max(line.len());
|
||||
data.push(line);
|
||||
}
|
||||
|
||||
let mut s_data = Vec::new();
|
||||
let mut d_data = Vec::new();
|
||||
let mut px = 0;
|
||||
let mut py = 0;
|
||||
|
||||
for (v, line) in data.iter().enumerate() {
|
||||
let mut s_temp = Vec::new();
|
||||
let mut d_temp = Vec::new();
|
||||
|
||||
for u in 0..w {
|
||||
let (s, d) = if u >= line.len() {
|
||||
(' ', ' ')
|
||||
} else {
|
||||
let c = line.chars().nth(u).unwrap();
|
||||
let mut s = ' ';
|
||||
let mut d = ' ';
|
||||
|
||||
match c {
|
||||
'#' => s = '#',
|
||||
'.' | '*' | '+' => s = '.',
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match c {
|
||||
'@' | '+' => {
|
||||
d = '@';
|
||||
px = u;
|
||||
py = v;
|
||||
}
|
||||
'$' | '*' => d = '*',
|
||||
_ => {}
|
||||
}
|
||||
|
||||
(s, d)
|
||||
};
|
||||
|
||||
s_temp.push(s);
|
||||
d_temp.push(d);
|
||||
}
|
||||
|
||||
s_data.push(s_temp);
|
||||
d_data.push(d_temp);
|
||||
}
|
||||
|
||||
Board {
|
||||
s_data,
|
||||
d_data,
|
||||
px,
|
||||
py,
|
||||
}
|
||||
}
|
||||
|
||||
fn move_player(&self, x: usize, y: usize, dx: i32, dy: i32, data: &mut Vec<Vec<char>>) -> bool {
|
||||
let new_x = (x as i32 + dx) as usize;
|
||||
let new_y = (y as i32 + dy) as usize;
|
||||
|
||||
if self.s_data[new_y][new_x] == '#' || data[new_y][new_x] != ' ' {
|
||||
return false;
|
||||
}
|
||||
|
||||
data[y][x] = ' ';
|
||||
data[new_y][new_x] = '@';
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn push_box(&self, x: usize, y: usize, dx: i32, dy: i32, data: &mut Vec<Vec<char>>) -> bool {
|
||||
let new_x = (x as i32 + dx) as usize;
|
||||
let new_y = (y as i32 + dy) as usize;
|
||||
let box_x = (x as i32 + 2 * dx) as usize;
|
||||
let box_y = (y as i32 + 2 * dy) as usize;
|
||||
|
||||
if self.s_data[box_y][box_x] == '#' || data[box_y][box_x] != ' ' {
|
||||
return false;
|
||||
}
|
||||
|
||||
data[y][x] = ' ';
|
||||
data[new_y][new_x] = '@';
|
||||
data[box_y][box_x] = '*';
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
fn is_solved(&self, data: &Vec<Vec<char>>) -> bool {
|
||||
for (v, row) in data.iter().enumerate() {
|
||||
for (u, &cell) in row.iter().enumerate() {
|
||||
if (self.s_data[v][u] == '.') != (cell == '*') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn solve(&self) -> String {
|
||||
let mut visited = HashSet::new();
|
||||
let mut open = VecDeque::new();
|
||||
|
||||
open.push_back((self.d_data.clone(), String::new(), self.px, self.py));
|
||||
visited.insert(self.d_data.clone());
|
||||
|
||||
let dirs = [
|
||||
(0, -1, 'u', 'U'),
|
||||
(1, 0, 'r', 'R'),
|
||||
(0, 1, 'd', 'D'),
|
||||
(-1, 0, 'l', 'L'),
|
||||
];
|
||||
|
||||
while let Some((cur, c_sol, x, y)) = open.pop_front() {
|
||||
for &(dx, dy, move_char, push_char) in &dirs {
|
||||
let mut temp = cur.clone();
|
||||
let new_x = (x as i32 + dx) as usize;
|
||||
let new_y = (y as i32 + dy) as usize;
|
||||
|
||||
if temp[new_y][new_x] == '*' {
|
||||
if self.push_box(x, y, dx, dy, &mut temp) && !visited.contains(&temp) {
|
||||
if self.is_solved(&temp) {
|
||||
return c_sol + &push_char.to_string();
|
||||
}
|
||||
open.push_back((temp.clone(), c_sol.clone() + &push_char.to_string(), new_x, new_y));
|
||||
visited.insert(temp);
|
||||
}
|
||||
} else if self.move_player(x, y, dx, dy, &mut temp) && !visited.contains(&temp) {
|
||||
if self.is_solved(&temp) {
|
||||
return c_sol + &move_char.to_string();
|
||||
}
|
||||
open.push_back((temp.clone(), c_sol.clone() + &move_char.to_string(), new_x, new_y));
|
||||
visited.insert(temp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
"No solution".to_string()
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let level = "#######\n\
|
||||
# #\n\
|
||||
# #\n\
|
||||
#. # #\n\
|
||||
#. $$ #\n\
|
||||
#.$$ #\n\
|
||||
#.# @#\n\
|
||||
#######";
|
||||
|
||||
let board = Board::new(level);
|
||||
println!("{}\n", level);
|
||||
println!("{}", board.solve());
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue