用C++和easyx库完成一个数独小游戏

按我之前产生数独的思路使用matlab产生数独和使用python产生数独游戏python数独游戏的思路,改写成了C++语言的数独游戏,并结合easyx库进行游戏界面输出和交互。(在我之前的博客里都有写,大家可以去看看,这里不多说了)
但是本人对C++的理解还不够深刻,没有用到对象和类的概念,完全是用函数的方式写的,弄得和c没什么区别,许多代码也不够简洁美观,导致虽然功能实现了,但一点也开心不起来,以后慢慢改进吧。
完整代码如下:

#include <iostream>
#include <graphics.h>
//#include <cstdlib>
//#include <ctime>
//#include <algorithm>    // std::find
//#include <vector>       // std::vector
//#include<cstdlib>

static int wrongtime = 0;
using namespace std;

int iniscreem()    //初始化屏幕
{
	initgraph(740, 580);	// 创建绘图窗口,大小为 740x580 像素
	setbkcolor(RGB(222, 213, 176));//设置背景颜色
	cleardevice();
	settextcolor(0);
	settextstyle(70, 0, _T("宋体"));
	outtextxy(90, 70, _T("欢迎来到数独游戏"));


	settextstyle(40, 0, _T("宋体"));
	outtextxy(230, 210, _T("请选择难度等级"));


	settextstyle(30, 0, _T("宋体"));
	setlinecolor(0);//设定线条颜色为黑
	settextcolor(0);
	rectangle(330, 300, 410, 340);//在对应位置画矩形
	outtextxy(340, 305, _T("普通"));

	setlinecolor(GREEN);//设定线条颜色为绿
	settextcolor(GREEN);
	rectangle(150, 300, 230, 340);
	outtextxy(160, 305, _T("简单"));

	setlinecolor(RED);//设定线条颜色为绿
	settextcolor(RED);
	rectangle(510, 300, 590, 340);
	outtextxy(520, 305, _T("困难"));

	int choice = 0;     //代表选择的难度
	int correct = 0;    //代表鼠标是否点下
	while (correct == 0)//correct为0表示鼠标一直没有点下
	{
		MOUSEMSG m;
		if (MouseHit())//判断鼠标是否点下
		{
			m = GetMouseMsg();

			switch (m.uMsg)
			{
				//检测鼠标左键是否按下
			case WM_LBUTTONDOWN:
				//如果鼠标点在预先设定的三个矩形内
				if (m.x > 150 && m.x < 230 && m.y>300 && m.y < 340)
				{
					correct = 1;//correct为1表明鼠标点下
					choice = 2;//choice为2表示选择简单模式,每行有两个空
				}
				if (m.x > 330 && m.x < 410 && m.y>300 && m.y < 340)
				{
					correct = 1;
					choice = 4;//choice为4表示选择普通模式,每行有四个空
				}
				if (m.x > 510 && m.x < 590 && m.y>300 && m.y < 340)
				{
					correct = 1;
					choice = 5;//choice为2表示选择困难模式,每行有五个空
				}
				break;
			default:
				break;
			}
		}
	}

	//system("pause");		//暂停
	//closegraph();			// 关闭绘图窗口


	return choice;//返回选择的难度,后面用来生成数独
}

int finish()//数独完成后的显示函数
{
	cleardevice();//清屏
	settextcolor(0);
	settextstyle(70, 0, _T("宋体"));
	outtextxy(280, 160, _T("恭喜!"));
	outtextxy(140, 250, _T("你获得了胜利!"));
	settextstyle(25, 0, _T("宋体"));
	outtextxy(280, 350, _T("按任意键关闭"));
	return 0;
}

int mysum(int* A[9])//判断数独是否填完
{
	int* ptr;
	int sum0 = 0;
	int count = 0;
	for (int i = 0; i < 9; i++)
	{
		ptr = A[i];//A是一个指针数组,存放数独
		for (int j = 0; j < 9; j++)
		{
			sum0 = sum0 + *ptr;//对数独的所有元素求和
			ptr++;
		}
	}
	if (sum0 == 405)
	{
		count = 1;//如果等于405则填完了,检测方法比较粗糙,但大部分情况下是好用的
	}
	return count;//返回标志位
}

int* my_getzero(int* arr)//获取一维数组所有非零元素
{
	int count = 0;
	for (int m = 0; m < 9; m++)
	{
		if (arr[m] != 0)
		{
			count++;//先判断有多少个非零元素
		}
	}
	int* p;
	int* p1;
	p = new int[count + 1];//生成动态数组
	//注意这里还没释放内存,主程序里也还没释放,以后可能会有问题
	p1 = p;
	*p1 = count;
	p1++;
	for (int n = 0; n < 9; n++)
	{
		if (arr[n] != 0)
		{
			*p1 = arr[n];//当元素不为零时,赋值到数组中
			p1++;
		}
	}
	return p;    //返回数组首地址                         
}

int** my_getzero_two(int** A)       //获取二维数组(数独)中非零元素的坐标
{
	int count = 0;
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (A[i][j] == 0)
			{
				count++;//判断有多少个非零元素
			}
		}
	}
	static int* arr1 = new int[count + 1];//用来存放行坐标,第一个元素用来存放非零元素的个数,所以数组长度为count+1
	static int* arr2 = new int[count + 1];  //用来存放列坐标,第一个元素为零,其余元素为坐标          
	static int* arr[2] = { arr1,arr2 };
	//这些动态数组都没释放,未来要注意
	*arr1 = count;//第一个元素为个数
	*arr2 = 0;
	int* Arr1 = arr1;
	int* Arr2 = arr2;
	Arr1++;//从第二个元素开始存放
	Arr2++;
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (A[i][j] == 0)
			{
				*Arr1 = i;//元素不为零时存放行列坐标
				*Arr2 = j;
				Arr1++;
				Arr2++;
			}
		}
	}
	return arr;
}

