Go: package main

import "fmt"

var h, w int
var maze [][]byte

var visited [][]bool

type dice struct {
	top, bottom, right, left, up, down int
}

func move(d *dice, dir byte) {
	now := d.top
	switch dir {
	case 'N':
		d.top = d.down
		d.down = d.bottom
		d.bottom = d.up
		d.up = now
	case 'S':
		d.top = d.up
		d.up = d.bottom
		d.bottom = d.down
		d.down = now
	case 'W':
		d.top = d.right
		d.right = d.bottom
		d.bottom = d.left
		d.left = now
	case 'E':
		d.top = d.left
		d.left = d.bottom
		d.bottom = d.right
		d.right = now
	}
}

var dx = [4]int{1, -1, 0, 0}
var dy = [4]int{0, 0, 1, -1}

func dfs(x, y int, d *dice) bool {
	// fmt.Printf("dfs(%d,%d) en: dice.bottom=%d\n", x, y, d.bottom)
	visited[y][x] = true // (x,y)に到達した
	if (y == h-1) && (x == w-1) {
		return true
	}
	// 4方のマス目に進めるかどうかチェック
	for i := 0; i < 4; i++ {
		nx := x + dx[i]
		ny := y + dy[i]
		dir := []byte{'E', 'W', 'S', 'N'}
		dc := *d
		move(&dc, dir[i]) // 動かしてみる
		if 0 <= nx && nx < w && 0 <= ny && ny < h && maze[ny][nx] != '#' && !visited[ny][nx] && dc.bottom == int(maze[ny][nx]-'0') {
			// fmt.Printf("move dir %c, new bottom=%d, move to (nx, ny)=(%d,%d)\n", dir[i], dc.bottom, nx, ny)
			if dfs(nx, ny, &dc) {
				return true
			}
		} else {
			continue
		}
	}
	return false
}

func main() {
	fmt.Scan(&h, &w)
	maze = make([][]byte, h)
	visited = make([][]bool, h)
	for i := 0; i < h; i++ {
		visited[i] = make([]bool, w)
		maze[i] = make([]byte, w)
		fmt.Scan(&maze[i])
	}
	// fmt.Println("h", h, "w", w, "maze", maze)
	// visited[0][0] = true
	var d dice
	d.bottom = 6
	d.top = 1
	d.right = 3
	d.left = 4
	d.down = 2
	d.up = 5
	if dfs(0, 0, &d) {
		fmt.Println("YES")
	} else {
		fmt.Println("NO")
	}
}

C++: #include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; } return false; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; } return false; }

int h, w;
struct indata
{
    vector<int> masme;
    int inh, inw;
};
vector<int> dx;
vector<int> dy;

int main() {
    cin >> h >> w;
    vector< vector < int > > s(h, vector<int>(w, 0));
    vector< vector < bool > > sb(h, vector<bool>(w, false));
    for(int i = 0; i < h; ++i) {
        for(int j = 0; j < w; ++j) {
            char ins;
            cin >> ins;
            if(ins == '#') {
                s.at(i).at(j) = -1;
            }else {
                s.at(i).at(j) = ins - '0';
            }
        }
    }

    dx.push_back(0);
    dx.push_back(1);
    dx.push_back(0);
    dx.push_back(-1);
    dy.push_back(-1);
    dy.push_back(0);
    dy.push_back(1);
    dy.push_back(0);

    indata first;
    first.masme.push_back(5);
    first.masme.push_back(3);
    first.inh = 0;
    first.inw = 0;
    queue<indata> que;
    que.push(first);
    sb.at(first.inh).at(first.inw) = true;

    bool flg = false;
    int ue = 0;
    int migi = 0;
    int sita = 0;
    int hidari = 0;
    while(!que.empty()) {
        indata exe = que.front();
        que.pop();
        if(exe.inh == h-1 && exe.inw == w-1) {
            flg = true;
            break;
        }else {
            int under = s.at(exe.inh).at(exe.inw);
            for(int i = 0; i < 4; ++i) {
                int nex = exe.inw + dx.at(i);
                int ney = exe.inh + dy.at(i);
                if(nex >= 0 && nex < w && ney >= 0 && ney < h && s.at(ney).at(nex) != -1 && (!sb.at(ney).at(nex))) {
                    ue = exe.masme.at(0); migi = exe.masme.at(1);
                    sita = 7-ue; hidari = 7-migi;
                    vector<int> check;
                    check.push_back(ue);
                    check.push_back(migi);
                    check.push_back(sita);
                    check.push_back(hidari);
                    if(s.at(ney).at(nex) == check.at(i)) {
                        indata next;
                        next.inh = ney;
                        next.inw = nex;
                        sb.at(ney).at(nex) = true;
                        if(i == 0) {
                            next.masme.push_back(7-under);
                            next.masme.push_back(check.at(1));
                        }else if(i == 1) {
                            next.masme.push_back(check.at(0));
                            next.masme.push_back(7-under);
                        }else if(i == 2) {
                            next.masme.push_back(under);
                            next.masme.push_back(check.at(1));
                        }else {
                            next.masme.push_back(check.at(0));
                            next.masme.push_back(under);
                        }
                        que.push(next);
                    }
                }
            }
        }
    }
    if(flg) cout << "YES" << endl;
    else cout << "NO" << endl;
}

