首页 > 其他分享 >数独Sudoku游戏解题C语言和Golang(Go语言)实现

数独Sudoku游戏解题C语言和Golang(Go语言)实现

时间:2024-01-19 10:33:06浏览次数:24  
标签:Sudoku int C语言 Golang num grid board col row

Go语言实现

package main

import (
	"fmt"
	"os"
)

const (
	N         = 9
	EmptyCell = '0'
)

func main() {
	if len(os.Args) != 2 || len(os.Args[1]) != 81 {
		fmt.Println("错误:程序需要一个正好包含 81 位数字的参数。")
		os.Exit(1)
	}

	board := parseBoard(os.Args[1])
	fmt.Println("未解决的数独:")
	printGrid(board)
	if solveSudoku(&board) {
		fmt.Println("已解决数独:")
		printGrid(board)
	} else {
		fmt.Println("没有解决方案")
	}
}

// parseBoard
// 将字符串转换为 81 位数字的二维数组
func parseBoard(input string) [N][N]rune {
	var board [N][N]rune
	for i, char := range input {
		board[i/N][i%N] = char
	}
	return board
}

// solveSudoku
// 采用部分填充的网格,并尝试将值分配给所有未分配的位置,以满足数独解决方案的要求
func solveSudoku(grid *[N][N]rune) bool {
	row, col := findEmptyCell(grid)
	if row == -1 {
		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] = EmptyCell // 回溯
		}
	}

	return false
}

// findEmptyCell
// 返回未填充的单元格的行和列
func findEmptyCell(board *[N][N]rune) (int, int) {
	for i := 0; i < N; i++ {
		for j := 0; j < N; j++ {
			if board[i][j] == EmptyCell {
				return i, j
			}
		}
	}
	return -1, -1
}

// isSafe
// 检查将 num 分配给给定的行是否合法
func isSafe(board *[N][N]rune, row, col int, num rune) bool {
	// 检查此行
	for x := 0; x < N; x++ {
		if board[row][x] == num {
			return false
		}
	}

	// 检查此列
	for y := 0; y < N; y++ {
		if board[y][col] == num {
			return false
		}
	}

	// 选中此框
	startRow := row - row%3
	startCol := col - col%3
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			if board[i+startRow][j+startCol] == num {
				return false
			}
		}
	}

	return true
}

// printGrid
// 打印网格
func printGrid(board [N][N]rune) {
	for i := 0; i < N; i++ {
		for j := 0; j < N; j++ {
			fmt.Printf("%c ", board[i][j])
		}
		fmt.Println()
	}
}

C语言实现

#include <stdio.h>
#include <string.h>
#include <locale.h>

#define UNASSIGNED 0
#define N 9

// 检查将 num 分配给给定行是否合法的函数
int isSafe(int grid[N][N], int row, int col, int num);

// 打印网格
void printGrid(int grid[N][N]) {
    for (int row = 0; row < N; row++) {
        for (int col = 0; col < N; col++)
            printf("%2d", grid[row][col]);
        printf("\n");
    }
}

// 此函数在网格中查找仍未分配的条目
int findUnassignedLocation(int grid[N][N], int *row, int *col) {
    for (*row = 0; *row < N; (*row)++)
        for (*col = 0; *col < N; (*col)++)
            if (grid[*row][*col] == UNASSIGNED)
                return 1;
    return 0;
}

// 检查将 num 分配给给定的行是否合法
int isSafe(int grid[N][N], int row, int col, int num) {
    // 检查“num”是否尚未放置在当前行、当前列和当前 3x3 框中
    int boxStartRow = row - row % 3;
    int boxStartCol = col - col % 3;

    for (int i = 0; i < N; i++)
        if (grid[row][i] == num || grid[i][col] == num || grid[boxStartRow + i / 3][boxStartCol + i % 3] == num)
            return 0;

    return 1;
}

// 采用部分填充的网格,并尝试将值分配给所有未分配的位置,以满足数独解决方案的要求
int solveSudoku(int grid[N][N]) {
    int row, col;

    // 如果没有未分配的位置,我们就完成了
    if (!findUnassignedLocation(grid, &row, &col))
        return 1; // 成功!

    // 数字 1 到 9
    for (int num = 1; num <= N; num++) {
        // 如果合法
        if (isSafe(grid, row, col, num)) {
            // 进行暂定分配
            grid[row][col] = num;

            // 如果成功,则返回
            if (solveSudoku(grid))
                return 1;

            // 失败,取消并重试
            grid[row][col] = UNASSIGNED;
        }
    }

    return 0; // 触发回溯
}