int* my_union(int* x, int* y)//对两个一维数组的元素取并集,
{
	//两个数组的构成都是第一个元素为存放非零元素的个数
	//比如[4,2,3,4,5]代表一共4个元素,2,3,4,5,参与取交集运算
	int a = *x;
	int b = *y;
	int count1 = 0;
	int count2 = 0;
	int p[9] = { 0 };
	int* p1 = p;
	for (int i = 1; i < a + 1; i++)//
	{
		for (int j = 1; j < b + 1; j++)
		{
			if (x[i] != y[j])//x数组的元素分别和y数组中的每一个元素相比较
			{
				count1++;//若不同则加1
			}
		}
		if (count1 == b)//若没有相同的元素
		{
			y[0]++;//将不同的元素跟在y数组后面,所以个数会加1
			count2++;//用来记录用多少个不同的元素
			*p1 = i;//记录不同元素在x数组中的位置
			p1++;
		}
		count1 = 0;//标志位清零
	}
	int* z = new int[1 + b + count2];//构造相应长度的动态数组                  
	//注意这里动态数组没有释放内存,可能会出现问题
	for (int i = 0; i < b + 1; i++)
	{
		z[i] = y[i];//首先将y数组一一对应粘贴
	}
	for (int j = 0; j < count2; j++)
	{
		z[b + j + 1] = x[p[j]];//然后根据坐标将x数组中的元素进行赋值
	}
	return z;
}

int* my_difference(int* x)//获取一个一维数组与[1,9]等差数列的差集
{
	int a = *x;//第一个元素代表x有多少个元素参与比较
	int count1 = 0;
	int count2 = 0;//记录差集中的元素个数
	int p[9] = { 0 };
	int* p1 = p;
	for (int i = 1; i < 10; i++)//1到9分别进行比较
	{
		for (int j = 1; j < a + 1; j++)
		{
			if (i != x[j])//i与x中元素不同则加1
			{
				count1++;
			}
		}
		if (count1 == a)//i和x中任意一个元素都不同
		{
			count2++;//找到一个差集元素
			*p1 = i;//i就是差集元素,保留下来
			p1++;
		}
		count1 = 0;
	}
	int* z = new int[1 + count2];                 
	//注意这里动态数组没有释放内存,可能会出现问题
	*z = count2;//z的第一个元素代表差集元素个数
	for (int i = 1; i < count2 + 1; i++)
	{
		z[i] = p[i - 1];//从第二个元素开始存放差集元素
	}
	return z;
}

int* my_random(int a)//产生一个有9个元素的一维数组,元素是1到9随机排列
{
	int num[9] = { 0 };
	int i = 0;
	int seed = a;//a代表随机种子
	while (num[8] == 0)
	{
		srand(50 * (seed * seed * seed + 100 + seed * seed * 5 - 20));//这个表达式是随便写的
		//这里要这么写的原因在我另一篇博客里,产生随机数组
		int a = (rand() % 9) + 1;//产生一个1到9之间的随机数
		int  start = 0;
		int  end = 8;
		int* result = find(num + start, num + end, a);//判断数组中是否已经有了这个数字
		if (result == num + end)//如果没有就把这个数字加入到数组中
		{
			num[i] = a;
			i++;
		}
		seed++;//改变随机种子
	}
	//直到数组最后一位不为0表示都填好了,循环结束

	/*for (int i1 = 0; i1 < 9; i1++)
	{
		cout << num[i1];
	}                                 
	cout << endl;*/                   //测试时候使用看结果
	return num;
}

