数独游戏设计与源码
数独小游戏编程实现
数独小游戏编程实现数独是一种经典的数字推理游戏,旨在填充一个9x9的方格,使每一行、每一列和每一个3x3的子网格中的数字都不重复。
在这篇文章中,我们将探讨如何使用编程实现一个数独小游戏。
1. 游戏介绍数独是一款传统的逻辑游戏,旨在通过推理和逻辑推断填充一个9x9的方格。
游戏规则简单,玩家需要在每个方格中填入1到9的数字,使得每一行、每一列和每一个3x3的子网格中的数字都不重复。
数独游戏的难度由初始提供的数字数量决定,有些数独游戏可能需要一些试错和推理才能解开。
2. 游戏实现为了实现一个数独小游戏,我们可以使用编程语言来创建一个数独游戏的逻辑和界面。
下面是一个简单的实现步骤:a) 创建一个9x9的空白方格。
b) 初始化一些方格中的数字,这些数字将用作初始提示。
c) 实现一个算法来解决数独问题。
d) 创建用户界面,允许玩家交互并填写数字。
e) 校验玩家填写的数字是否符合数独规则。
f) 判断玩家是否成功解开数独谜题。
3. 实现算法为了解决数独问题,我们可以使用回溯算法。
回溯算法是一种试错的算法,通过递归地尝试不同的数字来解决问题,如果当前选择导致问题无解,则回溯到上一步重新选择。
4. 用户界面设计为了创建一个用户友好的数独小游戏,我们可以使用图形用户界面(GUI)来展示游戏方格,并提供填写数字的功能。
在界面上,玩家可以点击一个方格,并输入数字进行填写。
游戏还可以提供一些提示和错误检查功能,以帮助玩家更方便地解决数独谜题。
5. 游戏规则校验为了保证玩家填写的数字符合数独游戏规则,我们需要实现一些校验逻辑。
在玩家填写数字时,我们可以检查当前行、当前列和当前子网格中是否存在重复的数字。
如果存在重复的数字,则提示玩家重新填写。
6. 解决数独谜题为了让玩家能够解决数独谜题,我们可以提供一个求解谜题的功能。
这个功能可以使用回溯算法来搜索解空间,直到找到一个满足数独规则的解。
如果谜题是有解的,玩家可以尝试使用这个功能来解决难度较高的数独问题。
数独代码源码
number_bitmap[2] = BitmapFactory.decodeResource(getResources(), R.drawable.b2);//2的图标
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
public class Content extends Activity{
Button start;
Button help;
Button exit;
GameView gameView;//游戏界面的引用
@Override
protected void onCreate(Bundle savedInstanceState) {
key_background = BitmapFactory.decodeResource(getResources(), R.drawable.key_background);
number_bitmap[0] = BitmapFactory.decodeResource(getResources(), R.drawable.b0);//0的图标
}
private class AccessToNext implements OnClickListener {
VC++ 6.0 API MFC 数独游戏源程序代码
本程序是基于API技术,用VC++ 6.0 MFC开发工具编写的,实现了数独小游戏。
以下为全部源程序代码。
//written by luweikang// shudu.cpp : Defines the entry point for the application.//finished 2010-06-20#include <windows.h>#include "stdafx.h"#include <stdlib.h>#include <stdio.h>#define tPaint 2 //重绘定时器的标识(编号)#define tPaintTime 50 //窗口重绘的时间间隔#define ROW 9 //方格的行数与列数#define COL 9 //方格的行数与列数#define LEN 40 //每个方格大小为40×40像素#define StartY 3 //#define StartX 3 //绘制方格地图时的边界起始位置int CurrentX=0;int CurrentY=0; //当前操作位置void InitMap_show( ); //初始化地图int value[ROW][COL]; //记录每个方格中的数字void Initvalue( ); //初始化方格中的数字为0int judge(); //判断当前位置是否能输入用户想要输入的数字void random(); //实现随机生成整张地图上的数字int change[9][9]; //用于记录各个位置的数字是否可改变,0不可变,1可变void Initchange(); //初始化change数组中的值int IsSuccess(); //判断是否完成int answer[9][9][9]; //用于保存每个方格可以填入的数字void Initanswer(); //初始化answer[81][9][9]全部为0void bauto(int n); //自动求解void showhelp(); //求辅助数据bool help=0; //是否显示辅助数据bool f; //成功标志int tmp=20; //记录当前地图是哪副int easy[21][9][9]={ //用于存储初级地图{{0,0,0,0,3,0,2,0,8},{0,2,8,0,4,0,1,3,0},{0,0,9,5,8,0,0,4,7},{0,3,1,0,2,0,5,9,0},{0,0,5,3,9,1,7,0,0},{0,9,0,4,7,5,8,1,3},{0,0,0,0,6,0,4,0,2},{0,0,0,0,0,3,0,6,0},{0,7,6,2,5,4,0,8,0}},{{0,0,0,0,0,4,0,5,2},{0,0,5,0,0,7,0,1,4},{0,0,1,0,0,8,3,0,6},{0,1,2,0,0,6,4,3,9},{0,0,9,0,4,1,6,8,5},{0,0,6,0,3,5,2,7,1},{0,6,7,0,1,0,0,0,0},{1,5,0,0,0,3,0,2,8},{0,2,0,0,5,9,0,6,0}},{{0,7,8,4,0,0,0,3,6},{4,1,9,0,0,8,2,0,0},{0,0,6,0,7,0,0,0,9},{0,9,5,0,6,4,0,7,1},{1,0,7,5,0,0,0,0,0},{0,8,1,0,0,9,6,2,4},{0,0,2,0,0,0,0,0,3},{0,4,0,0,2,0,0,8,5} },{{0,9,0,0,0,8,0,2,0},{0,8,0,0,9,7,0,4,0},{0,7,0,5,2,0,9,6,8},{0,0,7,0,4,0,0,5,3},{0,2,9,0,3,5,0,0,0},{0,3,5,2,7,1,6,8,0},{0,0,1,0,8,0,5,0,0},{0,0,0,7,0,0,0,9,4},{0,4,8,0,5,2,1,3,6} },{{0,0,5,0,0,0,1,6,7},{0,0,7,0,4,0,0,9,0},{3,0,0,0,0,1,0,0,0},{0,5,1,0,3,0,0,0,0},{0,2,3,0,1,8,5,0,0},{0,8,0,7,9,5,3,0,2},{1,3,6,0,5,0,2,8,0},{0,7,0,1,8,3,0,5,6},{5,9,8,0,6,0,7,0,1} },{{0,1,8,0,0,0,6,2,0},{0,7,9,0,0,0,5,8,0},{0,0,6,0,0,5,0,1,0},{0,5,2,0,3,7,9,0,8},{0,0,1,5,2,8,4,7,3},{0,3,7,0,9,6,0,0,1},{0,0,0,0,7,4,8,3,2},{0,0,0,0,1,0,0,4,5},{0,8,0,0,5,0,0,9,6} },{ //特殊{0,0,1,0,0,0,0,0,7},{0,7,8,5,6,0,3,9,2},{0,0,9,0,4,0,1,6,0},{0,2,3,0,0,5,9,0,6},{0,9,7,3,0,2,0,0,0},{0,4,0,1,2,9,0,7,0},{7,1,0,0,3,8,0,4,9},{0,8,0,0,5,0,0,3,0} },{ //第八种{0,1,2,0,0,9,0,5,8},{0,4,0,0,0,8,6,0,9},{9,0,8,0,5,0,3,1,2},{0,0,1,7,9,5,8,0,0},{0,7,3,0,0,0,0,9,1},{0,0,9,0,3,2,0,0,7},{0,5,7,0,2,4,0,6,3},{0,9,0,0,0,0,0,0,0},{0,0,6,5,7,1,0,8,4} },{{0,3,6,0,0,9,4,8,5},{9,4,0,0,0,8,0,7,0},{0,7,8,0,0,6,0,0,9},{4,6,0,7,8,0,0,9,0},{0,0,7,0,0,3,0,4,0},{0,0,9,0,6,0,7,1,2},{0,5,3,0,9,0,0,6,4},{0,9,4,0,0,0,1,5,0},{0,0,2,6,5,4,0,0,7} },{{0,0,1,8,9,3,5,6,7},{0,8,7,4,0,1,0,3,0},{0,3,9,7,5,0,0,1,0},{4,0,0,0,3,5,0,0,0},{0,0,8,0,0,4,0,9,1},{0,0,2,1,8,6,0,5,0},{0,2,0,5,0,7,0,8,6},{0,6,0,3,2,0,0,0,0},{0,7,0,0,0,8,3,4,0} },{{0,3,9,0,4,8,0,2,5},{6,8,2,0,5,0,0,0,0},{4,5,7,0,2,0,0,8,0},{5,1,6,9,0,3,0,0,4},{9,4,3,0,1,0,0,5,0},{0,2,0,0,0,0,0,6,3},{0,0,0,0,0,0,0,9,2},{0,0,4,2,3,6,0,0,0} },{{0,0,8,0,0,0,0,2,0},{0,3,2,0,4,0,9,0,0},{5,7,4,0,1,2,3,0,8},{0,0,7,0,2,6,0,4,0},{0,0,6,5,0,1,2,7,3},{0,1,5,0,0,0,0,0,9},{0,2,1,7,8,0,0,3,5},{0,4,3,1,0,0,0,0,0},{7,5,0,0,3,4,8,1,0} },{{0,8,0,3,0,0,0,5,9},{0,4,0,0,0,0,6,1,7},{0,5,7,0,1,9,0,3,8},{0,1,8,2,0,0,0,0,3},{0,2,0,0,7,3,8,0,4},{0,0,0,8,9,0,0,2,5},{0,3,2,0,4,5,9,8,0},{0,0,4,0,3,0,5,0,0},{7,6,5,9,8,0,0,0,0} },{{0,0,0,0,8,9,0,5,6},{0,8,6,4,0,5,0,2,9},{0,0,0,0,0,7,0,0,8},{0,1,8,6,4,2,0,9,3},{0,6,3,8,0,1,2,0,0},{0,0,5,0,7,3,0,8,1},{6,0,0,0,3,0,0,4,0},{0,0,7,0,9,4,0,6,2},{0,5,9,0,0,0,0,3,7} },{{0,0,0,2,0,0,0,0,9},{5,2,0,0,0,9,4,0,3},{0,8,9,0,0,0,0,0,0},{0,0,0,9,7,6,0,1,4},{0,9,4,5,2,8,3,7,0},{0,1,3,4,5,2,6,0,0},{0,0,2,8,0,1,0,0,7},{0,0,8,6,3,7,2,4,0} },{ //第16种{0,7,9,0,1,4,0,0,6},{0,1,0,0,2,7,0,0,0},{0,0,6,0,8,9,0,1,7},{9,5,0,0,3,2,6,7,0},{0,6,7,4,9,0,0,0,8},{0,3,1,0,6,0,0,0,0},{0,0,5,0,0,1,3,6,2},{0,0,0,8,7,3,5,4,1},{0,0,0,0,5,0,0,8,9} },{{0,0,5,0,6,0,0,0,9},{0,0,0,0,1,8,2,4,5},{8,9,2,3,0,0,0,7,0},{0,5,7,0,8,9,0,0,3},{0,2,1,0,0,6,0,9,0},{0,6,8,0,3,2,0,0,1},{0,8,0,0,2,1,0,6,0},{0,1,4,0,0,0,0,3,7},{0,0,9,8,4,0,5,1,2} },{{0,5,0,0,9,2,1,3,6},{0,0,0,0,5,4,0,0,8},{1,0,0,0,8,3,0,5,9},{0,8,3,9,2,0,0,1,4},{7,0,0,5,0,0,0,8,2},{0,2,0,0,3,0,0,6,0},{9,3,5,2,0,8,7,0,0},{0,6,7,4,1,5,8,0,0},{0,0,0,0,0,0,0,2,5} },{{0,3,7,2,0,9,0,0,4},{0,8,9,0,0,0,1,0,7},{0,5,6,7,1,8,0,0,0},{0,6,0,3,9,0,0,0,0},{0,0,2,0,7,5,0,4,8},{6,4,0,8,0,1,7,0,2},{7,0,3,9,4,6,0,8,1},{0,1,8,0,0,0,0,3,0}},{ //第20种{0,3,5,0,0,9,0,2,7},{0,2,9,3,5,1,0,6,8},{0,0,0,0,0,4,0,0,9},{0,5,0,5,6,0,0,0,3},{8,7,0,5,0,3,0,0,2},{0,4,0,0,0,2,0,0,5},{6,0,4,0,3,7,2,0,0},{0,1,3,9,2,0,8,7,4},{0,0,0,0,0,5,0,9,6}},{ //测试数据{7,1,2,3,6,9,4,5,8},{3,4,5,2,1,8,6,7,9},{9,6,8,4,5,7,3,1,2},{4,2,1,7,9,5,8,3,6},{5,7,3,8,4,6,2,9,1},{6,8,9,1,3,2,5,4,7},{8,5,7,9,2,4,1,6,3},{1,9,4,6,8,3,7,2,5},{2,3,6,5,7,1,0,8,4}}};LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM ); //窗口处理函数int APIENTRY WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPSTR lpCmdLine,int iCmdShow){// written by luweikang// TODO: Place code here.static TCHAR szAppName[ ] = TEXT ("Russion");HWND hwnd;MSG msg;WNDCLASS wndclass;wndclass.style = CS_HREDRAW | CS_VREDRAW;wndclass.lpfnWndProc = WndProc;wndclass.cbClsExtra = 0;wndclass.cbWndExtra = 0;wndclass.hInstance = hInstance;wndclass.hIcon = LoadIcon( NULL, IDI_APPLICATION );wndclass.hCursor = LoadCursor( NULL, IDC_ARROW );wndclass.hbrBackground = (HBRUSH)GetStockObject( WHITE_BRUSH );wndclass.lpszMenuName = NULL;wndclass.lpszClassName = szAppName;if( !RegisterClass( &wndclass ) ){MessageBox( NULL, TEXT ("Program requires Windows NT!" ),szAppName, MB_ICONERROR );return 0;}hwnd = CreateWindow( szAppName, TEXT ("数独游戏"),WS_OVERLAPPED | WS_SYSMENU | WS_BORDER,CW_USEDEFAULT, CW_USEDEFAULT,(COL + 4) * LEN+2, //窗口宽度ROW * LEN + 40, //窗口高度(包括标题栏部分29pix)NULL, NULL, hInstance, NULL );ShowWindow( hwnd, iCmdShow );UpdateWindow( hwnd );while( GetMessage( &msg, NULL, 0, 0 ) ){TranslateMessage( &msg );DispatchMessage( &msg );}return msg.wParam;}void Initvalue( ) //初始化地图上的每一个值,使其为零{int y, x;for( y = 0; y < ROW; y++ ){for( x = 0; x < COL; x++ ){value[y][x] = 0;}}}void Initchange(){int row2,col2;for(row2=0;row2<9;row2++){for(col2=0;col2<9;col2++){if(value[row2][col2]==0) change[row2][col2]=1;else change[row2][col2]=0;}}}void Initanswer(){int a,b,c;for(a=0;a<9;a++){for(b=0;b<9;b++){for(c=0;c<9;c++)answer[a][b][c]=0;}}}int IsSuccess(){int row4,col4;int count[]={81,9,9,9,9,9,9,9,9,9};for(row4=0;row4<9;row4++){for(col4=0;col4<9;col4++){count[value[row4][col4]]--;}}if(count[1]==0&&count[2]==0&&count[3]==0&&count[4]==0&&count[5]==0&&count[6] ==0&&count[7]==0&&count[8]==0&&count[9]==0)return 1;elsereturn 0;}int judge(int value1,int row,int col){int down_row,down_col,up_row,up_col;for(down_row=0;down_row<row;down_row++) //判断方格向上的格子{if(value1==value[down_row][col]) return 0;}for(up_row=8;up_row>row;up_row--) //判断方格向下的格子{if(value1==value[up_row][col]) return 0;}for(down_col=0;down_col<col;down_col++) //判断方格向左的格子{if(value1==value[row][down_col]) return 0;}for(up_col=8;up_col>col;up_col--) //判断方格向右的格子{if(value1==value[row][up_col]) return 0;}int a_row=row/3,b_row=row%3,a_col=col/3,b_col=col%3;//用于记录当前格子所在的小九宫格的位置int mini_row,mini_col;switch(a_row){case 0://这个大九宫格在最上三行switch(a_col){case 0://这个大九宫格在最前三列for(mini_row=0;mini_row<3;mini_row++){for(mini_col=0;mini_col<3;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;case 1://这个大九宫格在中间三列for(mini_row=0;mini_row<3;mini_row++){for(mini_col=3;mini_col<6;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;case 2://这个大九宫格在最后三列for(mini_row=0;mini_row<3;mini_row++){for(mini_col=6;mini_col<9;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;}break;case 1://这个大九宫格在中间三行switch(a_col){case 0://这个大九宫格在最前三列for(mini_row=3;mini_row<6;mini_row++){for(mini_col=0;mini_col<3;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;case 1://这个大九宫格在中间三列for(mini_row=3;mini_row<6;mini_row++){for(mini_col=3;mini_col<6;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;case 2://这个大九宫格在最后三列for(mini_row=3;mini_row<6;mini_row++){for(mini_col=6;mini_col<9;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;}break;case 2://这个大九宫格在最下三行switch(a_col){case 0://这个大九宫格在最前三列for(mini_row=6;mini_row<9;mini_row++){for(mini_col=0;mini_col<3;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;case 1://这个大九宫格在中间三列for(mini_row=6;mini_row<9;mini_row++){for(mini_col=3;mini_col<6;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;case 2://这个大九宫格在最后三列for(mini_row=6;mini_row<9;mini_row++){for(mini_col=6;mini_col<9;mini_col++)if(value1==value[mini_row][mini_col]) return 0;}break;}break;}return 1;}void showhelp(){Initanswer();int row8,col8,numbe,i;for(row8=0;row8<9;row8++){for(col8=0;col8<9;col8++){if(value[row8][col8]==0&&change[row8][col8]){i=0;for(numbe=1;numbe<10;numbe++){if(judge(numbe,row8,col8)){answer[row8][col8][i++]=numbe;}}}}}}void bauto(int n){int row7=n/9,col7=n%9,num;for(num=1;num<10&&change[row7][col7];num++){if(n<81&&judge(num,row7,col7)&&change[row7][col7]){value[row7][col7]=num;bauto(n+1);}}if(change[row7][col7]&&!f)value[row7][col7]=0;if(n<81&&!change[row7][col7]){bauto(n+1);}if(n==81)f=1;}LRESULT CALLBACK WndProc( HWND hwnd, UINT message, //窗口处理函数WPARAM wParam, LPARAM lParam ){HFONT hfont;HDC hdc, hdcMem;int y, x;PAINTSTRUCT ps;HBITMAP hBitMap;HPEN hPen;HBRUSH hBrush;int row3,col3,mem,mem_fuzhu;static int cxClient, cyClient; //窗口客户区宽度和高度static char *text[]={" ","1","2","3","4","5","6","7","8","9"};static char *info[]={"F1:生成地图","F2:显示辅助数据","F4:自动求解","F5:重开本局"};static char *t="success!";switch( message ){case WM_CREATE:SetTimer( hwnd, tPaint, tPaintTime, NULL );return 0;case WM_SIZE:cxClient = LOWORD( lParam ); //取得窗口客户区宽度和高度cyClient = HIWORD( lParam );return 0;case WM_TIMER:{switch( wParam ){case tPaint: //重绘定时器InvalidateRect(hwnd, NULL, FALSE); //强制重绘窗口工作区break;}}//end of case WM_TIMERcase WM_KEYDOWN:{switch( wParam ){case VK_LEFT: //"向左"方向键if(CurrentX>0)CurrentX-=1;else if(CurrentX==0)CurrentX=8;break;case VK_RIGHT: //"向右"方向键if(CurrentX<8)CurrentX+=1;else if(CurrentX==8)CurrentX=0;break;case VK_UP: //"向上"方向键:if(CurrentY>0)CurrentY-=1;else if(CurrentY==0)CurrentY=8;break;case VK_DOWN: //"向下"方向键:下移一个位置if(CurrentY<8)CurrentY+=1;else if(CurrentY==8)CurrentY=0;break;case 0x30: //响应数字0键value[CurrentY][CurrentX]=0;break;case 0x31:if(!judge(1,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=1;showhelp();break;case 0x32:if(!judge(2,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=2;showhelp();break;case 0x33:if(!judge(3,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=3;showhelp();break;case 0x34:if(!judge(4,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=4;showhelp();break;case 0x35:if(!judge(5,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=5;showhelp();break;case 0x36:if(!judge(6,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=6;showhelp();break;case 0x37:if(!judge(7,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=7;showhelp();break;case 0x38:if(!judge(8,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=8;showhelp();break;case 0x39:if(!judge(9,CurrentY,CurrentX)) break;value[CurrentY][CurrentX]=9;showhelp();break;case VK_F1:f=0;help=0;mem_fuzhu=10000;while(1){mem=rand()%20;if(mem_fuzhu!=mem)break;}tmp=mem;mem_fuzhu=mem;for(row3=0;row3<9;row3++){for(col3=0;col3<9;col3++)value[row3][col3]=easy[mem][row3][col3];}Initchange();break;case VK_F2:Initanswer();showhelp();help=!help;break;case VK_F4:bauto(0);break;case VK_F5:help=0;for(row3=0;row3<9;row3++){for(col3=0;col3<9;col3++)value[row3][col3]=easy[tmp][row3][col3];}f=0;}}//end of case WM_KEYDOWNbreak;case WM_PAINT: //重绘窗口工作区{hdc = BeginPaint( hwnd, &ps );hdcMem = CreateCompatibleDC( hdc );hBitMap = CreateCompatibleBitmap( hdc, cxClient, cyClient );SelectObject( hdcMem, hBitMap );//画地图最外面的白色矩形Rectangle( hdcMem, StartX,StartY,StartX + LEN * COL, StartY + LEN *ROW );Rectangle( hdcMem, StartX + LEN * COL+ 3, StartY , StartX + LEN * COL + 149, StartY + LEN * ROW); //画右边的白色文本区域///*hPen = CreatePen( PS_SOLID, 1, RGB(180, 180, 180) );SelectObject( hdcMem, hPen );hBrush = CreateSolidBrush( RGB(250, 250, 250) );SelectObject( hdcMem, hBrush );for( y = 0; y < ROW ; y++ ) //画地图中的每一格{for( x = 0; x < COL ; x++ ){Rectangle( hdcMem, StartX + LEN * x, StartY + LEN * y,StartX + LEN * (x + 1), StartY + LEN * (y + 1) );}}hPen = CreatePen( PS_SOLID, 1, RGB(255, 0, 0) );SelectObject( hdcMem, hPen );Rectangle( hdcMem, StartX + 119, StartY ,StartX + 121, StartY + 360); //横竖各两条画红线Rectangle( hdcMem, StartX + 239, StartY ,StartX + 241, StartY + 360);Rectangle( hdcMem, StartX , StartY + 119,StartX + 360, StartY + 121);Rectangle( hdcMem, StartX , StartY + 239,StartX + 360, StartY + 241);DeleteObject( hPen );DeleteObject( hBrush );//画能移动的当前活动的蓝色方格hPen = CreatePen( PS_SOLID, 1, RGB(0, 0, 255) );SelectObject( hdcMem, hPen );hBrush = CreateSolidBrush( RGB(255, 255, 255) );SelectObject(hdcMem, hBrush);Rectangle( hdcMem, StartX + LEN * CurrentX, StartY + LEN * CurrentY,StartX +LEN * (CurrentX + 1), StartY + LEN * (CurrentY + 1) );Rectangle( hdcMem, StartX + LEN * CurrentX+1, StartY + LEN * CurrentY+1,StartX +LEN * (CurrentX + 1)-1, StartY + LEN * (CurrentY + 1)-1 );DeleteObject( hPen );DeleteObject( hBrush );DeleteObject( hBitMap );hfont=CreateFont(35,0,0,0,FW_HEA VY,0,0,0,GB2312_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"粗体字");SelectObject(hdcMem,hfont);for(int ro=0;ro<9;ro++){for(int co=0;co<9;co++){if(change[ro][co]==0){SetTextColor(hdcMem,RGB(0,0,0)); //设置文本颜色为黑色TextOut(hdcMem,StartX+3+LEN*co,StartY+3+LEN*ro,text[value[ro][co]],strlen(text[value [ro][co]]));}if(change[ro][co]==1){SetTextColor(hdcMem,RGB(255,0 ,0)); //设置文本颜色为红色TextOut(hdcMem,StartX+3+LEN*co,StartY+3+LEN*ro,text[value[ro][co]],strlen(text[value [ro][co]]));}}}if(help){hfont=CreateFont(13,0,0,0,FW_HEA VY,0,0,0,GB2312_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"粗体字");SelectObject(hdcMem,hfont);SetTextColor(hdcMem,RGB(128,128 ,128));for(int ro=0;ro<9;ro++){for(int co=0;co<9;co++){for(intnumb=0;numb<9&&change[ro][co]&&value[ro][co]==0;numb++){for(int a=numb/3;a<3;a++){for(int b=numb%3;b<3;b++){TextOut(hdcMem,StartX+3+LEN*co+b*11,StartY+3+LEN*ro+a*11,text[answer[ro][co][nu mb]],strlen(text[answer[ro][co][numb]]));}}}}}}hfont=CreateFont(15,0,0,0,FW_HEA VY,0,0,0,GB2312_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"粗体字");SelectObject(hdcMem,hfont);SetTextColor(hdcMem,RGB(0,0,0)); //设置文本颜色为黑色TextOut(hdcMem,StartX + LEN * 9+4, StartY+1,info[0],strlen(info[0]));TextOut(hdcMem,StartX + LEN * 9+4, StartY+21,info[1],strlen(info[1]));TextOut(hdcMem,StartX + LEN * 9+4, StartY+41,info[2],strlen(info[2]));TextOut(hdcMem,StartX + LEN * 9+4, StartY+61,info[3],strlen(info[3]));if(IsSuccess()){hfont=CreateFont(30,0,0,0,FW_HEA VY,0,0,0,GB2312_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH|FF_DONTCARE,"粗体字");SelectObject(hdcMem,hfont);TextOut(hdcMem,StartX+364,StartY+300,t,strlen(t));}BitBlt( hdc, 0, 0, cxClient, cyClient, hdcMem, 0, 0, SRCCOPY );DeleteDC( hdcMem );EndPaint( hwnd, &ps );DeleteObject(hfont);return 0;}//end of case WM_PAINTcase WM_DESTROY:PostQuitMessage( 0 );return 0;}//end of switch( message )return DefWindowProc( hwnd, message, wParam, lParam );}。
数独游戏设计与源码
数据结构大型作业实验报告书设计题目:“数独”游戏设计与求解一.题目说明数独的游戏规则:1、在9×9的大九宫格内,已给定若干数字,其他宫位留白,玩家需要自己按照逻辑推敲出剩下的空格里是什么数字。
2、必须满足的条件:每一行与每一列都有1到9的数字,每个小九宫格里也有1到9的数字,并且一个数字在每行、每列及每个小九宫格里只能出现一次,既不能重复也不能少。
3、每个数独游戏都可根据给定的数字为线索,推算解答出来。
按照数独的游戏规则,用计算机实现已知数独的求解和数独题目的出题。
二.数据结构说明数据结构一维数组、二维数组以及类似于“栈”的数据结构。
主要操作有:进栈,出栈,栈顶元素的操作等等三.抽象数据类型(Abstract Data Type 简称ADT) 五个全局变量数组,其中两个二维数组,三个一维数组。
int a[10][10]接受输入数据,空白处则初始化为0。
之所以把数组范围设计为10*10,是为了程序的可读性。
符合人的习惯思维。
int sd[82]在实现“回溯”算法的时候,因为要用到栈的数据结构,所以把a[10][10]二维数组中的数据转换储存进sd[82]一维数组。
方便处理题目以及保存最后结果。
int fix[82]对应于sd[82],记录哪些位置已经确定。
确定则fix值为1,未确定为0。
int possible[82][10]第一维对应着sd[82]中的每一个,第二维的下标为每个位置的可能值。
有可能则为第二维的下标,不可能则为-1。
int stack[82]类似于“栈”数据结构的数组,实现“回溯”算法的关键所在。
回溯之前,把所有fix 值为0的数据存如stack 数组中,即进栈。
回溯中逐渐确定这些位置的数值,无法确定者(即1--9都不适合的)则应回退到前一位置,修改其fix 值,以此类推。
直至stack 中所有的值都确定下来(即题目完成),或者回退到了最初点的前一位置(说明题目有误)。
四.算法设计程序可以考虑人工智能的算法。
数独游戏(HTML游戏使用JavaScript开发)
数独游戏(HTML游戏使用JavaScript开发)随着计算机技术的不断发展,人们对于娱乐方式也有了更高的要求。
传统的纸笔数独游戏逐渐被现代化的电子版数独游戏所取代。
本文将介绍使用JavaScript开发的HTML数独游戏,并分享其中的技术要点。
I. 游戏概述数独游戏是一种传统的逻辑数学益智游戏,它的玩法是在9×9的方格内填入1-9的数字,要求每行、每列、每个3×3的小九宫格内的数字均不重复。
游戏的目标是根据已给出的数字,推理出所有剩余的空格数字,直到将整个数独填满。
II. 技术要点1. HTML布局在HTML中,利用表格标签`<table>`来构建数独游戏的界面,将一个个单元格组织成9行9列的网格。
通过CSS样式来设定单元格的样式,以美化游戏界面。
2. JavaScript数据管理使用JavaScript来管理数独游戏中的数据。
创建一个9×9的二维数组来表示数独的初始布局,其中空白单元格用0表示。
用户的输入操作将会对这个数组进行修改。
3. 规则校验编写JavaScript函数来验证用户输入的合法性。
每当用户填入一个数字,程序将会调用规则校验函数,检查该数字是否符合数独的规则。
如果不符合,将给出相应的错误提示。
4. 游戏求解算法在数独游戏中,为了帮助用户完成游戏,通常需要提供求解功能。
通过实现回溯算法,编写JavaScript函数来求解数独问题。
该算法通过穷举的方式找出符合规则的解,并将其填入空白单元格。
5. 用户交互通过JavaScript来实现用户与游戏的交互效果。
当用户点击某个单元格时,单元格将获得焦点,并且可以通过键盘输入数字进行填写。
同时,为提高用户体验,添加撤销和重做功能,帮助用户更方便地进行操作。
III. 开发流程1. HTML布局在`<body>`标签中创建一个`<table>`元素,通过嵌套`<tr>`和`<td>`标签生成数独游戏的网格布局。
高级语言程序设计数独游戏
#include<iostream>using namespace std;#include<windows.h>#include<stdlib.h>#include<time.h>#include<conio.h>void setColor(unsigned short ForeColor=4,unsigned short BackGroundColor=0) {HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hCon,ForeColor|BackGroundColor*16);};void gotoxy(int x, int y){COORD c;c.X=x-1; c.Y=y-1;SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),c);}void initArray(int A[9][9]){int i,j,k,p;for(k=0;k<3;k++){p=k;for(i=k*3;i<k*3+3;i++){for(j=0;j<9;j++)A[i][j]=(p+j)%9+1;p=p+3;}}}void shuffle(int A[9][9]){int i,j,k,p,q,col1,col2,temp;srand((unsigned)time(0));for(k=1;k<=20;k++){p=rand()%9+1;q=rand()%9+1;for(i=0;i<9;i++){for(j=0;j<9;j++){if(A[i][j]==p) col1=j;if(A[i][j]==p) col2=j;}temp=A[i][col1];A[i][col1]=A[i][col2];A[i][col2]=temp;}}}void createshudu(int A[9][9],int n){srand((unsigned)time(0));int i=0,r,c;while(i<n){r=rand()%9;c=rand()%9;if(A[r][c]!=0){A[r][c]=0;i++;}}}int judge(int A[9][9],int row,int col,int num) {int i,j,k,p;if(A[row][col]!=0) return 0;for(j=0;j<9;j++)if(A[row][j]==num) return 0;for(i=0;i<9;i++)if(A[i][col]==num) return 0;k=(row/3)*3;p=(col/3)*3;for(i=k;i<k+3;i++)for(j=p;j<p+3;j++)if(A[i][j]==num) return 0;return 1;}void FillCell(int A[9][9],bool b[9][9],int r,int c,int value) {r--;c--;if(r>8||c>8||r<0||c<0){setColor(14,9);gotoxy(27,21);printf(" Invalid cell ");getch();return ;}if(b[r][c]==true){setColor(14,9);gotoxy(27,21);printf(" Fixed cell cannot be changed! ");getch();return ;}if(value>9||value<1){setColor(14,9);gotoxy(27,21);printf(" Invalid value");getch();return;}if(judge(A,r,c,value)){A[r][c]=value;if(2<c&&c<6&&(r<3||r>5)||2<r&&r<6&&(c<3||c>5)) setColor(15,0);else setColor(12,0);gotoxy(24+c*4,r+5);printf("%1d",A[r][c]);}else{setColor(14,9);gotoxy(27,21);printf(" irregular value ");getch();}}void ClearCell(int A[9][9],bool b[9][9],int r,int c){r--;c--;if(r>8||c>8||r<0||c<0){setColor(14,9);gotoxy(27,21);printf(" Invalid cell ");getch();return ;}if(b[r][c]==true){setColor(14,9);gotoxy(27,21);printf(" Fixed cell cannot be changed! ");getch();return ;}A[r][c]=0;if(2<c&&c<6&&(r<3||r<5)||2<r&&r<6&&(c<3||c>5)) setColor(14,5);else setColor(11,1);gotoxy(24+c*4,r+5);printf(" ");}void NewGame(int A[9][9],bool b[9][9],int spaces){int i,j;initArray(A);shuffle(A);createshudu(A,spaces);for(i=0;i<9;i++){gotoxy(20,i+5);setColor(15,0);printf("%d ",i+1);for(j=0;j<9;j++){if(2<j&&j<6&&(i<3||i>5)||2<i&&i<6&&(j<3||j>5)) setColor(14,5);else setColor(11,1);if(A[i][j]){printf("%3d ",A[i][j]);b[i][j]=true;}else{printf(" ");b[i][j]=false;}}}}void begin(int A[9][9],bool b[9][9]){int i,j;initArray(A);shuffle(A);setColor(14,6);gotoxy(34,2);printf(" shudu Game");gotoxy(21,4);setColor(15,0);for(i=1;i<10;i++) printf("%4d",i);for(i=0;i<9;i++){gotoxy(20,i+5);setColor(15,0);printf("%1d ",i+1);for(j=0;j<9;j++){if(2<j&&j<6&&(i<3||i>5)||2<i&&i<6&&(j<3||j>5)) setColor(14,5);else setColor(11,1);printf("%3d ",A[i][j]);b[i][j]=true;}}}void ShowMenu(){setColor(14,0);gotoxy(20,15);printf("N spaces :NewGame");gotoxy(20,16);printf("D :Demo Game");gotoxy(20,17);printf("E row col value :Edit cell");gotoxy(20,18);printf("C row col :clesr cell");gotoxy(20,19);printf("Q :Quit Game");}int main(){int A[9][9],r,c,spaces=0,flag=1,p=0;bool b[9][9];char s[10];begin(A,b);ShowMenu();while(flag){setColor(13,0);gotoxy(22,20);printf(" ");gotoxy(22,21);printf(" ");//不完整。
python数独游戏源代码
python数独游戏源代码以下是一个使用 Python 实现数独游戏的源代码。
简单说明了如何生成和解决数独游戏。
```import randomdef generate_board(size=9):""" Generate a random Sudoku board of size `size`using the orthogonal Latin squares method """board = [[None for _ in range(size)] for _ in range(size)]# Fill the diagonal with one of each digitfor i in range(size):digit = i % size + 1board[i][i] = digit# Fill the rest of the boardfor row in board:for i in range(size):if row[i] is None:digits = set(range(1, size + 1))# Remove digits already used in the same rowdigits -= set(row)# Remove digits already used in the same columndigits -= {board[j][i] for j in range(size)}# Remove digits already used in the same squaresquare_size = int(size ** 0.5)x, y = i // square_size, row // square_sizesquare = [board[square_size * y + dy][square_size * x + dx]for dx in range(square_size)for dy in range(square_size)]digits -= set(square)# Pick a random digit and fill the cellrow[i] = random.choice(list(digits))return boarddef print_board(board):""" Print the Sudoku board """size = len(board)square_size = int(size ** 0.5)for i in range(size):if i % square_size == 0:print('- ' * (square_size + 1) * square_size)row = ['{:2}'.format(board[i][j] or '.') for j in range(size)]row = [row[j:j + square_size] for j in range(0, size, square_size)]print('| ' + ' | '.join(' '.join(row[j][i] for j in range(square_size))for i in range(square_size)) + ' |')print('- ' * (square_size + 1) * square_size)def solve_board(board):""" Solve the Sudoku board """size = len(board)square_size = int(size ** 0.5)# Find an empty cellfor i in range(size):for j in range(size):if board[i][j] is None:digits = set(range(1, size + 1))# Remove digits already used in the same rowdigits -= set(board[i])# Remove digits already used in the same columndigits -= {board[k][j] for k in range(size)}# Remove digits already used in the same squarex, y = j // square_size, i // square_sizesquare = [board[square_size * y + dy][square_size * x + dx]for dx in range(square_size)for dy in range(square_size)]digits -= set(square)# Try each remaining digitfor digit in sorted(digits):board[i][j] = digit# Recursively solve the boardif solve_board(board):return board# No digit worked, backtrackboard[i][j] = Nonereturn Falsereturn boardboard = generate_board()print_board(board)if solve_board(board):print('Solution:')print_board(board)else:print('No solution found :(')```这是一个基本的实现,生成游戏的算法使用了“正交拉丁方”方法。
数独算法及源代码
数独算法及源代码朋友⼿机装有数独游戏,开会报告等⽆聊的场合常拿来玩玩,游戏的算法似乎并不难,想想我也能做出来。
今早闲的蛋疼,就写了个数独玩玩。
记录如下:数独规则不知道的可以参考这⾥:。
游戏关键的算法就在于⽣成⼀个符合数独游戏规则的初始矩阵,⾸先想到的⾃然是号称万能解题法的“搜索+剪枝”了。
1.产⽣符合数独规则的初始矩阵第⼀⾏是随机⽣成的1~9的排列,第2到9⾏就要通过搜索来产⽣了。
对于第2到9⾏的每⼀个空格,要从1到9逐个尝试放⼊,看同⼀列、同⼀⾏、同⼀个3×3的⼩⽅阵中是否出现过相同的数字,若没有就尝试放⼊,然后递归地搜索下⼀个位置的数字,若1到9都不⾏就返回上⼀个位置尝试下⼀个数字。
直到找到⼀组解就返回。
先上C++代码:#include<iostream>#include<algorithm>#include <ctime>using namespace std;int Initial_State [ 10 ] [ 10 ] ;bool get_Initial_State( int i , int j ) //搜索第( i , j )位置处可以存储的数字,找到解则返回true,否则返回false{if( i > 9 || j > 9 )return true;for( int k = 1 ; k <= 9 ; ++k ){bool can = true; // can 变量⽤于记录数字k能否放在 ( i , j ) 处for( int m = 1 ; m < i ; ++m )if( Initial_State[m][j] == k ) // 检查同⼀列是否出现过数字k{can = false ;break ;}if ( can )for( int n = 1 ; n < j ; ++n )if( Initial_State[i][n] == k ) // 检查同⼀⾏是否出现过数字k{can = false ;break;}if( can ){int up1 = ( i/3 ) * 3 + 3 ; // (i,j)⽅格所在的3×3⼩⽅格i坐标的上限int up2 = ( j/3 ) *3 + 3; // (i,j)⽅格所在的3×3⼩⽅格在j坐标的上限if( i % 3 == 0 ) //这是针对特殊情况的处理up1 = i ;if( j % 3 == 0 )up2 = j ;for( int p = up1-2 ; p <= up1 ; ++p ) /* 检查在3×3的⼩⽅格中是否出现了同⼀个数字 */{if( can == false ) /* 跳出外层循环 */break ;for( int q = up2-2 ; q <= up2 ; ++q )if( Initial_State[p][q] == k ){can = false ;break ;}}}if( can ){Initial_State[i][j] = k ;if( j<9 ){if( get_Initial_State( i , j +1 ) ) /* 到同⼀⾏的下⼀位置开始搜索 */return true ;}else{if( i < 9 ){if( get_Initial_State( i + 1 , 1 ) ) /* 到下⼀⾏的第⼀个空格开始搜索 */return true ;}elsereturn true ; /* i >= 9 && j >= 9 , 搜索结束 */}Initial_State[i][j] = 0 ; /* 关键这⼀步:找不到解就要回复原状,否则会对下⾯的搜索造成影响 */}}return false ; /* 1到9都尝试过都不⾏,则返回递归的上⼀步 */}void start(){srand ( unsigned ( time (NULL) ) ); /* 产⽣random_shuffle的随机数种⼦ */for( int i = 1 ; i <= 9 ; ++i )for( int j = 1 ; j <= 9 ; ++j )Initial_State[i][j] = 0 ;for( int i = 1 ; i <= 9 ; ++i )Initial_State[1][i] = i ;random_shuffle( &( Initial_State[1][1]) , &( Initial_State[1][10]) ) ; /* 第⼀⾏随机排列产⽣ */get_Initial_State( 2 , 1 ) ; /* 从第⼆⾏开始搜索 */}int main(){start( ) ;for( int i = 1 ; i <= 9 ; ++ i ){for( int j = 1 ; j <= 9 ; ++j )cout<< Initial_State [i][j] <<" " ;cout<<endl;}getchar() ;return0 ;} 上⾯的算法在找到第⼀个解后就返回了,这样当第⼀⾏数字确定后,则只能得到⼀个矩阵了。
C语言数独游戏程序
C语⾔数独游戏程序/*** 数独程序*/public class ShuDu {/**存储数字的数组*/static int[][] n = new int[9][9];/**⽣成随机数字的源数组,随机数字从该数组中产⽣*/static int[] num = {1,2,3,4,5,6,7,8,9};public static void main(String[] args) {//⽣成数字for(int i = 0;i < 9;i++){//尝试填充的数字次数int time = 0;//填充数字for(int j = 0;j < 9;j++){//产⽣数字n[i][j] = generateNum(time);//如果返回值为0,则代表卡住,退回处理//退回处理的原则是:如果不是第⼀列,则先倒退到前⼀列,否则倒退到前⼀⾏的最后⼀列if(n[i][j] == 0){//不是第⼀列,则倒退⼀列if(j > 0){j-=2;continue;}else{//是第⼀列,则倒退到上⼀⾏的最后⼀列i--;j = 8;continue;}}//填充成功if(isCorret(i,j)){//初始化time,为下⼀次填充做准备time = 0;}else{ //继续填充//次数增加1time++;//继续填充当前格j--;}}}//输出结果for(int i = 0;i < 9;i++){for(int j = 0;j < 9;j++){System.out.print(n[i][j] + " ");}System.out.println();}}/*** 是否满⾜⾏、列和3X3区域不重复的要求* @param row ⾏号* @param col 列号* @return true代表符合要求*/public static boolean isCorret(int row,int col){return (checkRow(row) & checkLine(col) & checkNine(row,col));/*** 检查⾏是否符合要求* @param row 检查的⾏号* @return true代表符合要求*/public static boolean checkRow(int row){for(int j = 0;j < 8;j++){if(n[row][j] == 0){continue;}for(int k =j + 1;k< 9;k++){if(n[row][j] == n[row][k]){return false;}}}return true;}/*** 检查列是否符合要求* @param col 检查的列号* @return true代表符合要求*/public static boolean checkLine(int col){for(int j = 0;j < 8;j++){if(n[j][col] == 0){continue;}for(int k =j + 1;k< 9;k++){if(n[j][col] == n[k][col]){return false;}}}return true;}/*** 检查3X3区域是否符合要求* @param row 检查的⾏号* @param col 检查的列号* @return true代表符合要求*/public static boolean checkNine(int row,int col){ //获得左上⾓的坐标int j = row / 3 * 3;int k = col /3 * 3;//循环⽐较for(int i = 0;i < 8;i++){if(n[j + i/3][k + i % 3] == 0){continue;}for(int m = i+ 1;m < 9;m++){if(n[j + i/3][k + i % 3] == n[j + m/3][k + m % 3]){ return false;}}return true;}/*** 产⽣1-9之间的随机数字* 规则:⽣成的随机数字放置在数组8-time下标的位置,随着time的增加,已经尝试过的数字将不会在取到* 说明:即第⼀次次是从所有数字中随机,第⼆次时从前⼋个数字中随机,依次类推,* 这样既保证随机,也不会再重复取已经不符合要求的数字,提⾼程序的效率* 这个规则是本算法的核⼼* @param time 填充的次数,0代表第⼀次填充* @return*/public static int generateNum(int time){//第⼀次尝试时,初始化随机数字源数组if(time == 0){for(int i = 0;i < 9;i++){num[i] = i + 1;}}//第10次填充,表明该位置已经卡住,则返回0,由主程序处理退回if(time == 9){return 0;}//不是第⼀次填充//⽣成随机数字,该数字是数组的下标,取数组num中该下标对应的数字为随机数字int ranNum = (int)(Math.random() * (9 - time));//把数字放置在数组倒数第time个位置,int temp = num[8 - time];num[8 - time] = num[ranNum];num[ranNum] = temp;//返回数字return num[8 - time];}}。
数独游戏小程序(微信小程序使用JavaScript开发)
数独游戏小程序(微信小程序使用JavaScript开发)数独是一种古老的逻辑数学游戏,其中以9x9方格的宫格为基础,玩家需要填入数字1到9,使得每行、每列和每个宫格内的数字都不重复。
为了满足广大数独爱好者的需求,我们决定开发一款数独游戏小程序,通过微信小程序平台供用户使用。
本文将介绍数独游戏小程序的设计与开发过程。
一、小程序介绍数独游戏小程序旨在提供一个便捷、简洁而又有趣的数独游戏体验。
用户可以通过小程序解决数独难题,挑战不同难度的关卡,并享受解谜的乐趣。
此外,小程序还提供计时功能,用户可以用来衡量自己解决数独难题所需的时间,并与他人进行比较。
二、小程序界面设计数独游戏小程序的界面设计风格简洁明了,注重用户体验。
主界面分为数独棋盘和操作栏两部分。
数独棋盘占据大部分屏幕空间,以9x9的方格形式展现,以便用户填写数字。
操作栏位于棋盘上方,包括难度选择、重新开始、计时功能和帮助按钮。
三、数独算法实现为了保证数独难题的合法性且能保证解题时有唯一解,我们使用了基于回溯法的数独算法。
算法的基本思想是从左上角开始,逐个尝试填入数字,并递归地向下一格尝试,直到填满整个数独棋盘或发现填入数字不合法时回溯到上一格重新选择。
通过这种方式,我们可以找到数独问题的唯一解。
四、小程序功能实现1. 游戏难度选择:用户可以在操作栏中选择不同难度的关卡,包括简单、中等和困难。
每个难度级别都有一定数量的预设数字供用户参考。
2. 数字填写与删除:用户可以通过点击棋盘上的方格并在键盘上输入数字来填写数字。
若填写错误,用户可以再次点击方格并删除错误数字。
3. 重新开始:用户可以通过点击重新开始按钮重置当前关卡,清空棋盘并重新开始解题。
4. 计时功能:小程序提供计时功能,开始游戏后会启动计时器,记录用户完成游戏所花费的时间,并在游戏结束时停止计时。
5. 帮助功能:用户可以通过点击帮助按钮获取游戏规则和玩法说明。
五、小程序发布与优化1. 发布:开发完成后,我们会将数独游戏小程序发布到微信小程序平台,供用户下载和使用。
用Python实现一个简单的数独游戏
用Python实现一个简单的数独游戏在这篇文章中,我将介绍如何使用Python编写一个简单的数独游戏。
数独是一种数字逻辑游戏,通过使用逻辑和推理,玩家需要填写一个9x9的网格,使得每一列、每一行和每个3x3的子网格中的数字都只出现一次。
为了实现这个数独游戏,我们将使用Python的基本数据结构和一些算法。
让我们开始编写代码吧!首先,我们需要创建一个函数来打印数独网格。
代码如下:```pythondef print_grid(grid):for i in range(9):if i % 3 == 0 and i != 0:print("- - - - - - - - - - - -")for j in range(9):if j % 3 == 0 and j != 0:print(" | ", end="")if j == 8:print(grid[i][j])else:print(str(grid[i][j]) + " ", end="")```接下来,我们需要创建一个函数来检查某个数字是否可以放置在给定的位置上。
这个函数将检查数字是否已经在同一行、同一列和同一个3x3子网格中出现过。
代码如下:```pythondef is_valid(grid, row, col, num):# 检查行for i in range(9):if grid[row][i] == num:return False# 检查列for i in range(9):if grid[i][col] == num:return False# 检查3x3子网格start_row = row - row % 3start_col = col - col % 3for i in range(3):for j in range(3):if grid[i + start_row][j + start_col] == num:return Falsereturn True```接下来,我们需要创建一个递归函数来解决数独问题。
数字数独游戏完整源代码程序
outtextxy(120, 99, _T("求解中......"));
if (SecondCheck() == true) // 第二次检查,防止不必要的死循环
{
trace(0, 0); // 溯回法判断
bool Point[3][3];
int main()
{
initgraph(WIDTH, HEIGHT);
drawframe(); // 绘制表格框架
while (true)
{
while (true)
{
int m_x, m_y, number;
void Output(); // 输出答案
int MouseNumber = 0;
int sum = 0; // 数独多解的记录
int trace(int x, int y); // 算法的核心回溯法
int check(int x, int y); // 每次判断
outtextxy(120, 99, _T("该数独无解!"));
continue;
}
if (sum == 1)
{
setbkmode(OPAQUE);
settextcolor(0xf4b1a4);
settextstyle(20, 0, _T("楷体"));
break;
}
save(number, m_x, m_y);
if (FirstCheck() == false)
{
settextstyle(20, 0, _T("楷体"));
Java实现数独小游戏
Java实现数独⼩游戏本⽂实例为⼤家分享了Java实现数独⼩游戏的具体代码,供⼤家参考,具体内容如下题⽬要求:制作⼀个数独游戏。
数据游戏拼图由⼀个3*3的九宫格组成,每个格式⼜分成⼀个⼩九宫格,共九九⼋⼗⼀个⼩格⼦。
游戏规则:游戏开始前会有⼀些格式了写好了1-9的数,在剩下的格式⾥填写1-9的数,直到把所有格式填满,要求任何⼀⾏或⼀列或者任⼀个⼩九宫中没有相同的数字。
拼图⽰例如下:任务要求:(1)可以根据在九宫格中初始给出的数字个数设定游戏难度,如初始给出30个数设定为难、35个数设定为中等难度、40个数设定为容易。
(2)对于初始给出的数据要能验证题⽬的合法性(即验证给出数据本⾝是否符合游戏规则,⾏、列及⼩九宫中不能出现重复数字1-9),对玩游戏中填⼊的数字在提交后要能验证其正确性(任何⼀⾏或⼀列或者任⼀个⼩九宫中没有相同的数字)。
(3)程序能保存玩家的信息、游戏记录以及成绩(最⾼分),并能够在游戏结束时查看玩家排名。
⼯作流程如下:该数独游戏需要连接数据库,登录⽤户和保存数据记录,连接数据库创建表等暂不作显⽰。
主要数独游戏部分(除去登录页⾯,注册页⾯,查看排名页⾯不做显⽰)分为Main(⽣成数独,将⽣成100个数独保存在⽂件中,也可以不保存,每次⽣成数独都为⼀次新的数独不做记录,效率较差)和Play(数独显⽰页⾯,同时包括填写数独和判断数独是否正确)两类。
1、Main类package shudu;import java.awt.Color;import java.awt.Dimension;import java.awt.Font;import java.awt.GridLayout;import java.awt.SystemColor;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.util.Random;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JPanel;public class Main {private int[][] Arry; //得到⼀个9*9的数独private int[][] shudu; //挖空arry数组中的数字private int[][] answer; //存储数独答案private int[][] game; //最终数独private int grade;private int[] row; //每⼀⾏的个数private int[] col; //每⼀列的个数private int[] places; //每⼀个九宫格的个数private boolean flag=false;//读取⽂件名private String filename=new String("C:\\Users\\liaolilan\\Desktop\\shudu.txt");public static void main(String[] args){Main mainer=new Main();// mainer.UI();}public void UI(){for(int k=0;k<100;k++){this.Arry=new int[9][9];this.shudu=new int[9][9];this.game=new int[9][9];this.answer=new int[9][9];this.row=new int[9];this.col=new int[9];this.places=new int[9];this.grade=grade;flag=false;//初始化数组for(int i=0;i<9;i++)row[i]=col[i]=places[i]=9;//调试// this.answer=new int[9][9]; //最终答案存储再arry中rand();//先产⽣15个随机数加上随机位置,⼀定需要随机⽣成,不然就会⼀直都是⼀个数组 for(int i=0;i<9;i++){for(int j=0;j<9;j++)System.out.print(Arry[i][j]);System.out.println();}dfs(Arry,0);//获得⼀个数组答案d// diger(grade);//挖空数组//将100个数独写⼊⽂件中try{String data = "";File file =new File(filename);//if file doesnt exists, then create itif(!file.exists()){file.createNewFile();}//true = append fileFileWriter fileWritter = new FileWriter(filename,true);BufferedWriter bufferWritter = new BufferedWriter(fileWritter);bufferWritter.write(k+1+"\r\n");for(int i=0;i<9;i++){data="";for(int j=0;j<9;j++){data=data+answer[i][j]+"";}System.out.println(data);}bufferWritter.close();System.out.println("Done");}catch(IOException e){e.printStackTrace();}}}//随机给数public void rand(){int t=0;//t=14不随机性太⾼,容易产⽣没有解的数独,经过参考资料发现,当t=6的时候,⼏乎100%有解 while(t<6){int x=new Random().nextInt(9);int y=new Random().nextInt(9);int i=new Random().nextInt(9)+1;if(Arry[x][y]==0){if(istrue(Arry,x,y,i)){ //判断数是否能填Arry[x][y]=i;t++;}}}}//判断在arry[x][y]上是否能放numpublic boolean istrue(int arry[][],int x,int y,int num){//横竖是否有numfor(int i=0;i<9;i++){if(arry[x][i]==num||arry[i][y]==num)return false;}for(int i=(x/3)*3;i<(x/3+1)*3;i++)for(int j=(y/3)*3;j<(y/3+1)*3;j++)if(arry[i][j]==num)return false;return true;}//根据前⾯放的数获得⼀个正确的答案,dfs获取public void dfs(int arry[][],int n){if(n<81){if(flag==true) return;int x=n/9;//x第N个数的横坐标int y=n%9;//y第N个数的纵坐标if(arry[x][y]==0){//若第N个数为0,没有被填过,则判断0~9是否能被填for(int i=1;i<10;i++){if(istrue(arry,x,y,i)){//第N个数可以填i,填⼊然后dfsarry[x][y]=i;dfs(arry,n+1);//dfs回溯arry[x][y]=0;}}}else{dfs(arry,n+1);}}else{//获得第⼀个结果,flag置trueflag=true;//将获得的数组放⼊shudu中然后再挖空//if(all==false){for(int i=0;i<9;i++)for(int j=0;j<9;j++)shudu[i][j]=answer[i][j]=arry[i][j];System.out.println("###################");for(int i=0;i<9;i++){for(int j=0;j<9;j++)System.out.print(arry[i][j]);System.out.println();}}}//为了避免数独⽆解,保证数独有唯⼀解//挖空数组,分难易程度,,grade为挖空个数//是否有⼀个⾏、列、九宫格已经为空boolean emptyrow=false,emptycol=false,emptyplaces=false;public void diger(int grade,int level){this.shudu=new int[9][9];this.game=new int[9][9];this.answer=new int[9][9];this.row=new int[9];this.col=new int[9];this.places=new int[9];this.grade=grade;File file=new File(filename);BufferedReader reader = null;try {System.out.println("以⾏为单位读取⽂件内容,⼀次读⼀整⾏:");reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8")); // reader = new BufferedReader(new FileReader(file));String tempString = null;int line = 1,k=0;boolean flag=false;// ⼀次读⼊⼀⾏,直到读⼊null为⽂件结束while ((tempString = reader.readLine()) != null&&k<9) {// 显⽰⾏号System.out.println(" line " + line + ": " + tempString);if(tempString.equals(level+"")){flag=true;continue;}if(flag==true){for(int i=0;i<9;i++)answer[k][i]=tempString.charAt(i)-48;k++;}line++;}reader.close();} catch (IOException e) {e.printStackTrace();} finally {if (reader != null) {try {reader.close();} catch (IOException e1) {}}}for(int i=0;i<9;i++)for(int j=0;j<9;j++)shudu[i][j]=answer[i][j];int t=grade;while(t>0){//随机抽到x,yint x=new Random().nextInt(9);int y=new Random().nextInt(9);//若x,y没有被挖空则挖空x,yif(shudu[x][y]!=0){row[x]--;col[y]--;places[(y/3)*3+x/3]--;if((row[x]==0&&emptyrow)||(col[y]==0&&emptycol)||(places[(y/3)*3+x/3]==0&&emptyplaces)) {System.out.println(x+" "+y+" 不可以");continue;}else{shudu[x][y]=0;t=t-1;}if(row[x]==0)emptyrow=true;if(col[y]==0)emptycol=true;if(places[(y/3)*3+x/3]==0)emptyplaces=true;}}//获得最终游戏数独for(int i=0;i<9;i++)for(int j=0;j<9;j++)game[i][j]=shudu[i][j];}//获得最终游戏数独public int[][] getArr(){for(int i=0;i<9;i++){for(int j=0;j<9;j++){System.out.print(game[i][j]);if(game[i][j]==0)t++;}System.out.println();}System.out.println("###################");System.out.println("挖空数为:"+t);return this.game;}//获得答案数独public int[][] getAnswer(){for(int i=0;i<9;i++){for(int j=0;j<9;j++)System.out.print(answer[i][j]);System.out.println();}System.out.println("###################");return this.answer;}}2、Play类package shudu;import java.awt.BorderLayout;import java.awt.Color;import java.awt.Dimension;import java.awt.Font;import java.awt.GridLayout;import java.awt.SystemColor;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.awt.event.FocusEvent;import java.awt.event.FocusListener;import java.awt.event.WindowAdapter;import java.awt.event.WindowEvent;import java.io.BufferedReader;import java.io.BufferedWriter;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.FileReader;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStreamWriter;import java.util.ArrayList;import java.util.List;import java.util.Timer;import java.util.TimerTask;import javax.swing.BorderFactory;import javax.swing.JButton;import javax.swing.JFrame;import javax.swing.JLabel;import javax.swing.JOptionPane;import javax.swing.JPanel;import javax.swing.JTextField;import javax.swing.border.Border;import erDao;import shudu.Main;import er;//游戏界⾯的设计public class Play {//设置全局变量,九宫格JTextField[][] numberFields=new JTextField[9][9]; //游戏数独数组int[][] gamearr=new int[9][9];//游戏答案数组int[][] answerarr=new int[9][9];Color green=new Color(93, 200, 138);Color lightGray = new Color(217, 217, 217);Color blue = new Color(102, 183, 255);//挖空数!private int grade=40;//过去的private int usedgrade=0;//计时器Timer time;JLabel timeLabel;TimerTask task;//⽤标签表⽰游戏进展JLabel labelsc=new JLabel();//创建字体,之后所有的字体为该字体Font f=new Font("⽅正仿宋简体", Font.BOLD, 25);//选择九宫格中的格⼦的坐标int sx=10;int sy=10;//是否已经看过答案private boolean isanswer;//⽤户名JLabel username=new JLabel();JLabel usergrade=new JLabel();private int gamegrade=0;//游戏分数//登录login loger=new login();User user=er;//读取⽂件名private String filename=new String("C:\\Users\\liaolilan\\Desktop\\SuDoKu.txt");//以前游戏数组private int[][] usedgame=new int[9][9];//以前的游戏时间private int usedtim=1;//判断是不是新⽤户//是否为新⽤户private boolean isnew=true;//保存⽤户名存在在第⼏⾏private int act=-1;//关卡JLabel levels=new JLabel();int levs=1;//窗⼝private JFrame jf ;public Play(){//制作游戏界⾯System.out.println(user.getUsername()+" "+user.getUserpwd()+" "+user.getUsergrade());jf = new JFrame();jf.setTitle("数独游戏");jf.setBounds(400, 0, 1100, 1000);jf.setResizable(false);//不允许窗⼝最⼤化jf.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//不执⾏任何操作;要求程序在已注册的 WindowListener 对象的 windowClosing ⽅法中处理该操作 jf.setLocationRelativeTo(null);//居中,不⽤定位窗⼝⼤⼩jf.setVisible(true);//打开时,判断是否上⼀局游戏jf.addWindowListener(new WindowAdapter() {@Overridepublic void windowOpened(WindowEvent arg0) {//如果是新⽤户,保存数组//保存记录,读取⽂件,读出⽂件,在开始游戏的时候读出File file=new File(filename);BufferedReader reader = null;try {System.out.println("以⾏为单位读取⽂件内容,⼀次读⼀整⾏:");reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8"));// reader = new BufferedReader(new FileReader(file));String tempString = null;int line = 1;// ⼀次读⼊⼀⾏,直到读⼊null为⽂件结束while ((tempString = reader.readLine()) != null) {// 显⽰⾏号if(tempString.equals(user.getUsername())){act=line;isnew=false;}else if(isnew==false){//关卡levs=Integer.valueOf(tempString);System.out.println(levs);break;}line++;}reader.close();} catch (IOException e) {e.printStackTrace();} finally {if (reader != null) {try {reader.close();} catch (IOException e1) {}}}newGame(grade,levs);}});//关闭时,保存关卡记录jf.addWindowListener(new WindowAdapter() {@Overridepublic void windowClosing(WindowEvent arg0) {BufferedReader reader = null;//保存记录,读取⽂件,读出⽂件,在开始游戏的时候读出File file=new File(filename);int num=0;//第⼏⾏boolean flag=false;System.out.println("act:"+act);List list = new ArrayList();try{reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8"));// reader = new BufferedReader(new FileReader(file));String str = null;// ⼀次读⼊⼀⾏,直到读⼊null为⽂件结束while ((str = reader.readLine())!= null) {++num;System.out.println(num+"⾏:"+str);if(isnew==false&&(num==act||num==act+1)){System.out.println(str);continue;}list.add(str);}}catch(IOException e){e.printStackTrace();}System.out.println("list size:"+list.size());System.out.println("删除成功");//重新写⼊try{FileWriter fileWritter = new FileWriter(filename);BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename), "utf-8")); //BufferedWriter bw= new BufferedWriter(fileWritter);for( int i=0;i<list.size();i++ ){System.out.println("list["+i+"]"+list.get(i));bw.write(list.get(i).toString());bw.newLine();}String data = user.getUsername();//⽤户名,保存⽤户所通过的关卡?bw.write(data+"\r\n");//关卡bw.write(levs+"\r\n");System.out.println("Done");bw.flush();bw.close();}catch(IOException e){e.printStackTrace();}System.exit(0);}});JPanel bodyPanel=new JPanel();bodyPanel.setBackground(lightGray);jf.add(bodyPanel,BorderLayout.CENTER);bodyPanel.setLayout(new GridLayout(9,9,0,0));//右边布局,难易程度,计时,重新开始,换⼀题等选择按钮 JPanel rightPanel=new JPanel();//宽度⼤⼩设置rightPanel.setPreferredSize(new Dimension(200, 789));jf.add(rightPanel, BorderLayout.EAST);//显⽰⽤户名和当前分数username.setText("⽤户名: "+user.getUsername());username.setFont(f);rightPanel.add(username);usergrade.setText("总分数: "+user.getUsergrade());usergrade.setFont(f);rightPanel.add(usergrade);//显⽰当前关卡levels.setText("关卡: "+levs);levels.setFont(f);rightPanel.add(levels);//难度选择,默认为容易JLabel label1=new JLabel("请选择模式");label1.setFont(f);rightPanel.add(label1);//容易,中等,难String[] btnstr={"容易","中等","难"};for(int i=0;i<3;i++){JButton btn=new JButton(btnstr[i]);btn.setFont(f);btn.setBackground(lightGray);btn.setPreferredSize(new Dimension(120,60));//为难度按钮加上监听器btn.addActionListener(new funactionListener());rightPanel.add(btn);//加监听器}//功能按钮JLabel label2=new JLabel("功能按钮 ");label2.setFont(f);rightPanel.add(label2);//换⼀题JButton changebtn=new JButton("换⼀题");changebtn.setFont(f);changebtn.setPreferredSize(new Dimension(120,60));changebtn.setBackground(lightGray);changebtn.setForeground(Color.black);changebtn.addActionListener(new funactionListener());rightPanel.add(changebtn);//重做JButton newbtn=new JButton("重玩");newbtn.setFont(f);newbtn.setPreferredSize(new Dimension(120,60));newbtn.setBackground(lightGray);newbtn.setForeground(Color.BLACK);newbtn.addActionListener(new funactionListener());rightPanel.add(newbtn);//答案JButton answerbtn=new JButton("答案");answerbtn.setFont(f);answerbtn.setPreferredSize(new Dimension(120,60));answerbtn.setBackground(Color.red);answerbtn.setForeground(Color.WHITE);answerbtn.addActionListener(new funactionListener());rightPanel.add(answerbtn);//计时JLabel label3=new JLabel(" 计时 ");label3.setFont(f);rightPanel.add(label3);timeLabel=new JLabel("00:00");timeLabel.setFont(f);//放⼀个游戏进展rightPanel.add(labelsc);labelsc.setVisible(false);//下⾯布局JPanel lastPanel=new JPanel();jf.add(lastPanel,BorderLayout.SOUTH);lastPanel.setPreferredSize(new Dimension(1333, 100));lastPanel.setLayout(new GridLayout(0, 10, 0, 0));//放选择按钮JButton[] setNum=new JButton[10];for(int i=0;i<10;i++){if(i==9){setNum[i]=new JButton("清除");//加清除的监听器}else{setNum[i]=new JButton(i+1+"");//加按钮的监听器}setNum[i].setFont(f);setNum[i].setForeground(Color.WHITE);setNum[i].setBackground(green);setNum[i].setPreferredSize(new Dimension(90,70));setNum[i].setFocusPainted(false);//加下⽅按钮监听器setNum[i].addActionListener(new buttonaction());lastPanel.add(setNum[i]);}//对中间布局进⾏控制//组件边框Border centernBorder = BorderFactory.createMatteBorder(1, 1, 1, 1, Color.GRAY);Border rightAndBottomBorder = BorderFactory.createMatteBorder(1, 1, 4, 4, Color.GRAY); Border bottomBorder = BorderFactory.createMatteBorder(1, 1, 4, 1, Color.GRAY);Border rightBorder = BorderFactory.createMatteBorder(1, 1, 1, 4, Color.GRAY);//循环设置组件JTextField,九宫格//numberFields = new JTextField[9][9];for (int i = 0; i < 9; i++) {for (int j = 0; j < 9; j++) {//System.out.println(i+j+"");numberFields[i][j] = new JTextField();//不可编辑numberFields[i][j].setEditable(false);numberFields[i][j].setFont(new Font("微软雅⿊", Font.BOLD, 35));numberFields[i][j].setHorizontalAlignment(JTextField.CENTER);numberFields[i][j].setBackground(Color.WHITE);numberFields[i][j].setForeground(Color.BLACK);//加边框!if (i == 2 && j == 2 || i == 2 && j == 5 || i == 5 && j == 2 || i == 5 && j == 5) {numberFields[i][j].setBorder(rightAndBottomBorder);} else if (j == 2 || j == 5) {numberFields[i][j].setBorder(rightBorder);} else if (i == 2 || i == 5) {numberFields[i][j].setBorder(bottomBorder);} else {numberFields[i][j].setBorder(centernBorder);}//对每个格⼦加上名称来标识numberFields[i][j].setName(Integer.toString(i) + Integer.toString(j));//对每个格⼦加上监听器numberFields[i][j].addFocusListener(new textfocusaction());;bodyPanel.add(numberFields[i][j]);}}}//开始新游戏public void newGame(int grade,int level){isanswer=false;//显⽰总分数usergrade.setText("总分数: "+user.getUsergrade());//显⽰当前关卡levels.setText("关卡:"+levs+"");Main maker=new Main();maker.diger(grade, level);gamearr=maker.getArr();answerarr=maker.getAnswer();for(int i=0;i<9;i++){for(int j=0;j<9;j++)System.out.println();}System.out.println("###################");//先清空九宫格for(int i=0;i<9;i++)for(int j=0;j<9;j++){if(gamearr[i][j]!=0){numberFields[i][j].setText(gamearr[i][j]+"");numberFields[i][j].setBackground(lightGray);numberFields[i][j].setForeground(Color.BLACK);//加监听器!}else{numberFields[i][j].setText("");numberFields[i][j].setBackground(Color.WHITE);numberFields[i][j].setForeground(Color.BLACK);}}//开始计时startTime();}//游戏开始计时public void startTime(){//游戏开始计时!time = new Timer();task = new TimerTask() {int count = usedtim;@Overridepublic void run() {timeLabel.setText(gettime(count));count++;}};time.schedule(task, 1000L, 1000L); // 开始游戏时⾃动计时 }//时间重新计时public void restartTime(){//删除time记录,要使⽤过才能删除time.cancel();time=new Timer();timeLabel.setText("00:00");task = new TimerTask() {int count = 1;@Overridepublic void run() {timeLabel.setText(gettime(count));count++;}};time.schedule(task, 1000L, 1000L);}//将时间转换成分:秒public String gettime(int count){String second = null;String minute = null;if (count / 60 < 10) {minute = "0" + (count / 60);} else {minute = "" + (count / 60);}if (count % 60 < 10) {second = ":0" + count % 60;} else {second = ":" + count % 60;}return minute + second;}//重玩该关public void again(){//重新设置for(int i=0;i<9;i++)for(int j=0;j<9;j++){if(gamearr[i][j]!=0){numberFields[i][j].setBackground(lightGray);//加监听器!}}}//输出答案!!public void answer(){//gamearr中为0的地⽅放答案!!for(int i=0;i<9;i++)for(int j=0;j<9;j++){if(gamearr[i][j]==0){numberFields[i][j].setText(answerarr[i][j]+"");numberFields[i][j].setForeground(Color.RED);}}}//清空九宫格重新对获取新数独public void resetfields(){for(int i=0;i<9;i++)for(int j=0;j<9;j++){numberFields[i][j].setText("");numberFields[i][j].setBackground(Color.WHITE);}}//下⾯为各事件的处理//右边处理数独按钮监听器(难度类别监听,换⼀题,重玩,答案) class funactionListener implements ActionListener{//难度监听器String btnstr;@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubbtnstr=e.getActionCommand();if(btnstr.equals("容易")){grade=40;//若选择按钮难度为容易,重新开始游戏resetfields();newGame(grade,levs);restartTime();}else if(btnstr.equals("中等")){grade=45;//若选择按钮难度为中等,重新开始游戏resetfields();newGame(grade,levs);restartTime();}else if(btnstr.equals("难")){//同上grade=50;resetfields();newGame(grade,levs);restartTime();}else if(btnstr.equals("换⼀题")){resetfields();newGame(grade,levs);restartTime();}//重新开始计分else if(btnstr.equals("重玩")){resetfields();again();restartTime();}//将分归零else if(btnstr.equals("答案")){answer();time.cancel();isanswer=true;}}}//九宫格数组的监听器class textfocusaction implements FocusListener{//该各⾃获得焦点@Overridepublic void focusGained(FocusEvent e) {// TODO Auto-generated method stubJTextField jt=(JTextField) e.getSource();//点击之前还原颜⾊replace();sameNumber(jt);}//该格⼦失去焦点,将颜⾊还原@Overridepublic void focusLost(FocusEvent e) {// TODO Auto-generated method stublabelsc.setVisible(false);replace();}}//处理获得焦点的⽂本格⼦public void sameNumber(JTextField jt){String name=jt.getName();System.out.println(name);int x=Integer.parseInt(name.substring(0,1));int y=Integer.parseInt(name.substring(1));String number=jt.getText();//System.out.println(x+" "+y);if(gamearr[x][y]!=0){sx=10;sy=10;}else{sx=x;sy=y;System.out.println(sx+" "+sy);//格⼦为空if(number.equals("")){//使该⾏该列和该⼩九宫格的颜⾊置blue,提醒⽤户for(int i=0;i<9;i++){numberFields[i][sy].setBackground(blue);numberFields[sx][i].setBackground(blue);}for(int i=(sx/3)*3;i<((sx/3)+1)*3;i++)for(int j=(sy/3)*3;j<((sy/3)+1)*3;j++)numberFields[i][j].setBackground(blue);numberFields[sx][sy].setBackground(green);}//格⼦不为空,使与格⼦相同的数显⽰粉⾊else{for(int i=0;i<9;i++)for(int j=0;j<9;j++)if(numberFields[i][j].getText().equals(number))numberFields[i][j].setBackground(Color.pink);}}}//使格⼦颜⾊还原public void replace(){if(sx<10&&sy<10){for(int i=0;i<9;i++){if(gamearr[i][sy]!=0)numberFields[i][sy].setBackground(lightGray);elsenumberFields[i][sy].setBackground(Color.WHITE);if(gamearr[sx][i]!=0)numberFields[sx][i].setBackground(lightGray);elsenumberFields[sx][i].setBackground(Color.WHITE);}for(int i=(sx/3)*3;i<((sx/3)+1)*3;i++)for(int j=(sy/3)*3;j<((sy/3)+1)*3;j++)if(gamearr[i][j]!=0)numberFields[i][j].setBackground(lightGray);elsenumberFields[i][j].setBackground(Color.WHITE);for(int i=0;i<9;i++)for(int j=0;j<9;j++)if(numberFields[i][j].getText().equals(numberFields[sx][sy].getText())&&!(i==sx&&j==sy)){ if(gamearr[i][j]!=0)numberFields[i][j].setBackground(lightGray);elsenumberFields[i][j].setBackground(Color.WHITE);}}}//为下⽅的按钮增加监听器class buttonaction implements ActionListener{@Overridepublic void actionPerformed(ActionEvent e) {// TODO Auto-generated method stubString btnstr;btnstr=e.getActionCommand();replace();//如果按钮为清除,则将格⼦置空if(btnstr.equals("清除")&&(sx<10&&sy<10)){numberFields[sx][sy].setText("");numberFields[sx][sy].setBackground(Color.white);}//若为其他的,在格⼦中放⼊值else if(sx<10&&sy<10){numberFields[sx][sy].setText(btnstr);numberFields[sx][sy].setForeground(Color.blue);numberFields[sx][sy].setBackground(Color.white);//判断值放的是否正确,若不正确,则将该值和相冲突的格⼦背景颜⾊置为红⾊ jugewrong(btnstr);}}}//判断值放的是否正确,若不正确,则将该值和相冲突的格⼦背景颜⾊置为红⾊ public void jugewrong(String number){boolean flag=false; //该值是否正确//⾏列是否有相同的for(int i=0;i<9;i++){if(i!=sy&&(numberFields[sx][i].getText().equals(number))){numberFields[sx][i].setBackground(Color.red);flag=true;}if(i!=sx&&(numberFields[i][sy].getText().equals(number))){numberFields[i][sy].setBackground(Color.red);flag=true;}}//⼩九宫格内是否有已经存在过这个值for(int i=(sx/3)*3;i<((sx/3)+1)*3;i++)for(int j=(sy/3)*3;j<((sy/3)+1)*3;j++){if(!(i==sx&&j==sy)&&(numberFields[i][j].getText().equals(number))){numberFields[i][j].setBackground(Color.red);flag=true;}}if(flag){labelsc.setText("已有该数字,请检查!");labelsc.setFont(new Font("⽅正仿宋简体", Font.BOLD, 21));labelsc.setForeground(Color.RED);labelsc.setVisible(true);}else{//挑战成功后if(isanswer==false&&gamesc()){//关卡加⼀levs++;time.cancel();String runtime=new String();runtime=timeLabel.getText();System.out.println(runtime);//转换成秒int tim=((runtime.charAt(0)-48)*10+(runtime.charAt(1))-48)*60+(runtime.charAt(3)-48)*10+runtime.charAt(4)-48;//计分规则System.out.println(tim);if(grade==40){if(tim<=180)gamegrade=80;else if(tim<=600)gamegrade=70;else if(tim<=1800)gamegrade=60;elsegamegrade=50;}else if(grade==45){if(tim<=180)gamegrade=90;else if(tim<=600)gamegrade=85;else if(tim<=1800)gamegrade=75;elsegamegrade=65;}else{if(tim<=180)gamegrade=100;else if(tim<=600)gamegrade=90;else if(tim<=1800)gamegrade=85;elsegamegrade=80;}user.setUsergrade(user.getUsergrade()+gamegrade);System.out.println(user.getUsergrade());UserDao dao=new UserDao();dao.modifyuser(user);//弹出⼀个成功的对话框!Object[] options = { "查看排名", "继续挑战"};//查看排名是0,继续挑战是1int x = JOptionPane.showOptionDialog(null, "挑战成功!分数为"+gamegrade, "挑战成功!",JOptionPane.DEFAULT_OPTION, RMATION_MESSAGE, null, options, options[0]);System.out.println(x);if(x==0){rank ranker;ranker=new rank();//newGame(grade);}else{newGame(grade,levs);}}}}//判断点完之后数独是否成功!public boolean gamesc(){for(int i=0;i<9;i++)for(int j=0;j<9;j++){System.out.println(numberFields[i][j].getText());System.out.println("点击!");if(numberFields[i][j].getText().equals("")){// System.out.println("111失败!");return false;}for(int k=0;k<9;k++)if((k!=j&&numberFields[i][k].getText().equals(numberFields[i][j].getText()))||(k!=i&&numberFields[k][j].getText().equals(numberFields[i][j].getText()))){ numberFields[i][j].setBackground(Color.RED);numberFields[i][k].setBackground(Color.red);return false;}for(int m=(i/3)*3;m<(i/3+1)*3;m++)for(int n=(j/3)*3;n<(j/3+1)*3;n++)if(!(m==i&&n==j)&&(numberFields[m][n].getText().equals(numberFields[i][j].getText()))){return false;}}System.out.println("成功!");return true;}}最后⽣成数独页⾯的效果如下:以上就是本⽂的全部内容,希望对⼤家的学习有所帮助,也希望⼤家多多⽀持。
数独游戏的C代码实现
数独游戏的C代码实现⼈⼯智能实验时写的代码:1//shudu.cpp 数独游戏2#include<iostream>3 #include<iomanip>4 #include<fstream>5 #include<cstdlib>//c语⾔中为#include<stdlib.h>6usingnamespace std;78//定义数据结构9int shudu[9][9]={0};1011//初始化数据12void init()13 {14int i=0,j=0;15 ifstream fin("input.txt");//打开⽂件16//读⼊数字17for(i=0;i<9;i++)18for(j=0;j<9;j++)19 fin>>shudu[i][j];20 fin.close();21//输出刚刚读⼊的数据22 cout<<"The init structure is:"<<endl;23for(i=0;i<9;i++,cout<<endl)24for(j=0;j<9;j++)25 cout<<shudu[i][j]<<'';26 }2728//检查在(x,y)位置处赋予i值是否满⾜⾏列互不相同的条件29bool checkAssign1(int x,int y,int i)30 {31for(int c=0;c<9;c++) //c是指列32if(c!=y && shudu[x][c]==i)33returnfalse;34for(int r=0;r<9;r++)// r是指⾏35if(r!=x && shudu[r][y]==i)36returnfalse;37returntrue;38 }3940//检查(x,y)位置处是否满⾜其所在⼤⽅格中各数互不相同的条件41bool checkAssign2(int x,int y,int i)42 {43for(int r=(x/3)*3;r<(x/3)*3+3;r++) // (x/3,y/3)是(x,y)所在的⼤⽅格的位置44for(int c=(y/3)*3;c<(y/3*3)+3;c++) // x/3*3和y/3*3分别是(x,y)所在⼤⽅格45//位置的起始位置46 {47if(shudu[r][c]==i)48if(r==x && c==y)49continue;50else51returnfalse;52 }53returntrue;54 }5556//81个点中分别给每⼀个点搜索可⾏解57bool search(int depth)58 {59if(depth>=81)60 {61returntrue;62 }63int x,y;//检查当前位置(x,y)有没被赋值,没有则尝试赋值64//检查是否违法约束条件65 x=depth/9;y=depth%9;66if(shudu[x][y]!=0)//(x,y)已赋值67return search(depth+1);68else69for(int i=1;i<=9;i++)70 {71 shudu[x][y]=i;72if(checkAssign1(x,y,i) && checkAssign2(x,y,i)) 73 {74if(search(depth+1))75returntrue;76 }77 shudu[x][y]=0;78 }79returnfalse;80 }818283int main()84 {85 cout<<" 数独游戏设计 "<<endl;86 cout<<" 刘懿设计 "<<endl;87 cout<<"--------------------------"<<endl;88//define the data structure and input the data89 init();90 cout<<"--------------------------"<<endl;91if(search(0)) //search();92 {//output the answer93 cout<<"The answer is:"<<endl;94for(int i=0;i<9;i++,cout<<endl)95for(int j=0;j<9;j++)96 cout<<shudu[i][j]<<'';97 }98else99 {100 cout<<"haven't found a resolution"<<endl; 101 }102 system("pause"); //让画⾯停留,避免⼀闪⽽过103return0;104 }。
数独游戏代码
数独游戏代码//数独游戏c++class CSudoku{int map[9][9];int blanks;int smod;int solves;int check(int,int,int*);void dfs();public:enum{ANY=0,ALL=1};CSudoku(int);CSudoku::CSudoku(int *data);void SudokuGenerator(int); //随机⽣成数独,n越⼤越难void SudokuGenerator(int *data);//⼈⼯指定数独//virtual ~CSudoku();void display();//显⽰数独int resolve(int mod=ALL);//解数独void analyze();};#include "stdio.h"#include "stdlib.h"#include "time.h"#include "iostream"#include "iomanip"//要⽤到格式控制符using namespace std;CSudoku::CSudoku(int n){int j;j=rand()%3;blanks=n+j;SudokuGenerator(blanks);cout<<endl<<"随机数独: --->(Y轴)[x,y坐标均从0开始]"<<endl;cout<<endl<<"填数请按Enter键,按指⽰操作"<<endl;//cout<<(空格⼦数为"<<blanks<<")"<<endl;display();cout<<"press enter to continue! "<<endl;getchar();getchar();while(1){cout<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl;cout<<"%%请选择您的操作:%% "<<endl;cout<<"%%============================%% "<<endl;cout<<"%%%% "<<endl;cout<<"%%1.显⽰当前数独%% "<<endl;cout<<"%%2.分析求解%% "<<endl;cout<<"%%3. 查看结果%% "<<endl;cout<<"%%4.返回%% "<<endl;cout<<"%%%% "<<endl;cout<<"%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% "<<endl;int select;cin>>select;switch (select){case1:{cout<<endl<<"当前随机数独: "<<endl;display();cout<<"press enter to continue! "<<endl;getchar();getchar();break;}case2:{analyze();break;}case3:{cout<<endl<<"显⽰结果: "<<endl;resolve();cout<<"press enter to continue! "<<endl<<endl;getchar();getchar();break;}case4: return;default:{cout<<"输⼊错误,请重新输⼊."<<endl;break;}}}}CSudoku::CSudoku(int *data){SudokuGenerator(data);cout<<endl<<"已知数独为: "<<endl;display();cout<<"press enter to continue! "<<endl;getchar();getchar();analyze();}void CSudoku::SudokuGenerator(int n){int i,j;int mark[10];srand(time(0));//每⼀⾏i产⽣⼀个随机位置(列j)并置为当前⾏值i+1,0=<i,j<=8。
数独游戏-如何用代码实现(思路分析)
数独游戏-如何⽤代码实现(思路分析)数独游戏-如何⽤代码实现最近开始喜欢起来玩数独,在⼿机上找来⼏个数独⼩游戏玩着玩着突然想起我是个程序员.........那我何不⾃⼰写⼀个数独软件,⽹上查了⼀下数独有6,670,903,752,021,072,936,960(约有6.67×10的21次⽅)种组合。
我xxxx.......算了算了不想那么多了,先⾃⼰尝试做⼀个简单的下⾯的是我设计思路⾸先给没有玩过的同学普及⼀下数独:数独(shù dú)是源⾃18世纪瑞⼠的⼀种数学游戏。
是⼀种运⽤纸、笔进⾏演算的逻辑游戏。
玩家需要根据9×9盘⾯上的已知数字,推理出所有剩余空格的数字,并满⾜每⼀⾏、每⼀列、每⼀个粗线宫(3*3)内的数字均含1-9,不重复那么第⼀件事考虑如何如何⽣成⼀个9*9并且每⼀⾏,每⼀列,每⼀宫都不重复的⼆维数组?突然我灵机⼀动,如果..我⼿写个⼆维数组怎么样.int[][] arrray1 = new int[9][];arrray1[0] = new int[9] { 5, 6, 4, 8, 9, 7, 2, 3, 1 };arrray1[1] = new int[9] { 9, 7, 8, 3, 1, 2, 6, 4, 5 };arrray1[2] = new int[9] { 3, 1, 2, 6, 4, 5, 9, 7, 8 };arrray1[3] = new int[9] { 6, 4, 5, 9, 7, 8, 3, 1, 2 };arrray1[4] = new int[9] { 7, 8, 9, 1, 2, 3, 4, 5, 6 };arrray1[5] = new int[9] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };arrray1[6] = new int[9] { 4, 5, 6, 7, 8, 9, 1, 2, 3 };arrray1[7] = new int[9] { 8, 9, 7, 2, 3, 1, 5, 6, 4 };arrray1[8] = new int[9] { 2, 3, 1, 5, 6, 4, 8, 9, 7 };嗯~ o( ̄▽ ̄)o感觉也不是不可以,如果每⾏扣去4个的话 C94 有126种那⼀共应该有1134种组合上⾯的数组是固定的如果在写⼏组数组呢?好像是可以有更多的组合但是成本太⾼,并且要找到每⼀宫每⼀列都不重复的组合也需要花费些时间⽽且也失去了乐趣,换⼀个⾓度想如果不能变当前这个⼆维数组,可不可以通过其他⽅式来改变这个数组,可以使⽤⼀个⼀位数组同样是1-9的数字,通过判断⼆维数组中和⼀维数组相等的数据并取下⼀个位置的值,⽬的就是让⼀维数组把⼆维数组中的值循环变⼀下,因为⼀维数组也是1-9的不重复数字因此不会影响到⾏和列及宫的组合,⼤家可以⾃⾏验证⼀下.private static int[][] creatSudokuArray(int[][] seedArray, List<int> randomList){for (int i = 0; i < 9; i++){for (int j = 0; j < 9; j++){for (int k = 0; k < 9; k++){if (seedArray[i][j] == randomList[k]){seedArray[i][j] = randomList[(k + 1) % 9];break;}}}}return seedArray;}这样⽣成的数独也就有9!=362880 在通过扣掉若⼲个格⼦那最终的结果OK 数独⽣成了那下⾯具体就是需要去画⼀个9*9的矩阵并且把⽣成的数独填充进去然后扣掉部分我这⾥使⽤的是winform实现的具体填充代码就不说了下⾯会给贴出github的源码地址⼤家可以去下载,主要还是说思路.扣数据部分也是⽤随机数来操作的单纯的去掉⼏个感觉太死板了,附代码/// <summary>/// ⽣成数独选择难度/// </summary>/// <param name="a"></param>private void printArray(int[][] a){int length = 4;switch (boBox1.Text){case "简单":length = 4;break;case "中等":length = 5;break;case "困难":length = 6;break;}Random random = new Random();for (int i = 0; i < 9; i++){for (int j = 0; j < 9; j++){int randomNum = random.Next(9);if (randomNum > length){tbArray[i, j].Text = a[i][j].ToString();}else{tbArray[i, j].ReadOnly = false;}}}}最后就是要去验证⾃⼰填进去的数字是否满⾜数独的要求那么我们就需要每⼀⾏,每⼀列,每⼀宫的检查,⾏和列很简单只要验证当前⾏或者列是否有重复数据或者去重之后的长度是否⼩于9即可,相信⼤家可以通过各种语⾔来实现了把,下⾯贴出我的代码/// <summary>/// 校验⾏/// </summary>public bool rowCheck(){for (int y = 0; y < 9; y++)List<int> lines = new List<int>();for (int x = 0; x < 9; x++){string value = tbArray[x, y].Text;if (!String.IsNullOrEmpty(value)){lines.Add(Convert.ToInt32(value));}else{MessageBox.Show("请确认是否填写完毕");return false;}}if (lines.Distinct().Count() < 9){MessageBox.Show("验证失败,请检查完重新提交");return false;}}return true;}/// <summary>/// 校验列/// </summary>public bool cellCheck(){for (int y = 0; y < 9; y++){List<int> lines = new List<int>();for (int x = 0; x < 9; x++){string value = tbArray[y, x].Text;if (!string.IsNullOrEmpty(value)){lines.Add(Convert.ToInt32(value));}else{MessageBox.Show("请确认是否填写完毕");return false;}}if (lines.Distinct().Count() < 9){MessageBox.Show("验证失败,请检查完重新提交");return false;}}return true;}那么每⼀宫怎么检验呢?其实和⾏列的⽅法相识我们可以吧每⼀宫的数据计算出来放到⼀个数组中最后相同的⽅式去判断即可 /// <summary>/// 校验九宫格每⼀宫是否有重复/// </summary>public bool palaceCheck(){int[,] newArrary = block();for (int y = 0; y < 9; y++){List<int> lines = new List<int>();for (int x = 0; x < 9; x++){lines.Add(newArrary[x, y]);}if (lines.Distinct().Count() < 9){MessageBox.Show("验证失败,请检查完重新提交");return false;}}return true;}//将每块的数字保存⾄⼀个⼆维数组public int[,] block(){int[,] b = new int[9, 9];for (int i = 0; i < 9; i++)for (int j = 0; j < 9; j++)//将数独从左⾄右从上⾄下分为9块,求该单元格属于第⼏块,将该块数字保存⾄b第⼏⾏ int rowOfB = i / 3 * 3 + j / 3;//每块有9个数字,求该数字属于第⼏个,保存⾄b第⼏列int columnOfB = i % 3 * 3 + j % 3;b[rowOfB, columnOfB] = Convert.ToInt32(tbArray[i, j].Text);}return b;}整个的实现思路就完成了,下⾯的就是具体优化了,下⾯是我的最终效果源码:⼩伙伴们有更好的⽅式可以分享出来⼤家⼀起讨论。
150行Python代码实现带界面的数独游戏
150⾏Python代码实现带界⾯的数独游戏今天闲着没事⼲,以前做过html+js版的数独,这次做个python版本的,界⾯由pygame完成,数独⽣成由递归算法实现,由shuffle保证每次游戏都是不⼀样的情况,have fun;功能列表:图形化的数独游戏;python实现,依赖pygame库;随机⽣成游戏,每次运⾏都不⼀样;数字填⼊后的正确性判断以及颜⾊提⽰;显⽰剩余需填⼊的空格,已经操作的次数;难度可选,通过修改需要填⼊的空的数量;游戏界⾯初始界⾯过程中界⾯运⾏⽅式python main.py 15这⾥的15表⽰需要填⼊的空格数量为15,理论上这个值越⼤,难度就越⾼,⼤家可以随机调整,或者设置容易、简单、困难、地狱等对应不同的值即可,很⽅便修改;程序分析界⾯部分这部分很简单的通过pygame来实现,主要使⽤了其中的主循环、⿏标键盘监听、画矩形线条、字体、颜⾊控制等,理解起来很容易,对于这部分不太熟悉的同学,这样理解就好: pygame的主循环中⼀⽅⾯负责接收⽤户输⼊,⼀般就是⿏标和键盘,另⼀⽅⾯负责实时更新界⾯显⽰内容;对于界⾯上各部分内容的绘制的函数封装# 绘制背景部分,这⾥就是9*9的九宫格def draw_background():# white backgroundscreen.fill(COLORS['white'])# draw game boardpygame.draw.rect(screen,COLORS['black'],(0,0,300,900),5)pygame.draw.rect(screen,COLORS['black'],(300,0,300,900),5)pygame.draw.rect(screen,COLORS['black'],(600,0,300,900),5)pygame.draw.rect(screen,COLORS['black'],(0,0,900,300),5)pygame.draw.rect(screen,COLORS['black'],(0,300,900,300),5)pygame.draw.rect(screen,COLORS['black'],(0,600,900,300),5)# 将⽤户选中的各⾃背景改为蓝⾊块表⽰选中def draw_choose():pygame.draw.rect(screen,COLORS['blue'],(cur_j*100+5,cur_i*100+5,100-10,100-10),0)# 绘制九宫格中的数字,包括本来就有的,以及⽤户填⼊的,本来就在的⽤灰⾊,⽤户填⼊的如何合法则为绿⾊,否则为红⾊,是⼀种提⽰def draw_number():for i in range(len(MATRIX)):for j in range(len(MATRIX[0])):_color = check_color(MATRIX,i,j) if (i,j) in BLANK_IJ else COLORS['gray']txt = font80.render(str(MATRIX[i][j] if MATRIX[i][j] not in [0,'0'] else ''),True,_color)x,y = j*100+30,i*100+10screen.blit(txt,(x,y))# 绘制最下⽅的当前空格⼦数量以及⽤户的操作数量def draw_context():txt = font100.render('Blank:'+str(cur_blank_size)+' Change:'+str(cur_change_size),True,COLORS['black'])x,y = 10,900screen.blit(txt,(x,y))主循环中对上述函数的调⽤以及⿏标键盘事件处理# 主循环,负责监听⿏标键盘时间,以及刷新界⾯内容,以及检查是否赢得了游戏running = Truewhile running:for event in pygame.event.get():if event.type == pygame.QUIT:running = Falsebreakelif event.type == pygame.MOUSEBUTTONDOWN:cur_j,cur_i = int(event.pos[0]/100),int(event.pos[1]/100)elif event.type == event.type == pygame.KEYUP:if chr(event.key) in ['1','2','3','4','5','6','7','8','9'] and (cur_i,cur_j) in BLANK_IJ:MATRIX[cur_i][cur_j] = int(chr(event.key))cur_blank_size = sum([1 if col==0 or col=='0' else 0 for row in MATRIX for col in row])cur_change_size +=1# backgrounddraw_background()# choose itemdraw_choose()# numbersdraw_number()# pointdraw_context()# flippygame.display.flip()# check win or notif check_win(MATRIX_ANSWER,MATRIX):print('You win, smarty ass')breakpygame.quit()⽣成表⽰数独的⼆维数组相对于界⾯部分,这部分在逻辑上要难⼀些,思路以递归为核⼼,辅以随机性,得到⼀个每次⽣成都不⼀致的数独游戏,⽣成思路简单描述如下:遍历每个空格,填⼊⽬前为⽌合法的数字;如果有数字可以填⼊,则继续向下⼀个空格;如果没有数字可以填⼊,表⽰之前的数字有问题,则结束递归;当递归到最后⼀个格⼦的下⼀个时,表⽰已经⽣成完毕,返回即可;这个过程中对1~9这九个数字的遍历数字会经过shuffle处理,保证随机性⽽不是每次都得到同⼀个合法的数独数组;⽣成过程代码递归的⼀个优势是通常代码都很短,当然阅读性不强,欢迎⼤佬们改为循环;def shuffle_number(_list):random.shuffle(_list)return _listdef check(matrix,i,j,number):if number in matrix[i]:return Falseif number in [row[j] for row in matrix]:return Falsegroup_i,group_j = int(i/3),int(j/3)if number in [matrix[i][j] for i in range(group_i*3,(group_i+1)*3) for j in range(group_j*3,(group_j+1)*3)]:return Falsereturn Truedef build_game(matrix,i,j,number):if i>8 or j>8:return matrixif check(matrix,i,j,number):_matrix = [[col for col in row] for row in matrix]_matrix[i][j] = numbernext_i,next_j = (i+1,0) if j==8 else (i,j+1)for _number in shuffle_number(number_list):__matrix = build_game(_matrix,next_i,next_j,_number)if __matrix and sum([sum(row) for row in __matrix])==(sum(range(1,10))*9):return __matrixreturn None随机覆盖数独数组中的N个位置matrix_all表⽰整个数独数组matrix_blank表⽰部分被替换为0的⽤于显⽰的数组blank_ij表⽰被覆盖位置的i和jdef give_me_a_game(blank_size=9):matrix_all = build_game(matrix,0,0,random.choice(number_list))set_ij = set()while len(list(set_ij))<blank_size:set_ij.add(str(random.choice([0,1,2,3,4,5,6,7,8]))+','+str(random.choice([0,1,2,3,4,5,6,7,8]))) matrix_blank = [[col for col in row] for row in matrix_all]blank_ij = []for ij in list(set_ij):i,j = int(ij.split(',')[0]),int(ij.split(',')[1])blank_ij.append((i,j))matrix_blank[i][j] = 0return matrix_all,matrix_blank,blank_ij最后附上全部代码⼤家也可以直接从我的 fork下来直接运⾏;main.py:主流程+界⾯+执⾏import sysimport pygamefrom pygame.color import THECOLORS as COLORSfrom build import print_matrix,give_me_a_game,checkdef draw_background():# white backgroundscreen.fill(COLORS['white'])# draw game boardpygame.draw.rect(screen,COLORS['black'],(0,0,300,900),5)pygame.draw.rect(screen,COLORS['black'],(300,0,300,900),5)pygame.draw.rect(screen,COLORS['black'],(600,0,300,900),5)pygame.draw.rect(screen,COLORS['black'],(0,0,900,300),5)pygame.draw.rect(screen,COLORS['black'],(0,300,900,300),5)pygame.draw.rect(screen,COLORS['black'],(0,600,900,300),5)def draw_choose():pygame.draw.rect(screen,COLORS['blue'],(cur_j*100+5,cur_i*100+5,100-10,100-10),0)def check_win(matrix_all,matrix):if matrix_all == matrix:return Truereturn Falsedef check_color(matrix,i,j):_matrix = [[col for col in row]for row in matrix]_matrix[i][j] = 0if check(_matrix,i,j,matrix[i][j]):return COLORS['green']return COLORS['red']def draw_number():for i in range(len(MATRIX)):for j in range(len(MATRIX[0])):_color = check_color(MATRIX,i,j) if (i,j) in BLANK_IJ else COLORS['gray']txt = font80.render(str(MATRIX[i][j] if MATRIX[i][j] not in [0,'0'] else ''),True,_color)x,y = j*100+30,i*100+10screen.blit(txt,(x,y))def draw_context():txt = font100.render('Blank:'+str(cur_blank_size)+' Change:'+str(cur_change_size),True,COLORS['black']) x,y = 10,900screen.blit(txt,(x,y))if __name__ == "__main__":# init pygamepygame.init()# contantSIZE = [900,1000]font80 = pygame.font.SysFont('Times', 80)font100 = pygame.font.SysFont('Times', 90)# create screen 500*500screen = pygame.display.set_mode(SIZE)# variable parametercur_i, cur_j = 0,0cur_blank_size = int(sys.argv[1])cur_change_size = 0# matrix abountMATRIX_ANSWER,MATRIX,BLANK_IJ = give_me_a_game(blank_size=cur_blank_size)print(BLANK_IJ)print_matrix(MATRIX)# main looprunning = Truewhile running:for event in pygame.event.get():if event.type == pygame.QUIT:running = Falsebreakelif event.type == pygame.MOUSEBUTTONDOWN:cur_j,cur_i = int(event.pos[0]/100),int(event.pos[1]/100)elif event.type == event.type == pygame.KEYUP:if chr(event.key) in ['1','2','3','4','5','6','7','8','9'] and (cur_i,cur_j) in BLANK_IJ:MATRIX[cur_i][cur_j] = int(chr(event.key))cur_blank_size = sum([1 if col==0 or col=='0' else 0 for row in MATRIX for col in row])cur_change_size +=1# backgrounddraw_background()# choose itemdraw_choose()# numbersdraw_number()# pointdraw_context()# flippygame.display.flip()# check win or notif check_win(MATRIX_ANSWER,MATRIX):print('You win, smarty ass')breakpygame.quit()build.py:⽣成数独数组部分import randomdef print_matrix(matrix):print('—'*19)for row in matrix:print('|'+' '.join([str(col) for col in row])+'|')print('—'*19)def shuffle_number(_list):random.shuffle(_list)return _listdef check(matrix,i,j,number):if number in matrix[i]:return Falseif number in [row[j] for row in matrix]:return Falsegroup_i,group_j = int(i/3),int(j/3)if number in [matrix[i][j] for i in range(group_i*3,(group_i+1)*3) for j in range(group_j*3,(group_j+1)*3)]:return Falsereturn Truedef build_game(matrix,i,j,number):if i>8 or j>8:return matrixif check(matrix,i,j,number):_matrix = [[col for col in row] for row in matrix]_matrix[i][j] = numbernext_i,next_j = (i+1,0) if j==8 else (i,j+1)for _number in shuffle_number(number_list):#_matrixs.append(build_game(_matrix,next_i,next_j,_number))__matrix = build_game(_matrix,next_i,next_j,_number)if __matrix and sum([sum(row) for row in __matrix])==(sum(range(1,10))*9):return __matrix#return _matrixsreturn Nonedef give_me_a_game(blank_size=9):matrix_all = build_game(matrix,0,0,random.choice(number_list))set_ij = set()while len(list(set_ij))<blank_size:set_ij.add(str(random.choice([0,1,2,3,4,5,6,7,8]))+','+str(random.choice([0,1,2,3,4,5,6,7,8])))matrix_blank = [[col for col in row] for row in matrix_all]blank_ij = []for ij in list(set_ij):i,j = int(ij.split(',')[0]),int(ij.split(',')[1])blank_ij.append((i,j))matrix_blank[i][j] = 0return matrix_all,matrix_blank,blank_ijnumber_list = [1,2,3,4,5,6,7,8,9]matrix = [([0]*9) for i in range(9)]if __name__ == "__main__":print_matrix(build_game(matrix,0,0,random.choice(number_list)))总结如果刻意减少代码的话,实际应该控制在100⾏以内,这也充分表达了python的强⼤,确实可以在很短的时间内完成⼀些看似复杂的⼯作,这个例⼦供⼀些同学上⼿python个⼈觉得还是不错的,没有太复杂的⽤法,对界⾯开发有⼀点点了解,对递归有⼀些理解基本就能完全掌握这份代码,希望⼤家玩的开⼼,挑战⼀下50个空格呗,哈哈,反正我没通过,太难了。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
数据结构大型作业实验报告书设计题目:“数独”游戏设计与求解一.题目说明数独的游戏规则:1、在9×9的大九宫格内,已给定若干数字,其他宫位留白,玩家需要自己按照逻辑推敲出剩下的空格里是什么数字。
2、必须满足的条件:每一行与每一列都有1到9的数字,每个小九宫格里也有1到9的数字,并且一个数字在每行、每列及每个小九宫格里只能出现一次,既不能重复也不能少。
3、每个数独游戏都可根据给定的数字为线索,推算解答出来。
按照数独的游戏规则,用计算机实现已知数独的求解和数独题目的出题。
二.数据结构说明数据结构一维数组、二维数组以及类似于“栈”的数据结构。
主要操作有:进栈,出栈,栈顶元素的操作等等三.抽象数据类型(Abstract Data Type 简称ADT) 五个全局变量数组,其中两个二维数组,三个一维数组。
int a[10][10]接受输入数据,空白处则初始化为0。
之所以把数组范围设计为10*10,是为了程序的可读性。
符合人的习惯思维。
int sd[82]在实现“回溯”算法的时候,因为要用到栈的数据结构,所以把a[10][10]二维数组中的数据转换储存进sd[82]一维数组。
方便处理题目以及保存最后结果。
int fix[82]对应于sd[82],记录哪些位置已经确定。
确定则fix值为1,未确定为0。
int possible[82][10]第一维对应着sd[82]中的每一个,第二维的下标为每个位置的可能值。
有可能则为第二维的下标,不可能则为-1。
int stack[82]类似于“栈”数据结构的数组,实现“回溯”算法的关键所在。
回溯之前,把所有fix值为0的数据存如stack数组中,即进栈。
回溯中逐渐确定这些位置的数值,无法确定者(即1--9都不适合的)则应回退到前一位置,修改其fix值,以此类推。
直至stack 中所有的值都确定下来(即题目完成),或者回退到了最初点的前一位置(说明题目有误)。
四.算法设计程序可以考虑人工智能的算法。
所谓人工智能的算法,应当是算法设计者对该游戏的特性有较为深入的了解,依据其内在联系设计出的和人类思维相似的解决算法。
但这似乎太过复杂,所以这里决定采用“回溯”的方法解决数独问题。
基本框架如下:五.数独程序代码:#include"stdio.h" //标准输入输出头文件#include"conio.h" //包含getch()的头文件#include"stdlib.h" //包含rand()的头文件#include"assert.h" //包含assert()的头文件#include"time.h" //包含srand()的头文件//五个全局变量数组int a[10][10];//用来接收输入数据的数组int sd[82];//处理题目以及保存最终结果int fix[82];//记录哪些位置是确定的,确定为1,否则为0 int possible[82][10];//记录所有未确定数字的可能性int stack[82];//用来放置填入的数的栈void clssd()//初始化函数,所有位置设为0{int i,j,k;for(i=0;i<9;i++)for(j=0;j<9;j++)a[i][j]=0;for(k=1;k<=81;k++)sd[k]=0;}int line(int line,int value)//检验行{int i;for(i=1;i<=9;i++){if(a[line][i]==value) return 0;}return 1;}int row(int row,int value)//检验列{int i;for(i=1;i<=9;i++){if(a[i][row]==value) return 0;}return 1;}int square(int line,int row,int value)//检验3*3的九宫{int L,R,i,j;L=(line%3!=0)+line/3;//L表示所在九宫的行数R=(row%3!=0)+row/3;//R表示所在九宫的列数for(i=(L-1)*3+1;i<=L*3;i++){for(j=(R-1)*3+1;j<=R*3;j++)if(a[i][j]==value) return 0;}return 1;}//四个转换函数int transform_to_line(int i)//实现sd[i]->a[line][row]之间的转换{int line;line=i/9+(i%9!=0);return line;}int transform_to_row(int i)//实现sd[i]->a[line][row]之间的转换{int row;row=i%9+9*(i%9==0);return row;}void transform_to_a(int i)//sd[i]->a[line][row]的转换{int l,r;l=transform_to_line(i);r=transform_to_row(i);a[l][r]=sd[i];}void transform_to_sd()//实现a[line][row]->sd[i]的转换{int line,row,i=1;for(line=1;line<=9;line++)for(row=1;row<=9;row++)do{sd[i]=a[line][row];i++;break;}while(i<=81);}//输出函数void printAll(){int i;for(i=0;i<81;i++){if(i%9==0)printf("\n\n\t\t");printf("%4d",sd[i+1]);}printf("\n\n\n");}void input()//输入数据到a[10][10] {system("cls");//清屏int b[3]={0,0,0},i,j;printf("请输入已知数据");printf("\n\n例如输入7 8 9,表示第8行第9列的数值为7,以此类推。
\n\n\n");do{printf("\n输入数据:按照值/ 行/ 列的顺序,以0结束");for(i=0;i<3;i++){j=getch()-48;if(j==0&&i==0) break;//实现按0结束语句if(j>0&&j<10){b[i]=j;printf("%3d",b[i]);}else i--;}a[b[1]][b[2]]=b[0];}while(j);transform_to_sd();printf("\n\n\n\t您输入的题目为:\n\n");//打印输入的数独printAll();}//三个重要函数bool beExist(int i,int j)//判断sd 数组中位置为i 的元素是否存在{int l,r;l=transform_to_line(i);r=transform_to_row(i);//if(sd[i]!=0) return 1; 关键的错误所在!!!if(line(l,j)*row(r,j)*square(l,r,j)==0) return 1;else return 0;}void setPb()//控制possible数组{int i,j;for(i=1;i<=81;i++){for(j=1;j<=9;j++){if(sd[i]!=0) possible[i][j]=-1; //如果sd[i]为已知输入数据,则将可能值设为-1else if( beExist(i,j)){possible[i][j]=-1;}//若在行、列、九宫内,存在相同数值则possible设为-1else{possible[i][j]=j;}//其他情况讲可能值保存进possible数组}}}bool fixAll(int sd[],int fix[],int possible[82][10])//控制fix数组{int i,j;int k[82];for(i=1;i<=81;i++)//将已经存在的数据对应fix数组中的值设为1,不存在设为0{if(sd[i]!=0){fix[i]=1;}else{fix[i]=0;}}for(i=1;i<=81;i++)//判断未确定空格处值的可能性{if(sd[i]!=0) continue;if(fix[i]==0){for(j=1;j<=9;j++)if(possible[i][j]!=-1)k[i]++;}if(k[i]==1)//如果存在只有一种可能的位置则将fix[i]改为1fix[i]=1;sd[i]=possible[i][j];}for(i=1;i<=81;i++)//判断是否存在只有一种可能的位置,若没有返回0 {if(k[i]==1) return 1;else return 0;}}//判断是否完成int isFull(int sd[]){int i;for(i=1;i<=81;i++)if(sd[i]==0) return 0;return 1;}void preDo()//预处理{while(1){setPb();if(!fixAll(sd,fix,possible)) //即不存在只有一种可能性的位置break;if(isFull(sd)) //若已经推出全部结果break;}if(isFull(sd))printAll();//打印结果}int calculate()//填数独(关键算法){preDo();//预处理,找出所有的位置的可能数值if(isFull(sd)) return 1;int top=0;//将所有为0的位置入栈for(int i=1;i<82;i++){if(fix[i]==0)stack[top++]=i;}int max=top;//记录最大数目加1top=0;//指向栈顶int temp;bool flag=true;//该标志位说明了当前是正常入栈while(1){assert(top>=0);//宏定义,调试程序之用if(flag){int j;for(j=1;j<=9;j++)if(possible[stack[top]][j]!=-1&&!beExist(stack[top],j))//若top所示的位置上,可以安插j这个数值,则{fix[stack[top]]=1;sd[stack[top]]=j;transform_to_a(stack[top]);//实现a[line][row]与sd[i]同步变化++top;if(top>=max) return 1;break;}if(j>9)//该空所有可能值都不可以,则退一格{--top;if(top<0) {printAll(); return 0;}flag=false;}}else{if(sd[stack[top]]==9)//说明当前这个top也没有可以选择的数,继续回退{fix[stack[top]]=0;sd[stack[top]]=0;transform_to_a(stack[top]);--top;if(top<0) {printAll(); return 0;}}else{temp=sd[stack[top]];temp++;while(possible[stack[top]][temp]==-1||beExist(stack[top],temp)){temp++;if(temp>9)break;}if(temp>9)//当前节点没有更换的可能性,继续退回{fix[stack[top]]=0;sd[stack[top]]=0;transform_to_a(stack[top]);--top;if(top<0) {printAll(); return 0;}}else{sd[stack[top]]=temp;transform_to_a(stack[top]);++top;flag=true;//重新设定flag}}}}}void solve_problem()//解题{int p;system("cls"); //清屏clssd(); //赋初值为0input(); //输入数据transform_to_sd(); //转换为sd[i]数组p=calculate(); //计算数独if(p==0)printf("\t题目有误 ");printf("\n\n\t答案为:\n");printAll();}void random()//从1-9中随机产生几个值输入sd[1]至sd[9] {int i,j,r;int change=1;int b[10]={0,0,0,0,0,0,0,0,0,0};for(i=1;i<=9;)//从1-9中随机产生几个值{change=1;j=1+rand()%9;for(r=1;r<=9;r++)if(b[r]==j) change=0;if(change==1){b[i]=j; i++;}}for(i=1;i<=9;i++){sd[i]=b[i];transform_to_a(i);}}void hide()//遮罩函数{int i,f;printf("请输入难度:\n\n1.Easy\n\n2.Normal\n\n3.Hard\n\n4.So Hard\n\n5.Terrible Hard\n\n");do{f=getch()-48;}while(f>5||f<1);//一共5个级别for(i=1;i<=81;i++){if(rand()%6>=f)//利用随机数出现的概率出题printf("%4d",sd[i]);elseprintf(" 0");if(i%9==0)printf("\n\n");}}void make_problem()//出题函数{system("cls");//初始化clssd();random();//填9个随机值calculate();//算出答案hide();//遮罩,将答案中一些数值遮住printf("\t\t\t注意:题目中0代表待填数据\n\n\t\t 按空格键输出答案,其他键退出程序\n");int f;do{f=getch()-32;if(!f)printAll();else break;}while(f);}void main()//主函数{srand((unsigned)time(0));//设置时间种子为0system("cls");//清屏clssd();printf("\n\t数独游戏\n\n\t1.你出题,电脑来解\n\n\t2.电脑出题,你来解");int i;do{i=getch()-48;switch(i){case 1:solve_problem();break;case 2:make_problem();break;}}while(i>2||i<1);}六.调试报告1.整个程序最麻烦的地方是二维数组a[10][10]与一维数组sd[82]之间的转换。