C++: #include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <math.h>
#include <map>
#include <numeric>
#include <string>
#include <queue>
using namespace std;
typedef long long int ll;

bool can[101][101];

int dx[]={1,-1,0,0};
int dy[]={0,0,1,-1};

int num[6][2][4]=
{{{2,5,4,3},{5,2,3,4}},
{{1,6,3,4},{6,1,4,3}},
{{2,5,1,6},{5,2,6,1}},
{{2,5,6,1},{5,2,1,6}},
{{1,6,4,3},{6,1,3,4}},
{{2,5,3,4},{5,2,4,3}}
};

int main(){
    cin.tie(0);
    ios::sync_with_stdio(false);
    int h,w; cin >> h >> w;
    char fi[h][w];
    for(int i=0;i<h;i++){
        for(int j=0;j<w;j++){
            cin >> fi[i][j];
        }
    }
    can[0][0]=1;
    queue<pair<pair<int,int>,pair<int,int>>> q;
    q.push(make_pair(make_pair(0,0),make_pair(6,0)));
    while(q.size()){
        auto p=q.front(); q.pop();
        int x=p.first.first,y=p.first.second;
        for(int i=0;i<4;i++){
            int nx=dx[i]+x,ny=dy[i]+y;
            if(0<=nx&&nx<h&&0<=ny&&ny<w){
                if(can[nx][ny])continue;
                if(fi[nx][ny]=='#')continue;
                if(fi[nx][ny]-'0'!=num[p.second.first-1][p.second.second][i])continue;
                can[nx][ny]=1;
                int v=fi[x][y]-'0';
                int w=fi[nx][ny]-'0';
                int t=0;
                if(i==0||i==1){
                    if(v>=4&&i==1)t=1;
                    if(v<=3&&i==0)t=1;
                }
                else{
                    if(num[p.second.first-1][p.second.second][0]>=4)t=1;
                }
                q.push(make_pair(make_pair(nx,ny),make_pair(fi[nx][ny]-'0',t)));
            }
        }
    }
    if(can[h-1][w-1]){
        cout << "YES" << endl;
    }else{
        cout << "NO" << endl;
    }
}

C++: #include<bits/stdc++.h>

using namespace std;

int main(){
  int H, W;
  cin >> H >> W;
  
  vector<vector<char>> grid(H, vector<char>(W));
  for(int i = 0; i < H; i++){
    for(int j = 0; j < W; j++) cin >> grid[i][j];
  }
  
  char c[4][4] = {{'6', '3', '1', '4'},
                  {'2', '0', '2', '0'},
                  {'1', '3', '6', '4'},
                  {'5', '0', '5', '0'}};
  
  
  vector<vector<bool>> reach(H, vector<bool>(W, false));
  reach[0][0] = true;
  queue<pair<int, int>> q;
  
  q.push({0, 0});
  while(!q.empty()){
    int i = q.front().first, j = q.front().second;
    q.pop();
    
    if(i - 1 >= 0 && grid[i - 1][j] == c[(i + 3) % 4][j % 4]){
      if(!reach[i - 1][j]){
        reach[i - 1][j] = true;
        q.push({i - 1, j});
      }
    }
    if(j - 1 >= 0 && grid[i][j - 1] == c[i % 4][(j + 3) % 4]){
      if(!reach[i][j - 1]){
        reach[i][j - 1] = true;
        q.push({i, j - 1});
      }
    }
    if(i + 1 < H && grid[i + 1][j] == c[(i + 1) % 4][j % 4]){
      if(!reach[i + 1][j]){
        reach[i + 1][j] = true;
        q.push({i + 1, j});
      }
    }
    if(j + 1 < W && grid[i][j + 1] == c[i % 4][(j + 1) % 4]){
      if(!reach[i][j + 1]){
        reach[i][j + 1] = true;
        q.push({i, j + 1});
      }
    }
  }
  
  puts(reach[H - 1][W - 1] ? "YES" : "NO");
  
  return 0;
}