int** answer(int a)//产生数独矩阵,a用来传递随机种子
{

	int sum0 = 0;
	int N2 = 0;
	int seed = a;
	static int A1[9] = { 0 };
	static int A2[9] = { 0 };
	static int A3[9] = { 0 };
	static int A4[9] = { 0 };
	static int A5[9] = { 0 };
	static int A6[9] = { 0 };
	static int A7[9] = { 0 };
	static int A8[9] = { 0 };
	static int A9[9] = { 0 };
	/*int A1[9] = { 0 };
	int A2[9] = { 0 };
	int A3[9] = { 0 };
	int A4[9] = { 0 };
	int A5[9] = { 0 };
	int A6[9] = { 0 };
	int A7[9] = { 0 };
	int A8[9] = { 0 };
	int A9[9] = { 0 };*/
	static int* A[9] = { A1,A2,A3,A4,A5,A6,A7,A8,A9 };//创造一个全零的二维矩阵
	while (mysum(A) != 1)//用mysum函数判断是否填完
	{
		int N = 1;//判断状态位
		for (int i = 0; i < 9; i++)//每次填数失败以后就把整个数独全部清零
		{
			for (int j = 0; j < 9; j++)
			{
				A[i][j] = 0;
			}
		}

		int num[9] = { 0 };
		int i = 0;
		while (num[8] == 0)//产生一个随机数组,my_random是后来测试时候写的,这里就没改,但原理是一样的
		{
			//srand((int)time(0));  // 产生随机种子  把0换成NULL也行
			srand(50 * (seed * seed * seed + 100 + seed * seed * 5 - 20));  // 产生随机种子  
			int a = (rand() % 9) + 1;
			int  start = 0;
			int  end = 8;
			int* result = find(num + start, num + end, a);
			if (result == num + end)
			{
				num[i] = a;
				i++;
			}
			seed++;
		}
		for (int i1 = 0; i1 < 9; i1++)
		{
			A1[i1] = num[i1];
			//cout << num[i1];
		}                                 //随机生成1到9数列作为数独第一行
		//cout << endl;

		for (int i2 = 1; i2 < 9; i2++)      //开始填数
		{
			for (int j = 0; j < 9; j++)
			{
				int* x = A[i2];
				int x_int[9] = { 0 };
				for (int i3 = 0; i3 < 9; i3++)
				{
					x_int[i3] = *x;
					x++;
				}                                 //取出所在行

				int* y;
				int y_int[9] = { 0 };
				for (int i4 = 0; i4 < 9; i4++)
				{
					y = A[i4];
					y_int[i4] = *(y + j);
				}                                    //取出所在列

				int z[9][3];
				if (0 <= j && j < 3)
				{
					for (int m = 0; m < 9; m++)
					{
						for (int n = 0; n < 3; n++)
						{
							z[m][n] = A[m][n];
						}
					}
				}
				else if (3 <= j && j < 6)
				{
					for (int m = 0; m < 9; m++)
					{
						for (int n = 3; n < 6; n++)
						{
							z[m][n - 3] = A[m][n];
						}
					}
				}
				else if (6 <= j && j < 9)
				{
					for (int m = 0; m < 9; m++)
					{
						for (int n = 6; n < 9; n++)
						{
							z[m][n - 6] = A[m][n];
						}
					}
				}
				int z2[3][3];
				if (0 <= i2 && i2 < 3)
				{
					for (int m = 0; m < 3; m++)
					{
						for (int n = 0; n < 3; n++)
						{
							z2[m][n] = z[m][n];
						}
					}
				}
				else if (3 <= i2 && i2 < 6)
				{
					for (int m = 3; m < 6; m++)
					{
						for (int n = 0; n < 3; n++)
						{
							z2[m - 3][n] = z[m][n];
						}
					}
				}
				else if (6 <= i2 && i2 < 9)
				{
					for (int m = 6; m < 9; m++)
					{
						for (int n = 0; n < 3; n++)
						{
							z2[m - 6][n] = z[m][n];
						}
					}
				}
				int z_int[9];
				for (int m = 0; m < 3; m++)
				{
					for (int n = 0; n < 3; n++)
					{
						z_int[m * 3 + n] = z2[m][n];
					}
				}                                   //取出所在宫

				int* X = my_getzero(x_int);
				int* Y = my_getzero(y_int);
				int* Z = my_getzero(z_int);        //取出行,列,宫的所有非零值

				int* t = my_union(X, Y);
				t = my_union(t, Z);                //所有非零值取并集  ,注意t所指的第一个元素代表非零元素的个数   

				int* n = my_difference(t);         //并集与1到9取差集,判断有些数可以作为被选数

				if (*n == 0)
				{
					N = 2;//*n为0说明没有备选数了,这次填数就失败了,令N = 2
					N2++;
					//cout << N2 << endl;         //记录循环了多少次,测试时候用的
					break;//这次填数循环就退出了
				}
				int s = (rand() % *n) + 1;//如果没退出循环,则说明有数可填
				A[i2][j] = n[s];//随机选择第s位的元素进行赋值
			}
			if (N == 2)
			{
				break;//退出填数循环
			}
		}
		seed = seed * seed;//修改随机种子

	}


	//测试时候输出看结果的
	/*测试随机生成数组
	int num[9] = {0};
	int i = 0;
	while (num[8] == 0)
	{
		srand((int)time(0));  // 产生随机种子  把0换成NULL也行
		int a = (rand() % 9) + 1;  //产生随机数
		int  start = 0;
		int  end = 8;
		int * result = find(num + start, num + end, a);
		if (result == num + end)
		{
			num[i] = a;
			i++;
		}
	}
	for (int i1 = 0; i1 < 9; i1++)
	{
		A1[i1] = num[i1];
	}
	sum0 = mysum(A);
	cout << sum0 << endl;*/

	return A;//返回数独矩阵
}

int** chansheng(int** A, int grade)//随机挖空,产生题面。A是数独矩阵,grade就是iniscreem函数中的choice
{
	int k = (int)time(0);
	int* a;
	for (int i = 0; i < 9; i++)
	{
		a = my_random(k + i * i * i + 100);//产生随机数组
		for (int j = 0; j < grade; j++)
		{
			A[i][a[j] - 1] = 0;     //随机让几个空为0
			//产生的a数组是1到9的随机数组,进行赋值下标是0到8,所以要减1
			//A[i][a[j]-1] = 1;       //测试用
		}
	}
	return A;
}

