zoukankan      html  css  js  c++  java
  • MFC实现数独(2)

    主要功能描述:

    运行程序后对话框会显示一个9x9的待输入数独区域,并提供随机生成数独和生成数独按钮,生成数独按钮后会创建数独并随机显示其中一个至数独区域,随机生成数独会从已生成的数独中随机获取一个并显示至界面,目前只是框架功能。

     

    主要用到的类功能如下:

    SudukuFile,数独与文件之间的存取类,提供写接口与读接口。

    Suduku ,数独的生成与处理类,提供CreateSuduku,set与get数独元素,get随机数独的接口。

    DrawPad ,数独绘制类,绘制数独矩形区域的边框,绘制数独的数字,接受dlg的单击消息产生可编辑框并依据编辑框输入值改变数独显示。

    dlg,MFC的dlg派生类,初始化按钮、边框等对话框属性。

    SudukuFile类文件操作函数如下:

    bool SudukuFile::WriteSudukuToFile(int data[9][9], char* filename) 

    { //目的不明确导致的含糊函数,这里需要的是指针不为NULL且文件不存在 

     if(!CheckFileStatus(filename, FILE_NOT_EXIT))

     return false; 

     FILE* writefile;

     int err = fopen_s(&writefile, filename, "w"); 

     if(err != 0) 

     { return false; }

     strncpy_s(m_filelist[curindex], MAX_FILENAME, filename, strlen(filename)); 

     curindex++; 

     int offset = '1' - 1;

     for(int r = 0; r < 9; r++) 

      {

     for(int c = 0; c < 9; c++) 

     {

     fputc(data[r][c] + offset, writefile);

     }

     fputc(' ', writefile);

     }

     fclose(writefile);

     return true; 

    }

     bool SudukuFile::GetSudukuFromFile(char* filename, int data[9][9])

     {

     //需要文件指针不为NULL,且文件存在,解决方法:扩展参数,判断目的 

      if(!CheckFileStatus(filename, FILE_EXIT))

      return false;

     FILE* readfile; int err = fopen_s(&readfile, filename, "r");

      if(err != 0)

     { return false; }

     int result = 0; 

     int offset = '1' - 1; 

     for(int r = 0; r < 9; r++) 

      {

     for(int c = 0; c < 9; c++)

     { 

     if((result = fgetc(readfile)) != EOF)

     { data[r][c] = result - offset; }

     }

      if((result = fgetc(readfile)) == ' ') 

      { continue; }

      else

      { fclose(readfile); return false; } 

      }

     fclose(readfile);

     return true;

     }

    Suduku类增加了严谨suduku判断,即每一个3x3的区域都是1-9.

    bool Suduku::CheckRigorousSuduku(int r, int c)

     {

     for(int po = 1; po <= 9; po++) 

     {

     int ret = false;

     for(int row = r; row < r + 3; row++) 

     {

     for(int col = c; col < r + 3; col++)

     {

     if(m_chess[row][col] == po)

     ret = true;

     }

     }

      if(ret == false)

     return ret;

     

      return true; 

    }


    DrawPad类主要函数,重载了picture控件的OnPaint函数用来绘制数独的矩形边框,OnPaint函数还会调用Draw函数来绘制数独矩形的背景和数字;Draw函数遍历9x9的数独格子来绘制对应的背景和数字;重载了OnLButtonDown函数来接受对话框传来的单击消息,收到单击消息后会创建一个可供输入的编辑框;重载了OnEnChangeText,当编辑框的数值发生改变时会调用该函数将输入数值传给suduku;这里需要注意的是:OnEnChangeText需要手动与编辑框控件关联。

    void DrawPad::OnPaint() 

    {

     CPaintDC dc(this);

     // device context for painting

     CPen red10pen(PS_DOT, 10, #ff0000);

     dc.SelectObject(red10pen);

     CRect rect;

     GetClientRect(rect); 

     dc.Rectangle(rect);

     m_height = (rect.bottom - rect.top - 28)/9; 

     m_weight = (rect.right - rect.left - 28)/9;

     CPen red2pen(PS_DOT, 2, #ff0000);

     CPen red4pen(PS_DOT, 4, #ff0000); 

     dc.SelectObject(red4pen); 

     dc.Rectangle(rect.left+10, rect.top+10, rect.right-10, rect.bottom-10);

     dc.SelectObject(red2pen);

     for(int row = 0; row < 9; row++) 

     { 

     for(int col = 0; col < 9; col++) 

     {

     int left = col * m_weight+1 + 17;

     int top = row * m_height+1 + 14;

     int bottom = (row + 1) * m_height - 2 + 14;

     int right = (col + 1) * m_weight - 2 + 17;

     CRect rect;

     rect.bottom = bottom; 

     rect.left = left;

     rect.right = right;

     rect.top = top;

     dc.Rectangle(rect);

     }

     }

     Initialize();

     Draw(); 

     // TODO: 在此处添加消息处理程序代码 

     // 不为绘图消息调用 

    CStatic::OnPaint() 

    }


    void DrawPad::OnLButtonDown(UINT nFlags, CPoint point)

     {

      // TODO: 在此添加消息处理程序代码和/或调用默认值

      GetRowCol(point);

     Initialize();

     if(m_edit != NULL)

      delete m_edit;

      m_edit = new CEdit;

      m_edit->Create(ES_CENTER, m_rect[m_row][m_col], this, IDC_INPUT); m_edit->SetFont(&m_font); m_edit->SetFocus(); m_edit->ShowWindow(true); CStatic::OnLButtonDown(nFlags, point);

     }

    void DrawPad::OnEnChangeText()

     {

     CString str;

     m_edit->GetWindowTextW(str); 

     m_suduku.Set(m_row, m_col, _ttoi(str));

    }

    void DrawPad::Draw() 

    {

     CDC *pDC = GetDC();

     for(int r = 0; r < 9; r++) 

     {

     for(int c = 0; c < 9; c++)

     {

     pDC->FillSolidRect(m_rect[r][c], #850000);

     if(m_suduku.Get(r, c) != 0)

     {

     CString str;

     str.Format(_T("%d"),m_suduku.Get(r, c));

     CFont font = CFont();

     font.CreateFontW(40, 0, 0, 0, FW_BOLD, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH|FF_SWISS, _T("Arival"));

     pDC->SelectObject(&font);

     pDC->DrawText(str, m_rect[r][c],DT_CENTER|DT_VCENTER|DT_SINGLELINE);

     }

     }

     }

     }


    消息关联方法:ON_EN_CHANGE(IDC_INPUT, &DrawPad::OnEnChangeText)

    CXDoctorDlg类中重载了OnLButtonDown,判断游戏是否开始,如果游戏开始,且点击区域为picture控件时向picture发送左键单击消息。

    void CXDoctorDlg::OnLButtonDown(UINT nFlags, CPoint point)

     {

     // TODO: 在此添加消息处理程序代码和/或调用默认值 

     CRect rect;

     m_DrawPad.GetWindowRect(&rect);

     ScreenToClient(rect);

     if(!rect.PtInRect(point))

     { return; } 

     int x = point.x - rect.left;

     int y = point.y - rect.top;

     if(m_start)

     { 

     m_DrawPad.SetFocus();

     m_DrawPad.SendMessage(WM_LBUTTONDOWN, IDC_DRAWPAD, MAKELONG(x, y));

     }

     //CDialogEx::OnLButtonDown(nFlags, point);

     }


    真是水的拿自己没办法,断断续续这么久还只有基础功能,数独生成的递归函数到底哪里bug导致死循环还是不明了,路过的各位还请多多指教,邮箱:believing_dan@hotmail.com

  • 相关阅读:
    每日一小练——数值自乘递归解
    linux的webserver配置与管理——创建用户个人主页
    微价值:专訪《甜心爱消除》个人开发人员Lee,日入千元!
    四月二十五日,bugzilla for CentOS 安装
    【剑指offer】顺时针打印矩阵
    何从之
    Java实现 蓝桥杯VIP 基础练习 时间转换
    Java实现 蓝桥杯VIP 基础练习 时间转换
    Java实现 蓝桥杯VIP 基础练习 字符串对比
    Java实现 蓝桥杯VIP 基础练习 字符串对比
  • 原文地址:https://www.cnblogs.com/learn-my-life/p/3335199.html
Copyright © 2011-2022 走看看