【C++ 程序】 数字推盘游戏(15-puzzle)

这个游戏我认为是很考验思维含量的,毕竟登上了最强大脑的舞台。
然而写这个程序也累(主要有一个大bug没找出来,详见后面的分析)。

程序

//This is a simple 15-puzzle game.

#include <iostream>
#include <vector>
#include <Windows.h>
#include <string>
#include <random>
#include <ctime>
#include <conio.h>
using namespace std;

int sx = 3, sy = 3; // int connot be replaced by unsigned

vector<vector<char>> p = {
    
    
	{
    
    '1','2','3','4'},
	{
    
    '5','6','7','8'},
	{
    
    '9','A','B','C'},
    {
    
    'D','E','F',' '}};

vector<vector<char>> p0 = p; // the finished state

void change(int n)
{
    
    
	switch (n)
	{
    
    
	case 1: // up
		if (sx + 1 <= 3)
		{
    
    
			p[sx][sy] = p[sx + 1][sy];
			p[sx + 1][sy] = ' ';
			++sx;
		}
		break;
	case 2: // down
		if (sx - 1 >= 0)
		{
    
    
			p[sx][sy] =  p[sx - 1][sy];

			p[sx - 1][sy] = ' ';
			--sx;
		}
		break;
	case 3: // left
		if (sy + 1 <= 3)
		{
    
    
			p[sx][sy] = p[sx][sy + 1];
			p[sx][sy + 1] = ' ';
			++sy;
		}
		break;
	case 4: // right
		if (sy - 1 >= 0)
		{
    
    
			p[sx][sy] = p[sx][sy - 1];
			p[sx][sy - 1] = ' ';
			--sy;
		}
		break;
	default:
		break;
	}
}

void input(char c1, char c2)
{
    
    
	c1 = _getch();
	c2 = _getch();
	switch (c2)
	{
    
    
	case 72: // up
		change(1);
		break;
	case 80: // down
		change(2);
		break;
	case 75: // left
		change(3);
		break;
	case 77: // right
		change(4);
		break;
	default:
		break;
	}
}

void random_start() // create a random plate
{
    
    	
	default_random_engine random;
	vector<int> ivec;
	for (int i = 0; i != 400; i++)
		ivec.push_back(random() % 4 + 1);
	srand((unsigned)time(NULL));
	int ran = rand() % 200; // generate a random number ranging from 0 to 199
	for (int i = ran; i != ran + 200; i++) // make 200 moves
		change(ivec[i]);
	if (sx == 0) change(1);
	if (sx == 1) change(1);
	if (sx == 2) change(1);
	if (sy == 0) change(3);
	if (sy == 1) change(3);
	if (sy == 2) change(3); // move the empty place to p[3][3]
}

void print(vector<vector<char>> q)
{
    
    
	for (int i = 0; i != 4; i++)
	{
    
    
		for (int j = 0; j != 4; j++)
			cout << "|" << q[i][j];
		cout << "|" << endl;
	}
}

int main()
{
    
    
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO cci;
	GetConsoleCursorInfo(hOut, &cci);
	cci.bVisible = FALSE;
	SetConsoleCursorInfo(hOut, &cci);
	// The five lines above are used to hide the Console Cursor.	
	cout << "This is a simple 15-puzzle game.\nProgrammer:Teddy van Jerry" << endl;
	random_start();
	cout << "\nYou can move the number ranging from 1 to F using ↑,↓,←,→.\n" << endl;
	print(p);
	cout << "\nNow you have 10 seconds to get ready. After that, we will begin.\n" << endl;
	for (int i = 10; i != 0; i--)
	{
    
    
		cout << i;
		Sleep(1000); // wait for a second;
		cout << " ";
	}
	cout << "Go!\n" << endl;
	long time_start = clock(); // the starting point
	unsigned cnt = 0;
	while (p != p0) // when it's unfinshed
	{
    
    
		char a1 = '\0', a2 = '\0';
		input(a1, a2);
		print(p);
		cout << "\n" << endl;
		++cnt;
	}
	long total_time = clock() - time_start;
	int min = total_time / 60000;
	int second = (total_time % 60000) / 1000;
	string zero = (second < 10) ? "0" : "";
	cout << "You made it!" << endl;
	cout << "You made " << cnt << " moves. ";
	cout << "The total time is " << min << "'" << zero << second << "\"." << endl;
	cout << "\nALL RIGHTS RESERVED (c) 2020 Teddy van Jerry" << endl;
	char anything;
	cin >> anything;
	return 0;
}

//Copyright :2020 Teddy van Jerry

输出示例

1
2

分析

  • 首先说最令人头疼的bug!一直是以下错误:
    bug

然后发现问题就在move()函数中,好久之后发现move()是overloaded,改成change()还是错的,又搞了好久好久(一共已经两个多小时了),考虑了各种各样的情况,重看了不知道多少遍,最终忽然发现一切都是unsigned造成的。虽然空位的坐标不可能为负,但是在change()函数中判断是否为合法输入时有-1的操作,(事实上移到右边就对了)因为unsigned0-1就会翻上去一轮,就是很大很大的值,判断一定成立,因而就会有vector subscript out of range

  • 注意151行输出"要用转义字符\
  • 其他的类似于贪吃蛇游戏中问题,可以举一反三。

ALL RIGHTS RESERVED © 2020 Teddy van Jerry
欢迎转载,转载请注明出处。


See also

Teddy van Jerry 的导航页
【C++ 程序】 井字棋游戏(人 VS 人)
【C++ 程序】 井字棋游戏(人 VS Lv1电脑)
【C++ 程序】 井字棋游戏(人 VS Lv2电脑)
【C++ 程序】 井字棋游戏(人 VS Lv3电脑)
【C++ 程序】 井字棋游戏(人 VS Lv3电脑)(战绩统计版)
【C++ 程序】 五子棋游戏(人 VS 人)
【C++ 程序】 移动迷宫游戏
【C++ 程序】 随机数
【C++ 程序】 贪吃蛇游戏
【C++ 程序】 2048游戏
【C++ 程序】 井字棋游戏(人 VS 人)(EasyX 图形界面)
【C++ 程序】 井字棋游戏(人 VS Lv3电脑)(战绩统计版)(EasyX 图形界面)


问一下有没有发现bug的图有些异样?这其实是 Snake Game 里的,但被我用 3D Paint 给改过了。

猜你喜欢

转载自blog.csdn.net/weixin_50012998/article/details/108446155