int test_num(int** A, int x_pos, int y_pos)//检测填数是否正确,x_pos,y_pos表示填数的行列坐标,输出数独的时候使用
{
	int right_wrong = 1;    //1代表填数正确,2代表填数错误
	int num = 0;

	int* x = A[x_pos];
	int x_int[9] = { 0 };
	for (int i3 = 0; i3 < 9; i3++)
	{
		x_int[i3] = *x;
		x++;
	}                                 //取出所在行

	int* y;
	int y_int[9] = { 0 };
	for (int i4 = 0; i4 < 9; i4++)
	{
		y = A[i4];
		y_int[i4] = *(y + y_pos);
	}                                    //取出所在列

	int z[9][3];
	if (0 <= y_pos && y_pos < 3)
	{
		for (int m = 0; m < 9; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z[m][n] = A[m][n];
			}
		}
	}
	else if (3 <= y_pos && y_pos < 6)
	{
		for (int m = 0; m < 9; m++)
		{
			for (int n = 3; n < 6; n++)
			{
				z[m][n - 3] = A[m][n];
			}
		}
	}
	else if (6 <= y_pos && y_pos < 9)
	{
		for (int m = 0; m < 9; m++)
		{
			for (int n = 6; n < 9; n++)
			{
				z[m][n - 6] = A[m][n];
			}
		}
	}
	int z2[3][3];
	if (0 <= x_pos && x_pos < 3)
	{
		for (int m = 0; m < 3; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z2[m][n] = z[m][n];
			}
		}
	}
	else if (3 <= x_pos && x_pos < 6)
	{
		for (int m = 3; m < 6; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z2[m - 3][n] = z[m][n];
			}
		}
	}
	else if (6 <= x_pos && x_pos < 9)
	{
		for (int m = 6; m < 9; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z2[m - 6][n] = z[m][n];
			}
		}
	}
	int z_int[9];
	for (int m = 0; m < 3; m++)
	{
		for (int n = 0; n < 3; n++)
		{
			z_int[m * 3 + n] = z2[m][n];
		}
	}                                   //取出所在宫

	for (int k = 0; k < 9; k++)//判断A[x_pos][y_pos]在行数组中出现了几次
	{
		if (A[x_pos][y_pos] == x_int[k])
		{
			num++;
		}
		if (num > 1)//出现超过1次说明填错了
		{
			right_wrong = 2;//让填错的标志位为2
			break;
		}
	}
	num = 0;
	if (right_wrong == 1)
	{
		for (int k = 0; k < 9; k++)
		{
			if (A[x_pos][y_pos] == y_int[k])//同理判断列数组中出现几次
			{
				num++;
			}
			if (num > 1)
			{
				right_wrong = 2;
				break;
			}
		}
	}
	num = 0;
	if (right_wrong == 1)
	{
		for (int k = 0; k < 9; k++)
		{
			if (A[x_pos][y_pos] == z_int[k])//同理判断宫数组中出现几次
			{
				num++;
			}
			if (num > 1)
			{
				right_wrong = 2;
				break;
			}
		}
	}
	return right_wrong;//返回标志位
}

void test_num_second(int** A, int x_pos, int y_pos, int num2)//检测填数是否正确,记录错误次数时使用
{
	//这个函数绝大部分逻辑和上一个函数一模一样,这也是我非常难受的地方,没有想到更好地解决办法
	//两个函数的区别在于使用时数独矩阵的状态不同,
	//test_num使用时是已经将错误数据填进去了,test_num_second使用时错误数据还没填进去
	int num = 0;
	int* x = A[x_pos];
	int x_int[9] = { 0 };
	for (int i3 = 0; i3 < 9; i3++)
	{
		x_int[i3] = *x;
		x++;
	}                                 //取出所在行

	int* y;
	int y_int[9] = { 0 };
	for (int i4 = 0; i4 < 9; i4++)
	{
		y = A[i4];
		y_int[i4] = *(y + y_pos);
	}                                    //取出所在列

	int z[9][3];
	if (0 <= y_pos && y_pos < 3)
	{
		for (int m = 0; m < 9; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z[m][n] = A[m][n];
			}
		}
	}
	else if (3 <= y_pos && y_pos < 6)
	{
		for (int m = 0; m < 9; m++)
		{
			for (int n = 3; n < 6; n++)
			{
				z[m][n - 3] = A[m][n];
			}
		}
	}
	else if (6 <= y_pos && y_pos < 9)
	{
		for (int m = 0; m < 9; m++)
		{
			for (int n = 6; n < 9; n++)
			{
				z[m][n - 6] = A[m][n];
			}
		}
	}
	int z2[3][3];
	if (0 <= x_pos && x_pos < 3)
	{
		for (int m = 0; m < 3; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z2[m][n] = z[m][n];
			}
		}
	}
	else if (3 <= x_pos && x_pos < 6)
	{
		for (int m = 3; m < 6; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z2[m - 3][n] = z[m][n];
			}
		}
	}
	else if (6 <= x_pos && x_pos < 9)
	{
		for (int m = 6; m < 9; m++)
		{
			for (int n = 0; n < 3; n++)
			{
				z2[m - 6][n] = z[m][n];
			}
		}
	}
	int z_int[9];
	for (int m = 0; m < 3; m++)
	{
		for (int n = 0; n < 3; n++)
		{
			z_int[m * 3 + n] = z2[m][n];
		}
	}                                   //取出所在宫

	int* X = my_getzero(x_int);
	int* Y = my_getzero(y_int);
	int* Z = my_getzero(z_int);        //取出行,列,宫的所有非零值

	int* t = my_union(X, Y);
	t = my_union(t, Z);                //所有非零值取并集  ,注意t所指的第一个元素代表非零元素的个数   
	//得到所有已经填过的数字
	for (int k = 1; k < 10; k++)
	{
		if (t[k] == num2)//num2是准备要填进去的数
		{
			wrongtime++;//如果数组中出现了这个数字,说明就填错了,错误次数就加一
			break;
		}
	}
}