int main(int argc, char *argv[]) {
    // 设置C库函数使用的locale
    setlocale(LC_ALL, "");
    int grid[N][N];

    // 检查是否提供了正确数量的参数
    if (argc != 2 || strlen(argv[1]) != N*N) {
        wprintf(L"错误:程序需要一个正好包含 81 位数字的参数。\n");
        return 1;
    }

    // 将输入字符解析为网格
    for (int i = 0; i < N*N; i++) {
        if (argv[1][i] >= '0' && argv[1][i] <= '9') {
            grid[i/N][i%N] = argv[1][i] - '0';
        } else {
            wprintf(L"错误:参数应仅包含数字。\n");
            return 1;
        }
    }

    // 在求解之前打印网格
    wprintf(L"未解决的数独:\n");
    printGrid(grid);

    // 如果成功,打印已解决的数独题
    if (solveSudoku(grid) == 1) {
        wprintf(L"已解决数独:\n");
        printGrid(grid);
    } else {
        wprintf(L"对于提供的数独,没有解决方案。\n");
    }

    return 0;
}

使用方法如下:
Sudoku.exe 090020051010050603050000400530900000020001005600075108100400067300010020000087000

标签:Sudoku,int,C语言,Golang,num,grid,board,col,row
From: https://www.cnblogs.com/biltong/p/17974082

相关文章

  • C语言爬虫采集图书网站百万数据
    最近需要查阅一些资料,只给到相关项目名称以及关键词,想通过图书文库找到对应书籍,那么怎么才能在百万数据库中找到自己需要的文献呢?今天我依然用C语言写个爬虫程序,从百万数据库中查找到适合的文章,能节省很多事情。下面是一个简单的C#爬虫程序,它使用了HttpWebRequest和HttpWebResponse......
  • Golang静态类型、编译型的语言学习
    golang属于一种静态类型、编译型的语言,它的设计目标是提供一种简单、高效、可靠的编程语言,适用于构建大型软件系统。Go语言的设计哲学是简洁、直接、易于理解和使用,Go语言支持并发编程,引入了goroutine和channel的概念,使得并发编程更加简单和高效,无论是用于Web开发、服务器编程、......
  • Golang之文件系统事件监听
    Golang之文件系统事件监听基本介绍文件系统事件是指文件系统相关的各种操作和状态变化,当一个应用层的进程操作文件或目录时,会触发systemcall,内核的notification子系统可以守在那里,把该进程对文件的操作上报给应用层的监听进程。这些事件可以包括文件和目录的创建、修改、删除和......
  • Golang中的工厂模式:灵活选择存储方式实现文件存储
    Golang中的工厂模式:灵活选择存储方式实现文件存储原创 沙蒿 程序员的碎碎念 2024-01-0508:20 发表于广东 听全文 引言在现代软件开发中,文件存储是一个常见的需求,而选择合适的存储方式对于系统的可扩展性和性能至关重要。本文将介绍如何使用工厂模式在Golang中实......
  • mac m1 golang 运行go项目没法dbg解决
    1.首先终端看 uname-m如果是显示armd的话就是m12.go版本需要安装arm64版本(macm1) 3.golang编辑器也要安装m1版本的 4.dbg成功 ......
  • C语言基础-变量-day1
    一、变量的定义变量定义的一般形式就是:<类型名称><变量名称>;intprice;intprice,amount;二、变量命名规则变量需要一个名字,变量的名字是一种“标识符”,意思是它用来识别这个和那个的不同的名字标识符有标识符的构造规则。基本的原则是:标识符只能由字母、数字和下划线组......
  • C6031 返回值被忽略:"scanf"解决办法【C语言】
    环境vs2022报错C6031返回值被忽略:"scanf"解决办法【C语言】解决2.在禁用特定警告中添加4996,6031原因因为在ANSIC中没有scanf_s(),只有scanf(),但是scanf()在读取时不检查边界,所以可能会造成内存泄露......
  • Golang nil != nil
    先从一段代码看起,下面这个代码是将传入的对象转换成JSONstring并返回回去,其中,如果判断i==nil时,会返回""。funcToJSONString(iinterface{})string{ifi==nil{return""}bytes,_:=json.Marshal(i)returnstring(bytes)}这段代码初看并没有......
  • golang 处理未确定json字符串
    json字符串转golangmap我们知道golang处理json字符串时,需要先转成struct,并且struct必须是确定的。有时候我们传递的json是不固定的,针对每种情况都写一个struct比较麻烦,有没有处理不确定json的方法呢?答案是有的 varastring="{\"a\":1,\"b\":\"xx\"}" varbmap[string]in......
  • C语言爬虫程序编写的爬取APP通用模板
    互联网的飞快发展,尤其是手机终端业务的发展,让越来越多的事情都能通过手机来完成,电脑大部分的功能也都能通过手机实现,今天我就用C语言写一个手机APP类爬虫教程,方便后期拓展APP爬虫业务。而且这个模板是通用的适合各种APP爬虫,下面跟着我看下具体的代码吧。下面就是我给大家提供一个基......