JAVA数独(九宫格)游戏软件设计报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
佛山科学技术学院
《可视化编程技术》课程设计报告数独(九宫格)游戏软件设计
学生姓名:***
学号: **********
年级专业:12级教育技术学2班
指导老师:***
学院:教育科学学院
广东★佛山
提交日期:2014年6月
目录
1. 前言______________________________2 2.概要设计____________________________3
2.1 数独游戏分析_________________________3 2.2 数独游戏界面设计_______________________5
2.3 数独游戏程序功能_______________________5
3. 详细设计___________________________7 3.1类设计___________________________7
3.2 数独算法设计_________________________9
4.程序代码____________________________10
5.参考资料____________________________19
6.心得体会____________________________20
摘要:本程序是个简单的数独游戏界面,在9×9的大九宫格中有9个3×3的小九宫格,游戏根据玩家选择的难易程度提供不同数量的数字。
根据已给出的数字,利用逻辑和推理,在其余空格上填入1至9的数字。
每个数字在每个小九宫格内每行、每列只能出现一次。
虽然玩法简单,但数字排列方式却千变万化,是锻炼逻辑推理能力的好方法。
另外,设有“答案”和“玩法说明”窗口为玩家提供参考和帮助。
玩家完成所有数字的填写后,可进行提交,游戏系统会根据所填写的结果弹出相应的对话框。
关键字:java游戏软件,数独(九宫格),界面布局
1 前言
经济在发展,科学在发展,人也在发展。
在学习JAVA语言后,我决定使用Java语言编写一个简单的数独游戏,来锻炼人们的逻辑推理能力和思维活跃度,同时,也能满足人们日常空余时间的娱乐需要。
数独热潮已经在全球蔓延已久,随着数独游戏不断地发展完善,数独也越来越受到家长和孩子的青睐,认为数独不仅仅只是游戏,而是开发智力的一种方法。
在孩子游戏娱乐的同时还能得到逻辑思维的锻炼,又何乐而不为呢?
JAVA语言是一种纯面向对象的编程语言,自1995年诞生至今,已经得到飞速的发展,涉及计算机应用的方方面面,如浏览器应用、桌面应用、个人数字代理等等,Java语言面向对象、跨平台、安全性、多线程等特性,奠定了其作为网络应用开发首选工具的基础。
另外,本数独游戏程序框架结构清晰明朗,便于读者理解以及为以后增添新功能打下良好的基础;同时,虽然这是一个较为普通的数独游戏程序,但是具有较强的实用性,而且对程序的配置要求不高,能够广泛应用。
2 概要设计
2.1数独游戏分析
数独游戏组成元素:
单元格:数独中最小的单元,标准数独中共有81个;
行:横向9个单元格的集合;
列:纵向9个单元格的集合;
宫:粗黑线划分的区域,标准数独中为3×3的9个单元格的集合;
已知数:数独初始盘面给出的数字;
候选数:每个空单元格中可以填入的数字。
基本解法:
利用1 ~9 的数字在每一行、每一列、每一宫都只能出现一次的规则进行解题的方法。
使用单元排除法的目的就是要在某一单元(即行,列或区块)中找到能填入某一数字的唯一位置,换句话说,就是把单元中其他的空白位置都排除掉。
游戏布局:
①JPanel panel_txt=new JPanel(new GridLayout(3,3,2,2));
//将面板设置为3行3列网格布局,并设置大小
②for(int i=1;i<=9;i++){ //设置9个面板
panel[i]=new JPanel(new GridLayout(3,3)); //将面板设置为3行3列
网格布局:
panel_txt.add(panel[i]); //添加组件
int m=(i+2)/3*3-2; //生成九个3*3的网格,并添加数字
int n=((i-1)%3+1)*3-2;
for(int j=m;j<=m+2;j++){
for(int k=n;k<=n+2;k++){
panel[i].add(text[j][k]);
}
}
}
2.2数独游戏界面设计
2.3数独游戏程序功能
功能1:弹出游戏界面,可直接开始进行数独游戏,也可以在游戏过程中选择菜单栏中“文件”——“新局”,进行新一局的游戏,或者是“文件”——“重来”,重新开始当前局。
功能2:判断答案的正误。
游戏当前局完成后,可选择菜单栏中“文件”——“提交”,系统会根据玩家在当前局所填写的结果,弹出相应的对话框。
当输入的内容不符合要求时,弹出对话框:
当结果不正确时,弹出对话框:当答案正确时,弹出对话框:
功能3:选择菜单栏中“文件”——“答案”,会弹出当前局数独游戏的正确答案的新窗口,给玩家提供参考。
功能4:选择菜单栏中“帮助”——“说明”,会弹出次数独游戏玩法的相关说明的新窗口,给玩家提供帮助。
另外,选择菜单栏中“帮助”——“作者”,会弹出对话框,显示此程序作者的相关信息。
功能5:选择菜单栏中“文件”——“退出”,会自动关闭当前的数独游戏界面,退出系统。
功能6:玩家可根据自身的情况或兴趣,在数独游戏界面上方的下拉列表中选择适合自己的难度(难度共分为3级,分别是“简单”,“一般”和“困难”),然后选择重新开局,游戏的难度会进行相应的变化。
功能7:在九宫格数独游戏界面和弹出的消息提示界面以及答案显示窗口和玩法说明窗口有相关的最小化、最大化、关闭等按钮可以操作,玩家可根据需要自行选择相关操作。
3详细设计
3.1类设计
类的对象:
属于ShuDu1主类的对象成员: MenuBar、Menu、MenuItem、JComboBox 属于ShuDuAns类的对象:JTextField
属于String类的对象:atext[i][j]
属于JtextField类的对象:text[i][j]、
属于JPanel类的对象:apanel[ ]、panel[ ]
类:包括上述所有类及父类Jframe。
类的属性:
ShuDu1: public
String: public
JtextField:private
JPanel:private
Jframe:public
程序流程图:
3.2数独算法设计
static int DFS(){
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
if(data[i][j]==0){
for(int k=1;k<=9;k++){
if( row[i][k]==0 && col[j][k]==0 && sql[(i+2)/3][(j+2)/3][k]==0 ){ data[i][j]=k; row[i][k]=1; col[j][k]=1;
sql[(i+2)/3][(j+2)/3][k]=1;
if( DFS()==1 )
return 1;
else{
data[i][j]=0; row[i][k]=0; col[j][k]=0;
sql[(i+2)/3][(j+2)/3][k]=0;
}
}
if(k==9)
return 0;
}
}
}
}
return 1;
}
static void set_data_zero(){ //数独的初始化
for(int i=0;i<=9;i++){
for(int j=0;j<=9;j++){
data[i][j]=0;
}
}
}
static void setnum(){ //数独数字的设置
setzero(); set_data_zero();
for(int i=1;i<=9;i++){ //尝试填充的次数
int n =(int)(Math.random()*100)+1; //添加任意整数
int j=i*3-((i+2)/3*8-6);
data[i][j]=n%9+1; //产生数字
int k=data[i][j]; row[i][k]=1; col[j][k]=1;
sql[(i+2)/3][(j+2)/3][k]=1;
}
DFS();
}
算法核心:
数独游戏中的数字第一次是从所有数字中随机,第二次时从前八个数字中随机,依此类推,这样的数独算法既保证了随机性,也不会重复取已经不符合要求的数字,大大地提高程序的效率。
4程序代码
import java.awt.*; //置入包
import java.awt.event.*; //置入处理由awt组件产生的事件
import java.io.*;
import javax.swing.*;
import java.util.*;
public class ShuDu1 extends JFrame implements ActionListener,ItemListener{ //框架窗口响应单击事件
private MenuBar menubar=new MenuBar(); //私有成员变量
private Menu menu_file=new Menu("文件"); //定义“文件”菜单按钮
private Menu menu_help=new Menu("帮助"); //定义“帮助”菜单按钮
private MenuItem item_ans=new MenuItem("答案"); //定义菜单项
private MenuItem item_sol=new MenuItem("提交");
private MenuItem item_rem=new MenuItem("重来");
private MenuItem item_next=new MenuItem("新局");
private MenuItem item_exit=new MenuItem("退出");
private MenuItem item_auther=new MenuItem("作者");
private MenuItem item_explain=new MenuItem("说明");
private JComboBox box=new JComboBox(); //创建具有默认数据模型的复选框组件box static int data[][]=new int[10][10]; //新建10*10的二维数组
static int ansdata[][]=new int[10][10]; //新建存放正确答案的二维数组
static int row[][]=new int[10][10];
static int col[][]=new int[10][10];
static int sql[][][]=new int[4][4][10];
static JTextField text[][]=new JTextField[10][10]; //创建二维数组文本框组件text
static String atext[][]=new String[10][10];
static int hard=2; //默认初始难度为2
static int datahard[]={2,3,5}; // 不同的难度
class ShuDuAns extends JFrame{ //类声明;设置答案窗口
private JTextField atext[][]=new JTextField[10][10];
public ShuDuAns(){ //构造类
super("答案"); //设置框架窗口标题
this.setSize(300,300); //设置窗体框架尺寸
this.setLocation(200,200); //设置框架显示在屏幕的位置
this.setVisible(true); //组件设为可见
this.setResizable(false); //窗口大小不能改变
JPanel apanel_but=new JPanel(new FlowLayout()); //将面板设为流布局
JPanel apanel_txt=new JPanel(new GridLayout(3,3,2,2)); //将面板内部设为网格布局,参数指定为3行3列,并设置大小
JPanel apanel[]=new JPanel[10]; //创建面板数组apanel
for(int i=1;i<=9;i++){ //尝试填充的次数
apanel[i]=new JPanel(new GridLayout(3,3)); //给面板数组apanel添加GridLayout 布局管理器,设置3行3列的网格布局
apanel_txt.add(apanel[i]); //将面板数组apanel添加到有GridLayout布局管理器的面板apanel_txt中,依次添加组件,添加宫格
int m=(i+2)/3*3-2;
int n=((i-1)%3+1)*3-2;
for(int j=m;j<=m+2;j++){
for(int k=n;k<=n+2;k++){
atext[j][k]=new JTextField(Integer.toString(data[j][k])); //设置为整数 atext[j][k].setHorizontalAlignment(JTextField.CENTER); //文本设置为水平居中 atext[j][k].setEditable(false); //不可编辑,只能显示
apanel[i].add(atext[j][k]); //添加数字
}
}
}
this.add(apanel_txt); //为当前类添加宫格
}
}
class Another extends JFrame{
Another(){
this.setTitle("玩法说明");
this.setSize(500,400);
this.setAlwaysOnTop(true);
this.setVisible(true);
setLayout(new GridLayout(4,1));
Panel operate=new Panel();
JLabel label1,label2,label3,label4;
label1=new JLabel("1.在空格上填入1到9的数字,每个数字在每个小九宫格、每行、每列只能出现一次。
");
label2=new JLabel("2.玩家可自由选择难易程度,然后重新开局;或选择重来。
");
label3=new JLabel("3.玩家可打开文件菜单栏中的答案窗口,进行参考。
");
label4=new JLabel("4.玩家完成游戏后,可进行提交,同时根据所填写的结果弹出相应的提示对话框。
");
add(label1);
add(label2);
add(label3);
add(label4);
}
}
static int DFS(){ //静态成员方法
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
if(data[i][j]==0){
for(int k=1;k<=9;k++){
if( row[i][k]==0 && col[j][k]==0 && sql[(i+2)/3][(j+2)/3][k]==0 ){ //行、列3*3区域的检验
data[i][j]=k;
row[i][k]=1;
col[j][k]=1;
sql[(i+2)/3][(j+2)/3][k]=1; //九宫的间隔
if( DFS()==1 )
return 1;
else{
data[i][j]=0;
row[i][k]=0;
col[j][k]=0;
sql[(i+2)/3][(j+2)/3][k]=0; //宫内格子间的间隔 }
}
if(k==9)
return 0; //都设置完,结束
}
}
}
}
return 1;
}
static void set_data_zero(){ //数独初始化
for(int i=0;i<=9;i++){
for(int j=0;j<=9;j++){
data[i][j]=0; //0表示数字未给出
}
}
}
static void setnum(){ //设置数字
setzero(); //未给出的数字,需玩家填入
set_data_zero(); //初始化数独
for(int i=1;i<=9;i++){ //填充次数
int n =(int)(Math.random()*100)+1; //随机添加任意整数 int j=i*3-((i+2)/3*8-6);
data[i][j]=n%9+1; //产生数字
int k=data[i][j]; //设置间隔
row[i][k]=1;
col[j][k]=1;
sql[(i+2)/3][(j+2)/3][k]=1;
}
DFS();
}
static void setzero(){ //数独空格初始化
for(int i=0;i<=9;i++){
for(int k=0;k<=9;k++){
row[i][k]=0;
col[i][k]=0;
}
for(int j=0;j<=9;j++){
for(int k=0;k<=9;k++){
sql[(i+2)/3][(j+2)/3][k]=0;
}
}
}
}
static void settext(){ //设置数独游戏中的数字
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){ //int hard=2; //hard代表难度
int n =(int)(Math.random()*100)+1; //随机数
if(n%hard==0){ //根据选择的难易程度设置数独
text[i][j]=new JTextField(Integer.toString(data[i][j]));
text[i][j].setEditable(false); //不可编辑,只能显示
}
else{
text[i][j]=new JTextField(); //其他难度,新建文本行
}
text[i][j].setHorizontalAlignment(JTextField.CENTER); //水平居中 atext[i][j]=text[i][j].getText(); //设置组件
}
}
}
static int gettext(){ //玩家填入数字
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
try{ //异常处理
int k=Integer.parseInt(text[i][j].getText()); //第一个文本行输入操作
ansdata[i][j]=k;
}
catch(NumberFormatException nfe){ //捕获PerseInt( )方法声明的异常对象
JOptionPane.showMessageDialog(null,"所填入的数据中包括非数字字符或未完整填写,请重新输入!","提示",JOptionPane.PLAIN_MESSAGE); //提示出错信息
return 0;
}
}
}
return 1;
}
static int ans(){ //设置答案窗口的面板格局
setzero(); //空格初始化
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
int k=ansdata[i][j];
if( k>9 || k<1 ){
return 0;
}
if( row[i][k]==1 || col[j][k]==1 || sql[(i+2)/3][(j+2)/3][k]==1 ){
return 0;
}
row[i][k]=1;
col[j][k]=1;
sql[(i+2)/3][(j+2)/3][k]=1;
}
}
return 1;
}
public ShuDu1(){ //数独游戏布局
super("数独游戏"); //窗口标题
this.setSize(470,500); //设置窗口尺寸
this.setLocation(260,130); //窗口位置
this.setVisible(true); //显示窗口
this.setDefaultCloseOperation(EXIT_ON_CLOSE); //单击窗口按钮时,结束程序运行 this.setResizable(false); //窗口大小不可变
JPanel panel_but=new JPanel(new FlowLayout());
JPanel panel_txt=new JPanel(new GridLayout(3,3,2,2)); //将面板设置为3行3列网格布局,并设置大小
JPanel panel[]=new JPanel[10];
for(int i=1;i<=9;i++){ //设置9个面板
panel[i]=new JPanel(new GridLayout(3,3)); //将面板设置为3行3列网格布局 panel_txt.add(panel[i]); //添加组件
int m=(i+2)/3*3-2; //生成九个3*3的网格,并添加数字
int n=((i-1)%3+1)*3-2;
for(int j=m;j<=m+2;j++){
for(int k=n;k<=n+2;k++){
panel[i].add(text[j][k]);
}
}
}
this.add(panel_but,"North"); //为当前类添加框架
this.add(panel_txt); //添加文本
menubar.add(menu_file); //添加主菜单
menubar.add(menu_help);
menu_file.add(item_next); //添加下拉菜单选项
menu_file.add(item_rem);
menu_file.add(item_ans);
menu_file.add(item_sol);
menu_file.add(item_exit);
menu_help.add(item_auther);
menu_help.add(item_explain);
item_exit.addActionListener(this); //注册单击事件监听器,委托当前对象处理事件 item_next.addActionListener(this);
item_ans.addActionListener(this);
item_sol.addActionListener(this);
item_rem.addActionListener(this);
item_auther.addActionListener(this);
item_explain.addActionListener(this);
this.setMenuBar(menubar); //设置难易程度等级菜单
Object pro[]={" 简单 "," 一般 "," 困难 "};
box=new JComboBox(pro); //单击事件处理方法,实现ActionListener接口
if(hard==datahard[0]){
box.setSelectedIndex(0);
}
if(hard==datahard[1]){
box.setSelectedIndex(1);
}
if(hard==datahard[2]){
box.setSelectedIndex(2);
}
panel_but.add(box);
box.addItemListener(this);
}
public void actionPerformed(ActionEvent e){ //单击事件处理方法,实现ActionListener接口
if( e.getSource()==item_explain ) //说明
{
new Another();
}
if( e.getSource()==item_auther ) //作者
{
JOptionPane.showMessageDialog(null,"作者: 卫泶媚\n学号:2012914201\n","作者信息",JOptionPane.PLAIN_MESSAGE);
}
if( e.getSource()==item_exit )
{ //退出,e.getSource()获得当前事件源组件比较引用
System.exit(0);
}
if( e.getSource()==item_sol)
{ //提交
if(gettext()==1)
{
if(ans()==1)
{
JOptionPane.showMessageDialog(null,"恭喜!答案完全正确!太棒了!");
}
else
{
JOptionPane.showMessageDialog(null,"抱歉!答案不正确,请再接再厉!"); //弹出提示框,显示信息
}
}
}
if( e.getSource()==item_rem){ //重来
for(int i=1;i<=9;i++){
for(int j=1;j<=9;j++){
text[i][j].setText(atext[i][j]);
}
}
}
if( e.getSource()==item_ans){ //答案
new ShuDuAns();
}
if( e.getSource()==item_next){ //开局
setnum();
settext();
this.setVisible(false);
new ShuDu1();
}
}
public void itemStateChanged(ItemEvent e){ //改变难易程度,事件的处理方法
if(box.getSelectedIndex()==0){ // easy
hard=datahard[0];
}
if(box.getSelectedIndex()==1){ // normal
hard=datahard[1];
}
if(box.getSelectedIndex()==2){ // hard
hard=datahard[2];
}
}
public static void main(String args[]){ //声明main方法
setnum();
settext();
new ShuDu1();
}
}
5 参考资料
1.《Java语言程序设计》丁振凡(主编)薛清华(副主编)
2. 《Java语言程序设计实验指导与习题解答》丁振凡(主编)李宪伟(副主编)
3.《Java版数独设计》
本文来自:中国自学编程网()
详细出处参考:/html/20070921/27316_8.html
4.《Java课程设计九宫格数独》
5.《Java数独程序》作者:王洪晓、王美惠、路盟盟
6 心得体会
JA V A语言是一种纯面向对象的编程语言,经过接近一学期的学期,有了一定的JA V A 语言基础,但是当自己开始着手编写期末课程设计的程序时,感觉很茫然,不知道该做些什么才好。
后来,老师给了我们几个参考的程序,在仔细阅读和思考的过程中,我选定了此次课程设计的主题——数独游戏程序设计。
从课程设计的选题到程序代码的编写再到程序的调试运行,都遇到了许多大大小小的困难,而且这次没有老师辅导,基本上要靠自己独立完成,主要是通过上网和看书来查找资料解决各种问题,完成后自己尝试着总结,并撰写课程设计报告。
我觉得这次课程设计的经验是很宝贵的一次另类课堂,在自己试验的过程中自己查找资料解决问题,遇到的问题时耐心分析,认真思考,带着问题寻找解决的方法。
面对设计中出现的异常情况,不要恐惧,要善于运用网络和书籍着手解决问题,在设计之前理出设计思维,有条理的进行,尽量减少实验操作的盲目性,从而提高程序效率,详细记录设计中出现的现象并加以思考。
经过此次课程设计,我明白到:要学好JA V A,首先要熟悉JA V A语言的基本语法规则,其次,要熟悉JA V A类的库,掌握类库的体系和常用类的使用方法。
另一方面,软件设计是一件极赋创造性的工作,同时也是一项工程,只有经过亲自动手编程并上机调试,才能最快地提高编程的能力。
另外,JA V A语言的学习应该由浅入深、循序渐进,尽量使用规范的代码和适当添加备注会更加有利于JA V A语言的学习。