void show1(int** A)
{
	//initgraph(740, 580);	// 创建绘图窗口,大小为 740x580 像素
	//setbkcolor(RGB(222,213,176));
	//cleardevice();
	setlinecolor(0);//设定线条颜色为黑
	int a = 9;        //方格个数
	int w = 50;       //方格宽度
	for (int i = 0; i < a + 1; ++i)//画出数独9*9的方格,1,4,6,8,10条线加粗
	{
		if (i == 0 || i == 3 || i == 6 || i == 9)
		{
			setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 5);
			line(w, w + w * i, w + w * a, w + w * i);         //画横线
			line(w + w * i, w, w + w * i, w + w * a);         //画竖线
		}
		else
		{
			setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 2);
			line(w, w + w * i, w + w * a, w + w * i);         //画横线
			line(w + w * i, w, w + w * i, w + w * a);         //画竖线
		}
	}
	settextcolor(0);
	settextstyle(16, 0, _T("宋体"));
	//outtextxy(11 * w, 3 * w+100, _T("失败次数:"));
	for (int k = 0; k < a; k++)
	{
		for (int j = 0; j < a; j++)
		{
			if (A[j][k] != 0)//当数据不为0时才输出,数据为0不输出,相当于空白
			{
				wchar_t num[20];
				_itow_s(A[j][k], num, 10);//将数独中的整型数据转化成字符型
				//这里这么写的原因在我另一篇博客里,使用outtextxy输出整型
				//sprintf_s(num, "%d",A[k][j]);
				//char c = *itoa(A[j][k], str, 10);
				outtextxy(w + w * k + 21, w + w * j + 17, num);//输出在屏幕上
			}
		}
	}
	//system("pause");		//暂停
	//closegraph();			// 关闭绘图窗口
}
void show2(int** A, int** arr)//输出数独时判断数据是否正确,正确显示绿色,错误为红色
{
	int right_wrong = 0;
	setlinecolor(0);//设定线条颜色为黑
	int a = 9;        //方格个数
	int w = 50;       //方格宽度
	for (int i = 0; i < a + 1; ++i)
	{
		if (i == 0 || i == 3 || i == 6 || i == 9)
		{
			setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 5);
			line(w, w + w * i, w + w * a, w + w * i);         //画横线
			line(w + w * i, w, w + w * i, w + w * a);         //画竖线
		}
		else
		{
			setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 2);
			line(w, w + w * i, w + w * a, w + w * i);         //画横线
			line(w + w * i, w, w + w * i, w + w * a);         //画竖线
		}
	}
	settextcolor(0);
	settextstyle(16, 0, _T("宋体"));
	//outtextxy(11 * w, 3 * w+100, _T("失败次数:"));
	for (int k = 0; k < a; k++)
	{
		for (int j = 0; j < a; j++)
		{
			if (A[j][k] != 0)//当数据不为0时,判断是否是可以修改的数据
			{
				wchar_t num[20];
				_itow_s(A[j][k], num, 10);
				//sprintf_s(num, "%d",A[k][j]);
				//char c = *itoa(A[j][k], str, 10);
				for (int i = 1; i < arr[0][0] + 1; i++)//arr数组中存放生成题面中为0的位置的行列坐标,也就是可以由玩家填数的位置
				{
					if (j == arr[0][i] && k == arr[1][i])//当行列坐标都正确
					{
						right_wrong = test_num(A, j, k);//检测这个数据是否正确
						if (right_wrong == 1)
						{
							settextcolor(GREEN);//正确则为绿色
						}
						else
						{
							settextcolor(RED);//错误则为红色
						}
					}
				}
				outtextxy(w + w * k + 21, w + w * j + 17, num);//输出数据
			}
			settextcolor(0);//题面固定数据用黑色输出
		}
	}
	//system("pause");		//暂停
	//closegraph();			// 关闭绘图窗口
}
void show3()//显示选择数据区域(就是界面右上角的区域)和错误次数
{
	int A[3][3] = { 1,2,3,4,5,6,7,8,9 };
	setlinecolor(0);//设定线条颜色为黑
	int a = 3;        //方格个数
	int w = 35;       //方格宽度
	for (int i = 0; i < a + 1; ++i)
	{
		setlinestyle(PS_SOLID | PS_JOIN_BEVEL, 2);
		line(w + 530, w + w * i + 30, w + w * a + 530, w + w * i + 30);         //画横线
		line(w + w * i + 530, w + 30, w + w * i + 530, w + w * a + 30);         //画竖线
	}
	settextcolor(0);
	settextstyle(26, 0, _T("宋体"));
	outtextxy(11 * w + 150, 3 * w + 150, _T("错误次数:"));


	wchar_t num3[20];
	_itow_s(wrongtime, num3, 10);     //失败次数
	//sprintf_s(num, "%d",A[k][j]);
	//char c = *itoa(A[j][k], str, 10);
	settextstyle(26, 0, _T("宋体"));
	outtextxy(665, 255, num3);

	for (int k = 0; k < a; k++)
	{
		for (int j = 0; j < a; j++)
		{

			wchar_t num[20];
			_itow_s(A[j][k], num, 10);
			//sprintf_s(num, "%d",A[k][j]);
			//char c = *itoa(A[j][k], str, 10);
			settextstyle(16, 0, _T("宋体"));
			outtextxy(w + w * k + 545, w + w * j + 38, num);

		}
	}
	//system("pause");		//暂停
	//closegraph();			// 关闭绘图窗口
}

