拼图游戏(C语言)

sustoj

Description

拼图游戏即任意一个N*N(N>1)的拼图中,会把一张完整的图片裁切成N*N块,去掉尾部一块,然后打乱顺序,通过调换空格块与邻块的位置来还原图片。为了方便计算,我们规定右下角最后一块图片为空,用0代替,其余每一块图片用从1~N*N-1的数字来表示。我们简单示范一下数字拼图的操作吧。

例如3*3的拼图

142

835

670

可以通过0与其他数字横竖交换得到新的拼图

142

830

675

中间可进行无限次0与其他数字的交换。我们最终需要将整张图还原为

123

456

780

我们需要做的就是计算数字拼图还原。是计算还原所需最小的步数吗?当然不是,那对于现在的你们来说还有点困难。我们就从简单的开始吧。首先为了简化操作可以将规定2<=N<=4。

问:任意给一个N*N数字矩阵,能否证明:经过无限次的交换,一定能到达目标矩阵或者经过无限的交换也不能实现目标矩阵?如果能输出YES,如果不能输出NO。

Input Format

第一行输出N,接下来为(0~N*N-1)的数字矩阵。同行数字间保证有一空格。我们保证一开始0在右下角,且数字符合要求。N为0结束。

Output Format

如果能还原输出YES,如果不能还原输出NO。

思路:线性代数逆序数定理

#include <stdio.h>

int main()
{	
	int i, j, k = 0, K, sum, n;
	int x, y;
	int a[100][100], b[10000];//a用于求解 0 的行号列号,b 用于求解逆序数 
	
	while(scanf("%d", &n) && n)
	{
		sum = 0; k = 0;// 运用到++或--的变量,在循环时要初始化 
		for(i = 0; i < n; i++)
		{
			for(j = 0; j < n; j++)
			{
				scanf("%d", &a[i][j]);
				if(a[i][j] == 0)
				{
					x = i; y = j;
				}
				b[k++] = a[i][j];
			}
		}
		
		K = k;
		//图形逆序数计算 
		for(i = 0; i <= K - 1; i++)
		{
			for(j = i + 1; j <= K - 1; j++)
			{
				if(b[i] > b[j])
				{
					sum++;
				}
			}
		}
		//利用图形A与图形B等价的充要条件图形A的排列的逆序数加上0元素行号和列号的奇偶性等于图形B的排列的逆序数加上0元素行号和列号的奇偶性定理 
		sum += (x + y);
		 
		if(((sum % 2 == 0) && ((n * n - 1) % 2 == 0)) || 
			((sum % 2 != 0) && ((n * n - 1) % 2 != 0)))
		{
			printf("YES\n");
		}
		else
		{
			printf("NO\n");
		}
	}

	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,滑动拼图游戏可以用C语言实现。以下是一个简单的实现示例: ```c #include <stdio.h> #include <stdlib.h> #include <time.h> #define SIZE 3 // 拼图大小 void init_game(int game[SIZE][SIZE]) { int i, j, k = 1; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { game[i][j] = k++; } } game[SIZE-1][SIZE-1] = 0; // 0表示空格 } void shuffle_game(int game[SIZE][SIZE], int steps) { int i, j, k, x, y; srand(time(NULL)); for (k = 0; k < steps; k++) { for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { if (game[i][j] == 0) { x = i; y = j; break; } } } switch (rand() % 4) { case 0: if (x > 0) { game[x][y] = game[x-1][y]; game[x-1][y] = 0; } break; case 1: if (x < SIZE-1) { game[x][y] = game[x+1][y]; game[x+1][y] = 0; } break; case 2: if (y > 0) { game[x][y] = game[x][y-1]; game[x][y-1] = 0; } break; case 3: if (y < SIZE-1) { game[x][y] = game[x][y+1]; game[x][y+1] = 0; } break; } } } void print_game(int game[SIZE][SIZE]) { int i, j; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { if (game[i][j] == 0) { printf(" "); } else { printf("%2d", game[i][j]); } printf(" "); } printf("\n"); } } int check_game(int game[SIZE][SIZE]) { int i, j, k = 1; for (i = 0; i < SIZE; i++) { for (j = 0; j < SIZE; j++) { if (game[i][j] != k++) { return 0; } } } return 1; } int main() { int game[SIZE][SIZE]; int steps = 10; init_game(game); shuffle_game(game, steps); while (!check_game(game)) { print_game(game); int x, y; printf("请输入要移动的数字的坐标(x y): "); scanf("%d%d", &x, &y); if (x < 0 || x >= SIZE || y < 0 || y >= SIZE || game[x][y] == 0) { printf("无效的坐标,请重新输入!\n"); continue; } int dx, dy; printf("请输入移动方向(-1 0 1 0或0 -1 0 1): "); scanf("%d%d", &dx, &dy); if ((dx == -1 && x == 0) || (dx == 1 && x == SIZE-1) || (dy == -1 && y == 0) || (dy == 1 && y == SIZE-1)) { printf("无法移动,请重新输入!\n"); continue; } game[x][y] = game[x+dx][y+dy]; game[x+dx][y+dy] = 0; } print_game(game); printf("恭喜你,拼图成功!\n"); return 0; } ``` 这个实现使用了一个SIZE x SIZE的二维数组表示拼图,每个数字表示一个拼图块,0表示空格。首先通过init_game函数初始化拼图,然后通过shuffle_game函数随机打乱拼图。shuffle_game函数通过随机的方式模拟玩家移动拼图,这里只随机移动了steps步,可以根据需要进行调整。打乱完成后进入主循环,每次循环先打印出当前的拼图,然后读取玩家的输入,如果玩家输入的坐标和移动方向合法,则移动相应的拼图块。移动完成后再次检查拼图是否已经完成。如果拼图已经完成,则退出循环并输出恭喜信息。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值