SQL实现马踏棋盘

这个博客介绍了如何使用SQL解决马踏棋盘问题。通过创建一系列存储过程和函数,逐步计算并记录马的移动路径,确保每个方格只被访问一次,最终实现遍历整个棋盘。博客详细展示了SQL脚本,包括初始化棋盘、检查位置合法性、获取移动方向和计数等步骤。
摘要由CSDN通过智能技术生成
/*
关于马踏棋盘的基本过程
国际象棋的棋盘为8*8的方格棋盘,现将马放在任意指定的方格中,按照马走棋的规则将马进行移动,要求每个方格只能进入一次,最终使得马走遍棋盘的64个方格
*/
IF OBJECT_ID('sp_init') IS NOT NULL
DROP PROCEDURE sp_init
GO
IF OBJECT_ID('sp_getDirection') IS NOT NULL
DROP PROCEDURE sp_getDirection
GO
IF OBJECT_ID('sp_getWayCount') IS NOT NULL
DROP PROCEDURE sp_getWayCount
GO
IF OBJECT_ID('sp_print') IS NOT NULL
DROP PROCEDURE sp_print
GO
IF OBJECT_ID('sp_travel') IS NOT NULL
DROP PROCEDURE sp_travel
GO
IF OBJECT_ID('sp_mtqp2') IS NOT NULL
DROP PROCEDURE sp_mtqp2
GO
IF OBJECT_ID('mt_check') IS NOT NULL
DROP FUNCTION mt_check
GO
IF OBJECT_ID('mt_getMin') IS NOT NULL
DROP PROCEDURE mt_getMin
GO


CREATE PROCEDURE sp_init
AS
BEGIN 
	IF OBJECT_ID('mt_count') IS NOT NULL
	DROP  TABLE mt_count
	IF OBJECT_ID('mt_board') IS NOT NULL
	DROP  TABLE mt_board 
	IF OBJECT_ID('mt_waycount') IS NOT NULL
	DROP  TABLE mt_waycount 
	IF OBJECT_ID('mt_direction') IS NOT NULL
	DROP  TABLE mt_direction 
	IF OBJECT_ID('mt_destination') IS NOT NULL
	DROP  TABLE mt_destination 

	CREATE TABLE mt_count
	(
		x INT,
		v INT  
	)
		
	CREATE TABLE mt_destination
	(
		i INT,
		j INT,
		v INT 
	)
	 
	SELECT i,j,0 AS v INTO mt_board FROM 
	(        
		SELECT number AS i FROM master..spt_values WHERE type='p' AND number BETWEEN 0 AND 7
	) a 
	CROSS JOIN 
	(
		SELECT number AS j FROM master..spt_values WHERE type='p' AND number BETWEEN 0 AND 7
	) b 

	SELECT * INTO mt_waycount FROM mt_board 
	 
	SELECT i,j,k,0 AS v INTO  mt_direction
	FROM mt_board a CROSS JOIN (SELECT number AS k FROM master..spt_values WHERE type='p' AND number BETWEEN 0 AND 7)  c 

	INSERT INTO dbo.mt_count
	SELECT number AS k,0 FROM master..spt_values WHERE type='p' AND number BETWEEN 0 AND 7
	 
	INSERT INTO mt_destination VALUES(0,0,1),(0,1,2)
	INSERT INTO mt_destination VALUES(1,0,2),(1,1,1)
	INSERT INTO mt_destination VALUES(2,0,2),(2,1,-1)
	INSERT INTO mt_destination VALUES(3,0,1),(3,1,-2)
	INSERT INTO mt_destination VALUES(4,0,-1),(4,1,-2)
	INSERT INTO mt_destination VALUES(5,0,-2),(5,1,-1)
	INSERT INTO mt_destination VALUES(6,0,-2),(6,1,1)
	INSERT INTO mt_destination VALUES(7,0,-1),(7,1,2)
END 
go
 
CREATE FUNCTION mt_check(@x INT,@y int)
RETURNS BIT
AS
BEGIN 
	IF ((@x <= 7 and @x >= 0) and (@y <= 7 and @y >= 0))
      RETURN 'true'
    RETURN 'false'
END 
go

CREATE  PROCEDURE mt_getMin( @min INT OUTPUT )
AS
BEGIN 
	 
	SET  @min =0
	
	SELECT TOP 1 @min=x FROM dbo.mt_count WHERE v>0 AND v<999 ORDER  BY v ,x DESC 
	UPDATE  mt_count SET v=999 WHERE x= @min 