int** answer_test()//测试时候用的函数,真正主函数里没用到
{
	static int A1[9] = { 0 };
	cout << A1 << endl;
	static int A2[9] = { 0 };
	static int A3[9] = { 0 };
	static int A4[9] = { 0 };
	static int A5[9] = { 0 };
	static int A6[9] = { 0 };
	static int A7[9] = { 0 };
	static int A8[9] = { 0 };
	static int A9[9] = { 0 };
	/*int A1[9] = { 0 };
	int A2[9] = { 0 };
	int A3[9] = { 0 };
	int A4[9] = { 0 };
	int A5[9] = { 0 };
	int A6[9] = { 0 };
	int A7[9] = { 0 };
	int A8[9] = { 0 };
	int A9[9] = { 0 };*/
	static int* A[9] = { A1,A2,A3,A4,A5,A6,A7,A8,A9 };
	return  A;
}

int** amend(int** A, int correct, int x, int y)//同样,测试用的,主函数里没用到
{

	if (correct == 1)
	{
		A[x][y] = 10;
	}
	return A;
}

int* test_mouse(int** arr)     //检测鼠标点击的格子是否可以修改,可以的话correct为1
{
	int num = 0;
	int correct = 0;
	int x_pos = 0;
	int y_pos = 0;
	MOUSEMSG m;
	if (MouseHit())//检测鼠标是否按下
	{
		m = GetMouseMsg();

		switch (m.uMsg)
		{
			//检测鼠标左键是否按下
		case WM_LBUTTONDOWN:
			//如果鼠标点击在数独9*9的区域内
			if (m.x > 50 && m.x < 500 && m.y>50 && m.y < 500)
			{
				x_pos = (m.x - 50) / 50;//x_pos表示点击在在哪一行,可能值为0到8
				y_pos = (m.y - 50) / 50;//y_pos表示点击在在哪一列,可能值为0到8
				for (int i = 1; i < arr[0][0] + 1; i++)
				{
					if (y_pos == arr[0][i] && x_pos == arr[1][i])//同样arr内存放可修改的位置坐标
					{
						correct = 1;//如果可修改,correct为1
						break;
					}
				}
			}
			break;
		default:
			break;
		}
	}
	int a[3] = { correct,x_pos,y_pos };//返回数组a,第一个元素表示是否可以修改,二三元素表示点击位置的行列值
	return a;
}

int* test_mouse_second(int** daan, int j, int k)     //第二次检测鼠标的位置,判断要填入的数字是几
{
	int correct = 2;   //点击区域的标志位
	int x_pos = 0;
	int y_pos = 0;
	int A[3][3] = { 1,2,3,4,5,6,7,8,9 };
	int num = 0;
	MOUSEMSG m;
	if (MouseHit())
	{
		m = GetMouseMsg();

		switch (m.uMsg)
		{
			//检测鼠标左键是否按下
		case WM_LBUTTONDOWN:
			if (m.x > 565 && m.x < 670 && m.y>65 && m.y < 170)
			{
				correct = 1;//代表点在了选择数字区
				x_pos = (m.x - 565) / 35;
				y_pos = (m.y - 65) / 35;
				num = A[y_pos][x_pos];
				test_num_second(daan, j, k, num);//检测填入的数据是否正确,错误的话wrongtime加1
			}
			else
			{
				correct = 0;//代表点在了其他地方
			}
			break;
		default:
			break;
		}
	}
	int a[2] = { correct,num };
	return a;
}

int* test_mouse_test()//测试用的函数,现在不用了
{
	int correct = 0;
	int x_pos = 20;
	int y_pos = 10;
	MOUSEMSG m;
	if (MouseHit())
	{
		m = GetMouseMsg();
		switch (m.uMsg)
		{
			//检测鼠标左键是否按下
		case WM_LBUTTONDOWN:
			if (m.x > 50 && m.x < 500 && m.y>50 && m.y < 500)
			{
				x_pos = (m.x - 50) / 50;
				y_pos = (m.y - 50) / 50;
				correct = 1;
			}
			break;
		default:
			break;
		}
	}
	int a[3] = { correct,x_pos,y_pos };
	return a;
}

