Golang新手-对指针感到困惑,请帮助转换c++;要去的片段
我是刚来戈兰的新手,正在慢慢学习。为了学习,我选择将这段算法转换为golang“”。 我已经尽了最大努力,但戈兰指针比C++更让人迷惑。 我尝试了很多不同的方法让它工作,但指针的东西仍然让我感到不安。我就是不能让下面提到的两个函数正常工作。有时输出为-未找到解决方案。有时,它只输出不变的网格。Golang新手-对指针感到困惑,请帮助转换c++;要去的片段,go,Go,我是刚来戈兰的新手,正在慢慢学习。为了学习,我选择将这段算法转换为golang“”。 我已经尽了最大努力,但戈兰指针比C++更让人迷惑。 我尝试了很多不同的方法让它工作,但指针的东西仍然让我感到不安。我就是不能让下面提到的两个函数正常工作。有时输出为-未找到解决方案。有时,它只输出不变的网格。 有人可以修复SolveSudoku()和FindUnassignedLocation()函数(以及其他任何函数,如果有的话),并解释如何在GO中使用引用和指针。 我还试着阅读GO网站上的一些文档,但这并不
有人可以修复SolveSudoku()和FindUnassignedLocation()函数(以及其他任何函数,如果有的话),并解释如何在GO中使用引用和指针。
我还试着阅读GO网站上的一些文档,但这并不是很好,而且我没有足够的经验来理解其中给出的非常小的内容。
如果有人建议在这段代码中还有一些可以改进的地方,我也会非常感激,bugs,错误?什么都可以
package main
import "fmt"
const (
UNASSIGNED = 0
N = 9
)
func SolveSudoku(grid [N][N]int) bool {
var row, col int
if !FindUnassignedLocation(grid, row, col) {
return true
}
for num := 1; num <= 9; num++ {
if isSafe(grid, row, col, num) {
grid[row][col] = num
if SolveSudoku(grid) {
return true
}
grid[row][col] = UNASSIGNED
}
}
return false
}
func FindUnassignedLocation(grid [N][N]int, row int, col int) bool {
for row = 0; row < N; row++ {
for col = 0; col < N; col++ {
if grid[row][col] == UNASSIGNED {
return true
}
}
}
return false
}
func UsedInRow(grid [N][N]int, row int, num int) bool {
for col := 0; col < N; col++ {
if grid[row][col] == num {
return true
}
}
return false
}
func UsedInCol(grid [N][N]int, col int, num int) bool {
for row := 0; row < N; row++ {
if grid[row][col] == num {
return true
}
}
return false
}
func UsedInBox(grid [N][N]int, boxStartRow int, boxStartCol int, num int) bool {
for row := 0; row < 3; row++ {
for col := 0; col < 3; col++ {
if grid[row+boxStartRow][col+boxStartCol] == num {
return true
}
}
}
return false
}
func isSafe(grid [N][N]int, row int, col int, num int) bool {
return !UsedInRow(grid, row, num) && !UsedInCol(grid, col, num) && !UsedInBox(grid, row-row%3, col-col%3, num)
}
func printGrid(grid [N][N]int) {
for row := 0; row < N; row++ {
for col := 0; col < N; col++ {
fmt.Printf("%2d", grid[row][col])
}
fmt.Printf("\n")
}
}
func main() {
var grid = [N][N]int{
[N]int{3, 0, 6, 5, 0, 8, 4, 0, 0},
[N]int{5, 2, 0, 0, 0, 0, 0, 0, 0},
[N]int{0, 8, 7, 0, 0, 0, 0, 3, 1},
[N]int{0, 0, 3, 0, 1, 0, 0, 8, 0},
[N]int{9, 0, 0, 8, 6, 3, 0, 0, 5},
[N]int{0, 5, 0, 0, 9, 0, 6, 0, 0},
[N]int{1, 3, 0, 0, 0, 0, 2, 5, 0},
[N]int{0, 0, 0, 0, 0, 0, 0, 7, 4},
[N]int{0, 0, 5, 2, 0, 6, 3, 0, 0},
}
if SolveSudoku(grid) == true {
printGrid(grid)
} else {
fmt.Printf("No solution exists")
}
return
}
主程序包
输入“fmt”
常数(
未分配=0
N=9
)
func数独(网格[N][N]int)布尔{
变量行,列int
if!FindUnassignedLocation(网格、行、列){
返回真值
}
对于num:= 1;Num < P>你的问题并不是你不理解指针。指针在C++中的运行方式与C++一样(除了GO有逃避分析和GCS之类的东西,你不必担心悬空或无效指针,而没有指针运算的可疑代价)。
<>你的问题是C++和GO数组之间的差异,在C++中,数组是指针,语法是别名。
和int*a
是同一种类型,静态大小调整和自由初始化只是一个很酷的编译器技巧。访问数组是指针算术的奇特语法,然后是解引用——正如前面提到的,这是Go没有的
在Go中,数组是值而不是指针。当你有一个接受a[9]int的函数时,你实际上是在告诉编译器复制九个整数值,而不是指向内存中恰好有九个整数值的位置的指针。想想func(a[2]int)
是编写func(a1,a2int)
的好方法
这也导致了另一个微妙的代码差异,在C++ +Calp>int中,[9 ] [9 ] 是指向九个指针的指针,每个指针指向九个INT。
Go中有两个简单的解决方案:
使用指向数组的指针。如在grid*[N][N]int
中一样。这可以正常工作,但在数组中访问和存储内容有点不干净。您必须使用(*grid)[i][j]
来显式取消对指针的引用,该指针看起来很难看,可能有点难以读取
使用切片。这是更好的选择,也是更惯用的Go样式。它还避免了到处都是讨厌的全局常量。折衷是,您确实牺牲了一些关于列大小的先验保证
我将用带有注释的切片重写几个方法,剩下的留给您:
func main() {
// We can omit the []int on every line, Go infers it
var grid = [][]int{
{3, 0, 6, 5, 0, 8, 4, 0, 0},
{5, 2, 0, 0, 0, 0, 0, 0, 0},
{0, 8, 7, 0, 0, 0, 0, 3, 1},
{0, 0, 3, 0, 1, 0, 0, 8, 0},
{9, 0, 0, 8, 6, 3, 0, 0, 5},
{0, 5, 0, 0, 9, 0, 6, 0, 0},
{1, 3, 0, 0, 0, 0, 2, 5, 0},
{0, 0, 0, 0, 0, 0, 0, 7, 4},
{0, 0, 5, 2, 0, 6, 3, 0, 0},
}
// == true is superfluous
if SolveSudoku(grid) {
printGrid(grid)
} else {
fmt.Println("No solution exists")
}
// Don't need to explicitly return, Go's mains are "void"
}
func UsedInCol(grid [][]int, col int, num int) bool {
// We can use range to iterate over the whole slice.
// The first value (which we ignore) is the slice index, the value you
// used to call "row".
// Now row is the slice containing the given row, this is similar to an iterator.
for _,row := range grid {
if row[col] == num {
return true
}
}
return false
}
杂项说明:
以前使用常量N
时,现在可以使用len(网格)
。要获取列的长度,请使用len(网格[0])
(警告:确保grid[0]
存在)
由于它是一个值,因此将[N][N]int
作为参数或返回值几乎总是效率低下,因为每次函数调用时它都是一个相当大的副本。指针跟踪通常更快,但N值非常小(可能是1-2)
Go中不存在引用,除非在非常技术的意义上,如闭合变量的行为
更好的方法是使用某种At/Set方法Set声明类似于类型SudokuGrid struct{grid[]int;rows,cols int}
的东西,这可以让您获得一些大小保证。我将把这件事留给您(或者这是否是一个好主意)
你的问题并不是你不理解指针。指针在C++中的运行方式和C++一样(除了GO有逃避分析和GCS之类的东西,你不用担心指针或指针无效,在没有指针运算的可疑成本下)。
<>你的问题是C++和GO数组之间的差异,在C++中,数组是指针,语法是别名。
和int*a
是同一种类型,静态大小调整和自由初始化只是一个很酷的编译器技巧。访问数组是指针算术的奇特语法,然后是解引用——正如前面提到的,这是Go没有的
在Go中,数组是值而不是指针。当你有一个接受a[9]int的函数时,你实际上是在告诉编译器复制九个整数值,而不是指向内存中恰好有九个整数值的位置的指针。想想func(a[2]int)
是编写func(a1,a2int)
的好方法
这也导致了另一个微妙的代码差异,在C++ +Calp>int中,[9 ] [9 ] 是指向九个指针的指针,每个指针指向九个INT。
Go中有两个简单的解决方案:
使用指向数组的指针。如在grid*[N][N]int
中一样。这可以正常工作,但在数组中访问和存储内容有点不干净。您必须使用(*grid)[i][j]
来显式取消对指针的引用,该指针看起来很难看,可能有点难以读取
使用切片。这是更好的选择,更惯用的围棋风格。它还避免了到处都是讨厌的全局常量。权衡是