END 
GO 
 
CREATE PROCEDURE sp_getDirection 
AS
BEGIN
	DECLARE @x INT=0
	DECLARE @y INT=0  
	DECLARE @i INT=0
	DECLARE @x1 INT 
	DECLARE @y1 INT
	DECLARE @min INT
	   
	EXEC sp_getWayCount
	
	
	WHILE @x<8
	BEGIN 
		SET @y=0
		WHILE @y<8
		BEGIN 
			SET @i=0
			WHILE @i<8
			BEGIN
				SELECT @x1=@x+v FROM mt_destination WHERE i=@i AND j=0
				SELECT @y1=@y+v FROM mt_destination WHERE i=@i AND j=1
				IF dbo.mt_check(@x1,@y1)=1
				BEGIN
					update mt_count SET v=(SELECT  v FROM mt_waycount WHERE i=@x1 AND j=@y1) WHERE x=@i 
				END 
				ELSE 
				BEGIN 
					update mt_count SET v=100 WHERE x=@i 
				END 
				SET @i=@i+1
			END 

			SET @i=0
			WHILE @i<8
			BEGIN 
				EXEC mt_getMin @min OUTPUT
				update mt_direction SET v= @min WHERE  i=@x AND j=@y AND k=@i 
				SET @i=@i+1
			END 
                    
			SET @y=@y+1
		END 
		SET @x=@x+1
	END 
END 
go           


CREATE PROCEDURE sp_getWayCount
AS
BEGIN 
	DECLARE @x INT=0
	DECLARE @y INT=0
	DECLARE @i INT =0
	DECLARE @x1 INT 
	DECLARE @y1 INT
	
	WHILE @x<8
	BEGIN 
		SET @y=0 
		WHILE @y<8
		BEGIN
			SET @i=0
			WHILE @i<8
			BEGIN 
				SELECT @x1=@x+v FROM mt_destination WHERE i=@i AND j=0
				SELECT @y1=@y+v FROM mt_destination WHERE i=@i AND j=1
				IF dbo.mt_check(@x1,@y1)=1
				BEGIN
					UPDATE 	mt_waycount SET v=v+1 WHERE i=@x AND j=@y
				END 
				SET @i=@i+1
			END 
			SET @y=@y+1
		END 
		SET @x=@x+1
	END  

END  
GO 


CREATE PROCEDURE sp_print
AS
BEGIN
	SELECT *  FROM mt_board
	PIVOT
	(
		MAX(v)
		FOR j IN ([0],[1],[2],[3],[4],[5],[6],[7])
	) p
END 
GO 


CREATE PROCEDURE sp_travel(@step INT,@no INT,@x INT ,@y INT)
AS
BEGIN 
	DECLARE @i INT=0
	DECLARE @x1 INT 
	DECLARE @y1 INT
  
	WHILE @i<8
	BEGIN 
		IF @step=64
		BEGIN
			EXEC sp_print 
			SET @no=@no+1
			return
		END 
		
		SELECT @x1=@x+v FROM mt_destination WHERE i=(SELECT v FROM mt_direction WHERE i=@x AND j=@y AND k=@i) AND j=0  
		SELECT @y1=@y+v FROM mt_destination WHERE i=(SELECT v FROM mt_direction WHERE i=@x AND j=@y AND k=@i) AND j=1  
        IF dbo.mt_check(@x1,@y1)=1       
        BEGIN 
			IF EXISTS(SELECT 1 FROM mt_board WHERE i=@x1 AND j=@y1 AND v= 0)
			BEGIN 
				SET @step=@step+1
				UPDATE mt_board SET v=@step WHERE i=@x1 AND j=@y1
				IF @no<1
				BEGIN 
					  EXEC dbo.sp_travel @step,@no,@x1,@y1
				END 	
				SET @step=@step-1	  
				UPDATE mt_board SET v=0 WHERE i=@x1 AND j=@y1		
			END 
        END         
		SET @i=@i+1
	END  
END 
GO 

CREATE PROCEDURE sp_mtqp2(@x INT,@y INT)
AS
BEGIN 
	BEGIN TRY
	EXEC sp_init
	EXEC sp_getDirection
	UPDATE mt_board SET v=1 WHERE i=@x AND j=@y 
	EXEC sp_travel 1,0,@x,@y  
	END TRY
	BEGIN CATCH
	END CATCH
	EXEC sp_print
END

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值