int main()
{
	
	int choice = iniscreem();//初始化屏幕,选择难度
	int right_wrong = 1;
	cleardevice();//清空屏幕
	int Num = 0;//用来接收准备填入的数据
	int correct = 0;//第一次鼠标是否点击的标志位
	int correct2 = 2;//第二次鼠标是否点击的标志位
	int n = 0;
	int m = 0;//用来接收行列坐标
	int k = (int)time(0);//获得时间,准备初始化随机种子
	int** daanptr;//用来接收产生的数独数组
	int* pos;//用来接收第一次鼠标点击得到的数组
	int* pos2;//用来接收第二次鼠标点击得到的数组
	daanptr = answer(k);//产生答案
	daanptr = chansheng(daanptr, choice);//产生题面
	//daanptr = chansheng(daanptr, 1);    //测试时候用这一行
	int** nunposptr = my_getzero_two(daanptr);//获取0元素的位置,也就是以后可由玩家填数的位置
	show1(daanptr);//展示数独
	show3();

	while (mysum(daanptr) != 1)//游戏循环
	//但此时用这个判断游戏是否结束会有问题,有可能几个数据都是错的但恰好数独和是405,游戏也会结束
	{
		pos = test_mouse(nunposptr);//检测鼠标是否点下
		correct = *pos;//获取是否点下的标志位
		if (*pos == 1)//如果点下,等待获取下一次点击位置
		{
			n = pos[1];
			m = pos[2];
			while (correct2 != 1 && correct2 != 0)//循环等待第二次是否点下
			{
				pos2 = test_mouse_second(daanptr, m, n);
				//daanptr[m][n] = i;
				correct2 = *pos2;//获取是否点下的标志位
				Num = pos2[1];//获取准备填的数字

				//i++;
				//show2(daanptr);
			}
			if (correct2 == 1)//如果点在了选数区
			{
				daanptr[m][n] = Num;//将点击的数据填入数独矩阵
				correct2 = 2;//修改标志位使循环退出
			}
			else//corect不为1说明点在了其他地方
			{
				correct2 = 2;//修改标志位使循环退出
			}
		}
		show2(daanptr, nunposptr);//展示修改后的数独
		show3();//展示失败次数
	}

	finish();//展示结束界面,游戏结束

	system("pause");		//暂停
	closegraph();			// 关闭绘图窗口
	

	//以下代码都是测试上面函数是否正确时候使用的

	//测试test_num函数
	/*
	int A1[9] = { 9,8,6,7,2,8,3,5,4 };
	int A2[9] = { 3,5,8,0,9,6,1,2,7 };
	int A3[9] = { 2,0,4,5,1,3,8,6,9 };
	int A4[9] = { 7,6,3,2,5,1,9,4,0 };
	int A5[9] = { 4,2,0,9,8,7,6,1,3 };
	int A6[9] = { 1,8,9,6,0,4,2,7,5 };
	int A7[9] = { 5,3,2,1,7,0,4,8,6,};
	int A8[9] = { 8,4,7,3,6,2,5,0,1 };
	int A9[9] = { 6,9,1,8,4,5,7,3,0 };
	int* A[9] = { A1,A2,A3,A4,A5,A6,A7,A8,A9 };
	int r = test_num(A,0,1);
	cout << r << endl;
	cout << A[0][1] << endl;
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (*(A[i] + j) != 0)
			{
				cout << *(A[i] + j) << " ";
			}
			else
			{
				cout << ' ' << " ";
			}
		}
		cout << endl;
	}
	*/
	//测试test_mouse_test函数
	/*
	int correct = 0;
	int* p1;
	int x = 0;
	int y = 0;
	int A1[9] = { 1,2,3,4,5,6,7,8,0 };
	int A2[9] = { 2,3,4,5,6,7,8,9,1 };
	int A3[9] = { 3,4,5,6,7,0,9,1,2 };
	int A4[9] = { 4,5,6,7,8,9,1,2,3 };
	int A5[9] = { 5,6,0,8,9,1,2,3,4 };
	int A6[9] = { 0,7,8,9,1,2,3,4,5 };
	int A7[9] = { 7,8,9,1,2,3,4,5,6 };
	int A8[9] = { 8,0,1,2,3,4,0,6,7 };
	int A9[9] = { 9,1,2,3,4,5,6,7,0 };
	int* A[9] = { A1,A2,A3,A4,A5,A6,A7,A8,A9 };
	initgraph(740, 580);	// 创建绘图窗口,大小为 740x580 像素
	setbkcolor(RGB(222, 213, 176));
	cleardevice();
	setlinecolor(0);//设定线条颜色为黑
	int a = 9;        //方格个数
	int w = 50;       //方格宽度
	for (int i = 0; i < a + 1; ++i)
	{
		line(w, w + w * i, w + w * a, w + w * i);         //画横线
		line(w + w * i, w, w + w * i, w + w * a);         //画竖线
	}
	settextcolor(0);
	while (true)
	{
		p1 = test_mouse_test();    //检测鼠标是否按下,并返回鼠标坐标
		correct = *p1;
		if (correct == 1)
		{
			wchar_t num[20];
			wchar_t num2[20];
			int n = p1[1];
			int m = p1[2];
			_itow_s(n, num, 10);
			_itow_s(m, num2, 10);
			outtextxy(200, 300, num);
			outtextxy(300, 300, num2);
		}
		//Sleep(1000);
	}
	system("pause");		//暂停
	closegraph();			// 关闭绘图窗口
	*/
	//测试my_getnonzero函数,但这个函数后来改成my_getzero_two函数了
	/*
	int k = (int)time(0);
	int** daanptr;
	daanptr = answer(k);
	daanptr = chansheng(daanptr, 7);
	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			cout << *(daanptr[i] + j) << " ";
		}
		cout << endl;
	}
	int** posptr = my_getnonzero(daanptr);
	for (int i = 1; i < posptr[0][0]+1; i++)
	{
		cout << posptr[0][i] << ' ' << posptr[1][i];
		cout << endl;
	}
	cout << posptr[0][0] << endl;
	system("pause");
	*/
	//测试运行主函数
	/*
	int k = (int)time(0);
	int ** daanptr;
	daanptr = answer(k);
	daanptr = chansheng(daanptr, 1);

	for(int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			if (*(daanptr[i] + j) != 0)
			{
				cout << *(daanptr[i] + j) << " ";
			}
			else
			{
				cout << ' ' << " ";
			}
		}
		cout << endl;
	}*/
	//测试二级指针输出
	/*
	for (int i = 0; i < 9; i++)
	{
		cout <<  daanptr << endl;
		daanptr++;
	}
	*/
	//测试my_getzero函数
	/*
	int A[9] = { 1,2,0,4,0,6,8,0,9 };
	int * p;
	p = my_getzero(A);
	int a = *p;
	p++;
	for (int i = 0; i < a; i++)
	{
		cout << *p << endl;
		p++;
	}*/
	//测试my_union函数
	/*
	int A[] = { 6,1,2,3,7,8,9};
	int B[] = { 4,5,2,3,6 };
	int C[] = { 3,4,5,6 };
	int* p1 = A;
	int* p2 = B;
	int* p3 = C;
	int* t = my_union(p1, p2);
	t = my_union(t, p3);
	int a = *t;
	for (int i = 0; i < a + 1; i++)
	{
		cout << t[i] << endl;
	}*/
	//测试my_difference函数
	/*
	int A[6] = { 5,1,2,3,7,9 };
	int* p = A;
	int* p1 = my_difference(p);
	int a = *p1;
	for (int i = 1; i < a + 1; i++)
	{
		cout << p1[i] << endl;
	}
	*/
	//测试my_random函数
	/*
	for (int i = 0; i < 9; i++)
	{
		my_random(50*(i*i*i+100+i*i*5-20));
	}
	*/
	//测试chansheng函数
	/*static int A1[9] = { 0 };
	static int A2[9] = { 0 };
	static int A3[9] = { 0 };
	static int A4[9] = { 0 };
	static int A5[9] = { 0 };
	static int A6[9] = { 0 };
	static int A7[9] = { 0 };
	static int A8[9] = { 0 };
	static int A9[9] = { 0 };
	static int* A[9] = { A1,A2,A3,A4,A5,A6,A7,A8,A9 };
	int k = (int)time(0);
	int** daanptr = A;
	daanptr = chansheng(daanptr, 2);

	for (int i = 0; i < 9; i++)
	{
		for (int j = 0; j < 9; j++)
		{
			cout << *(daanptr[i] + j) << " ";
		}
		cout << endl;
	}*/

	return 0;
}

只要把代码复制到cpp文件中就应该可以跑了,运行效果如图
初始界面
在这里插入图片描述产生数独界面
简单模式
在这里插入图片描述困难模式
在这里插入图片描述

填数时正确和错的情况
在这里插入图片描述
结束界面展示
在这里插入图片描述
最后,在编译的时候把这里改成release然后编译,debug编译正确,运行会报错,我也不知道为什么

在这里插入图片描述

  • 7
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
当然可以!下面是一个简单的用C++EasyX编写的飞机大战小游戏的示例代码: ```c++ #include <graphics.h> #include <conio.h> #define WIDTH 480 #define HEIGHT 640 IMAGE bgImg; // 背景图片 IMAGE planeImg; // 飞机图片 IMAGE bulletImg; // 子弹图片 IMAGE enemyImg; // 敌机图片 int planeX = WIDTH / 2 - 50; // 飞机初始位置 int planeY = HEIGHT - 150; int bulletX; // 子弹位置 int bulletY; int enemyX; // 敌机位置 int enemyY; bool isBulletExist = false; // 子弹是否存在 bool isEnemyExist = false; // 敌机是否存在 void init() { initgraph(WIDTH, HEIGHT); // 初始化绘图窗口 loadimage(&bgImg, _T("background.jpg")); // 加载背景图片 loadimage(&planeImg, _T("plane.png")); // 加载飞机图片 loadimage(&bulletImg, _T("bullet.png")); // 加载子弹图片 loadimage(&enemyImg, _T("enemy.png")); // 加载敌机图片 } void draw() { putimage(0, 0, &bgImg); // 绘制背景图片 putimage(planeX, planeY, &planeImg); // 绘制飞机图片 if (isBulletExist) { putimage(bulletX, bulletY, &bulletImg); // 绘制子弹图片 } if (isEnemyExist) { putimage(enemyX, enemyY, &enemyImg); // 绘制敌机图片 } } void updateWithoutInput() { if (isBulletExist) { bulletY -= 5; // 更新子弹位置 if (bulletY <= 0) { isBulletExist = false; // 子弹超出屏幕,不存在 } } if (isEnemyExist) { enemyY += 2; // 更新敌机位置 if (enemyY >= HEIGHT) { isEnemyExist = false; // 敌机超出屏幕,不存在 } } } void updateWithInput() { if (_kbhit()) { char ch = _getch(); if (ch == ' ') { // 按下空格键,发射子弹 if (!isBulletExist) { bulletX = planeX + 45; // 子弹的初始位置 bulletY = planeY - 30; isBulletExist = true; } } else if (ch == 'a' && planeX > 0) { // 按下左箭头键,飞机向左移动 planeX -= 10; } else if (ch == 'd' && planeX < WIDTH - 100) { // 按下右箭头键,飞机向右移动 planeX += 10; } } } int main() { init(); while (true) { draw(); updateWithoutInput(); updateWithInput(); Sleep(10); // 控制游戏帧率 } closegraph(); return 0; } ``` 请确保在运行前,将`background.jpg`、`plane.png`、`bullet.png`和`enemy.png`这四个图片放在与源代码相同的目录下。 这只是一个简单的示例,你可以根据自己的需求进一步完善游戏的功能和画面效果。希望对你有帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值